prima: WLAN Driver Release 3.1.7.9
This is the initial release of the Prima WLAN Driver
diff --git a/CORE/SME/inc/btcApi.h b/CORE/SME/inc/btcApi.h
new file mode 100644
index 0000000..9cd2466
--- /dev/null
+++ b/CORE/SME/inc/btcApi.h
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/******************************************************************************
+*
+* Name: btcApi.h
+*
+* Description: BTC Events Layer API definitions.
+*
+* Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+* Qualcomm Confidential and Proprietary.
+*
+******************************************************************************/
+
+#ifndef __BTC_API_H__
+#define __BTC_API_H__
+
+#include "vos_types.h"
+#include "vos_timer.h"
+
+#define BT_INVALID_CONN_HANDLE (0xFFFF) /**< Invalid connection handle */
+
+/* ACL and Sync connection attempt results */
+#define BT_CONN_STATUS_FAIL (0) /**< Connection failed */
+#define BT_CONN_STATUS_SUCCESS (1) /**< Connection successful */
+#define BT_CONN_STATUS_MAX (2) /**< This and beyond are invalid values */
+
+/** ACL and Sync link types
+ These must match the Bluetooth Spec!
+*/
+#define BT_SCO (0) /**< SCO Link */
+#define BT_ACL (1) /**< ACL Link */
+#define BT_eSCO (2) /**< eSCO Link */
+#define BT_LINK_TYPE_MAX (3) /**< This value and higher are invalid */
+
+/** ACL link modes
+ These must match the Bluetooth Spec!
+*/
+#define BT_ACL_ACTIVE (0) /**< Active mode */
+#define BT_ACL_HOLD (1) /**< Hold mode */
+#define BT_ACL_SNIFF (2) /**< Sniff mode */
+#define BT_ACL_PARK (3) /**< Park mode */
+#define BT_ACL_MODE_MAX (4) /**< This value and higher are invalid */
+
+/**
+ * A2DP BTC max no of BT sub intervals
+ *
+ * **/
+#define BTC_MAX_NUM_ACL_BT_SUB_INTS (7)
+
+/** BTC Executions Modes allowed to be set by user
+*/
+#define BTC_SMART_COEXISTENCE (0) /** BTC Mapping Layer decides whats best */
+#define BTC_WLAN_ONLY (1) /** WLAN takes all mode */
+#define BTC_PTA_ONLY (2) /** Allow only 3 wire protocol in H/W */
+#define BTC_SMART_MAX_WLAN (3) /** BTC Mapping Layer decides whats best, WLAN weighted */
+#define BTC_SMART_MAX_BT (4) /** BTC Mapping Layer decides whats best, BT weighted */
+#define BTC_SMART_BT_A2DP (5) /** BTC Mapping Layer decides whats best, balanced + BT A2DP weight */
+#define BT_EXEC_MODE_MAX (6) /** This and beyond are invalid values */
+
+/** Enumeration of different kinds actions that BTC Mapping Layer
+ can do if PM indication (to AP) fails.
+*/
+#define BTC_RESTART_CURRENT (0) /** Restart the interval we just failed to leave */
+#define BTC_START_NEXT (1) /** Start the next interval even though the PM transition at the AP was unsuccessful */
+#define BTC_ACTION_TYPE_MAX (2) /** This and beyond are invalid values */
+
+#define BTC_BT_INTERVAL_MODE1_DEFAULT (120) /** BT Interval in Mode 1 */
+#define BTC_WLAN_INTERVAL_MODE1_DEFAULT (30) /** WLAN Interval in Mode 1 */
+
+/** Bitmaps used for maintaining various BT events that requires
+ enough time to complete such that it might require disbling of
+ heartbeat monitoring to avoid WLAN link loss with the AP
+*/
+#define BT_INQUIRY_STARTED (1<<0)
+#define BT_PAGE_STARTED (1<<1)
+#define BT_CREATE_ACL_CONNECTION_STARTED (1<<2)
+#define BT_CREATE_SYNC_CONNECTION_STARTED (1<<3)
+
+/** Maximum time duration in milliseconds between a specific BT start event and its
+ respective stop event, before it can be declared timed out on receiving the stop event.
+*/
+#define BT_MAX_EVENT_DONE_TIMEOUT 45000
+
+
+/*
+ To suppurt multiple SCO connections for BT+UAPSD work
+*/
+#define BT_MAX_SCO_SUPPORT 3
+#define BT_MAX_ACL_SUPPORT 3
+#define BT_MAX_DISCONN_SUPPORT (BT_MAX_SCO_SUPPORT+BT_MAX_ACL_SUPPORT)
+#define BT_MAX_NUM_EVENT_ACL_DEFERRED 4 //We may need to defer these many BT events for ACL
+#define BT_MAX_NUM_EVENT_SCO_DEFERRED 4 //We may need to defer these many BT events for SYNC
+
+
+/** Enumeration of all the different kinds of BT events
+*/
+typedef enum eSmeBtEventType
+{
+ BT_EVENT_DEVICE_SWITCHED_ON,
+ BT_EVENT_DEVICE_SWITCHED_OFF,
+ BT_EVENT_INQUIRY_STARTED,
+ BT_EVENT_INQUIRY_STOPPED,
+ BT_EVENT_INQUIRY_SCAN_STARTED,
+ BT_EVENT_INQUIRY_SCAN_STOPPED,
+ BT_EVENT_PAGE_STARTED,
+ BT_EVENT_PAGE_STOPPED,
+ BT_EVENT_PAGE_SCAN_STARTED,
+ BT_EVENT_PAGE_SCAN_STOPPED,
+ BT_EVENT_CREATE_ACL_CONNECTION,
+ BT_EVENT_ACL_CONNECTION_COMPLETE,
+ BT_EVENT_CREATE_SYNC_CONNECTION,
+ BT_EVENT_SYNC_CONNECTION_COMPLETE,
+ BT_EVENT_SYNC_CONNECTION_UPDATED,
+ BT_EVENT_DISCONNECTION_COMPLETE,
+ BT_EVENT_MODE_CHANGED,
+ BT_EVENT_A2DP_STREAM_START,
+ BT_EVENT_A2DP_STREAM_STOP,
+ BT_EVENT_TYPE_MAX, //This and beyond are invalid values
+} tSmeBtEventType;
+
+/** BT-AMP events type
+*/
+typedef enum eSmeBtAmpEventType
+{
+ BTAMP_EVENT_CONNECTION_START,
+ BTAMP_EVENT_CONNECTION_STOP,
+ BTAMP_EVENT_CONNECTION_TERMINATED,
+ BTAMP_EVENT_TYPE_MAX, //This and beyond are invalid values
+} tSmeBtAmpEventType;
+
+
+/**Data structure that specifies the needed event parameters for
+ BT_EVENT_CREATE_ACL_CONNECTION and BT_EVENT_ACL_CONNECTION_COMPLETE
+*/
+typedef struct sSmeBtAclConnectionParam
+{
+ v_U8_t bdAddr[6];
+ v_U16_t connectionHandle;
+ v_U8_t status;
+} tSmeBtAclConnectionParam, *tpSmeBtAclConnectionParam;
+
+/** Data structure that specifies the needed event parameters for
+ BT_EVENT_CREATE_SYNC_CONNECTION, BT_EVENT_SYNC_CONNECTION_COMPLETE
+ and BT_EVENT_SYNC_CONNECTION_UPDATED
+*/
+typedef struct sSmeBtSyncConnectionParam
+{
+ v_U8_t bdAddr[6];
+ v_U16_t connectionHandle;
+ v_U8_t status;
+ v_U8_t linkType;
+ v_U8_t scoInterval; //units in number of 625us slots
+ v_U8_t scoWindow; //units in number of 625us slots
+ v_U8_t retransmisisonWindow; //units in number of 625us slots
+} tSmeBtSyncConnectionParam, *tpSmeBtSyncConnectionParam;
+
+typedef struct sSmeBtSyncUpdateHist
+{
+ tSmeBtSyncConnectionParam btSyncConnection;
+ v_BOOL_t fValid;
+} tSmeBtSyncUpdateHist, *tpSmeBtSyncUpdateHist;
+
+/**Data structure that specifies the needed event parameters for
+ BT_EVENT_MODE_CHANGED
+*/
+typedef struct sSmeBtAclModeChangeParam
+{
+ v_U16_t connectionHandle;
+ v_U8_t mode;
+} tSmeBtAclModeChangeParam, *tpSmeBtAclModeChangeParam;
+
+/*Data structure that specifies the needed event parameters for
+ BT_EVENT_DISCONNECTION_COMPLETE
+*/
+typedef struct sSmeBtDisconnectParam
+{
+ v_U16_t connectionHandle;
+} tSmeBtDisconnectParam, *tpSmeBtDisconnectParam;
+
+/*Data structure that specifies the needed event parameters for
+ BT_EVENT_A2DP_STREAM_START
+ BT_EVENT_A2DP_STREAM_STOP
+*/
+typedef struct sSmeBtA2DPParam
+{
+ v_U8_t bdAddr[6];
+} tSmeBtA2DPParam, *tpSmeBtA2DPParam;
+
+
+/** Generic Bluetooth Event structure for BTC
+*/
+typedef struct sSmeBtcBtEvent
+{
+ tSmeBtEventType btEventType;
+ union
+ {
+ v_U8_t bdAddr[6]; /**< For events with only a BT Addr in event_data */
+ tSmeBtAclConnectionParam btAclConnection;
+ tSmeBtSyncConnectionParam btSyncConnection;
+ tSmeBtDisconnectParam btDisconnect;
+ tSmeBtAclModeChangeParam btAclModeChange;
+ }uEventParam;
+} tSmeBtEvent, *tpSmeBtEvent;
+
+
+/**
+ BT-AMP Event Structure
+*/
+typedef struct sSmeBtAmpEvent
+{
+ tSmeBtAmpEventType btAmpEventType;
+
+} tSmeBtAmpEvent, *tpSmeBtAmpEvent;
+
+
+/** Data structure that specifies the BTC Configuration parameters
+*/
+typedef struct sSmeBtcConfig
+{
+ v_U8_t btcExecutionMode;
+ v_U8_t btcConsBtSlotsToBlockDuringDhcp;
+ v_U8_t btcA2DPBtSubIntervalsDuringDhcp;
+ v_U8_t btcActionOnPmFail;
+ v_U8_t btcBtIntervalMode1;
+ v_U8_t btcWlanIntervalMode1;
+
+} tSmeBtcConfig, *tpSmeBtcConfig;
+
+
+typedef struct sSmeBtAclModeChangeEventHist
+{
+ tSmeBtAclModeChangeParam btAclModeChange;
+ v_BOOL_t fValid;
+} tSmeBtAclModeChangeEventHist, *tpSmeBtAclModeChangeEventHist;
+
+typedef struct sSmeBtAclEventHist
+{
+ //At most, cached events are COMPLETION, DISCONNECT, CREATION, COMPLETION
+ tSmeBtEventType btEventType[BT_MAX_NUM_EVENT_ACL_DEFERRED];
+ tSmeBtAclConnectionParam btAclConnection[BT_MAX_NUM_EVENT_ACL_DEFERRED];
+ //bNextEventIdx == 0 meaning no event cached here
+ tANI_U8 bNextEventIdx;
+} tSmeBtAclEventHist, *tpSmeBtAclEventHist;
+
+typedef struct sSmeBtSyncEventHist
+{
+ //At most, cached events are COMPLETION, DISCONNECT, CREATION, COMPLETION
+ tSmeBtEventType btEventType[BT_MAX_NUM_EVENT_SCO_DEFERRED];
+ tSmeBtSyncConnectionParam btSyncConnection[BT_MAX_NUM_EVENT_SCO_DEFERRED];
+ //bNextEventIdx == 0 meaning no event cached here
+ tANI_U8 bNextEventIdx;
+} tSmeBtSyncEventHist, *tpSmeBtSyncEventHist;
+
+typedef struct sSmeBtDisconnectEventHist
+{
+ tSmeBtDisconnectParam btDisconnect;
+ v_BOOL_t fValid;
+} tSmeBtDisconnectEventHist, *tpSmeBtDisconnectEventHist;
+
+
+/*
+ Data structure for the history of BT events
+*/
+typedef struct sSmeBtcEventHist
+{
+ tSmeBtSyncEventHist btSyncConnectionEvent[BT_MAX_SCO_SUPPORT];
+ tSmeBtAclEventHist btAclConnectionEvent[BT_MAX_ACL_SUPPORT];
+ tSmeBtAclModeChangeEventHist btAclModeChangeEvent[BT_MAX_ACL_SUPPORT];
+ tSmeBtDisconnectEventHist btDisconnectEvent[BT_MAX_DISCONN_SUPPORT];
+ tSmeBtSyncUpdateHist btSyncUpdateEvent[BT_MAX_SCO_SUPPORT];
+ int nInquiryEvent; //>0 for # of outstanding inquiriy starts
+ //<0 for # of outstanding inquiry stops
+ //0 == no inquiry event
+ int nPageEvent; //>0 for # of outstanding page starts
+ //<0 for # of outstanding page stops
+ //0 == no page event
+ v_BOOL_t fA2DPStarted;
+ v_BOOL_t fA2DPStopped;
+} tSmeBtcEventHist, *tpSmeBtcEventHist;
+
+typedef struct sSmeBtcEventReplay
+{
+ tSmeBtcEventHist btcEventHist;
+ v_BOOL_t fBTSwitchOn;
+ v_BOOL_t fBTSwitchOff;
+ //This is not directly tied to BT event so leave it alone when processing BT events
+ v_BOOL_t fRestoreHBMonitor;
+} tSmeBtcEventReplay, *tpSmeBtcEventReplay;
+
+typedef struct sSmeBtcInfo
+{
+ tSmeBtcConfig btcConfig;
+ v_BOOL_t btcReady;
+ v_U8_t btcEventState;
+ v_U8_t btcHBActive; /* Is HB currently active */
+ v_U8_t btcHBCount; /* default HB count */
+ vos_timer_t restoreHBTimer; /* Timer to restore heart beat */
+ tSmeBtcEventReplay btcEventReplay;
+ v_BOOL_t fReplayBTEvents;
+ v_BOOL_t btcUapsdOk; /* Indicate whether BTC is ok with UAPSD */
+ v_BOOL_t fA2DPTrafStop;/*flag to check A2DP_STOP event has come before MODE_CHANGED*/
+ v_U16_t btcScoHandles[BT_MAX_SCO_SUPPORT]; /* Handles for SCO, if any*/
+ v_BOOL_t fA2DPUp; /*remember whether A2DP is in session*/
+} tSmeBtcInfo, *tpSmeBtcInfo;
+
+
+/** Routine definitions
+*/
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+VOS_STATUS btcOpen (tHalHandle hHal);
+VOS_STATUS btcClose (tHalHandle hHal);
+VOS_STATUS btcReady (tHalHandle hHal);
+VOS_STATUS btcSendCfgMsg(tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig);
+VOS_STATUS btcSignalBTEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent);
+VOS_STATUS btcSetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig);
+VOS_STATUS btcGetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig);
+/*
+ Caller can check whether BTC's current event allows UAPSD. This doesn't affect
+ BMPS.
+ return: VOS_TRUE -- BTC is ready for UAPSD
+ VOS_FALSE -- certain BT event is active, cannot enter UAPSD
+*/
+v_BOOL_t btcIsReadyForUapsd( tHalHandle hHal );
+eHalStatus btcHandleCoexInd(tHalHandle hHal, void* pMsg);
+#endif /* End of WLAN_MDM_CODE_REDUCTION_OPT */
+
+#endif
diff --git a/CORE/SME/inc/ccmApi.h b/CORE/SME/inc/ccmApi.h
new file mode 100644
index 0000000..5195459
--- /dev/null
+++ b/CORE/SME/inc/ccmApi.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+ \file ccmApi.h
+
+ \brief Exports and types for the Common Config Module (CCM)
+
+ $Id$
+
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+
+ This file contains all the interfaces for thge Platform Abstration Layer
+ functions. It is intended to be included in all modules that are using
+ the PAL interfaces.
+
+ ========================================================================== */
+#ifndef CCMAPI_H__
+#define CCMAPI_H__
+
+//#include "wniCfgAp.h" /* CFG_PARAM_MAX_NUM */
+#include "wniCfgSta.h"
+#include "halTypes.h"
+
+#define CCM_11B_CHANNEL_END 14
+
+#define CCM_IS_RESULT_SUCCESS(result) (WNI_CFG_SUCCESS == (result) ||\
+ WNI_CFG_NEED_RESTART == (result) || \
+ WNI_CFG_NEED_RELOAD == (result))
+
+#define CCM_INTEGER_TYPE 0
+#define CCM_STRING_TYPE 1
+
+typedef void (*tCcmCfgSetCallback)(tHalHandle hHal, tANI_S32 result) ;
+
+typedef enum {
+ eCCM_STOPPED,
+ eCCM_STARTED,
+ eCCM_REQ_SENT,
+ eCCM_REQ_QUEUED,
+ eCCM_REQ_DONE,
+} eCcmState ;
+
+/* We do not use Linux's list facility */
+typedef struct cfgreq {
+ struct cfgreq *next ;
+ tANI_U16 cfgId ;
+ tANI_U8 type ;
+ tANI_U8 state : 7 ;
+ tANI_U8 toBeSaved : 1 ;
+ tANI_S32 length ;
+ void *ccmPtr;
+ tANI_U32 ccmValue;
+ tCcmCfgSetCallback callback;
+ void *done ;
+} tCfgReq ;
+
+typedef struct {
+ tANI_U16 started : 1 ;
+ tANI_U16 in_progress : 1 ;
+ tANI_U16 reserved : 14 ;
+ tANI_S16 nr_param ;
+ tANI_U32 result ;
+ tCcmCfgSetCallback callback ;
+ void *done ;
+} tCfgReplay ;
+
+struct ccmlink {
+ tCfgReq *head;
+ tCfgReq *tail;
+} ;
+
+typedef struct {
+ struct ccmlink reqQ ;
+ eCcmState state ;
+ tCfgReq * comp[CFG_PARAM_MAX_NUM] ;
+ tCfgReplay replay ;
+ void *lock;
+} tCcm ;
+
+void ccmCfgCnfMsgHandler(tHalHandle hHal, void *msg) ;
+eHalStatus ccmOpen(tHalHandle hHal) ;
+eHalStatus ccmClose(tHalHandle hHal) ;
+void ccmStart(tHalHandle hHal) ;
+void ccmStop(tHalHandle hHal) ;
+//If callback is NULL, the API is not serialized for the CFGs
+eHalStatus ccmCfgSetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 ccmValue, tCcmCfgSetCallback callback, eAniBoolean toBeSaved) ;
+//If callback is NULL, the API is not serialized for the CFGs
+eHalStatus ccmCfgSetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pStr, tANI_U32 length, tCcmCfgSetCallback callback, eAniBoolean toBeSaved) ;
+eHalStatus ccmCfgUpdate(tHalHandle hHal, tCcmCfgSetCallback callback) ;
+eHalStatus ccmCfgGetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 *pValue) ;
+eHalStatus ccmCfgGetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pBuf, tANI_U32 *pLength) ;
+
+void ccmDumpInit(tHalHandle hHal);
+
+#endif /*CCMAPI_H__*/
diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h
new file mode 100644
index 0000000..60d9da9
--- /dev/null
+++ b/CORE/SME/inc/csrApi.h
@@ -0,0 +1,1385 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+ \file csrApi.h
+
+ Exports and types for the Common Scan and Roaming Module interfaces.
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+ ========================================================================== */
+#ifndef CSRAPI_H__
+#define CSRAPI_H__
+
+#include "sirApi.h"
+#include "sirMacProtDef.h"
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include "halRfTypes.h"
+#endif
+#include "csrLinkList.h"
+
+typedef enum
+{
+ eCSR_AUTH_TYPE_NONE, //never used
+ // MAC layer authentication types
+ eCSR_AUTH_TYPE_OPEN_SYSTEM,
+ eCSR_AUTH_TYPE_SHARED_KEY,
+ eCSR_AUTH_TYPE_AUTOSWITCH,
+
+ // Upper layer authentication types
+ eCSR_AUTH_TYPE_WPA,
+ eCSR_AUTH_TYPE_WPA_PSK,
+ eCSR_AUTH_TYPE_WPA_NONE,
+
+ eCSR_AUTH_TYPE_RSN,
+ eCSR_AUTH_TYPE_RSN_PSK,
+#if defined WLAN_FEATURE_VOWIFI_11R
+ eCSR_AUTH_TYPE_FT_RSN,
+ eCSR_AUTH_TYPE_FT_RSN_PSK,
+#endif
+#ifdef FEATURE_WLAN_WAPI
+ eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE,
+ eCSR_AUTH_TYPE_WAPI_WAI_PSK,
+#endif /* FEATURE_WLAN_WAPI */
+#ifdef FEATURE_WLAN_CCX
+ eCSR_AUTH_TYPE_CCKM_WPA,
+ eCSR_AUTH_TYPE_CCKM_RSN,
+#endif /* FEATURE_WLAN_CCX */
+ eCSR_NUM_OF_SUPPORT_AUTH_TYPE,
+ eCSR_AUTH_TYPE_FAILED = 0xff,
+ eCSR_AUTH_TYPE_UNKNOWN = eCSR_AUTH_TYPE_FAILED,
+
+}eCsrAuthType;
+
+
+typedef enum
+{
+ eCSR_ENCRYPT_TYPE_NONE,
+ eCSR_ENCRYPT_TYPE_WEP40_STATICKEY,
+ eCSR_ENCRYPT_TYPE_WEP104_STATICKEY,
+
+ eCSR_ENCRYPT_TYPE_WEP40,
+ eCSR_ENCRYPT_TYPE_WEP104,
+ eCSR_ENCRYPT_TYPE_TKIP,
+ eCSR_ENCRYPT_TYPE_AES,
+#ifdef FEATURE_WLAN_WAPI
+ eCSR_ENCRYPT_TYPE_WPI, //WAPI
+#endif /* FEATURE_WLAN_WAPI */
+#ifdef FEATURE_WLAN_CCX
+ eCSR_ENCRYPT_TYPE_KRK,
+#endif /* FEATURE_WLAN_CCX */
+#ifdef WLAN_FEATURE_11W
+ //11w BIP
+ eCSR_ENCRYPT_TYPE_AES_CMAC,
+#endif
+ eCSR_ENCRYPT_TYPE_ANY,
+ eCSR_NUM_OF_ENCRYPT_TYPE = eCSR_ENCRYPT_TYPE_ANY,
+
+ eCSR_ENCRYPT_TYPE_FAILED = 0xff,
+ eCSR_ENCRYPT_TYPE_UNKNOWN = eCSR_ENCRYPT_TYPE_FAILED,
+
+}eCsrEncryptionType;
+
+/*---------------------------------------------------------------------------
+ Enumeration of the various Security types
+---------------------------------------------------------------------------*/
+typedef enum
+{
+ eCSR_SECURITY_TYPE_WPA,
+ eCSR_SECURITY_TYPE_RSN,
+#ifdef FEATURE_WLAN_WAPI
+ eCSR_SECURITY_TYPE_WAPI,
+#endif /* FEATURE_WLAN_WAPI */
+ eCSR_SECURITY_TYPE_UNKNOWN,
+
+}eCsrSecurityType;
+
+typedef enum
+{
+ eCSR_DOT11_MODE_TAURUS = 0, //This mean everything because it covers all thing we support
+ eCSR_DOT11_MODE_abg = 0x0001, //11a/b/g only, no HT, no proprietary
+ eCSR_DOT11_MODE_11a = 0x0002,
+ eCSR_DOT11_MODE_11b = 0x0004,
+ eCSR_DOT11_MODE_11g = 0x0008,
+ eCSR_DOT11_MODE_11n = 0x0010,
+ eCSR_DOT11_MODE_POLARIS = 0x0020,
+ eCSR_DOT11_MODE_TITAN = 0x0040,
+ eCSR_DOT11_MODE_11g_ONLY = 0x0080,
+ eCSR_DOT11_MODE_11n_ONLY = 0x0100,
+ eCSR_DOT11_MODE_TAURUS_ONLY = 0x0200,
+ eCSR_DOT11_MODE_11b_ONLY = 0x0400,
+ eCSR_DOT11_MODE_11a_ONLY = 0x0800,
+ //This is for WIFI test. It is same as eWNIAPI_MAC_PROTOCOL_ALL except when it starts IBSS in 11B of 2.4GHz
+ //It is for CSR internal use
+ eCSR_DOT11_MODE_AUTO = 0x1000,
+
+ eCSR_NUM_PHY_MODE = 16, //specify the number of maximum bits for phyMode
+}eCsrPhyMode;
+
+
+typedef tANI_U8 tCsrBssid[WNI_CFG_BSSID_LEN];
+
+typedef enum
+{
+ eCSR_BSS_TYPE_INFRASTRUCTURE,
+#ifdef WLAN_SOFTAP_FEATURE
+ eCSR_BSS_TYPE_INFRA_AP, // SoftAP AP
+#endif
+ eCSR_BSS_TYPE_IBSS, // an IBSS network we will NOT start
+ eCSR_BSS_TYPE_START_IBSS, // an IBSS network we will start if no partners detected.
+ eCSR_BSS_TYPE_WDS_AP, // BT-AMP AP
+ eCSR_BSS_TYPE_WDS_STA, // BT-AMP station
+ eCSR_BSS_TYPE_ANY, // any BSS type (IBSS or Infrastructure).
+}eCsrRoamBssType;
+
+
+
+typedef enum {
+ eCSR_SCAN_REQUEST_11D_SCAN = 1,
+ eCSR_SCAN_REQUEST_FULL_SCAN,
+ eCSR_SCAN_IDLE_MODE_SCAN,
+ eCSR_SCAN_HO_BG_SCAN, // bg scan request in NRT & RT Handoff sub-states
+ eCSR_SCAN_HO_PROBE_SCAN, // directed probe on an entry from the candidate list
+ eCSR_SCAN_HO_NT_BG_SCAN, // bg scan request in NT sub-state
+ eCSR_SCAN_P2P_DISCOVERY,
+
+ eCSR_SCAN_SOFTAP_CHANNEL_RANGE,
+ eCSR_SCAN_P2P_FIND_PEER,
+}eCsrRequestType;
+
+typedef enum {
+ eCSR_SCAN_RESULT_GET = 0,
+ eCSR_SCAN_RESULT_FLUSH = 1, //to delete all cached scan results
+}eCsrScanResultCmd;
+
+typedef enum
+{
+ eCSR_SCAN_SUCCESS,
+ eCSR_SCAN_FAILURE,
+ eCSR_SCAN_ABORT,
+ eCSR_SCAN_FOUND_PEER,
+}eCsrScanStatus;
+
+#define CSR_SCAN_TIME_DEFAULT 0
+#define CSR_VALUE_IGNORED 0xFFFFFFFF
+#define CSR_RSN_PMKID_SIZE 16
+#define CSR_MAX_PMKID_ALLOWED 16
+#define CSR_WEP40_KEY_LEN 5
+#define CSR_WEP104_KEY_LEN 13
+#define CSR_TKIP_KEY_LEN 32
+#define CSR_AES_KEY_LEN 16
+#define CSR_MAX_TX_POWER ( WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMAX )
+#define CSR_MAX_RSC_LEN 16
+#ifdef FEATURE_WLAN_WAPI
+#define CSR_WAPI_BKID_SIZE 16
+#define CSR_MAX_BKID_ALLOWED 16
+#define CSR_WAPI_KEY_LEN 32
+#define CSR_MAX_KEY_LEN ( CSR_WAPI_KEY_LEN ) //longest one is for WAPI
+#else
+#define CSR_MAX_KEY_LEN ( CSR_TKIP_KEY_LEN ) //longest one is for TKIP
+#endif /* FEATURE_WLAN_WAPI */
+#ifdef FEATURE_WLAN_CCX
+#define CSR_KRK_KEY_LEN 16
+#endif
+
+
+
+typedef struct tagCsrChannelInfo
+{
+ tANI_U8 numOfChannels;
+ tANI_U8 *ChannelList; //it will be an array of channels
+}tCsrChannelInfo;
+
+typedef struct tagCsrSSIDInfo
+{
+ tSirMacSSid SSID;
+ tANI_BOOLEAN handoffPermitted;
+ tANI_BOOLEAN ssidHidden;
+}tCsrSSIDInfo;
+
+typedef struct tagCsrSSIDs
+{
+ tANI_U32 numOfSSIDs;
+ tCsrSSIDInfo *SSIDList; //To be allocated for array of SSIDs
+}tCsrSSIDs;
+
+typedef struct tagCsrBSSIDs
+{
+ tANI_U32 numOfBSSIDs;
+ tCsrBssid *bssid;
+}tCsrBSSIDs;
+
+
+typedef struct tagCsrScanRequest
+{
+ tSirScanType scanType;
+ tCsrBssid bssid;
+ eCsrRoamBssType BSSType;
+ tCsrSSIDs SSIDs;
+ tCsrChannelInfo ChannelInfo;
+ tANI_U32 minChnTime; //in units of milliseconds
+ tANI_U32 maxChnTime; //in units of milliseconds
+ tANI_U32 restTime; //in units of milliseconds //ignored when not connected
+ tANI_U32 uIEFieldLen;
+ tANI_U8 *pIEField;
+ eCsrRequestType requestType; //11d scan or full scan
+#ifdef WLAN_FEATURE_P2P
+ tANI_BOOLEAN p2pSearch;
+#endif
+}tCsrScanRequest;
+
+typedef struct tagCsrBGScanRequest
+{
+ tSirScanType scanType;
+ tSirMacSSid SSID;
+ tCsrChannelInfo ChannelInfo;
+ tANI_U32 scanInterval; //in units of milliseconds
+ tANI_U32 minChnTime; //in units of milliseconds
+ tANI_U32 maxChnTime; //in units of milliseconds
+ tANI_U32 restTime; //in units of milliseconds //ignored when not connected
+ tANI_U32 throughputImpact; //specify whether BG scan cares about impacting throughput //ignored when not connected
+ tCsrBssid bssid; //how to use it?? Apple
+}tCsrBGScanRequest;
+
+
+typedef struct tagCsrScanResultInfo
+{
+ //Carry the IEs for the current BSSDescription. A pointer to tDot11fBeaconIEs. Maybe NULL for start BSS.
+ void *pvIes;
+ tAniSSID ssId;
+ v_TIME_t timer; // timer is variable which is used for hidden SSID's timer value
+ //This member must be the last in the structure because the end of tSirBssDescription is an
+ // array with nonknown size at this time
+ tSirBssDescription BssDescriptor;
+}tCsrScanResultInfo;
+
+typedef struct tagCsrEncryptionList
+{
+
+ tANI_U32 numEntries;
+ eCsrEncryptionType encryptionType[eCSR_NUM_OF_ENCRYPT_TYPE];
+
+}tCsrEncryptionList, *tpCsrEncryptionList;
+
+typedef struct tagCsrAuthList
+{
+ tANI_U32 numEntries;
+ eCsrAuthType authType[eCSR_NUM_OF_SUPPORT_AUTH_TYPE];
+}tCsrAuthList, *tpCsrAuthList;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+typedef struct tagCsrMobilityDomainInfo
+{
+ tANI_U8 mdiePresent;
+ tANI_U16 mobilityDomain;
+} tCsrMobilityDomainInfo;
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+typedef struct tagCsrCcxCckmInfo
+{
+ tANI_U32 reassoc_req_num;
+ tANI_BOOLEAN krk_plumbed;
+ tANI_U8 krk[CSR_KRK_KEY_LEN];
+} tCsrCcxCckmInfo;
+#endif
+
+
+typedef struct tagCsrScanResultFilter
+{
+ tCsrBSSIDs BSSIDs; //each bssid has a length of WNI_CFG_BSSID_LEN (6)
+ tCsrSSIDs SSIDs;
+ tCsrChannelInfo ChannelInfo;
+ tCsrAuthList authType;
+ tCsrEncryptionList EncryptionType;
+ //eCSR_ENCRYPT_TYPE_ANY cannot be set in multicast encryption type. If caller doesn't case,
+ //put all supported encryption types in here
+ tCsrEncryptionList mcEncryptionType;
+ eCsrRoamBssType BSSType;
+ //this is a bit mask of all the needed phy mode defined in eCsrPhyMode
+ tANI_U32 phyMode;
+ //If countryCode[0] is not 0, countryCode is checked independent of fCheckUnknownCountryCode
+ tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN];
+ tANI_U8 uapsd_mask;
+ /*For WPS filtering if true => auth and ecryption should be ignored*/
+ tANI_BOOLEAN bWPSAssociation;
+#if defined WLAN_FEATURE_VOWIFI
+ /*For measurement reports --> if set, only SSID, BSSID and channel is considered for filtering.*/
+ tANI_BOOLEAN fMeasurement;
+#endif
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ tCsrMobilityDomainInfo MDID;
+#endif
+ tANI_BOOLEAN p2pResult;
+}tCsrScanResultFilter;
+
+
+typedef struct sCsrChnPower_
+{
+ tANI_U8 firstChannel;
+ tANI_U8 numChannels;
+ tANI_U8 maxtxPower;
+}sCsrChnPower;
+
+
+typedef struct sCsrChannel_
+{
+ tANI_U8 numChannels;
+ tANI_U8 channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+}sCsrChannel;
+
+
+typedef struct tagCsr11dinfo
+{
+ sCsrChannel Channels;
+ tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN+1];
+ //max power channel list
+ sCsrChnPower ChnPower[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+}tCsr11dinfo;
+
+
+typedef enum
+{
+ eCSR_ROAM_CANCELLED = 1,
+ //this mean error happens before association_start or roaming_start is called.
+ eCSR_ROAM_FAILED,
+ //a CSR trigger roaming operation starts, callback may get a pointer to tCsrConnectedProfile
+ eCSR_ROAM_ROAMING_START,
+ //a CSR trigger roaming operation is completed
+ eCSR_ROAM_ROAMING_COMPLETION,
+ //Connection completed status.
+ eCSR_ROAM_CONNECT_COMPLETION,
+ //an association or start_IBSS operation starts,
+ //callback may get a pointer to tCsrRoamProfile and a pointer to tSirBssDescription
+ eCSR_ROAM_ASSOCIATION_START,
+ //a roaming operation is finish, see eCsrRoamResult for
+ //possible data passed back
+ eCSR_ROAM_ASSOCIATION_COMPLETION,
+ eCSR_ROAM_DISASSOCIATED,
+ eCSR_ROAM_ASSOCIATION_FAILURE,
+ //when callback with this flag. callback gets a pointer to the BSS desc.
+ eCSR_ROAM_SHOULD_ROAM,
+ //A new candidate for PMKID is found
+ eCSR_ROAM_SCAN_FOUND_NEW_BSS,
+ //CSR is done lostlink roaming and still cannot reconnect
+ eCSR_ROAM_LOSTLINK,
+ //a link lost is detected. CSR starts roaming.
+ eCSR_ROAM_LOSTLINK_DETECTED,
+ //TKIP MIC error detected, callback gets a pointer to tpSirSmeMicFailureInd
+ eCSR_ROAM_MIC_ERROR_IND,
+ eCSR_ROAM_IBSS_IND, //IBSS indications.
+ //Update the connection status, useful for IBSS: new peer added, network is active etc.
+ eCSR_ROAM_CONNECT_STATUS_UPDATE,
+ eCSR_ROAM_GEN_INFO,
+ eCSR_ROAM_SET_KEY_COMPLETE,
+ eCSR_ROAM_REMOVE_KEY_COMPLETE,
+ eCSR_ROAM_IBSS_LEAVE, //IBSS indications.
+ //BSS in WDS mode status indication
+ eCSR_ROAM_WDS_IND,
+#ifdef WLAN_SOFTAP_FEATURE
+ //BSS in SoftAP mode status indication
+ eCSR_ROAM_INFRA_IND,
+ eCSR_ROAM_WPS_PBC_PROBE_REQ_IND,
+#endif
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ eCSR_ROAM_FT_RESPONSE,
+#endif
+ eCSR_ROAM_FT_START,
+ eCSR_ROAM_INDICATE_MGMT_FRAME,
+ eCSR_ROAM_REMAIN_CHAN_READY,
+ eCSR_ROAM_SEND_ACTION_CNF,
+ //this mean error happens before association_start or roaming_start is called.
+ eCSR_ROAM_SESSION_OPENED,
+ eCSR_ROAM_FT_REASSOC_FAILED,
+}eRoamCmdStatus;
+
+
+//comment inside indicates what roaming callback gets
+typedef enum
+{
+ eCSR_ROAM_RESULT_NONE,
+ //this means no more action in CSR
+ //If roamStatus is eCSR_ROAM_ASSOCIATION_COMPLETION, tCsrRoamInfo's pBssDesc may pass back
+ eCSR_ROAM_RESULT_FAILURE,
+ //Pass back pointer to tCsrRoamInfo
+ eCSR_ROAM_RESULT_ASSOCIATED,
+ eCSR_ROAM_RESULT_NOT_ASSOCIATED,
+ eCSR_ROAM_RESULT_MIC_FAILURE,
+ eCSR_ROAM_RESULT_FORCED,
+ eCSR_ROAM_RESULT_DISASSOC_IND,
+ eCSR_ROAM_RESULT_DEAUTH_IND,
+ eCSR_ROAM_RESULT_CAP_CHANGED,
+ //This means we starts an IBSS
+ //tCsrRoamInfo's pBssDesc may pass back
+ eCSR_ROAM_RESULT_IBSS_STARTED,
+ //START_BSS failed
+ //tCsrRoamInfo's pBssDesc may pass back
+ eCSR_ROAM_RESULT_IBSS_START_FAILED,
+ eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS,
+ eCSR_ROAM_RESULT_IBSS_JOIN_FAILED,
+ eCSR_ROAM_RESULT_IBSS_CONNECT,
+ eCSR_ROAM_RESULT_IBSS_INACTIVE,
+ //If roamStatus is eCSR_ROAM_ASSOCIATION_COMPLETION
+ //tCsrRoamInfo's pBssDesc may pass back. and the peer's MAC address in peerMacOrBssid
+ //If roamStatus is eCSR_ROAM_IBSS_IND,
+ //the peer's MAC address in peerMacOrBssid and a beacon frame of the IBSS in pbFrames
+ eCSR_ROAM_RESULT_IBSS_NEW_PEER,
+ //Peer departed from IBSS, Callback may get a pointer tSmeIbssPeerInd in pIbssPeerInd
+ eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED,
+ //Coalescing in the IBSS network (joined an IBSS network)
+ //Callback pass a BSSID in peerMacOrBssid
+ eCSR_ROAM_RESULT_IBSS_COALESCED,
+ //If roamStatus is eCSR_ROAM_ROAMING_START, callback may get a pointer to tCsrConnectedProfile used to connect.
+ eCSR_ROAM_RESULT_IBSS_STOP,
+ eCSR_ROAM_RESULT_LOSTLINK,
+ eCSR_ROAM_RESULT_MIC_ERROR_UNICAST,
+ eCSR_ROAM_RESULT_MIC_ERROR_GROUP,
+ eCSR_ROAM_RESULT_AUTHENTICATED,
+ eCSR_ROAM_RESULT_NEW_RSN_BSS,
+#ifdef FEATURE_WLAN_WAPI
+ eCSR_ROAM_RESULT_NEW_WAPI_BSS,
+#endif /* FEATURE_WLAN_WAPI */
+ // WDS started successfully
+ eCSR_ROAM_RESULT_WDS_STARTED,
+ // WDS start failed
+ eCSR_ROAM_RESULT_WDS_START_FAILED,
+ // WDS stopped
+ eCSR_ROAM_RESULT_WDS_STOPPED,
+ // WDS joined successfully in STA mode
+ eCSR_ROAM_RESULT_WDS_ASSOCIATED,
+ // A station joined WDS AP
+ eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND,
+ // WDS join failed in STA mode
+ eCSR_ROAM_RESULT_WDS_NOT_ASSOCIATED,
+ // WDS disassociated
+ eCSR_ROAM_RESULT_WDS_DISASSOCIATED,
+#ifdef WLAN_SOFTAP_FEATURE
+ // INFRA started successfully
+ eCSR_ROAM_RESULT_INFRA_STARTED,
+ // INFRA start failed
+ eCSR_ROAM_RESULT_INFRA_START_FAILED,
+ // INFRA stopped
+ eCSR_ROAM_RESULT_INFRA_STOPPED,
+ // A station joining INFRA AP
+ eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND,
+ // A station joined INFRA AP
+ eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF,
+ // INFRA disassociated
+ eCSR_ROAM_RESULT_INFRA_DISASSOCIATED,
+ eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND,
+#endif
+#ifdef WLAN_FEATURE_P2P
+ eCSR_ROAM_RESULT_SEND_ACTION_FAIL,
+#endif
+ // peer rejected assoc because max assoc limit reached. callback gets pointer to peer
+ eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED,
+}eCsrRoamResult;
+
+
+
+/*----------------------------------------------------------------------------
+ List of link quality indications HDD can receive from SME
+-----------------------------------------------------------------------------*/
+typedef enum
+{
+ eCSR_ROAM_LINK_QUAL_MIN_IND = -1,
+
+ eCSR_ROAM_LINK_QUAL_POOR_IND = 0, /* bad link */
+ eCSR_ROAM_LINK_QUAL_GOOD_IND = 1, /* acceptable for voice */
+ eCSR_ROAM_LINK_QUAL_VERY_GOOD_IND = 2, /* suitable for voice */
+ eCSR_ROAM_LINK_QUAL_EXCELLENT_IND = 3, /* suitable for voice */
+
+ eCSR_ROAM_LINK_QUAL_MAX_IND /* invalid value */
+
+} eCsrRoamLinkQualityInd;
+
+typedef enum
+{
+ eCSR_DISCONNECT_REASON_UNSPECIFIED = 0,
+ eCSR_DISCONNECT_REASON_MIC_ERROR,
+ eCSR_DISCONNECT_REASON_DISASSOC,
+ eCSR_DISCONNECT_REASON_DEAUTH,
+ eCSR_DISCONNECT_REASON_HANDOFF,
+ eCSR_DISCONNECT_REASON_IBSS_JOIN_FAILURE,
+ eCSR_DISCONNECT_REASON_IBSS_LEAVE,
+}eCsrRoamDisconnectReason;
+
+typedef enum
+{
+ // Not associated in Infra or participating in an IBSS / Ad-hoc network.
+ eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED,
+ // Associated in an Infrastructure network.
+ eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED,
+ // Participating in an IBSS network though disconnected (no partner stations
+ // in the IBSS).
+ eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED,
+ // Participating in an IBSS network with partner stations also present
+ eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED,
+ // Participating in a WDS network in AP or STA mode but not connected yet
+ eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED,
+ // Participating in a WDS network and connected peer to peer
+ eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED,
+#ifdef WLAN_SOFTAP_FEATURE
+ // Participating in a Infra network in AP not yet in connected state
+ eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED,
+ // Participating in a Infra network and connected to a peer
+ eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED,
+#endif
+
+}eCsrConnectState;
+
+
+// This parameter is no longer supported in the Profile. Need to set this in the global properties
+// for the adapter.
+typedef enum eCSR_MEDIUM_ACCESS
+{
+ eCSR_MEDIUM_ACCESS_AUTO = 0,
+ eCSR_MEDIUM_ACCESS_DCF,
+ eCSR_MEDIUM_ACCESS_eDCF,
+ eCSR_MEDIUM_ACCESS_HCF,
+
+ eCSR_MEDIUM_ACCESS_WMM_eDCF_802dot1p,
+ eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP,
+ eCSR_MEDIUM_ACCESS_WMM_eDCF_NoClassify,
+ eCSR_MEDIUM_ACCESS_11e_eDCF = eCSR_MEDIUM_ACCESS_eDCF,
+ eCSR_MEDIUM_ACCESS_11e_HCF = eCSR_MEDIUM_ACCESS_HCF,
+}eCsrMediaAccessType;
+
+typedef enum
+{
+ eCSR_TX_RATE_AUTO = 0, // use rate adaption to determine Tx rate.
+
+ eCSR_TX_RATE_1Mbps = 0x00000001,
+ eCSR_TX_RATE_2Mbps = 0x00000002,
+ eCSR_TX_RATE_5_5Mbps = 0x00000004,
+ eCSR_TX_RATE_6Mbps = 0x00000008,
+ eCSR_TX_RATE_9Mbps = 0x00000010,
+ eCSR_TX_RATE_11Mbps = 0x00000020,
+ eCSR_TX_RATE_12Mbps = 0x00000040,
+ eCSR_TX_RATE_18Mbps = 0x00000080,
+ eCSR_TX_RATE_24Mbps = 0x00000100,
+ eCSR_TX_RATE_36Mbps = 0x00000200,
+ eCSR_TX_RATE_42Mbps = 0x00000400,
+ eCSR_TX_RATE_48Mbps = 0x00000800,
+ eCSR_TX_RATE_54Mbps = 0x00001000,
+ eCSR_TX_RATE_72Mbps = 0x00002000,
+ eCSR_TX_RATE_84Mbps = 0x00004000,
+ eCSR_TX_RATE_96Mbps = 0x00008000,
+ eCSR_TX_RATE_108Mbps = 0x00010000,
+ eCSR_TX_RATE_126Mbps = 0x00020000,
+ eCSR_TX_RATE_144Mbps = 0x00040000,
+ eCSR_TX_RATE_168Mbps = 0x00080000,
+ eCSR_TX_RATE_192Mbps = 0x00100000,
+ eCSR_TX_RATE_216Mbps = 0x00200000,
+ eCSR_TX_RATE_240Mbps = 0x00400000,
+
+}eCsrExposedTxRate;
+
+typedef enum
+{
+ eCSR_OPERATING_CHANNEL_ALL = 0,
+ eCSR_OPERATING_CHANNEL_AUTO = eCSR_OPERATING_CHANNEL_ALL,
+ eCSR_OPERATING_CHANNEL_ANY = eCSR_OPERATING_CHANNEL_ALL,
+}eOperationChannel;
+
+typedef enum
+{
+ eCSR_DOT11_FRAG_THRESH_AUTO = -1,
+ eCSR_DOT11_FRAG_THRESH_MIN = 256,
+ eCSR_DOT11_FRAG_THRESH_MAX = 2346,
+ eCSR_DOT11_FRAG_THRESH_DEFAULT = 2000
+}eCsrDot11FragThresh;
+
+
+//for channel bonding for ibss
+typedef enum
+{
+ eCSR_CB_OFF = 0,
+ eCSR_CB_AUTO = 1,
+ eCSR_CB_DOWN = 2,
+ eCSR_CB_UP = 3,
+}eCsrCBChoice;
+
+//For channel bonding, the channel number gap is 4, either up or down. For both 11a and 11g mode.
+#define CSR_CB_CHANNEL_GAP 4
+#define CSR_CB_CENTER_CHANNEL_OFFSET 2
+#define CSR_MAX_24GHz_CHANNEL_NUMBER ( SIR_11B_CHANNEL_END )
+
+// WEP keysize (in bits)...
+typedef enum
+{
+ eCSR_SECURITY_WEP_KEYSIZE_40 = 40, // 40 bit key + 24bit IV = 64bit WEP
+ eCSR_SECURITY_WEP_KEYSIZE_104 = 104, // 104bit key + 24bit IV = 128bit WEP
+
+ eCSR_SECURITY_WEP_KEYSIZE_MIN = eCSR_SECURITY_WEP_KEYSIZE_40,
+ eCSR_SECURITY_WEP_KEYSIZE_MAX = eCSR_SECURITY_WEP_KEYSIZE_104,
+ eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES = ( eCSR_SECURITY_WEP_KEYSIZE_MAX / 8 ),
+}eCsrWEPKeySize;
+
+
+// Possible values for the WEP static key ID...
+typedef enum
+{
+
+ eCSR_SECURITY_WEP_STATIC_KEY_ID_MIN = 0,
+ eCSR_SECURITY_WEP_STATIC_KEY_ID_MAX = 3,
+ eCSR_SECURITY_WEP_STATIC_KEY_ID_DEFAULT = 0,
+
+ eCSR_SECURITY_WEP_STATIC_KEY_ID_INVALID = -1,
+
+}eCsrWEPStaticKeyID;
+
+#define CSR_MAX_NUM_KEY (eCSR_SECURITY_WEP_STATIC_KEY_ID_MAX + 1)
+
+typedef enum
+{
+ eCSR_SECURITY_SET_KEY_ACTION_NO_CHANGE,
+ eCSR_SECURITY_SET_KEY_ACTION_SET_KEY,
+ eCSR_SECURITY_SET_KEY_ACTION_DELETE_KEY,
+}eCsrSetKeyAction;
+
+typedef enum
+{
+ eCSR_BAND_ALL,
+ eCSR_BAND_24,
+ eCSR_BAND_5G,
+ eCSR_BAND_MAX,
+}eCsrBand;
+
+
+typedef enum
+{
+ // Roaming because HDD requested for reassoc by changing one of the fields in
+ // tCsrRoamModifyProfileFields. OR
+ // Roaming because SME requested for reassoc by changing one of the fields in
+ // tCsrRoamModifyProfileFields.
+ eCsrRoamReasonStaCapabilityChanged,
+ // Roaming because SME requested for reassoc to a different AP, as part of
+ // inter AP handoff.
+ eCsrRoamReasonBetterAP,
+ // Roaming because SME requested it as the link is lost - placeholder, will
+ // clean it up once handoff code gets in
+ eCsrRoamReasonSmeIssuedForLostLink,
+
+}eCsrRoamReasonCodes;
+
+typedef enum
+{
+ eCsrRoamWmmAuto = 0,
+ eCsrRoamWmmQbssOnly = 1,
+ eCsrRoamWmmNoQos = 2,
+
+} eCsrRoamWmmUserModeType;
+
+typedef enum
+{
+ eCSR_REQUESTER_MIN = 0,
+ eCSR_DIAG,
+ eCSR_UMA_GAN,
+ eCSR_HDD
+} eCsrStatsRequesterType;
+
+typedef struct tagPmkidCandidateInfo
+{
+ tCsrBssid BSSID;
+ tANI_BOOLEAN preAuthSupported;
+}tPmkidCandidateInfo;
+
+typedef struct tagPmkidCacheInfo
+{
+ tCsrBssid BSSID;
+ tANI_U8 PMKID[CSR_RSN_PMKID_SIZE];
+}tPmkidCacheInfo;
+
+#ifdef FEATURE_WLAN_WAPI
+typedef struct tagBkidCandidateInfo
+{
+ tCsrBssid BSSID;
+ tANI_BOOLEAN preAuthSupported;
+}tBkidCandidateInfo;
+
+typedef struct tagBkidCacheInfo
+{
+ tCsrBssid BSSID;
+ tANI_U8 BKID[CSR_WAPI_BKID_SIZE];
+}tBkidCacheInfo;
+#endif /* FEATURE_WLAN_WAPI */
+
+typedef struct tagCsrKeys
+{
+ tANI_U8 KeyLength[ CSR_MAX_NUM_KEY ]; //Also use to indicate whether the key index is set
+ tANI_U8 KeyMaterial[ CSR_MAX_NUM_KEY ][ CSR_MAX_KEY_LEN ];
+ tANI_U8 defaultIndex;
+}tCsrKeys;
+
+/* Following are fields which are part of tCsrRoamConnectedProfile might need
+ modification dynamically once STA is up & running and this could trigger
+ reassoc */
+typedef struct tagCsrRoamModifyProfileFields
+{
+ // during connect this specifies ACs U-APSD is to be setup
+ // for (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored).
+ // During assoc response this COULD carry confirmation of what ACs U-APSD
+ // got setup for. Later if an APP looking for APSD, SME-QoS might need to
+ // modify this field
+ tANI_U8 uapsd_mask;
+ // HDD might ask to modify this field
+ tANI_U16 listen_interval;
+}tCsrRoamModifyProfileFields;
+
+typedef struct tagCsrRoamProfile
+{
+ //For eCSR_BSS_TYPE_WDS_AP. There must be one SSID in SSIDs.
+ //For eCSR_BSS_TYPE_WDS_STA. There must be two SSIDs. Index 0 is the SSID of the WDS-AP
+ //that we need to join. Index 1 is the SSID for self BSS.
+ tCsrSSIDs SSIDs;
+ tCsrBSSIDs BSSIDs;
+ tANI_U32 phyMode; //this is a bit mask of all the needed phy mode defined in eCsrPhyMode
+ eCsrRoamBssType BSSType;
+
+ tCsrAuthList AuthType;
+ eCsrAuthType negotiatedAuthType;
+
+ tCsrEncryptionList EncryptionType;
+ //This field is for output only, not for input
+ eCsrEncryptionType negotiatedUCEncryptionType;
+
+ //eCSR_ENCRYPT_TYPE_ANY cannot be set in multicast encryption type. If caller doesn't case,
+ //put all supported encryption types in here
+ tCsrEncryptionList mcEncryptionType;
+ //This field is for output only, not for input
+ eCsrEncryptionType negotiatedMCEncryptionType;
+
+ tCsrKeys Keys;
+ eCsrCBChoice CBMode; //up, down or auto
+ tCsrChannelInfo ChannelInfo;
+ tANI_U8 operationChannel;
+ tANI_U16 beaconInterval; //If this is 0, SME will fill in for caller.
+ // during connect this specifies ACs U-APSD is to be setup
+ // for (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored).
+ // During assoc response this COULD carry confirmation of what ACs U-APSD got setup for
+ tANI_U8 uapsd_mask;
+ tANI_U32 nWPAReqIELength; //The byte count in the pWPAReqIE
+ tANI_U8 *pWPAReqIE; //If not null, it has the IE byte stream for WPA
+ tANI_U32 nRSNReqIELength; //The byte count in the pRSNReqIE
+ tANI_U8 *pRSNReqIE; //If not null, it has the IE byte stream for RSN
+#ifdef FEATURE_WLAN_WAPI
+ tANI_U32 nWAPIReqIELength; //The byte count in the pWAPIReqIE
+ tANI_U8 *pWAPIReqIE; //If not null, it has the IE byte stream for WAPI
+#endif /* FEATURE_WLAN_WAPI */
+
+ tANI_U32 nAddIEScanLength; //The byte count in the pAddIE for scan (at the time of join)
+ tANI_U8 *pAddIEScan; //If not null, it has the IE byte stream for additional IE, which can be WSC IE and/or P2P IE
+ tANI_U32 nAddIEAssocLength; //The byte count in the pAddIE for assoc
+ tANI_U8 *pAddIEAssoc; //If not null, it has the IE byte stream for additional IE, which can be WSC IE and/or P2P IE
+
+ tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN]; //it is ignored if [0] is 0.
+ /*WPS Association if true => auth and ecryption should be ignored*/
+ tANI_BOOLEAN bWPSAssociation;
+ tANI_U32 nWSCReqIELength; //The byte count in the pWSCReqIE
+ tANI_U8 *pWSCReqIE; //If not null, it has the IE byte stream for WSC
+
+#ifdef WLAN_SOFTAP_FEATURE
+ tANI_U8 ieee80211d;
+ tANI_U8 privacy;
+ tANI_BOOLEAN fwdWPSPBCProbeReq;
+ tAniAuthType csr80211AuthType;
+ tANI_U32 dtimPeriod;
+ tANI_BOOLEAN ApUapsdEnable;
+ tANI_BOOLEAN protEnabled;
+ tANI_BOOLEAN obssProtEnabled;
+ tANI_U16 cfg_protection;
+ tANI_U8 wps_state;
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ tCsrMobilityDomainInfo MDID;
+#endif
+ tVOS_CON_MODE csrPersona;
+
+}tCsrRoamProfile;
+
+
+typedef struct tagCsrRoamConnectedProfile
+{
+ tSirMacSSid SSID;
+ tANI_BOOLEAN handoffPermitted;
+ tANI_BOOLEAN ssidHidden;
+ tCsrBssid bssid;
+ eCsrRoamBssType BSSType;
+ eCsrAuthType AuthType;
+ tCsrAuthList AuthInfo;
+ eCsrEncryptionType EncryptionType;
+ tCsrEncryptionList EncryptionInfo;
+ eCsrEncryptionType mcEncryptionType;
+ tCsrEncryptionList mcEncryptionInfo;
+ eCsrCBChoice CBMode; //up, down or auto
+ tANI_U8 operationChannel;
+ tCsrKeys Keys;
+ // meaningless on connect. It's an OUT param from CSR's point of view
+ // During assoc response carries the ACM bit-mask i.e. what
+ // ACs have ACM=1 (if any),
+ // (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored)
+ tANI_U8 acm_mask;
+ tCsrRoamModifyProfileFields modifyProfileFields;
+ tSirBssDescription *pBssDesc;
+ tANI_BOOLEAN qap; //AP supports QoS
+ tANI_BOOLEAN qosConnection; //A connection is QoS enabled
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ tCsrMobilityDomainInfo MDID;
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+ tCsrCcxCckmInfo ccxCckmInfo;
+ tANI_BOOLEAN isCCXAssoc;
+#endif
+}tCsrRoamConnectedProfile;
+
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+typedef struct tagCsr11rConfigParams
+{
+ tANI_BOOLEAN IsFTResourceReqSupported;
+} tCsr11rConfigParams;
+#endif
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+typedef struct tagCsrNeighborRoamConfigParams
+{
+
+ tANI_U32 nNeighborScanTimerPeriod;
+ tANI_U8 nNeighborLookupRssiThreshold;
+ tANI_U8 nNeighborReassocRssiThreshold;
+ tANI_U16 nNeighborScanMinChanTime;
+ tANI_U16 nNeighborScanMaxChanTime;
+ sCsrChannel neighborScanChanList;
+ tANI_U8 nMaxNeighborRetries;
+ tANI_U16 nNeighborResultsRefreshPeriod;
+}tCsrNeighborRoamConfigParams;
+#endif
+
+typedef struct tagCsrConfigParam
+{
+ tANI_U32 FragmentationThreshold;
+ tANI_U32 channelBondingMode24GHz;
+ tANI_U32 channelBondingMode5GHz;
+ eCsrPhyMode phyMode;
+ eCsrBand eBand;
+ tANI_U32 RTSThreshold;
+ tANI_U32 HeartbeatThresh50;
+ tANI_U32 HeartbeatThresh24;
+ eCsrCBChoice cbChoice;
+ eCsrBand bandCapability; //indicate hw capability
+ tANI_U32 bgScanInterval;
+ tANI_U16 TxRate;
+ eCsrRoamWmmUserModeType WMMSupportMode;
+ tANI_BOOLEAN Is11eSupportEnabled;
+ tANI_BOOLEAN Is11dSupportEnabled;
+ tANI_BOOLEAN Is11dSupportEnabledOriginal;
+ tANI_BOOLEAN Is11hSupportEnabled;
+ tANI_BOOLEAN shortSlotTime;
+ tANI_BOOLEAN ProprietaryRatesEnabled;
+ tANI_U8 AdHocChannel24;
+ tANI_U8 AdHocChannel5G;
+ tANI_U32 impsSleepTime; //in units of seconds
+ tANI_U32 nScanResultAgeCount; //this number minus one is the number of times a scan doesn't find it before it is removed
+ tANI_U32 scanAgeTimeNCNPS; //scan result aging time threshold when Not-Connect-No-Power-Save, in seconds
+ tANI_U32 scanAgeTimeNCPS; //scan result aging time threshold when Not-Connect-Power-Save, in seconds
+ tANI_U32 scanAgeTimeCNPS; //scan result aging time threshold when Connect-No-Power-Save, in seconds,
+ tANI_U32 scanAgeTimeCPS; //scan result aging time threshold when Connect-Power-Savein seconds
+ tANI_U32 nRoamingTime; //In seconds, CSR will try this long before gives up. 0 means no roaming
+ tANI_U8 bCatRssiOffset; //to set the RSSI difference for each category
+ tANI_U8 fEnableMCCMode; //to set MCC Enable/Disable mode
+
+ tCsr11dinfo Csr11dinfo;
+ //Whether to limit the channels to the ones set in Csr11dInfo. If true, the opertaional
+ //channels are limited to the default channel list. It is an "AND" operation between the
+ //default channels and the channels in the 802.11d IE.
+ tANI_BOOLEAN fEnforce11dChannels;
+ //Country Code Priority
+ //0 = 802.11D > Country IOCTL > NV
+ //1 = Country IOCTL > 802.11D > NV
+ tANI_BOOLEAN fSupplicantCountryCodeHasPriority;
+ //When true, AP with unknown country code won't be see.
+ //"Unknown country code" means either Ap doesn't have 11d IE or we cannot
+ //find a domain for the country code in its 11d IE.
+ tANI_BOOLEAN fEnforceCountryCodeMatch;
+ //When true, only APs in the default domain can be seen. If the Ap has "unknown country
+ //code", or the domain of the country code doesn't match the default domain, the Ap is
+ //not acceptable.
+ tANI_BOOLEAN fEnforceDefaultDomain;
+
+ tANI_U16 vccRssiThreshold;
+ tANI_U32 vccUlMacLossThreshold;
+
+ tANI_U32 nPassiveMinChnTime; //in units of milliseconds
+ tANI_U32 nPassiveMaxChnTime; //in units of milliseconds
+ tANI_U32 nActiveMinChnTime; //in units of milliseconds
+ tANI_U32 nActiveMaxChnTime; //in units of milliseconds
+
+ tANI_BOOLEAN IsIdleScanEnabled;
+ //in dBm, the maximum TX power
+ //The actual TX power is the lesser of this value and 11d.
+ //If 11d is disable, the lesser of this and default setting.
+ tANI_U8 nTxPowerCap;
+ tANI_U32 statsReqPeriodicity; //stats request frequency from PE while in full power
+ tANI_U32 statsReqPeriodicityInPS;//stats request frequency from PE while in power save
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ tCsr11rConfigParams csr11rConfig;
+#endif
+#ifdef FEATURE_WLAN_CCX
+ tANI_U8 isCcxIniFeatureEnabled;
+#endif
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ tANI_U8 isFastTransitionEnabled;
+#endif
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ tCsrNeighborRoamConfigParams neighborRoamConfig;
+#endif
+
+ /* Instead of Reassoc, send ADDTS/DELTS even when ACM is off for that AC
+ * This is mandated by WMM-AC certification */
+ tANI_BOOLEAN addTSWhenACMIsOff;
+
+
+ /*channelPowerInfoList24 has been seen corrupted. Set this flag to true trying to
+ * detect when it happens. Adding this into code because we can't reproduce it easily.
+ * We don't know when it happens. */
+ tANI_BOOLEAN fValidateList;
+
+ /*Customer wants to start with an active scan based on the default country code.
+ * This optimization will minimize the driver load to association time.
+ * Based on this flag we will bypass the initial passive scan needed for 11d
+ * to determine the country code & domain */
+ tANI_BOOLEAN fEnableBypass11d;
+
+ /*Customer wants to optimize the scan time. Avoiding scans(passive) on DFS
+ * channels while swipping through both bands can save some time
+ * (apprx 1.3 sec) */
+ tANI_BOOLEAN fEnableDFSChnlScan;
+
+ //To enable/disable scanning 2.4Ghz channels twice on a single scan request from HDD
+ tANI_BOOLEAN fScanTwice;
+
+}tCsrConfigParam;
+
+//Tush
+typedef struct tagCsrUpdateConfigParam
+{
+ tCsr11dinfo Csr11dinfo;
+}tCsrUpdateConfigParam;
+
+typedef struct tagCsrRoamInfo
+{
+ tCsrRoamProfile *pProfile; //may be NULL
+ tSirBssDescription *pBssDesc; //May be NULL
+ tANI_U32 nBeaconLength; //the length, in bytes, of the beacon frame, can be 0
+ tANI_U32 nAssocReqLength; //the length, in bytes, of the assoc req frame, can be 0
+ tANI_U32 nAssocRspLength; //The length, in bytes, of the assoc rsp frame, can be 0
+ tANI_U32 nFrameLength;
+ tANI_U8 frameType;
+ tANI_U8 *pbFrames; //Point to a buffer contain the beacon, assoc req, assoc rsp frame, in that order
+ //user needs to use nBeaconLength, nAssocReqLength, nAssocRspLength to desice where
+ //each frame starts and ends.
+ tANI_BOOLEAN fReassocReq; //set to true if for re-association
+ tANI_BOOLEAN fReassocRsp; //set to true if for re-association
+ tCsrBssid bssid;
+ //Only valid in IBSS
+ //this is the peers MAC address for eCSR_ROAM_RESULT_IBSS_NEW_PEER or PEER_DEPARTED
+ tCsrBssid peerMac;
+ tSirResultCodes statusCode;
+ tANI_U32 reasonCode; //this could be our own defined or sent from the other BSS(per 802.11 spec)
+ tANI_U8 staId; // Peer stationId when connected
+ /*The DPU signatures will be sent eventually to TL to help it determine the
+ association to which a packet belongs to*/
+ /*Unicast DPU signature*/
+ tANI_U8 ucastSig;
+
+ /*Broadcast DPU signature*/
+ tANI_U8 bcastSig;
+
+ tANI_BOOLEAN fAuthRequired; //FALSE means auth needed from supplicant. TRUE means authenticated(static WEP, open)
+ tANI_U8 sessionId;
+ tANI_U8 rsnIELen;
+ tANI_U8 *prsnIE;
+
+ tANI_U8 addIELen;
+ tANI_U8 *paddIE;
+
+ union
+ {
+ tSirMicFailureInfo *pMICFailureInfo;
+ tCsrRoamConnectedProfile *pConnectedProfile;
+#ifdef WLAN_SOFTAP_FEATURE
+ tSirWPSPBCProbeReq *pWPSPBCProbeReq;
+#endif
+ } u;
+
+#ifdef WLAN_SOFTAP_FEATURE
+ tANI_BOOLEAN wmmEnabledSta; //set to true if WMM enabled STA
+ tANI_U32 dtimPeriod;
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+ tANI_BOOLEAN isCCXAssoc;
+#endif
+#ifdef WLAN_FEATURE_P2P
+ void* pRemainCtx;
+ tANI_U32 rxChan;
+#endif
+
+ // Required for indicating the frames to upper layer
+ tANI_U32 beaconLength;
+ tANI_U8* beaconPtr;
+ tANI_U32 assocReqLength;
+ tANI_U8* assocReqPtr;
+}tCsrRoamInfo;
+
+
+
+
+
+typedef struct tagCsrFreqScanInfo
+{
+ tANI_U32 nStartFreq; //in unit of MHz
+ tANI_U32 nEndFreq; //in unit of MHz
+ tSirScanType scanType;
+}tCsrFreqScanInfo;
+
+
+#ifdef WLAN_SOFTAP_FEATURE
+typedef struct sSirSmeAssocIndToUpperLayerCnf
+{
+ tANI_U16 messageType; // eWNI_SME_ASSOC_CNF
+ tANI_U16 length;
+ tANI_U8 sessionId;
+ tSirResultCodes statusCode;
+ tSirMacAddr bssId; // Self BSSID
+ tSirMacAddr peerMacAddr;
+ tANI_U16 aid;
+ tSirMacAddr alternateBssId;
+ tANI_U8 alternateChannelId;
+ tANI_U8 wmmEnabledSta; //set to true if WMM enabled STA
+ tSirRSNie rsnIE; // RSN IE received from peer
+ tSirAddie addIE; // Additional IE received from peer, which can be WSC and/or P2P IE
+ tANI_U8 reassocReq; //set to true if reassoc
+} tSirSmeAssocIndToUpperLayerCnf, *tpSirSmeAssocIndToUpperLayerCnf;
+#endif
+
+typedef struct tagCsrSummaryStatsInfo
+{
+ tANI_U32 retry_cnt[4];
+ tANI_U32 multiple_retry_cnt[4];
+ tANI_U32 tx_frm_cnt[4];
+ //tANI_U32 num_rx_frm_crc_err; same as rx_error_cnt
+ //tANI_U32 num_rx_frm_crc_ok; same as rx_frm_cnt
+ tANI_U32 rx_frm_cnt;
+ tANI_U32 frm_dup_cnt;
+ tANI_U32 fail_cnt[4];
+ tANI_U32 rts_fail_cnt;
+ tANI_U32 ack_fail_cnt;
+ tANI_U32 rts_succ_cnt;
+ tANI_U32 rx_discard_cnt;
+ tANI_U32 rx_error_cnt;
+ tANI_U32 tx_byte_cnt;
+
+}tCsrSummaryStatsInfo;
+
+typedef struct tagCsrGlobalClassAStatsInfo
+{
+ tANI_U32 rx_frag_cnt;
+ tANI_U32 promiscuous_rx_frag_cnt;
+ //tANI_U32 rx_fcs_err;
+ tANI_U32 rx_input_sensitivity;
+ tANI_U32 max_pwr;
+ //tANI_U32 default_pwr;
+ tANI_U32 sync_fail_cnt;
+ tANI_U32 tx_rate;
+ //mcs index for HT20 and HT40 rates
+ tANI_U32 mcs_index;
+ //to defferentiate between HT20 and HT40 rates;short and long guard interval
+ tANI_U32 tx_rate_flags;
+
+}tCsrGlobalClassAStatsInfo;
+
+typedef struct tagCsrGlobalClassBStatsInfo
+{
+ tANI_U32 uc_rx_wep_unencrypted_frm_cnt;
+ tANI_U32 uc_rx_mic_fail_cnt;
+ tANI_U32 uc_tkip_icv_err;
+ tANI_U32 uc_aes_ccmp_format_err;
+ tANI_U32 uc_aes_ccmp_replay_cnt;
+ tANI_U32 uc_aes_ccmp_decrpt_err;
+ tANI_U32 uc_wep_undecryptable_cnt;
+ tANI_U32 uc_wep_icv_err;
+ tANI_U32 uc_rx_decrypt_succ_cnt;
+ tANI_U32 uc_rx_decrypt_fail_cnt;
+ tANI_U32 mcbc_rx_wep_unencrypted_frm_cnt;
+ tANI_U32 mcbc_rx_mic_fail_cnt;
+ tANI_U32 mcbc_tkip_icv_err;
+ tANI_U32 mcbc_aes_ccmp_format_err;
+ tANI_U32 mcbc_aes_ccmp_replay_cnt;
+ tANI_U32 mcbc_aes_ccmp_decrpt_err;
+ tANI_U32 mcbc_wep_undecryptable_cnt;
+ tANI_U32 mcbc_wep_icv_err;
+ tANI_U32 mcbc_rx_decrypt_succ_cnt;
+ tANI_U32 mcbc_rx_decrypt_fail_cnt;
+
+}tCsrGlobalClassBStatsInfo;
+
+typedef struct tagCsrGlobalClassCStatsInfo
+{
+ tANI_U32 rx_amsdu_cnt;
+ tANI_U32 rx_ampdu_cnt;
+ tANI_U32 tx_20_frm_cnt;
+ tANI_U32 rx_20_frm_cnt;
+ tANI_U32 rx_mpdu_in_ampdu_cnt;
+ tANI_U32 ampdu_delimiter_crc_err;
+
+}tCsrGlobalClassCStatsInfo;
+
+typedef struct tagCsrGlobalClassDStatsInfo
+{
+ tANI_U32 tx_uc_frm_cnt;
+ tANI_U32 tx_mc_frm_cnt;
+ tANI_U32 tx_bc_frm_cnt;
+ tANI_U32 rx_uc_frm_cnt;
+ tANI_U32 rx_mc_frm_cnt;
+ tANI_U32 rx_bc_frm_cnt;
+ tANI_U32 tx_uc_byte_cnt[4];
+ tANI_U32 tx_mc_byte_cnt;
+ tANI_U32 tx_bc_byte_cnt;
+ tANI_U32 rx_uc_byte_cnt[4];
+ tANI_U32 rx_mc_byte_cnt;
+ tANI_U32 rx_bc_byte_cnt;
+ tANI_U32 rx_byte_cnt;
+ tANI_U32 num_rx_bytes_crc_ok;
+ tANI_U32 rx_rate;
+
+}tCsrGlobalClassDStatsInfo;
+
+typedef struct tagCsrPerStaStatsInfo
+{
+ tANI_U32 tx_frag_cnt[4];
+ tANI_U32 tx_ampdu_cnt;
+ tANI_U32 tx_mpdu_in_ampdu_cnt;
+} tCsrPerStaStatsInfo;
+
+typedef struct tagCsrRoamSetKey
+{
+ eCsrEncryptionType encType;
+ tAniKeyDirection keyDirection; //Tx, Rx or Tx-and-Rx
+ tCsrBssid peerMac; //Peers MAC address. ALL 1's for group key
+ tANI_U8 paeRole; //0 for supplicant
+ tANI_U8 keyId; // Kye index
+ tANI_U16 keyLength; //Number of bytes containing the key in pKey
+ tANI_U8 Key[CSR_MAX_KEY_LEN];
+ tANI_U8 keyRsc[CSR_MAX_RSC_LEN];
+} tCsrRoamSetKey;
+
+typedef struct tagCsrRoamRemoveKey
+{
+ eCsrEncryptionType encType;
+ tCsrBssid peerMac; //Peers MAC address. ALL 1's for group key
+ tANI_U8 keyId; //key index
+} tCsrRoamRemoveKey;
+
+
+typedef void * tScanResultHandle;
+
+#define CSR_INVALID_SCANRESULT_HANDLE (NULL)
+
+
+
+////////////////////////////////////////////Common SCAN starts
+
+//void *p2 -- the second context pass in for the caller
+//***what if callback is called before requester gets the scanId??
+typedef eHalStatus (*csrScanCompleteCallback)(tHalHandle, void *p2, tANI_U32 scanID, eCsrScanStatus status);
+
+
+
+///////////////////////////////////////////Common Roam starts
+
+//pContext is the pContext passed in with the roam request
+//pParam is a pointer to a tCsrRoamInfo, see definition of eRoamCmdStatus and
+// eRoamCmdResult for detail valid members. It may be NULL
+//roamId is to identify the callback related roam request. 0 means unsolicit
+//roamStatus is a flag indicating the status of the callback
+//roamResult is the result
+typedef eHalStatus (*csrRoamCompleteCallback)(void *pContext, tCsrRoamInfo *pParam, tANI_U32 roamId,
+ eRoamCmdStatus roamStatus, eCsrRoamResult roamResult);
+
+typedef eHalStatus (*csrRoamSessionCloseCallback)(void *pContext);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetNumPMKIDCache
+ \brief return number of PMKID cache entries
+ \return tANI_U32 - the number of PMKID cache entries
+ -------------------------------------------------------------------------------*/
+//tANI_U32 csrRoamGetNumPMKIDCache(tHalHandle hHal);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetPMKIDCache
+ \brief return PMKID cache from CSR
+ \param pNum - caller allocated memory that has the space of the number of pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the
+ needed or actually number in tPmkidCacheInfo.
+ \param pPmkidCache - Caller allocated memory that contains PMKID cache, if any, upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not big enough
+ -------------------------------------------------------------------------------*/
+//eHalStatus csrRoamGetPMKIDCache(tHalHandle hHal, tANI_U32 *pNum, tPmkidCacheInfo *pPmkidCache);
+
+//pProfile - pointer to tCsrRoamProfile
+#define CSR_IS_START_IBSS(pProfile) (eCSR_BSS_TYPE_START_IBSS == (pProfile)->BSSType)
+#define CSR_IS_JOIN_TO_IBSS(pProfile) (eCSR_BSS_TYPE_IBSS == (pProfile)->BSSType)
+#define CSR_IS_IBSS(pProfile) ( CSR_IS_START_IBSS(pProfile) || CSR_IS_JOIN_TO_IBSS(pProfile) )
+#define CSR_IS_INFRASTRUCTURE(pProfile) (eCSR_BSS_TYPE_INFRASTRUCTURE == (pProfile)->BSSType)
+#define CSR_IS_ANY_BSS_TYPE(pProfile) (eCSR_BSS_TYPE_ANY == (pProfile)->BSSType)
+#define CSR_IS_WDS_AP( pProfile ) ( eCSR_BSS_TYPE_WDS_AP == (pProfile)->BSSType )
+#define CSR_IS_WDS_STA( pProfile ) ( eCSR_BSS_TYPE_WDS_STA == (pProfile)->BSSType )
+#define CSR_IS_WDS( pProfile ) ( CSR_IS_WDS_AP( pProfile ) || CSR_IS_WDS_STA( pProfile ) )
+#ifdef WLAN_SOFTAP_FEATURE
+#define CSR_IS_INFRA_AP( pProfile ) ( eCSR_BSS_TYPE_INFRA_AP == (pProfile)->BSSType )
+#endif
+
+//pProfile - pointer to tCsrRoamConnectedProfile
+#ifdef WLAN_SOFTAP_FEATURE
+#define CSR_IS_CONN_INFRA_AP( pProfile ) ( eCSR_BSS_TYPE_INFRA_AP == (pProfile)->BSSType )
+#endif
+#define CSR_IS_CONN_WDS_AP( pProfile ) ( eCSR_BSS_TYPE_WDS_AP == (pProfile)->BSSType )
+#define CSR_IS_CONN_WDS_STA( pProfile ) ( eCSR_BSS_TYPE_WDS_STA == (pProfile)->BSSType )
+#define CSR_IS_CONN_WDS( pProfile ) ( CSR_IS_WDS_AP( pProfile ) || CSR_IS_WDS_STA( pProfile ) )
+
+
+
+///////////////////////////////////////////Common Roam ends
+
+
+
+#ifdef WLAN_SOFTAP_FEATURE
+/* ---------------------------------------------------------------------------
+ \fn csrSetChannels
+ \brief HDD calls this function to change some global settings.
+ caller must set the all fields or call csrGetConfigParam to prefill the fields.
+ \param pParam - caller allocated memory
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+
+eHalStatus csrSetChannels(tHalHandle hHal, tCsrConfigParam *pParam );
+
+eHalStatus csrSetRegInfo(tHalHandle hHal, tANI_U8 *apCntryCode);
+#endif
+
+
+//enum to string conversion for debug output
+const char * get_eRoamCmdStatus_str(eRoamCmdStatus val);
+const char * get_eCsrRoamResult_str(eCsrRoamResult val);
+/* ---------------------------------------------------------------------------
+ \fn csrSetPhyMode
+ \brief HDD calls this function to set the phyMode.
+ This function must be called after CFG is downloaded and all the band/mode setting already passed into
+ CSR.
+ \param phyMode - indicate the phyMode needs to set to. The value has to be either 0, or some bits set.
+ See eCsrPhyMode for definition
+ \param eBand - specify the operational band (2.4, 5 or both)
+ \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether
+ a restart is needed to apply the change
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrSetPhyMode(tHalHandle hHal, tANI_U32 phyMode, eCsrBand eBand, tANI_BOOLEAN *pfRestartNeeded);
+
+void csrDumpInit(tHalHandle hHal);
+
+
+/*---------------------------------------------------------------------------
+ This is the type for a link quality callback to be registered with SME
+ for indications
+ Once the link quality has been indicated, subsequently, link indications are
+ posted each time there is a CHANGE in link quality.
+ *** If there is no change in link, there will be no indication ***
+
+ The indications may be based on one or more criteria internal to SME
+ such as RSSI and PER.
+
+ \param ind - Indication being posted
+ \param pContext - any user data given at callback registration.
+ \return None
+
+---------------------------------------------------------------------------*/
+typedef void (* csrRoamLinkQualityIndCallback)
+ (eCsrRoamLinkQualityInd ind, void *pContext);
+
+
+/*---------------------------------------------------------------------------
+ This is the type for a statistics callback to be registered with SME
+ for stats reporting
+
+ Since the client requesting for the stats already know which class/type of
+ stats it asked for, the callback will carry them in the rsp buffer
+ (void * stats) whose size will be same as the size of requested stats &
+ will be exactly in the same order requested in the stats mask from LSB to MSB
+
+ \param stats - stats rsp buffer sent back with the report
+ \param pContext - any user data given at callback registration.
+ \return None
+
+---------------------------------------------------------------------------*/
+typedef void ( *tCsrStatsCallback) (void * stats, void *pContext);
+
+/*---------------------------------------------------------------------------
+ This is the type for a rssi callback to be registered with SME
+ for getting rssi
+
+ \param rssi - rssi
+ \param pContext - any user data given at callback registration.
+ \return None
+
+---------------------------------------------------------------------------*/
+
+typedef void ( *tCsrRssiCallback) (v_S7_t rssi, tANI_U32 staId, void *pContext);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+eHalStatus csrRoamIssueFTPreauthReq(tHalHandle hHal, tANI_U32 sessionId, tpSirBssDescription pBssDescription);
+#endif
+
+/*---------------------------------------------------------------------------
+ This is the function to change the Band configuraiton (ALL/2.4 GHZ/5 GHZ)
+
+ \param hHal - handle to Hal context
+ \param eBand - band value
+ \return eHalStatus
+
+---------------------------------------------------------------------------*/
+eHalStatus csrSetBand(tHalHandle hHal, eCsrBand eBand);
+
+/*---------------------------------------------------------------------------
+ This is the function to get the current operating band value
+ \param hHal - handl to Hal context
+ \return eCsrband - band value
+
+---------------------------------------------------------------------------*/
+eCsrBand csrGetCurrentBand (tHalHandle hHal);
+
+#endif
+
diff --git a/CORE/SME/inc/csrInternal.h b/CORE/SME/inc/csrInternal.h
new file mode 100644
index 0000000..9fc423d
--- /dev/null
+++ b/CORE/SME/inc/csrInternal.h
@@ -0,0 +1,1177 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+
+
+ \file csrInternal.h
+
+ Define internal data structure for MAC.
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+ ========================================================================== */
+#ifndef CSRINTERNAL_H__
+#define CSRINTERNAL_H__
+
+#if defined(VOSS_ENABLED)
+#include "vos_status.h"
+#include "vos_lock.h"
+#endif //#if defined(VOSS_ENABLED)
+
+#include "palTimer.h"
+#include "csrSupport.h"
+#include "vos_nvitem.h"
+#include "wlan_qct_tl.h"
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+#include "csrNeighborRoam.h"
+#endif
+
+#define CSR_MAX_STA (HAL_NUM_STA)
+
+#define CSR_SME_SCAN_FLAGS_DELETE_CACHE 0x80
+
+#define CSR_TITAN_MAX_RATE_MIMO_CB 240
+#define CSR_TITAN_MAX_RATE_MIMO 126
+
+//define scan return criteria. LIM should use these define as well
+#define CSR_SCAN_RETURN_AFTER_ALL_CHANNELS ( 0 )
+#define CSR_SCAN_RETURN_AFTER_FIRST_MATCH ( 0x01 )
+#define CSR_SCAN_RETURN_AFTER_5_BAND_11d_FOUND ( 0x80 )
+#define CSR_SCAN_RETURN_AFTER_24_BAND_11d_FOUND ( 0x40 )
+#define CSR_SCAN_RETURN_AFTER_EITHER_BAND_11d_FOUND ( CSR_SCAN_RETURN_AFTER_5_BAND_11d_FOUND | CSR_SCAN_RETURN_AFTER_24_BAND_11d_FOUND )
+#define CSR_NUM_RSSI_CAT 5
+#define CSR_MAX_STATISTICS_REQ 10
+
+//Support for multiple session
+#define CSR_SESSION_ID_INVALID 0xFF // session ID invalid
+#define CSR_ROAM_SESSION_MAX 5 // No of sessions to be supported, and a
+ // session is for Infra, IBSS or BT-AMP
+
+#define CSR_IS_SESSION_VALID( pMac, sessionId ) ( ( (sessionId) < CSR_ROAM_SESSION_MAX ) \
+ && ( (pMac)->roam.roamSession[(sessionId)].sessionActive ) )
+#define CSR_GET_SESSION( pMac, sessionId ) \
+( \
+ (sessionId < CSR_ROAM_SESSION_MAX) ? \
+ (&(pMac)->roam.roamSession[(sessionId)]) :\
+ NULL \
+)
+
+
+
+typedef enum
+{
+ //eCSR_CFG_DOT11_MODE_BEST = 0,
+ eCSR_CFG_DOT11_MODE_TAURUS = 0,
+ eCSR_CFG_DOT11_MODE_ABG,
+ eCSR_CFG_DOT11_MODE_11A,
+ eCSR_CFG_DOT11_MODE_11B,
+ eCSR_CFG_DOT11_MODE_11G,
+ eCSR_CFG_DOT11_MODE_11N,
+ eCSR_CFG_DOT11_MODE_POLARIS,
+ eCSR_CFG_DOT11_MODE_TITAN,
+#ifdef WLAN_SOFTAP_FEATURE
+ eCSR_CFG_DOT11_MODE_11G_ONLY,
+ eCSR_CFG_DOT11_MODE_11N_ONLY,
+#endif
+ //This value can never set to CFG. It is for CSR's internal use
+ eCSR_CFG_DOT11_MODE_AUTO,
+}eCsrCfgDot11Mode; //Used to determine what to set to the WNI_CFG_DOT11_MODE
+
+typedef enum etCsrRoamCommands
+{
+ eCsrRoamNoCommand,
+ eCsrRoamCommandScan,
+ eCsrRoamCommandRoam,
+ eCsrRoamCommandWmStatusChange,
+ eCsrRoamCommandSetKey,
+ eCsrRoamCommandRemoveKey,
+
+} eCsrRoamCommands;
+
+typedef enum
+{
+ eCsrScanOther = 1,
+ eCsrScanLostLink1,
+ eCsrScanLostLink2,
+ eCsrScanLostLink3,
+ eCsrScanLostLink4,
+ eCsrScan11d1, //First 11d scan
+ eCsrScan11d2, //First 11d scan has failed
+ eCsrScan11dDone, //11d scan succeeded, try the rest of the channel
+ eCsrScanUserRequest,
+ eCsrScanGetResult,
+ eCsrScanSetBGScanParam, //used for HO too - bg scan request in NT Handoff sub-state
+ eCsrScanForSsid,
+ eCsrScanForCapsChange,
+ eCsrScanBGScanAbort,
+ eCsrScanBGScanEnable,
+ eCsrScanIdleScan,
+ eCsrScanGetScanChnInfo, //To get the list of channels scanned
+
+ eCsrScanBgScan, // bg scan request in NRT & RT Handoff sub-states
+ eCsrScanProbeBss, // directed probe on an entry from the candidate list - HO
+ eCsrScanAbortBgScan, //aborting a BG scan (meaning the scan is triggered by LIM timer)
+ eCsrScanAbortNormalScan, //aborting a normal scan (the scan is trigger by eWNI_SME_SCAN_REQ)
+ eCsrScanP2PFindPeer
+}eCsrScanReason;
+
+typedef enum
+{
+ eCsrNoConnection, // Roaming because we have not established the initial connection.
+ eCsrCapsChange, // roaming because LIM reported a Capability change in the associated AP.
+ eCsrForcedDisassoc, // roaming becuase someone asked us to Disassoc and stay disassociated.
+ eCsrHddIssued, // roaming because an 802.11 request was issued to the driver.
+ eCsrLostLink1, // roaming because we lost link to an associated AP
+ eCsrLostLink2,
+ eCsrLostLink3,
+ eCsrForcedDisassocMICFailure, // roaming because we need to force a Disassoc due to MIC failure
+ eCsrHddIssuedReassocToSameAP,
+ eCsrSmeIssuedReassocToSameAP,
+ eCsrSmeIssuedReassocToDiffAP,
+ eCsrForcedDeauth, // roaming becuase someone asked us to deauth and stay disassociated.
+ eCsrSmeIssuedDisassocForHandoff, // will be issued by Handoff logic to disconect from current AP
+ eCsrSmeIssuedAssocToSimilarAP, // will be issued by Handoff logic to join a new AP with same profile
+ eCsrSmeIssuedIbssJoinFailure, // ibss join timer fired before any perr showed up, so shut down the network
+ eCsrForcedIbssLeave,
+ eCsrStopBss,
+ eCsrSmeIssuedFTReassoc,
+ eCsrForcedDisassocSta,
+ eCsrForcedDeauthSta,
+
+}eCsrRoamReason;
+
+typedef enum
+{
+ eCSR_ROAM_SUBSTATE_NONE = 0,
+ eCSR_ROAM_SUBSTATE_START_BSS_REQ,
+ eCSR_ROAM_SUBSTATE_JOIN_REQ,
+ eCSR_ROAM_SUBSTATE_REASSOC_REQ,
+ eCSR_ROAM_SUBSTATE_DISASSOC_REQ,
+ eCSR_ROAM_SUBSTATE_STOP_BSS_REQ,
+ eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, //Continue the current roam command after disconnect
+ eCSR_ROAM_SUBSTATE_AUTH_REQ,
+ eCSR_ROAM_SUBSTATE_CONFIG,
+ eCSR_ROAM_SUBSTATE_DEAUTH_REQ,
+ eCSR_ROAM_SUBSTATE_DISASSOC_NOTHING_TO_JOIN,
+ eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE,
+ eCSR_ROAM_SUBSTATE_DISASSOC_FORCED,
+ eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY,
+ eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF,
+ eCSR_ROAM_SUBSTATE_JOINED_NO_TRAFFIC,
+ eCSR_ROAM_SUBSTATE_JOINED_NON_REALTIME_TRAFFIC,
+ eCSR_ROAM_SUBSTATE_JOINED_REALTIME_TRAFFIC,
+// max is 15 unless the bitfield is expanded...
+} eCsrRoamSubState;
+
+
+typedef enum
+{
+ eCSR_ROAMING_STATE_STOP = 0,
+ eCSR_ROAMING_STATE_IDLE,
+ eCSR_ROAMING_STATE_SCANNING,
+ eCSR_ROAMING_STATE_JOINING,
+ eCSR_ROAMING_STATE_JOINED,
+}eCsrRoamState;
+
+
+typedef enum
+{
+ eCsrContinueRoaming,
+ eCsrStopRoaming,
+ eCsrStartIbss,
+ eCsrStartIbssSameIbss,
+ eCsrReassocToSelfNoCapChange,
+
+}eCsrJoinState;
+
+typedef enum
+{
+ eCsrNotRoaming,
+ eCsrLostlinkRoamingDisassoc,
+ eCsrLostlinkRoamingDeauth,
+ eCsrDynamicRoaming,
+ eCsrReassocRoaming,
+}eCsrRoamingReason;
+
+typedef enum
+{
+ eCsrDisassociated,
+ eCsrDeauthenticated
+
+}eCsrRoamWmStatusChangeTypes;
+
+typedef enum
+{
+ eCsrSummaryStats = 0,
+ eCsrGlobalClassAStats,
+ eCsrGlobalClassBStats,
+ eCsrGlobalClassCStats,
+ eCsrGlobalClassDStats,
+ eCsrPerStaStats,
+ eCsrMaxStats
+}eCsrRoamStatsClassTypes;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+typedef enum
+{
+ eCSR_WLAN_STATUS_CONNECT =0,
+ eCSR_WLAN_STATUS_DISCONNECT
+
+}eCsrDiagWlanStatusEventSubtype;
+
+typedef enum
+{
+ eCSR_REASON_UNSPECIFIED = 0,
+ eCSR_REASON_USER_REQUESTED,
+ eCSR_REASON_MIC_ERROR,
+ eCSR_REASON_DISASSOC,
+ eCSR_REASON_DEAUTH,
+ eCSR_REASON_HANDOFF,
+
+}eCsrDiagWlanStatusEventReason;
+
+typedef enum
+{
+ eCSR_WLAN_HANDOFF_EVENT =0,
+
+}eCsrDiagWlanHandoffEventSubtype;
+
+typedef enum
+{
+ eCSR_WLAN_VCC_EVENT =0,
+
+}eCsrDiagWlanVccEventSubtype;
+
+#endif //FEATURE_WLAN_DIAG_SUPPORT
+
+typedef struct tagCsrChannel
+{
+ tANI_U8 numChannels;
+ tANI_U8 channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+}tCsrChannel;
+
+typedef struct tagScanProfile
+{
+ tANI_U32 minChnTime;
+ tANI_U32 maxChnTime;
+ tANI_U32 restTime; //This is ignored if not associated
+ tANI_U32 numOfChannels;
+ tANI_U8 *pChannelList;
+ tSirScanType scanType; //active or passive
+ eCsrRoamBssType bssType; //BSS or IBSS
+ tANI_U8 ssid[WNI_CFG_SSID_LEN];
+ tANI_U8 bReturnAfter1stMatch;
+ tANI_U8 fUniqueResult;
+ tANI_U8 freshScan;
+ tCsrBssid bssid;
+}tScanProfile;
+
+typedef struct tagBssConfigParam
+{
+ eCsrMediaAccessType qosType;
+ tSirMacSSid SSID;
+ tANI_U32 uRTSThresh;
+ tANI_U32 uDeferThresh; //
+ eCsrCfgDot11Mode uCfgDot11Mode;
+ eCsrBand eBand;
+ tANI_U8 standardRate[CSR_DOT11_SUPPORTED_RATES_MAX];
+ tANI_U8 extendedRate[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
+ eCsrExposedTxRate txRate;
+ tAniAuthType authType;
+ eCsrEncryptionType encType;
+ tANI_U32 uShortSlotTime;
+ tANI_U32 uHTSupport; //High throughput
+ tANI_U32 uPowerLimit;
+ tANI_U32 uHeartBeatThresh;
+ tANI_U32 uJoinTimeOut;
+ tSirMacCapabilityInfo BssCap;
+ tANI_BOOLEAN f11hSupport;
+ tAniCBSecondaryMode cbMode;
+}tBssConfigParam;
+
+
+typedef struct tagCsrRoamStartBssParams
+{
+ tSirMacSSid ssId;
+ tCsrBssid bssid; //this is the BSSID for the party we want to join (only use for IBSS or WDS)
+ tSirNwType sirNwType;
+ tAniCBSecondaryMode cbMode;
+ tSirMacRateSet operationalRateSet;
+ tSirMacRateSet extendedRateSet;
+ tANI_U8 operationChn;
+ eCsrCfgDot11Mode uCfgDot11Mode;
+#ifdef WLAN_SOFTAP_FEATURE
+ tANI_U8 privacy;
+ tANI_BOOLEAN fwdWPSPBCProbeReq;
+ tANI_BOOLEAN protEnabled;
+ tANI_BOOLEAN obssProtEnabled;
+ tAniAuthType authType;
+ tANI_U16 beaconInterval; //If this is 0, SME will fill in for caller.
+ tANI_U16 ht_protection;
+ tANI_U32 dtimPeriod;
+ tANI_U8 ApUapsdEnable;
+ tANI_U8 ssidHidden;
+ tANI_U8 wps_state;
+#endif
+ tVOS_CON_MODE bssPersona;
+ tANI_U16 nRSNIELength; //The byte count in the pRSNIE, if 0, pRSNIE is ignored.
+ tANI_U8 *pRSNIE; //If not null, it has the IE byte stream for RSN
+}tCsrRoamStartBssParams;
+
+
+typedef struct tagScanCmd
+{
+ tANI_U32 scanID;
+ csrScanCompleteCallback callback;
+ void *pContext;
+ eCsrScanReason reason;
+ eCsrRoamState lastRoamState[CSR_ROAM_SESSION_MAX];
+ tCsrRoamProfile *pToRoamProfile;
+ tANI_U32 roamId; //this is the ID related to the pToRoamProfile
+ union
+ {
+ tCsrScanRequest scanRequest;
+ tCsrBGScanRequest bgScanRequest;
+ }u;
+}tScanCmd;
+
+typedef struct tagRoamCmd
+{
+ tANI_U32 roamId;
+ eCsrRoamReason roamReason;
+ tCsrRoamProfile roamProfile;
+ tScanResultHandle hBSSList; //BSS list fits the profile
+ tListElem *pRoamBssEntry; //point to the current BSS in the list that is roaming. It starts from head to tail
+ tSirBssDescription *pLastRoamBss; //the last BSS we try and failed
+ tANI_BOOLEAN fReleaseBssList; //whether to free hBSSList
+ tANI_BOOLEAN fReleaseProfile; //whether to free roamProfile
+ tANI_BOOLEAN fReassoc; //whether this command is for reassociation
+ tANI_BOOLEAN fUpdateCurRoamProfile; //whether pMac->roam.pCurRoamProfile needs to be updated
+ //this is for CSR internal used only. And it should not be assigned when creating the command
+ //This causes the roam command not to do anything.
+ tANI_BOOLEAN fReassocToSelfNoCapChange;
+
+ tANI_BOOLEAN fStopWds;
+ tSirMacAddr peerMac;
+ tSirMacReasonCodes reason;
+}tRoamCmd;
+
+typedef struct tagSetKeyCmd
+{
+ tANI_U32 roamId;
+ eCsrEncryptionType encType;
+ eCsrAuthType authType;
+ tAniKeyDirection keyDirection; //Tx, Rx or Tx-and-Rx
+ tSirMacAddr peerMac; //Peer's MAC address. ALL 1's for group key
+ tANI_U8 paeRole; //0 for supplicant
+ tANI_U8 keyId; // Kye index
+ tANI_U8 keyLength; //Number of bytes containing the key in pKey
+ tANI_U8 Key[CSR_MAX_KEY_LEN];
+ tANI_U8 keyRsc[CSR_MAX_RSC_LEN];
+} tSetKeyCmd;
+
+typedef struct tahRemoveKeyCmd
+{
+ tANI_U32 roamId;
+ eCsrEncryptionType encType;
+ eCsrAuthType authType;
+ tSirMacAddr peerMac; //Peer's MAC address. ALL 1's for group key
+ tANI_U8 keyId; //key index
+} tRemoveKeyCmd;
+
+typedef struct tagWmStatusChangeCmd
+{
+ eCsrRoamWmStatusChangeTypes Type;
+ union
+ {
+ tSirSmeDeauthInd DeauthIndMsg;
+ tSirSmeDisassocInd DisassocIndMsg;
+ }u;
+
+}tWmStatusChangeCmd;
+
+typedef struct tagAddStaForSessionCmd
+{
+ //Session self mac addr
+ tSirMacAddr selfMacAddr;
+}tAddStaForSessionCmd;
+
+typedef struct tagDelStaForSessionCmd
+{
+ //Session self mac addr
+ tSirMacAddr selfMacAddr;
+ csrRoamSessionCloseCallback callback;
+ void *pContext;
+}tDelStaForSessionCmd;
+
+//This structure represents one scan request
+typedef struct tagCsrCmd
+{
+ tListElem Link;
+ eCsrRoamCommands command;
+ tANI_U8 sessionId; // Session ID for this command
+ union
+ {
+ tScanCmd scanCmd;
+ tRoamCmd roamCmd;
+ tWmStatusChangeCmd wmStatusChangeCmd;
+ tSetKeyCmd setKeyCmd;
+ tRemoveKeyCmd removeKeyCmd;
+ tAddStaForSessionCmd addStaSessionCmd;
+ tDelStaForSessionCmd delStaSessionCmd;
+ }u;
+}tCsrCmd;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+typedef struct tagCsr11rConfig
+{
+ tANI_BOOLEAN IsFTResourceReqSupported;
+} tCsr11rConfig;
+#endif
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+typedef struct tagCsrNeighborRoamConfig
+{
+ tANI_U32 nNeighborScanTimerPeriod;
+ tANI_U8 nNeighborLookupRssiThreshold;
+ tANI_U8 nNeighborReassocRssiThreshold;
+ tANI_U16 nNeighborScanMinChanTime;
+ tANI_U16 nNeighborScanMaxChanTime;
+ sCsrChannel neighborScanChanList;
+ tANI_U8 nMaxNeighborRetries;
+ tANI_U16 nNeighborResultsRefreshPeriod;
+}tCsrNeighborRoamConfig;
+#endif
+
+typedef struct tagCsrConfig
+{
+ tANI_U32 agingCount;
+ tANI_U32 FragmentationThreshold;
+ tANI_U32 channelBondingMode24GHz;
+ tANI_U32 channelBondingMode5GHz;
+ tANI_U32 RTSThreshold;
+ eCsrPhyMode phyMode;
+ eCsrCfgDot11Mode uCfgDot11Mode;
+ eCsrBand eBand;
+ tANI_U32 HeartbeatThresh50;
+ tANI_U32 HeartbeatThresh24;
+ tANI_U32 bgScanInterval;
+ eCsrCBChoice cbChoice;
+ eCsrBand bandCapability; //indicate hw capability
+ eCsrRoamWmmUserModeType WMMSupportMode;
+ tANI_BOOLEAN Is11eSupportEnabled;
+ tANI_BOOLEAN Is11dSupportEnabled;
+ tANI_BOOLEAN Is11dSupportEnabledOriginal;
+ tANI_BOOLEAN Is11hSupportEnabled;
+ tANI_BOOLEAN shortSlotTime;
+ tANI_BOOLEAN ProprietaryRatesEnabled;
+ tANI_BOOLEAN fenableMCCMode;
+ tANI_U16 TxRate;
+ tANI_U8 AdHocChannel24;
+ tANI_U8 AdHocChannel5G;
+ tANI_U32 impsSleepTime; //in units of microseconds
+ tANI_U32 scanAgeTimeNCNPS; //scan result aging time threshold when Not-Connect-No-Power-Save, in seconds
+ tANI_U32 scanAgeTimeNCPS; //scan result aging time threshold when Not-Connect-Power-Save, in seconds
+ tANI_U32 scanAgeTimeCNPS; //scan result aging time threshold when Connect-No-Power-Save, in seconds,
+ tANI_U32 scanAgeTimeCPS; //scan result aging time threshold when Connect-Power-Savein seconds
+ tANI_U32 BssPreferValue[CSR_NUM_RSSI_CAT]; //each RSSI category has one value
+ int RSSICat[CSR_NUM_RSSI_CAT];
+ tANI_U8 bCatRssiOffset; //to set the RSSI difference for each category
+ tANI_U32 nRoamingTime; //In seconds, CSR will try this long before gives up, 0 means no roaming
+ //Whether to limit the channels to the ones set in Csr11dInfo. If true, the opertaional
+ //channels are limited to the default channel list. It is an "AND" operation between the
+ //default channels and the channels in the 802.11d IE.
+ tANI_BOOLEAN fEnforce11dChannels;
+ //Country Code Priority
+ //0 = 802.11D > Configured Country > NV
+ //1 = Configured Country > 802.11D > NV
+ tANI_BOOLEAN fSupplicantCountryCodeHasPriority;
+ //When true, AP with unknown country code won't be see.
+ //"Unknown country code" means either Ap doesn't have 11d IE or we cannot
+ //find a domain for the country code in its 11d IE.
+ tANI_BOOLEAN fEnforceCountryCodeMatch;
+ //When true, only APs in the default domain can be seen. If the Ap has "unknown country
+ //code", or the doamin of the country code doesn't match the default domain, the Ap is
+ //not acceptable.
+ tANI_BOOLEAN fEnforceDefaultDomain;
+
+ tANI_U16 vccRssiThreshold;
+ tANI_U32 vccUlMacLossThreshold;
+
+ tANI_U32 nPassiveMinChnTime; //in units of milliseconds
+ tANI_U32 nPassiveMaxChnTime; //in units of milliseconds
+ tANI_U32 nActiveMinChnTime; //in units of milliseconds
+ tANI_U32 nActiveMaxChnTime; //in units of milliseconds
+
+ tANI_BOOLEAN IsIdleScanEnabled;
+ //in dBm, the maximum TX power
+ //The actual TX power is the lesser of this value and 11d.
+ //If 11d is disable, the lesser of this and default setting.
+ tANI_U8 nTxPowerCap;
+ tANI_U32 statsReqPeriodicity; //stats request frequency from PE while in full power
+ tANI_U32 statsReqPeriodicityInPS;//stats request frequency from PE while in power save
+#ifdef WLAN_SOFTAP_FEATURE
+ tANI_U32 dtimPeriod;
+ tANI_BOOLEAN ssidHidden;
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ tCsr11rConfig csr11rConfig;
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+ tANI_U8 isCcxIniFeatureEnabled;
+#endif
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ tANI_U8 isFastTransitionEnabled;
+#endif
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ tCsrNeighborRoamConfig neighborRoamConfig;
+#endif
+
+ /* Instead of Reassoc, send ADDTS/DELTS even when ACM is off for that AC
+ * This is mandated by WMM-AC certification */
+ tANI_BOOLEAN addTSWhenACMIsOff;
+
+ tANI_BOOLEAN fValidateList;
+ tANI_BOOLEAN concurrencyEnabled;
+
+ //To enable/disable scanning 2.4Ghz channels twice on a single scan request from HDD
+ tANI_BOOLEAN fScanTwice;
+
+}tCsrConfig;
+
+typedef struct tagCsrChannelPowerInfo
+{
+ tListElem link;
+ tANI_U8 firstChannel;
+ tANI_U8 numChannels;
+ tANI_U8 txPower;
+ tANI_U8 interChannelOffset;
+}tCsrChannelPowerInfo;
+
+typedef struct tagRoamJoinStatus
+{
+ tSirResultCodes statusCode;
+ //this is set to unspecified if statusCode indicates timeout. Or it is the failed reason from the other BSS(per 802.11 spec)
+ tANI_U32 reasonCode;
+}tCsrRoamJoinStatus;
+
+typedef struct tagCsrOsChannelMask
+{
+ tANI_U8 numChannels;
+ tANI_BOOLEAN scanEnabled[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ tANI_U8 channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+}tCsrOsChannelMask;
+
+
+typedef struct tagCsrScanStruct
+{
+ tScanProfile scanProfile;
+ tANI_U32 nextScanID;
+ tDblLinkList scanResultList;
+ tDblLinkList tempScanResults;
+ tANI_BOOLEAN fScanEnable;
+ tANI_BOOLEAN fFullScanIssued;
+ tPalTimerHandle hTimerGetResult;
+#ifdef WLAN_AP_STA_CONCURRENCY
+ tPalTimerHandle hTimerStaApConcTimer;
+#endif
+ tPalTimerHandle hTimerIdleScan;
+ tPalTimerHandle hTimerResultAging;
+ tPalTimerHandle hTimerBgScan;
+ //changes on every scan, it is used as a flag for whether 11d info is found on every scan
+ tANI_U8 channelOf11dInfo;
+ //changes on every scan, a flag to tell whether conflict 11d info found on each BSS
+ tANI_BOOLEAN fAmbiguous11dInfoFound;
+ //Tush: changes on every scan, a flag to tell whether the applied 11d info present in one of the scan results
+ tANI_BOOLEAN fCurrent11dInfoMatch;
+ tANI_BOOLEAN f11dInfoReset; //to indicate whether the 11d info in CFG is reset to default
+ tSirScanType curScanType;
+ tCsrChannel baseChannels; //This are all the supported channels AND(&) to the current eBand
+ tCsrChannel channels11d;
+ tChannelListWithPower defaultPowerTable[WNI_CFG_VALID_CHANNEL_LIST_LEN]; //From NV
+ tChannelListWithPower defaultPowerTable40MHz[WNI_CFG_VALID_CHANNEL_LIST_LEN]; //From NV
+ tANI_U32 numChannelsDefault; //total channels of NV
+ tCsrChannel base20MHzChannels; //The channel base to work on
+ tCsrChannel base40MHzChannels; //center channels for 40MHz channels
+ tDblLinkList channelPowerInfoList24;
+ tDblLinkList channelPowerInfoList5G;
+ tANI_U32 nLastAgeTimeOut;
+ tANI_U32 nAgingCountDown;
+ tANI_U8 countryCodeDefault[WNI_CFG_COUNTRY_CODE_LEN+1]; //The country code from NV
+ tANI_U8 countryCodeCurrent[WNI_CFG_COUNTRY_CODE_LEN+1];
+ tANI_U8 countryCode11d[WNI_CFG_COUNTRY_CODE_LEN+1];
+ v_REGDOMAIN_t domainIdDefault; //default regulatory domain
+ v_REGDOMAIN_t domainIdCurrent; //current regulatory domain
+ tANI_BOOLEAN f11dInfoApplied;
+ tANI_BOOLEAN fCancelIdleScan;
+#ifdef FEATURE_WLAN_WAPI
+// tANI_U16 NumBkidCandidate;
+// tBkidCandidateInfo BkidCandidateInfo[CSR_MAX_BKID_ALLOWED]; /* Move this as part of SessionEntry */
+#endif /* FEATURE_WLAN_WAPI */
+ tANI_U8 numBGScanChannel; //number of valid channels in the bgScanChannelList
+ tANI_U8 bgScanChannelList[WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN];
+ //the ChannelInfo member is not used in this structure.
+ //numBGScanChannel and bgScanChannelList are used for the BG scan channel info
+ tCsrBGScanRequest bgScanParams;
+ tANI_BOOLEAN fRestartIdleScan;
+ tANI_U32 nIdleScanTimeGap; //the time since last trying to trigger idle scan
+ tCsrOsChannelMask osScanChannelMask;//keep a track of channels to be scnned while in traffic condition
+ tANI_U16 nBssLimit; //the maximum number of BSS in scan cache
+ /*channelPowerInfoList24 has been seen corrupted. Set this flag to true trying to
+ * detect when it happens. Adding this into code because we can't reproduce it easily.
+ * We don't know when it happens. */
+ tANI_BOOLEAN fValidateList;
+ /*Customer wants to start with an active scan based on the default country code.
+ * This optimization will minimize the driver load to association time.
+ * Based on this flag we will bypass the initial passive scan needed for 11d
+ * to determine the country code & domain */
+ tANI_BOOLEAN fEnableBypass11d;
+
+ /*Customer wants to optimize the scan time. Avoiding scans(passive) on DFS
+ * channels while swipping through both bands can save some time
+ * (apprx 1.3 sec) */
+ tANI_BOOLEAN fEnableDFSChnlScan;
+
+ tANI_BOOLEAN fDropScanCmd; //true means we don't accept scan commands
+
+#ifdef WLAN_AP_STA_CONCURRENCY
+ tDblLinkList scanCmdPendingList;
+#endif
+}tCsrScanStruct;
+
+
+//Save the connected information. This structure + connectedProfile
+//should contain all information about the connection
+typedef struct tagRoamCsrConnectedInfo
+{
+ tANI_U32 nBeaconLength; //the length, in bytes, of the beacon frame, can be 0
+ tANI_U32 nAssocReqLength; //the length, in bytes, of the assoc req frame, can be 0
+ tANI_U32 nAssocRspLength; //The length, in bytes, of the assoc rsp frame, can be 0
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ tANI_U32 nRICRspLength; //Length of the parsed RIC response IEs received in reassoc response
+#endif
+#ifdef FEATURE_WLAN_CCX
+ tANI_U32 nTspecIeLength;
+#endif
+ tANI_U8 *pbFrames; //Point to a buffer contain the beacon, assoc req, assoc rsp frame, in that order
+ //user needs to use nBeaconLength, nAssocReqLength, nAssocRspLength to desice where
+ //each frame starts and ends.
+ tANI_U8 staId;
+}tCsrRoamConnectedInfo;
+
+
+typedef struct tagCsrLinkQualityIndInfo
+{
+ csrRoamLinkQualityIndCallback callback;
+ void *context;
+}tCsrLinkQualityIndInfo;
+
+typedef struct tagCsrPeStatsReqInfo
+{
+ tListElem link; /* list links */
+ tANI_U32 statsMask;
+ tANI_U32 periodicity;
+ tANI_BOOLEAN rspPending;
+ vos_timer_t hPeStatsTimer;
+ tANI_BOOLEAN timerRunning;
+ tANI_U8 staId;
+ tANI_U8 numClient;
+ tpAniSirGlobal pMac;
+ /* To remember if the peStats timer is stopped successfully or not */
+ tANI_BOOLEAN timerStopFailed;
+
+}tCsrPeStatsReqInfo;
+
+typedef struct tagCsrStatsClientReqInfo
+{
+ tListElem link; /* list links */
+ eCsrStatsRequesterType requesterId;
+ tCsrStatsCallback callback;
+ tANI_U32 periodicity;
+ void *pContext;
+ tANI_U32 statsMask;
+ tCsrPeStatsReqInfo *pPeStaEntry;
+ tANI_U8 staId;
+ vos_timer_t timer;
+ tANI_BOOLEAN timerExpired;
+ tpAniSirGlobal pMac; // TODO: Confirm this change BTAMP
+}tCsrStatsClientReqInfo;
+
+typedef struct tagCsrTlStatsReqInfo
+{
+ tANI_U32 periodicity;
+ tANI_BOOLEAN timerRunning;
+ tPalTimerHandle hTlStatsTimer;
+ tANI_U8 numClient;
+}tCsrTlStatsReqInfo;
+
+typedef struct tagCsrRoamSession
+{
+ tANI_U8 sessionId; // Session ID
+ tANI_BOOLEAN sessionActive; // TRUE if it is used
+ tCsrBssid selfMacAddr; // For BT-AMP station, this serve as BSSID for self-BSS.
+ csrRoamCompleteCallback callback;
+ void *pContext;
+ eCsrConnectState connectState;
+ tCsrRoamConnectedProfile connectedProfile;
+ tCsrRoamConnectedInfo connectedInfo;
+ tCsrRoamProfile *pCurRoamProfile;
+ tSirBssDescription *pConnectBssDesc;
+ tANI_U16 NumPmkidCache;
+ tPmkidCacheInfo PmkidCacheInfo[CSR_MAX_PMKID_ALLOWED];
+ tANI_U8 cJoinAttemps;
+ //This may or may not have the up-to-date valid channel list
+ //It is used to get WNI_CFG_VALID_CHANNEL_LIST and not allocate memory all the time
+ tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ tANI_S32 sPendingCommands; //0 means CSR is ok to low power
+#ifdef FEATURE_WLAN_WAPI
+ tANI_U16 NumBkidCache;
+ tBkidCacheInfo BkidCacheInfo[CSR_MAX_BKID_ALLOWED];
+#endif /* FEATURE_WLAN_WAPI */
+ tANI_BOOLEAN fRoaming; //indicate whether CSR is roaming (either via lostlink or dynamic roaming)
+ //to remember some parameters needed for START_BSS.
+ //All member must be set every time we try to join or start an IBSS or BT-AMP
+ tCsrRoamStartBssParams bssParams;
+ tANI_U32 nWpaRsnReqIeLength; //the byte count of pWpaRsnIE;
+ tANI_U8 *pWpaRsnReqIE; //this contain the WPA/RSN IE in assoc request or the one sent in beacon (IBSS)
+ tANI_U32 nWpaRsnRspIeLength; //the byte count for pWpaRsnRspIE
+ tANI_U8 *pWpaRsnRspIE; //this contain the WPA/RSN IE in beacon/probe rsp
+#ifdef FEATURE_WLAN_WAPI
+ tANI_U32 nWapiReqIeLength; //the byte count of pWapiReqIE;
+ tANI_U8 *pWapiReqIE; //this contain the WAPI IE in assoc request or the one sent in beacon (IBSS)
+ tANI_U32 nWapiRspIeLength; //the byte count for pWapiRspIE
+ tANI_U8 *pWapiRspIE; //this contain the WAPI IE in beacon/probe rsp
+#endif /* FEATURE_WLAN_WAPI */
+ tANI_U32 nAddIEScanLength; //the byte count of pAddIeScanIE;
+ tANI_U8 *pAddIEScan; //this contains the additional IE in (unicast) probe request at the time of join
+ tANI_U32 nAddIEAssocLength; //the byte count for pAddIeAssocIE
+ tANI_U8 *pAddIEAssoc; //this contains the additional IE in (re) assoc request
+
+ tANI_TIMESTAMP roamingStartTime; //in units of 10ms
+ tCsrTimerInfo roamingTimerInfo;
+ eCsrRoamingReason roamingReason;
+ tANI_BOOLEAN fCancelRoaming;
+ tPalTimerHandle hTimerRoaming;
+ tPalTimerHandle hTimerIbssJoining;
+ tCsrTimerInfo ibssJoinTimerInfo;
+ tANI_BOOLEAN ibss_join_pending;
+ eCsrRoamResult roamResult; //the roamResult that is used when the roaming timer fires
+ tCsrRoamJoinStatus joinFailStatusCode; //This is the reason code for join(assoc) failure
+ //The status code returned from PE for deauth or disassoc (in case of lostlink), or our own dynamic roaming
+ tANI_U32 roamingStatusCode;
+ tANI_U16 NumPmkidCandidate;
+ tPmkidCandidateInfo PmkidCandidateInfo[CSR_MAX_PMKID_ALLOWED];
+ #ifdef FEATURE_WLAN_WAPI
+ tANI_U16 NumBkidCandidate;
+ tBkidCandidateInfo BkidCandidateInfo[CSR_MAX_BKID_ALLOWED];
+#endif
+ tANI_BOOLEAN fWMMConnection;
+#ifdef FEATURE_WLAN_BTAMP_UT_RF
+ //To retry a join later when it fails if so desired
+ tPalTimerHandle hTimerJoinRetry;
+ tCsrTimerInfo joinRetryTimerInfo;
+ tANI_U32 maxRetryCount;
+#endif
+#ifdef FEATURE_WLAN_CCX
+ tCsrCcxCckmInfo ccxCckmInfo;
+ tANI_BOOLEAN isPrevApInfoValid;
+ tSirMacSSid prevApSSID;
+ tCsrBssid prevApBssid;
+ tANI_U8 prevOpChannel;
+ tANI_U16 clientDissSecs;
+ tANI_U32 roamTS1;
+#endif
+ tANI_U8 bRefAssocStartCnt; //Tracking assoc start indication
+} tCsrRoamSession;
+
+typedef struct tagCsrRoamStruct
+{
+ tANI_U32 nextRoamId;
+ tDblLinkList roamCmdPendingList;
+ tDblLinkList channelList5G;
+ tDblLinkList channelList24;
+ tCsrConfig configParam;
+ tANI_U32 numChannelsEeprom; //total channels of eeprom
+ tCsrChannel base20MHzChannels; //The channel base to work on
+ tCsrChannel base40MHzChannels; //center channels for 40MHz channels
+ eCsrRoamState curState[CSR_ROAM_SESSION_MAX];
+ eCsrRoamSubState curSubState[CSR_ROAM_SESSION_MAX];
+ //This may or may not have the up-to-date valid channel list
+ //It is used to get WNI_CFG_VALID_CHANNEL_LIST and not allocate memory all the time
+ tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ tANI_U32 numValidChannels; //total number of channels in CFG
+
+ tANI_S32 sPendingCommands;
+ tChannelListWithPower *powerTableFromEeprom;
+ tChannelListWithPower *powerTableFromEeprom40MHz;
+ tPalTimerHandle hTimerWaitForKey; //To support timeout for WaitForKey state
+ tCsrSummaryStatsInfo summaryStatsInfo;
+ tCsrGlobalClassAStatsInfo classAStatsInfo;
+ tCsrGlobalClassBStatsInfo classBStatsInfo;
+ tCsrGlobalClassCStatsInfo classCStatsInfo;
+ tCsrGlobalClassDStatsInfo classDStatsInfo;
+ tCsrPerStaStatsInfo perStaStatsInfo[CSR_MAX_STA];
+ tDblLinkList statsClientReqList;
+ tDblLinkList peStatsReqList;
+ tCsrTlStatsReqInfo tlStatsReqInfo;
+ eCsrRoamLinkQualityInd vccLinkQuality;
+ tCsrLinkQualityIndInfo linkQualityIndInfo;
+ v_CONTEXT_t gVosContext; //used for interaction with TL
+ //To specify whether an association or a IBSS is WMM enabled
+ //This parameter is only valid during a join or start BSS command is being executed
+ //tANI_BOOLEAN fWMMConnection; /* Moving it to be part of roamsession */
+ v_U8_t ucACWeights[WLANTL_MAX_AC];
+ /* TODO : Upto here */
+ tCsrTimerInfo WaitForKeyTimerInfo;
+ tCsrRoamSession *roamSession;
+ tANI_U32 transactionId; // Current transaction ID for internal use.
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ tCsrNeighborRoamControlInfo neighborRoamInfo;
+#endif
+#ifdef FEATURE_WLAN_CCX
+ tANI_U8 isCcxIniFeatureEnabled;
+#endif
+}tCsrRoamStruct;
+
+
+#define GET_NEXT_ROAM_ID(pRoamStruct) (((pRoamStruct)->nextRoamId + 1 == 0) ? 1 : (pRoamStruct)->nextRoamId)
+#define CSR_IS_ROAM_STATE(pMac, state, sessionId) ( (state) == (pMac)->roam.curState[sessionId] )
+
+#define CSR_IS_ROAM_STOP(pMac, sessionId) CSR_IS_ROAM_STATE( (pMac), eCSR_ROAMING_STATE_STOP, sessionId )
+#define CSR_IS_ROAM_INIT(pMac, sessionId) CSR_IS_ROAM_STATE( (pMac), eCSR_ROAMING_STATE_INIT, sessionId )
+#define CSR_IS_ROAM_SCANNING(pMac, sessionId) CSR_IS_ROAM_STATE( pMac, eCSR_ROAMING_STATE_SCANNING, sessionId )
+#define CSR_IS_ROAM_JOINING(pMac, sessionId) CSR_IS_ROAM_STATE( pMac, eCSR_ROAMING_STATE_JOINING, sessionId )
+#define CSR_IS_ROAM_IDLE(pMac, sessionId) CSR_IS_ROAM_STATE( pMac, eCSR_ROAMING_STATE_IDLE, sessionId )
+#define CSR_IS_ROAM_JOINED(pMac, sessionId) CSR_IS_ROAM_STATE( pMac, eCSR_ROAMING_STATE_JOINED, sessionId )
+
+#define CSR_IS_ROAM_SUBSTATE(pMac, subState, sessionId) ((subState) == (pMac)->roam.curSubState[sessionId])
+#define CSR_IS_ROAM_SUBSTATE_JOIN_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_JOIN_REQ, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_AUTH_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_AUTH_REQ, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_REASSOC_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_REASSOC_REQ, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_DISASSOC_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_REQ, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_DISASSOC_NO_JOIN(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_NOTHING_TO_JOIN, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_REASSOC_FAIL(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_DISASSOC_FORCED(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_FORCED, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DEAUTH_REQ, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_START_BSS_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_START_BSS_REQ, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_STOP_BSS_REQ, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_DISCONNECT_CONTINUE(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_CONFIG(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_CONFIG, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_WAITFORKEY(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_DISASSOC_HO(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_HO_NT(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_JOINED_NO_TRAFFIC, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_HO_NRT(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_JOINED_NON_REALTIME_TRAFFIC, sessionId)
+#define CSR_IS_ROAM_SUBSTATE_HO_RT(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_JOINED_REALTIME_TRAFFIC, sessionId)
+
+#define CSR_IS_PHY_MODE_B_ONLY(pMac) \
+ ((eCSR_DOT11_MODE_11b == (pMac)->roam.configParam.phyMode) ||\
+ (eCSR_DOT11_MODE_11b_ONLY == (pMac)->roam.configParam.phyMode))
+
+#define CSR_IS_PHY_MODE_G_ONLY(pMac) \
+ (eCSR_DOT11_MODE_11g == (pMac)->roam.configParam.phyMode || eCSR_DOT11_MODE_11g_ONLY == (pMac)->roam.configParam.phyMode)
+
+#define CSR_IS_PHY_MODE_A_ONLY(pMac) \
+ ((eCSR_DOT11_MODE_11a == (pMac)->roam.configParam.phyMode) ||\
+ (eCSR_DOT11_MODE_11a_ONLY == (pMac)->roam.configParam.phyMode))
+
+#define CSR_IS_PHY_MODE_DUAL_BAND(phyMode) \
+ ((eCSR_DOT11_MODE_abg & (phyMode)) || (eCSR_DOT11_MODE_11n & (phyMode)) || \
+ (eCSR_DOT11_MODE_TAURUS & (phyMode)) || \
+ (eCSR_DOT11_MODE_AUTO & (phyMode)))
+
+// this function returns TRUE if the NIC is operating exclusively in the 2.4 GHz band, meaning
+// it is NOT operating in the 5.0 GHz band.
+#define CSR_IS_24_BAND_ONLY(pMac) \
+ (eCSR_BAND_24 == (pMac)->roam.configParam.eBand)
+
+#define CSR_IS_5G_BAND_ONLY(pMac) \
+ (eCSR_BAND_5G == (pMac)->roam.configParam.eBand)
+
+#define CSR_IS_RADIO_DUAL_BAND(pMac) \
+ (eCSR_BAND_ALL == (pMac)->roam.configParam.bandCapability)
+
+#define CSR_IS_RADIO_BG_ONLY(pMac) \
+ (eCSR_BAND_24 == (pMac)->roam.configParam.bandCapability)
+
+// this function returns TRUE if the NIC is operating exclusively in the 5.0 GHz band, meaning
+// it is NOT operating in the 2.4 GHz band
+#define CSR_IS_RADIO_A_ONLY(pMac) \
+ (eCSR_BAND_5G == (pMac)->roam.configParam.bandCapability)
+
+// this function returns TRUE if the NIC is operating in both bands.
+#define CSR_IS_OPEARTING_DUAL_BAND(pMac) \
+ ((eCSR_BAND_ALL == (pMac)->roam.configParam.bandCapability) && (eCSR_BAND_ALL == (pMac)->roam.configParam.eBand))
+
+// this function returns TRUE if the NIC can operate in the 5.0 GHz band (could operate in the
+// 2.4 GHz band also).
+#define CSR_IS_OPERATING_A_BAND(pMac) \
+ (CSR_IS_OPEARTING_DUAL_BAND((pMac)) || CSR_IS_RADIO_A_ONLY((pMac)) || CSR_IS_5G_BAND_ONLY((pMac)))
+
+// this function returns TRUE if the NIC can operate in the 2.4 GHz band (could operate in the
+// 5.0 GHz band also).
+#define CSR_IS_OPERATING_BG_BAND(pMac) \
+ (CSR_IS_OPEARTING_DUAL_BAND((pMac)) || CSR_IS_RADIO_BG_ONLY((pMac)) || CSR_IS_24_BAND_ONLY((pMac)))
+
+#define CSR_IS_CHANNEL_5GHZ(chnNum) \
+ ((chnNum) > CSR_MAX_24GHz_CHANNEL_NUMBER)
+
+#define CSR_IS_CHANNEL_24GHZ(chnNum) \
+ (((chnNum) > 0) && ((chnNum) <= CSR_MAX_24GHz_CHANNEL_NUMBER))
+
+#define CSR_IS_SAME_BAND_CHANNELS(ch1, ch2) (CSR_IS_CHANNEL_5GHZ(ch1) == CSR_IS_CHANNEL_5GHZ(ch2))
+
+
+#define CSR_IS_11D_INFO_FOUND(pMac) \
+ (0 != (pMac)->scan.channelOf11dInfo)
+// DEAUTHIND
+#define CSR_IS_ROAMING(pSession) ((CSR_IS_LOSTLINK_ROAMING((pSession)->roamingReason)) || \
+ (eCsrDynamicRoaming == (pSession)->roamingReason) || \
+ (eCsrReassocRoaming == (pSession)->roamingReason))
+
+
+#define CSR_IS_SET_KEY_COMMAND( pCommand ) ( eSmeCommandSetKey == (pCommand)->command )
+
+#define CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) (pMac->roam.configParam.addTSWhenACMIsOff)
+// DEAUTHIND
+#define CSR_IS_LOSTLINK_ROAMING(reason) ((eCsrLostlinkRoamingDisassoc == (reason)) || (eCsrLostlinkRoamingDeauth == (reason)))
+
+//Stop CSR from asking for IMPS, This function doesn't disable IMPS from CSR
+void csrScanSuspendIMPS( tpAniSirGlobal pMac );
+//Start CSR from asking for IMPS. This function doesn't trigger CSR to request entering IMPS
+//because IMPS maybe disabled.
+void csrScanResumeIMPS( tpAniSirGlobal pMac );
+
+eHalStatus csrInitGetChannels(tpAniSirGlobal pMac);
+
+eHalStatus csrSetModifyProfileFields(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tCsrRoamModifyProfileFields *pModifyProfileFields);
+/* ---------------------------------------------------------------------------
+ \fn csrGetModifyProfileFields
+ \brief HDD or SME - QOS calls this function to get the current values of
+ connected profile fields changing which can cause reassoc.
+ This function must be called after CFG is downloaded and STA is in connected
+ state.
+ \param pModifyProfileFields - pointer to the connected profile fields
+ changing which can cause reassoc
+
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrGetModifyProfileFields(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tCsrRoamModifyProfileFields * pModifyProfileFields);
+void csrSetGlobalCfgs( tpAniSirGlobal pMac );
+void csrSetDefaultDot11Mode( tpAniSirGlobal pMac );
+void csrScanSetChannelMask(tpAniSirGlobal pMac, tCsrChannelInfo *pChannelInfo);
+tANI_BOOLEAN csrIsConnStateDisconnected(tpAniSirGlobal pMac, tANI_U32 sessionId);
+tANI_BOOLEAN csrIsConnStateConnectedIbss( tpAniSirGlobal pMac, tANI_U32 sessionId );
+tANI_BOOLEAN csrIsConnStateDisconnectedIbss( tpAniSirGlobal pMac, tANI_U32 sessionId );
+tANI_BOOLEAN csrIsConnStateConnectedInfra( tpAniSirGlobal pMac, tANI_U32 sessionId );
+tANI_BOOLEAN csrIsConnStateConnected( tpAniSirGlobal pMac, tANI_U32 sessionId );
+tANI_BOOLEAN csrIsConnStateInfra( tpAniSirGlobal pMac, tANI_U32 sessionId );
+tANI_BOOLEAN csrIsConnStateIbss( tpAniSirGlobal pMac, tANI_U32 sessionId );
+tANI_BOOLEAN csrIsConnStateWds( tpAniSirGlobal pMac, tANI_U32 sessionId );
+tANI_BOOLEAN csrIsConnStateConnectedWds( tpAniSirGlobal pMac, tANI_U32 sessionId );
+tANI_BOOLEAN csrIsConnStateDisconnectedWds( tpAniSirGlobal pMac, tANI_U32 sessionId );
+tANI_BOOLEAN csrIsAnySessionInConnectState( tpAniSirGlobal pMac );
+tANI_BOOLEAN csrIsAllSessionDisconnected( tpAniSirGlobal pMac );
+tANI_BOOLEAN csrIsInfraConnected( tpAniSirGlobal pMac );
+tANI_BOOLEAN csrIsConcurrentInfraConnected( tpAniSirGlobal pMac );
+tANI_BOOLEAN csrIsIBSSStarted( tpAniSirGlobal pMac );
+tANI_BOOLEAN csrIsBTAMPStarted( tpAniSirGlobal pMac );
+tANI_BOOLEAN csrIsBTAMP( tpAniSirGlobal pMac, tANI_U32 sessionId );
+eHalStatus csrIsBTAMPAllowed( tpAniSirGlobal pMac, tANI_U32 chnId );
+tANI_BOOLEAN csrIsValidMcConcurrentSession(tpAniSirGlobal pMac, tANI_U32 sessionId);
+#ifdef WLAN_SOFTAP_FEATURE
+tANI_BOOLEAN csrIsConnStateConnectedInfraAp( tpAniSirGlobal pMac, tANI_U32 sessionId );
+#endif
+/*----------------------------------------------------------------------------
+ \fn csrRoamRegisterLinkQualityIndCallback
+
+ \brief
+ a CSR function to allow HDD to register a callback handler with CSR for
+ link quality indications.
+
+ Only one callback may be registered at any time.
+ In order to deregister the callback, a NULL cback may be provided.
+
+ Registration happens in the task context of the caller.
+
+ \param callback - Call back being registered
+ \param pContext - user data
+
+ DEPENDENCIES: After CSR open
+
+ \return eHalStatus
+-----------------------------------------------------------------------------*/
+eHalStatus csrRoamRegisterLinkQualityIndCallback(tpAniSirGlobal pMac,
+ csrRoamLinkQualityIndCallback callback,
+ void *pContext);
+/* ---------------------------------------------------------------------------
+ \fn csrGetStatistics
+ \brief csr function that client calls to register a callback to get
+ different PHY level statistics from CSR.
+
+ \param requesterId - different client requesting for statistics, HDD, UMA/GAN etc
+ \param statsMask - The different category/categories of stats requester is looking for
+ \param callback - SME sends back the requested stats using the callback
+ \param periodicity - If requester needs periodic update, 0 means it's an one
+ time request
+ \param cache - If requester is happy with cached stats
+ \param staId - The station ID for which the stats is requested for
+ \param pContext - user context to be passed back along with the callback
+
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requesterId,
+ tANI_U32 statsMask,
+ tCsrStatsCallback callback,
+ tANI_U32 periodicity, tANI_BOOLEAN cache,
+ tANI_U8 staId, void *pContext);
+
+
+eHalStatus csrGetRssi(tpAniSirGlobal pMac,tCsrRssiCallback callback,tANI_U8 staId,tCsrBssid bssId,void * pContext,void * pVosContext);
+eHalStatus csrRoamRegisterCallback(tpAniSirGlobal pMac, csrRoamCompleteCallback callback, void *pContext);
+/* ---------------------------------------------------------------------------
+ \fn csrGetConfigParam
+ \brief HDD calls this function to get the global settings currently maintained by CSR.
+ \param pParam - caller allocated memory
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam);
+
+/* ---------------------------------------------------------------------------
+ \fn csrMsgProcessor
+ \brief HDD calls this function to change some global settings.
+ caller must set the all fields or call csrGetConfigParam to prefill the fields.
+ \param pParam - caller allocated memory
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam);
+
+
+/* ---------------------------------------------------------------------------
+ \fn csrMsgProcessor
+ \brief HDD calls this function for the messages that are handled by CSR.
+ \param pMsgBuf - a pointer to a buffer that maps to various structures base on the message type.
+ The beginning of the buffer can always map to tSirSmeRsp.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf );
+
+/* ---------------------------------------------------------------------------
+ \fn csrOpen
+ \brief This function must be called before any API call to CSR.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrOpen(tpAniSirGlobal pMac);
+/* ---------------------------------------------------------------------------
+ \fn csrClose
+ \brief To close down CSR module. There should not be any API call into CSR after calling this function.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrClose(tpAniSirGlobal pMac);
+/* ---------------------------------------------------------------------------
+ \fn csrStart
+ \brief To start CSR.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrStart(tpAniSirGlobal pMac);
+/* ---------------------------------------------------------------------------
+ \fn csrStop
+ \brief To stop CSR. CSR still keeps its current setting.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrStop(tpAniSirGlobal pMac);
+/* ---------------------------------------------------------------------------
+ \fn csrReady
+ \brief To let CSR is ready to operate
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrReady(tpAniSirGlobal pMac);
+
+#ifdef FEATURE_WLAN_WAPI
+eHalStatus csrRoamGetBKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pNum,
+ tBkidCacheInfo *pBkidCache);
+
+
+eHalStatus csrScanGetBKIDCandidateList(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tBkidCandidateInfo *pBkidList, tANI_U32 *pNumItems );
+tANI_U32 csrRoamGetNumBKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId);
+eHalStatus csrRoamSetBKIDCache( tpAniSirGlobal pMac, tANI_U32 sessionId, tBkidCacheInfo *pBKIDCache,
+ tANI_U32 numItems );
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetWapiReqIE
+ \brief return the WAPI IE CSR passes to PE to JOIN request or START_BSS request
+ \param pLen - caller allocated memory that has the length of pBuf as input. Upon returned, *pLen has the
+ needed or IE length in pBuf.
+ \param pBuf - Caller allocated memory that contain the IE field, if any, upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not big enough
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamGetWapiReqIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetWapiRspIE
+ \brief return the WAPI IE from the beacon or probe rsp if connected
+ \param pLen - caller allocated memory that has the length of pBuf as input. Upon returned, *pLen has the
+ needed or IE length in pBuf.
+ \param pBuf - Caller allocated memory that contain the IE field, if any, upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not big enough
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamGetWapiRspIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf);
+tANI_U8 csrConstructWapiIe( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe );
+#endif /* FEATURE_WLAN_WAPI */
+
+#ifdef WLAN_SOFTAP_FEATURE
+eHalStatus csrRoamUpdateAPWPSIE( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirAPWPSIEs *pAPWPSIES );
+eHalStatus csrRoamUpdateWPARSNIEs( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirRSNie * pAPSirRSNie);
+#endif
+void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOLEAN fPrivacy );
+tANI_S8 csrGetInfraSessionId( tpAniSirGlobal pMac );
+tANI_U8 csrGetInfraOperationChannel( tpAniSirGlobal pMac, tANI_U8 sessionId);
+tANI_U8 csrGetConcurrentOperationChannel( tpAniSirGlobal pMac );
+
+eHalStatus csrRoamCopyConnectProfile(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tCsrRoamConnectedProfile *pProfile);
+tANI_BOOLEAN csrIsSetKeyAllowed(tpAniSirGlobal pMac, tANI_U32 sessionId);
+
+void csrSetOppositeBandChannelInfo( tpAniSirGlobal pMac );
+void csrConstructCurrentValidChannelList( tpAniSirGlobal pMac, tDblLinkList *pChannelSetList,
+ tANI_U8 *pChannelList, tANI_U8 bSize, tANI_U8 *pNumChannels );
+
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+//Returns whether the current association is a 11r assoc or not
+tANI_BOOLEAN csrRoamIs11rAssoc(tpAniSirGlobal pMac);
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+//Returns whether the current association is a CCX assoc or not
+tANI_BOOLEAN csrRoamIsCCXAssoc(tpAniSirGlobal pMac);
+#endif
+
+void csrDisconnectAllActiveSessions(tpAniSirGlobal pMac);
diff --git a/CORE/SME/inc/csrLinkList.h b/CORE/SME/inc/csrLinkList.h
new file mode 100644
index 0000000..569ca14
--- /dev/null
+++ b/CORE/SME/inc/csrLinkList.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+ \file csrLinkList.h
+
+ Exports and types for the Common link list interfaces.
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+
+ ========================================================================== */
+#ifndef CSR_LINK_LIST_H__
+#define CSR_LINK_LIST_H__
+
+#include "vos_lock.h"
+
+
+#define LL_ACCESS_LOCK eANI_BOOLEAN_TRUE
+#define LL_ACCESS_NOLOCK eANI_BOOLEAN_FALSE
+
+typedef struct tagListElem
+{
+ struct tagListElem *last;
+ struct tagListElem *next;
+}tListElem;
+
+typedef enum
+{
+ LIST_FLAG_CLOSE = 0,
+ LIST_FLAG_OPEN = 0xa1b2c4d7,
+}tListFlag;
+
+//This is a circular double link list
+typedef struct tagDblLinkList
+{
+ tListElem ListHead;
+ vos_lock_t Lock;
+ tANI_U32 Count;
+ tHddHandle hHdd;
+ tListFlag Flag;
+}tDblLinkList;
+
+//To get the address of an object of (type) base on the (address) of one of its (field)
+#define GET_BASE_ADDR(address, type, field) ((type *)( \
+ (tANI_U8 *)(address) - \
+ (tANI_U8 *)(&((type *)0)->field)))
+
+//To get the offset of (field) inside structure (type)
+#define GET_FIELD_OFFSET(type, field) ((tANI_U32_OR_PTR)(&(((type *)0)->field)))
+
+#define GET_ROUND_UP( _Field, _Boundary ) (((_Field) + ((_Boundary) - 1)) & ~((_Boundary) - 1))
+#define BITS_ON( _Field, _Bitmask ) ( (_Field) |= (_Bitmask) )
+#define BITS_OFF( _Field, _Bitmask ) ( (_Field) &= ~(_Bitmask) )
+
+#define CSR_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define CSR_MIN(a, b) ((a) < (b) ? (a) : (b))
+
+
+#define csrIsListEmpty(pHead) ((pHead)->next == (pHead))
+
+tANI_U32 csrLLCount( tDblLinkList *pList );
+
+eHalStatus csrLLOpen( tHddHandle hHdd, tDblLinkList *pList );
+void csrLLClose( tDblLinkList *pList );
+
+void csrLLLock( tDblLinkList *pList );
+void csrLLUnlock( tDblLinkList *pList );
+
+tANI_BOOLEAN csrLLIsListEmpty( tDblLinkList *pList, tANI_BOOLEAN fInterlocked );
+
+void csrLLInsertHead( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked );
+void csrLLInsertTail( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked );
+//This function put pNewEntry before pEntry. Caller should have found pEntry
+void csrLLInsertEntry( tDblLinkList *pList, tListElem *pEntry, tListElem *pNewEntry, tANI_BOOLEAN fInterlocked );
+
+tListElem *csrLLPeekHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked );
+tListElem *csrLLPeekTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked );
+
+tListElem *csrLLRemoveHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked );
+tListElem *csrLLRemoveTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked );
+tANI_BOOLEAN csrLLRemoveEntry( tDblLinkList *pList, tListElem *pEntryToRemove, tANI_BOOLEAN fInterlocked );
+void csrLLPurge( tDblLinkList *pList, tANI_BOOLEAN fInterlocked );
+
+//csrLLNext return NULL if reaching the end or list is empty
+tListElem *csrLLNext( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked );
+
+tListElem *csrLLPrevious( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked );
+
+tANI_BOOLEAN csrLLFindEntry( tDblLinkList *pList, tListElem *pEntryToFind );
+
+
+#endif
+
diff --git a/CORE/SME/inc/csrNeighborRoam.h b/CORE/SME/inc/csrNeighborRoam.h
new file mode 100644
index 0000000..b5f535b
--- /dev/null
+++ b/CORE/SME/inc/csrNeighborRoam.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+
+
+ \file csrNeighborRoam.h
+
+ Exports and types for the neighbor roaming algorithm which is sepcifically
+ designed for Android.
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+
+========================================================================== */
+#ifndef CSR_NEIGHBOR_ROAM_H
+#define CSR_NEIGHBOR_ROAM_H
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+
+/* Enumeration of various states in neighbor roam algorithm */
+typedef enum
+{
+ eCSR_NEIGHBOR_ROAM_STATE_CLOSED,
+ eCSR_NEIGHBOR_ROAM_STATE_INIT,
+ eCSR_NEIGHBOR_ROAM_STATE_CONNECTED,
+ eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN,
+ eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING,
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY,
+ eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN,
+ eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING,
+ eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE,
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+ eNEIGHBOR_STATE_MAX
+} eCsrNeighborRoamState;
+
+/* Parameters that are obtained from CFG */
+typedef struct sCsrNeighborRoamCfgParams
+{
+ tANI_U8 maxNeighborRetries;
+ tANI_U32 neighborScanPeriod;
+ tCsrChannelInfo channelInfo;
+ tANI_U8 neighborLookupThreshold;
+ tANI_U8 neighborReassocThreshold;
+ tANI_U32 minChannelScanTime;
+ tANI_U32 maxChannelScanTime;
+ tANI_U16 neighborResultsRefreshPeriod;
+} tCsrNeighborRoamCfgParams, *tpCsrNeighborRoamCfgParams;
+
+#define CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX 255
+typedef struct sCsrNeighborRoamChannelInfo
+{
+ tANI_BOOLEAN IAPPNeighborListReceived; // Flag to mark reception of IAPP Neighbor list
+ tANI_BOOLEAN chanListScanInProgress;
+ tANI_U8 currentChanIndex; //Current channel index that is being scanned
+ tCsrChannelInfo currentChannelListInfo; //Max number of channels in channel list and the list of channels
+} tCsrNeighborRoamChannelInfo, *tpCsrNeighborRoamChannelInfo;
+
+typedef struct sCsrNeighborRoamBSSInfo
+{
+ tListElem List;
+ tANI_U8 apPreferenceVal;
+// tCsrScanResultInfo *scanResultInfo;
+ tpSirBssDescription pBssDescription;
+} tCsrNeighborRoamBSSInfo, *tpCsrNeighborRoamBSSInfo;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#define CSR_NEIGHBOR_ROAM_REPORT_QUERY_TIMEOUT 1000 //in milliseconds
+#define CSR_NEIGHBOR_ROAM_PREAUTH_RSP_WAIT_MULTIPLIER 5 //in milliseconds
+#define MAX_NUM_PREAUTH_FAIL_LIST_ADDRESS 10 //Max number of MAC addresses with which the pre-auth was failed
+#define MAX_BSS_IN_NEIGHBOR_RPT 4
+#define CSR_NEIGHBOR_ROAM_MAX_NUM_PREAUTH_RETRIES 3
+
+/* Black listed APs. List of MAC Addresses with which the Preauthentication was failed. */
+typedef struct sCsrPreauthFailListInfo
+{
+ tANI_U8 numMACAddress;
+ tSirMacAddr macAddress[MAX_NUM_PREAUTH_FAIL_LIST_ADDRESS];
+} tCsrPreauthFailListInfo, *tpCsrPreauthFailListInfo;
+
+typedef struct sCsrNeighborReportBssInfo
+{
+ tANI_U8 channelNum;
+ tANI_U8 neighborScore;
+ tSirMacAddr neighborBssId;
+} tCsrNeighborReportBssInfo, *tpCsrNeighborReportBssInfo;
+
+typedef struct sCsr11rAssocNeighborInfo
+{
+ tANI_BOOLEAN preauthRspPending;
+ tANI_BOOLEAN neighborRptPending;
+ tANI_U8 currentNeighborRptRetryNum;
+ tPalTimerHandle preAuthRspWaitTimer; //This timer is used for preauth response
+ tCsrTimerInfo preAuthRspWaitTimerInfo;
+ tCsrPreauthFailListInfo preAuthFailList;
+ tANI_U32 neighborReportTimeout;
+ tANI_U32 PEPreauthRespTimeout;
+ tANI_U8 numPreAuthRetries;
+ tDblLinkList preAuthDoneList; /* Linked list which consists or preauthenticated nodes */
+ tANI_U8 numBssFromNeighborReport;
+ tCsrNeighborReportBssInfo neighboReportBssInfo[MAX_BSS_IN_NEIGHBOR_RPT]; //Contains info needed during REPORT_SCAN State
+} tCsr11rAssocNeighborInfo, *tpCsr11rAssocNeighborInfo;
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+/* Below macros are used to increase the registered neighbor Lookup threshold with TL when
+ * we dont see any AP during back ground scanning. The values are incremented from neighborLookupThreshold
+ * from CFG, incremented by 5,10,15...50(LOOKUP_THRESHOLD_INCREMENT_MULTIPLIER_MAX *
+ * NEIGHBOR_LOOKUP_THRESHOLD_INCREMENT_CONSTANT) */
+#define NEIGHBOR_LOOKUP_THRESHOLD_INCREMENT_CONSTANT 5
+#define LOOKUP_THRESHOLD_INCREMENT_MULTIPLIER_MAX 4
+
+/* Complete control information for neighbor roam algorithm */
+typedef struct sCsrNeighborRoamControlInfo
+{
+ eCsrNeighborRoamState neighborRoamState;
+ eCsrNeighborRoamState prevNeighborRoamState;
+ tCsrNeighborRoamCfgParams cfgParams;
+ tCsrBssid currAPbssid; // current assoc AP
+ tANI_U8 currAPoperationChannel; // current assoc AP
+ tPalTimerHandle neighborScanTimer;
+ tPalTimerHandle neighborResultsRefreshTimer;
+ tCsrTimerInfo neighborScanTimerInfo;
+ tCsrNeighborRoamChannelInfo roamChannelInfo;
+ tANI_U8 currentNeighborLookupThreshold;
+ tANI_U8 currentLookupIncrementMultiplier;
+ tANI_BOOLEAN scanRspPending;
+ tANI_TIMESTAMP scanRequestTimeStamp;
+ tDblLinkList roamableAPList; // List of current FT candidates
+ tANI_U32 csrSessionId;
+ tCsrRoamProfile csrNeighborRoamProfile;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ tANI_BOOLEAN is11rAssoc;
+ tCsr11rAssocNeighborInfo FTRoamInfo;
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+#ifdef FEATURE_WLAN_CCX
+ tANI_BOOLEAN isCCXAssoc;
+ tANI_BOOLEAN isVOAdmitted;
+ tANI_U32 MinQBssLoadRequired;
+#endif
+} tCsrNeighborRoamControlInfo, *tpCsrNeighborRoamControlInfo;
+
+
+/* All the necessary Function declarations are here */
+eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac,tANI_U8 sessionId, VOS_STATUS status);
+eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac,tANI_U8 sessionId);
+tANI_BOOLEAN csrNeighborRoamIsHandoffInProgress(tpAniSirGlobal pMac);
+void csrNeighborRoamRequestHandoff(tpAniSirGlobal pMac);
+eHalStatus csrNeighborRoamInit(tpAniSirGlobal pMac);
+void csrNeighborRoamClose(tpAniSirGlobal pMac);
+void csrNeighborRoamPurgePreauthFailedList(tpAniSirGlobal pMac);
+VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac);
+VOS_STATUS csrNeighborRoamTransitionToPreauthDone(tpAniSirGlobal pMac);
+eHalStatus csrNeighborRoamPrepareScanProfileFilter(tpAniSirGlobal pMac, tCsrScanResultFilter *pScanFilter);
+void csrNeighborRoamGetHandoffAPInfo(tpAniSirGlobal pMac, tpCsrNeighborRoamBSSInfo pHandoffNode);
+void csrNeighborRoamPreauthRspHandler(tpAniSirGlobal pMac, VOS_STATUS vosStatus);
+#ifdef WLAN_FEATURE_VOWIFI_11R
+tANI_BOOLEAN csrNeighborRoamIs11rAssoc(tpAniSirGlobal pMac);
+#endif
+VOS_STATUS csrNeighborRoamCreateChanListFromNeighborReport(tpAniSirGlobal pMac);
+void csrNeighborRoamTranistionPreauthDoneToDisconnected(tpAniSirGlobal pMac);
+tANI_BOOLEAN csrNeighborRoamStatePreauthDone(tpAniSirGlobal pMac);
+
+
+
+#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */
+
+#endif /* CSR_NEIGHBOR_ROAM_H */
diff --git a/CORE/SME/inc/csrSupport.h b/CORE/SME/inc/csrSupport.h
new file mode 100644
index 0000000..d7257e7
--- /dev/null
+++ b/CORE/SME/inc/csrSupport.h
@@ -0,0 +1,813 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+
+
+ \file csrSupport.h
+
+ Exports and types for the Common Scan and Roaming supporting interfaces.
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+
+ ========================================================================== */
+#ifndef CSR_SUPPORT_H__
+#define CSR_SUPPORT_H__
+
+#include "csrLinkList.h"
+#include "csrApi.h"
+#include "vos_nvitem.h"
+
+#ifdef FEATURE_WLAN_WAPI
+#define CSR_WAPI_OUI_SIZE ( 4 )
+#define CSR_WAPI_VERSION_SUPPORTED ( 1 )
+#define CSR_WAPI_MAX_AUTH_SUITES ( 2 )
+#define CSR_WAPI_MAX_CYPHERS ( 5 )
+#define CSR_WAPI_MAX_UNICAST_CYPHERS ( 5 )
+#define CSR_WAPI_MAX_MULTICAST_CYPHERS ( 1 )
+#endif /* FEATURE_WLAN_WAPI */
+
+#define CSR_RSN_OUI_SIZE ( 4 )
+#define CSR_RSN_VERSION_SUPPORTED ( 1 )
+#define CSR_RSN_MAX_AUTH_SUITES ( 2 )
+#define CSR_RSN_MAX_CYPHERS ( 5 )
+#define CSR_RSN_MAX_UNICAST_CYPHERS ( 5 )
+#define CSR_RSN_MAX_MULTICAST_CYPHERS ( 1 )
+
+#define CSR_WPA_OUI_SIZE ( 4 )
+#define CSR_WPA_VERSION_SUPPORTED ( 1 )
+#define CSR_WME_OUI_SIZE ( 4 )
+#define CSR_WPA_MAX_AUTH_SUITES ( 2 )
+#define CSR_WPA_MAX_CYPHERS ( 5 )
+#define CSR_WPA_MAX_UNICAST_CYPHERS ( 5 )
+#define CSR_WPA_MAX_MULTICAST_CYPHERS ( 1 )
+#define CSR_WPA_IE_MIN_SIZE ( 6 ) // minimum size of the IE->length is the size of the Oui + Version.
+#define CSR_WPA_IE_MIN_SIZE_W_MULTICAST ( HDD_WPA_IE_MIN_SIZE + HDD_WPA_OUI_SIZE )
+#define CSR_WPA_IE_MIN_SIZE_W_UNICAST ( HDD_WPA_IE_MIN_SIZE + HDD_WPA_OUI_SIZE + sizeof( pWpaIe->cUnicastCyphers ) )
+
+#define CSR_DOT11_SUPPORTED_RATES_MAX ( 12 )
+#define CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX ( 8 )
+
+#define CSR_DOT11_MAX_NUM_SUPPORTED_11B_RATES ( 4 )
+#define CSR_DOT11_MAX_NUM_SUPPORTED_11A_RATES ( 8 )
+#define CSR_DOT11_BASIC_RATE_MASK ( 0x80 )
+
+#define CSR_WME_INFO_IE_VERSION_SUPPORTED ( 1 )
+#define CSR_WME_PARM_IE_VERSION_SUPPORTED ( 1 )
+
+#define CSR_PASSIVE_SCAN_STARTING_CHANNEL ( 52)
+#define CSR_PASSIVE_SCAN_ENDING_CHANNEL ( 140)
+
+#define CSR_DOT11_MAX_11A_RATE ( 54 * 2 )
+#define CSR_DOT11_MIN_11A_RATE ( 6 * 2 )
+#define CSR_DOT11_MAX_11B_RATE ( 11 * 2 )
+#define CSR_DOT11_MIN_11B_RATE ( 1 * 2 )
+#define CSR_DOT11_MAX_11G_RATE ( 54 * 2 )
+#define CSR_DOT11_MIN_11G_RATE ( 6 * 2 )
+
+//Define the frequency ranges that need to be passive scan, MHz
+#define CSR_PASSIVE_SCAN_CAT1_LOW 5250
+#define CSR_PASSIVE_SCAN_CAT1_HIGH 5350
+#define CSR_PASSIVE_SCAN_CAT2_LOW 5470
+#define CSR_PASSIVE_SCAN_CAT2_HIGH 5725
+#define CSR_PASSIVE_SCAN_CAT3_LOW 5500
+#define CSR_PASSIVE_SCAN_CAT3_HIGH 5560
+
+#define CSR_OUI_USE_GROUP_CIPHER_INDEX 0x00
+#define CSR_OUI_WEP40_OR_1X_INDEX 0x01
+#define CSR_OUI_TKIP_OR_PSK_INDEX 0x02
+#define CSR_OUI_RESERVED_INDEX 0x03
+#define CSR_OUI_AES_INDEX 0x04
+#define CSR_OUI_WEP104_INDEX 0x05
+
+#ifdef FEATURE_WLAN_WAPI
+#define CSR_OUI_WAPI_RESERVED_INDEX 0x00
+#define CSR_OUI_WAPI_WAI_CERT_OR_SMS4_INDEX 0x01
+#define CSR_OUI_WAPI_WAI_PSK_INDEX 0x02
+#endif /* FEATURE_WLAN_WAPI */
+
+
+typedef enum
+{
+ // 11b rates
+ eCsrSuppRate_1Mbps = 1 * 2,
+ eCsrSuppRate_2Mbps = 2 * 2,
+ eCsrSuppRate_5_5Mbps = 11, // 5.5 * 2
+ eCsrSuppRate_11Mbps = 11 * 2,
+
+ // 11a / 11g rates
+ eCsrSuppRate_6Mbps = 6 * 2,
+ eCsrSuppRate_9Mbps = 9 * 2,
+ eCsrSuppRate_12Mbps = 12 * 2,
+ eCsrSuppRate_18Mbps = 18 * 2,
+ eCsrSuppRate_24Mbps = 24 * 2,
+ eCsrSuppRate_36Mbps = 36 * 2,
+ eCsrSuppRate_48Mbps = 48 * 2,
+ eCsrSuppRate_54Mbps = 54 * 2,
+
+ // airgo proprietary rates
+ eCsrSuppRate_10Mbps = 10 * 2,
+ eCsrSuppRate_10_5Mbps= 21, // 10.5 * 2
+ eCsrSuppRate_20Mbps = 20 * 2,
+ eCsrSuppRate_21Mbps = 21 * 2,
+ eCsrSuppRate_40Mbps = 40 * 2,
+ eCsrSuppRate_42Mbps = 42 * 2,
+ eCsrSuppRate_60Mbps = 60 * 2,
+ eCsrSuppRate_63Mbps = 63 * 2,
+ eCsrSuppRate_72Mbps = 72 * 2,
+ eCsrSuppRate_80Mbps = 80 * 2,
+ eCsrSuppRate_84Mbps = 84 * 2,
+ eCsrSuppRate_96Mbps = 96 * 2,
+ eCsrSuppRate_108Mbps = 108 * 2,
+ eCsrSuppRate_120Mbps = 120 * 2,
+ eCsrSuppRate_126Mbps = 126 * 2,
+ eCsrSuppRate_144Mbps = 144 * 2,
+ eCsrSuppRate_160Mbps = 160 * 2,
+ eCsrSuppRate_168Mbps = 168 * 2,
+ eCsrSuppRate_192Mbps = 192 * 2,
+ eCsrSuppRate_216Mbps = 216 * 2,
+ eCsrSuppRate_240Mbps = 240 * 2
+}eCsrSupportedRates;
+
+typedef enum
+{
+ eCsrPassiveScanNot, //can be scanned actively on the whole 5GHz band
+ eCsrPassiveScanCat1, //always passive scan from 5250 to 5350MHz
+ eCsrPassiveScanCat2, //always passive scan from 5250 to 5350MHz, and from 5470 to 5725MHz
+ eCsrPassiveScanCat3, //always passive scan from 5250 to 5350MHz, from 5470 to 5725MHz, and from 5500 to 5560MHz
+}eCsrPassiveScanCat;
+
+
+//Please donot insert in the middle of the enum here because they tie to the indiex
+typedef enum
+{
+ eCSR_COUNTRY_INDEX_US = 0, //Always set US as index 0
+ eCSR_COUNTRY_INDEX_ANDORRA,
+ eCSR_COUNTRY_INDEX_UAE, //United Arab Emirates
+ eCSR_COUNTRY_INDEX_AFGHANISTAN,
+ eCSR_COUNTRY_INDEX_ANTIGUA_AND_BARBUDA,
+ eCSR_COUNTRY_INDEX_ANGUILLA,
+ eCSR_COUNTRY_INDEX_ALBANIA,
+ eCSR_COUNTRY_INDEX_ARMENIA,
+ eCSR_COUNTRY_INDEX_NETHERLANDS_ANTILLES,
+ eCSR_COUNTRY_INDEX_ANGOLA,
+ eCSR_COUNTRY_INDEX_ANTARCTICA,
+ eCSR_COUNTRY_INDEX_ARGENTINA,
+ eCSR_COUNTRY_INDEX_AMERICAN_SAMOA,
+ eCSR_COUNTRY_INDEX_AUSTRIA,
+ eCSR_COUNTRY_INDEX_AUSTRALIA,
+ eCSR_COUNTRY_INDEX_ARUBA,
+ eCSR_COUNTRY_INDEX_ALAND_ISLANDS,
+ eCSR_COUNTRY_INDEX_AZERBAIJAN,
+ eCSR_COUNTRY_INDEX_BOSNIA_AND_HERZEGOVINA,
+ eCSR_COUNTRY_INDEX_BARBADOS,
+ eCSR_COUNTRY_INDEX_BANGLADESH,
+ eCSR_COUNTRY_INDEX_BELGIUM,
+ eCSR_COUNTRY_INDEX_BURKINA_FASO,
+ eCSR_COUNTRY_INDEX_BULGARIA,
+ eCSR_COUNTRY_INDEX_BAHRAIN,
+ eCSR_COUNTRY_INDEX_BURUNDI,
+ eCSR_COUNTRY_INDEX_BENIN,
+ eCSR_COUNTRY_INDEX_SAINT_BARTHELEMY,
+ eCSR_COUNTRY_INDEX_BERMUDA,
+ eCSR_COUNTRY_INDEX_BRUNEI_DARUSSALAM,
+ eCSR_COUNTRY_INDEX_BOLVIA,
+ eCSR_COUNTRY_INDEX_BRAZIL,
+ eCSR_COUNTRY_INDEX_BAHAMAS,
+ eCSR_COUNTRY_INDEX_BHUTAN,
+ eCSR_COUNTRY_INDEX_BOUVET_ISLAND,
+ eCSR_COUNTRY_INDEX_BOTSWANA,
+ eCSR_COUNTRY_INDEX_BELARUS,
+ eCSR_COUNTRY_INDEX_BELIZE,
+ eCSR_COUNTRY_INDEX_CANADA,
+ eCSR_COUNTRY_INDEX_COCOS_KEELING_ISLANDS,
+ eCSR_COUNTRY_INDEX_CONGO_REP,
+ eCSR_COUNTRY_INDEX_CENTRAL_AFRICAN,
+ eCSR_COUNTRY_INDEX_CONGO,
+ eCSR_COUNTRY_INDEX_SWITZERLAND,
+ eCSR_COUNTRY_INDEX_COTE_DIVOIRE,
+ eCSR_COUNTRY_INDEX_COOK_ISLANDS,
+ eCSR_COUNTRY_INDEX_CHILE,
+ eCSR_COUNTRY_INDEX_CAMEROON,
+ eCSR_COUNTRY_INDEX_CHINA,
+ eCSR_COUNTRY_INDEX_COLUMBIA,
+ eCSR_COUNTRY_INDEX_COSTA_RICA,
+ eCSR_COUNTRY_INDEX_CUBA,
+ eCSR_COUNTRY_INDEX_CAPE_VERDE,
+ eCSR_COUNTRY_INDEX_CHRISTMAS_ISLAND,
+ eCSR_COUNTRY_INDEX_CYPRUS,
+ eCSR_COUNTRY_INDEX_CZECH,
+ eCSR_COUNTRY_INDEX_GERMANY,
+ eCSR_COUNTRY_INDEX_DJIBOUTI,
+ eCSR_COUNTRY_INDEX_DENMARK,
+ eCSR_COUNTRY_INDEX_DOMINICA,
+ eCSR_COUNTRY_INDEX_DOMINICAN_REP,
+ eCSR_COUNTRY_INDEX_ALGERIA,
+ eCSR_COUNTRY_INDEX_ECUADOR,
+ eCSR_COUNTRY_INDEX_ESTONIA,
+ eCSR_COUNTRY_INDEX_EGYPT,
+ eCSR_COUNTRY_INDEX_WESTERN_SAHARA,
+ eCSR_COUNTRY_INDEX_ERITREA,
+ eCSR_COUNTRY_INDEX_SPAIN,
+ eCSR_COUNTRY_INDEX_ETHIOPIA,
+ eCSR_COUNTRY_INDEX_FINLAND,
+ eCSR_COUNTRY_INDEX_FIJI,
+ eCSR_COUNTRY_INDEX_FALKLAND_ISLANDS,
+ eCSR_COUNTRY_INDEX_MICRONESIA,
+ eCSR_COUNTRY_INDEX_FAROE_ISLANDS,
+ eCSR_COUNTRY_INDEX_FRANCE,
+ eCSR_COUNTRY_INDEX_GABON,
+ eCSR_COUNTRY_INDEX_UNITED_KINGDOM,
+ eCSR_COUNTRY_INDEX_GRENADA,
+ eCSR_COUNTRY_INDEX_GEORGIA,
+ eCSR_COUNTRY_INDEX_FRENCH_GUIANA,
+ eCSR_COUNTRY_INDEX_GUERNSEY,
+ eCSR_COUNTRY_INDEX_GHANA,
+ eCSR_COUNTRY_INDEX_GIBRALTAR,
+ eCSR_COUNTRY_INDEX_GREENLAND,
+ eCSR_COUNTRY_INDEX_GAMBIA,
+ eCSR_COUNTRY_INDEX_GUINEA,
+ eCSR_COUNTRY_INDEX_GUADELOUPE,
+ eCSR_COUNTRY_INDEX_EQUATORIAL_GUINEA,
+ eCSR_COUNTRY_INDEX_GREECE,
+ eCSR_COUNTRY_INDEX_SOUTH_GEORGIA,
+ eCSR_COUNTRY_INDEX_GUATEMALA,
+ eCSR_COUNTRY_INDEX_GUAM,
+ eCSR_COUNTRY_INDEX_GUINEA_BISSAU,
+ eCSR_COUNTRY_INDEX_GUYANA,
+ eCSR_COUNTRY_INDEX_HONGKONG,
+ eCSR_COUNTRY_INDEX_HEARD_ISLAND,
+ eCSR_COUNTRY_INDEX_HONDURAS,
+ eCSR_COUNTRY_INDEX_CROATIA,
+ eCSR_COUNTRY_INDEX_HAITI,
+ eCSR_COUNTRY_INDEX_HUNGARY,
+ eCSR_COUNTRY_INDEX_INDONESIA,
+ eCSR_COUNTRY_INDEX_IRELAND,
+ eCSR_COUNTRY_INDEX_ISRAEL,
+ eCSR_COUNTRY_INDEX_ISLE_OF_MAN,
+ eCSR_COUNTRY_INDEX_INDIA,
+ eCSR_COUNTRY_INDEX_BRITISH_INDIAN,
+ eCSR_COUNTRY_INDEX_IRAQ,
+ eCSR_COUNTRY_INDEX_IRAN,
+ eCSR_COUNTRY_INDEX_ICELAND,
+ eCSR_COUNTRY_INDEX_ITALY,
+ eCSR_COUNTRY_INDEX_JERSEY,
+ eCSR_COUNTRY_INDEX_JAMAICA,
+ eCSR_COUNTRY_INDEX_JORDAN,
+ eCSR_COUNTRY_INDEX_JAPAN,
+ eCSR_COUNTRY_INDEX_KENYA,
+ eCSR_COUNTRY_INDEX_KYRGYZSTAN,
+ eCSR_COUNTRY_INDEX_CAMBODIA,
+ eCSR_COUNTRY_INDEX_KIRIBATI,
+ eCSR_COUNTRY_INDEX_COMOROS,
+ eCSR_COUNTRY_INDEX_SAINT_KITTS_AND_NEVIS,
+ eCSR_COUNTRY_INDEX_KOREA_NORTH,
+ eCSR_COUNTRY_INDEX_KOREA_SOUTH,
+ eCSR_COUNTRY_INDEX_KUWAIT,
+ eCSR_COUNTRY_INDEX_CAYMAN_ISLANDS,
+ eCSR_COUNTRY_INDEX_KAZAKHSTAN,
+ eCSR_COUNTRY_INDEX_LAO,
+ eCSR_COUNTRY_INDEX_LEBANON,
+ eCSR_COUNTRY_INDEX_SAINT_LUCIA,
+ eCSR_COUNTRY_INDEX_LIECHTENSTEIN,
+ eCSR_COUNTRY_INDEX_SRI_LANKA,
+ eCSR_COUNTRY_INDEX_LIBERIA,
+ eCSR_COUNTRY_INDEX_LESOTHO,
+ eCSR_COUNTRY_INDEX_LITHUANIA,
+ eCSR_COUNTRY_INDEX_LUXEMBOURG,
+ eCSR_COUNTRY_INDEX_LATVIA,
+ eCSR_COUNTRY_INDEX_LIBYAN_ARAB_JAMAHIRIYA,
+ eCSR_COUNTRY_INDEX_MOROCCO,
+ eCSR_COUNTRY_INDEX_MONACO,
+ eCSR_COUNTRY_INDEX_MOLDOVA,
+ eCSR_COUNTRY_INDEX_MONTENEGRO,
+ eCSR_COUNTRY_INDEX_MADAGASCAR,
+ eCSR_COUNTRY_INDEX_MARSHALL_ISLANDS,
+ eCSR_COUNTRY_INDEX_MACEDONIA,
+ eCSR_COUNTRY_INDEX_MALI,
+ eCSR_COUNTRY_INDEX_MYANMAR,
+ eCSR_COUNTRY_INDEX_MONGOLIA,
+ eCSR_COUNTRY_INDEX_MACAO,
+ eCSR_COUNTRY_INDEX_NORTHERN_MARIANA_ISLANDS,
+ eCSR_COUNTRY_INDEX_MARTINIQUE,
+ eCSR_COUNTRY_INDEX_MAURITANIA,
+ eCSR_COUNTRY_INDEX_MONTSERRAT,
+ eCSR_COUNTRY_INDEX_MALTA,
+ eCSR_COUNTRY_INDEX_MAURITIUS,
+ eCSR_COUNTRY_INDEX_MALDIVES,
+ eCSR_COUNTRY_INDEX_MALAWI,
+ eCSR_COUNTRY_INDEX_MEXICO,
+ eCSR_COUNTRY_INDEX_MALAYSIA,
+ eCSR_COUNTRY_INDEX_MOZAMBIQUE,
+ eCSR_COUNTRY_INDEX_NAMIBIA,
+ eCSR_COUNTRY_INDEX_NEW_CALENDONIA,
+ eCSR_COUNTRY_INDEX_NIGER,
+ eCSR_COUNTRY_INDEX_NORFOLK_ISLAND,
+ eCSR_COUNTRY_INDEX_NIGERIA,
+ eCSR_COUNTRY_INDEX_NICARAGUA,
+ eCSR_COUNTRY_INDEX_NETHERLANDS,
+ eCSR_COUNTRY_INDEX_NORWAY,
+ eCSR_COUNTRY_INDEX_NEPAL,
+ eCSR_COUNTRY_INDEX_NAURU,
+ eCSR_COUNTRY_INDEX_NIUE,
+ eCSR_COUNTRY_INDEX_NEW_ZEALAND,
+ eCSR_COUNTRY_INDEX_OMAN,
+ eCSR_COUNTRY_INDEX_PANAMA,
+ eCSR_COUNTRY_INDEX_PERU,
+ eCSR_COUNTRY_INDEX_FRENCH_POLYNESIA,
+ eCSR_COUNTRY_INDEX_PAPUA_NEW_HUINEA,
+ eCSR_COUNTRY_INDEX_PHILIPPINES,
+ eCSR_COUNTRY_INDEX_PAKISTAN,
+ eCSR_COUNTRY_INDEX_POLAND,
+ eCSR_COUNTRY_INDEX_SAINT_PIERRE_AND_MIQUELON,
+ eCSR_COUNTRY_INDEX_PITCAIRN,
+ eCSR_COUNTRY_INDEX_PUERTO_RICO,
+ eCSR_COUNTRY_INDEX_PALESTINIAN_TERRITOTY_OCCUPIED,
+ eCSR_COUNTRY_INDEX_PORTUGAL,
+ eCSR_COUNTRY_INDEX_PALAU,
+ eCSR_COUNTRY_INDEX_PARAGUAY,
+ eCSR_COUNTRY_INDEX_QATAR,
+ eCSR_COUNTRY_INDEX_REUNION,
+ eCSR_COUNTRY_INDEX_ROMANIA,
+ eCSR_COUNTRY_INDEX_SERBIA,
+ eCSR_COUNTRY_INDEX_RUSSIAN,
+ eCSR_COUNTRY_INDEX_RWANDA,
+ eCSR_COUNTRY_INDEX_SAUDI_ARABIA,
+ eCSR_COUNTRY_INDEX_SOLOMON_ISLANDS,
+ eCSR_COUNTRY_INDEX_SEYCHELLES,
+ eCSR_COUNTRY_INDEX_SUDAN,
+ eCSR_COUNTRY_INDEX_SWEDEN,
+ eCSR_COUNTRY_INDEX_SINGAPORE,
+ eCSR_COUNTRY_INDEX_SAINT_HELENA,
+ eCSR_COUNTRY_INDEX_SLOVENIA,
+ eCSR_COUNTRY_INDEX_SVALBARD_AND_JAN_MAYEN,
+ eCSR_COUNTRY_INDEX_SLOVAKIA,
+ eCSR_COUNTRY_INDEX_SIERRA_LEONE,
+ eCSR_COUNTRY_INDEX_SAN_MARINO,
+ eCSR_COUNTRY_INDEX_SENEGAL,
+ eCSR_COUNTRY_INDEX_SOMOLIA,
+ eCSR_COUNTRY_INDEX_SURINAME,
+ eCSR_COUNTRY_INDEX_SAO_TOME_AND_PRINCIPE,
+ eCSR_COUNTRY_INDEX_EL_SALVADOR,
+ eCSR_COUNTRY_INDEX_SYRIAN_REP,
+ eCSR_COUNTRY_INDEX_SWAZILAND,
+ eCSR_COUNTRY_INDEX_TURKS_AND_CAICOS_ISLANDS,
+ eCSR_COUNTRY_INDEX_CHAD,
+ eCSR_COUNTRY_INDEX_FRENCH_SOUTHERN_TERRRTORY,
+ eCSR_COUNTRY_INDEX_TOGO,
+ eCSR_COUNTRY_INDEX_THAILAND,
+ eCSR_COUNTRY_INDEX_TAJIKSTAN,
+ eCSR_COUNTRY_INDEX_TOKELAU,
+ eCSR_COUNTRY_INDEX_TIMOR_LESTE,
+ eCSR_COUNTRY_INDEX_TURKMENISTAN,
+ eCSR_COUNTRY_INDEX_TUNISIA,
+ eCSR_COUNTRY_INDEX_TONGA,
+ eCSR_COUNTRY_INDEX_TURKEY,
+ eCSR_COUNTRY_INDEX_TRINIDAD_AND_TOBAGO,
+ eCSR_COUNTRY_INDEX_TUVALU,
+ eCSR_COUNTRY_INDEX_TAIWAN,
+ eCSR_COUNTRY_INDEX_TANZANIA,
+ eCSR_COUNTRY_INDEX_UKRAINE,
+ eCSR_COUNTRY_INDEX_UGANDA,
+ eCSR_COUNTRY_INDEX_US_MINOR_OUTLYING_ISLANDS,
+ eCSR_COUNTRY_INDEX_URUGUAY,
+ eCSR_COUNTRY_INDEX_UZBEKISTAN,
+ eCSR_COUNTRY_INDEX_HOLY_SEE,
+ eCSR_COUNTRY_INDEX_SAINT_VINCENT_AND_THE_GRENADINES,
+ eCSR_COUNTRY_INDEX_VENESUELA,
+ eCSR_COUNTRY_INDEX_VIRGIN_ISLANDS_BRITISH,
+ eCSR_COUNTRY_INDEX_VIRGIN_ISLANDS_US,
+ eCSR_COUNTRY_INDEX_VIET_NAM,
+ eCSR_COUNTRY_INDEX_VANUATU,
+ eCSR_COUNTRY_INDEX_WALLIS_AND_FUTUNA,
+ eCSR_COUNTRY_INDEX_SAMOA,
+ eCSR_COUNTRY_INDEX_YEMEN,
+ eCSR_COUNTRY_INDEX_MAYOTTE,
+ eCSR_COUNTRY_INDEX_SOTHER_AFRICA,
+ eCSR_COUNTRY_INDEX_ZAMBIA,
+ eCSR_COUNTRY_INDEX_ZIMBABWE,
+
+ eCSR_COUNTRY_INDEX_KOREA_1,
+ eCSR_COUNTRY_INDEX_KOREA_2,
+ eCSR_COUNTRY_INDEX_KOREA_3,
+ eCSR_COUNTRY_INDEX_KOREA_4,
+
+ eCSR_NUM_COUNTRY_INDEX,
+}eCsrCountryIndex;
+//Please donot insert in the middle of the enum above because they tie to the indiex
+
+
+typedef struct tagCsrSirMBMsgHdr
+{
+ tANI_U16 type;
+ tANI_U16 msgLen;
+
+}tCsrSirMBMsgHdr;
+
+typedef struct tagCsrCfgMsgTlvHdr
+{
+ tANI_U32 type;
+ tANI_U32 length;
+
+}tCsrCfgMsgTlvHdr;
+
+
+
+typedef struct tagCsrCfgMsgTlv
+{
+ tCsrCfgMsgTlvHdr Hdr;
+ tANI_U32 variable[ 1 ]; // placeholder for the data
+
+}tCsrCfgMsgTlv;
+
+typedef struct tagCsrCfgGetRsp
+{
+ tCsrSirMBMsgHdr hdr;
+ tANI_U32 respStatus;
+ tANI_U32 paramId;
+ tANI_U32 attribLen;
+ tANI_U32 attribVal[1];
+}tCsrCfgGetRsp;
+
+typedef struct tagCsrCfgSetRsp
+{
+
+ tCsrSirMBMsgHdr hdr;
+ tANI_U32 respStatus;
+ tANI_U32 paramId;
+}tCsrCfgSetRsp;
+
+
+typedef struct tagCsrDomainChnScanInfo
+{
+ tANI_U8 chnId;
+ tSirScanType scanType; //whether this channel must be scan passively
+}tCsrDomainChnScanInfo;
+
+
+#if defined(__ANI_COMPILER_PRAGMA_PACK_STACK)
+#pragma pack( push )
+#pragma pack( 1 )
+#elif defined(__ANI_COMPILER_PRAGMA_PACK)
+#pragma pack( 1 )
+#endif
+
+// Generic Information Element Structure
+typedef __ani_attr_pre_packed struct sDot11IEHeader
+{
+ tANI_U8 ElementID;
+ tANI_U8 Length;
+}__ani_attr_packed tDot11IEHeader;
+
+typedef __ani_attr_pre_packed struct tagCsrWmeInfoIe
+{
+ tDot11IEHeader IeHeader;
+ tANI_U8 Oui[ CSR_WME_OUI_SIZE ]; // includes the 3 byte OUI + 1 byte Type
+ tANI_U8 Subtype;
+ tANI_U8 Version;
+ tANI_U8 QoSInfo;
+
+} __ani_attr_packed tCsrWmeInfoIe;
+
+typedef __ani_attr_pre_packed struct tagCsrWmeAcParms
+{
+ tANI_U8 AciAifsn;
+ tANI_U8 EcwMinEcwMax;
+ tANI_U16 TxOpLimit;
+
+} __ani_attr_packed tCsrWmeAcParms;
+
+typedef __ani_attr_pre_packed struct tagCsrWmeParmIe
+{
+ tDot11IEHeader IeHeader;
+ tANI_U8 Oui[ CSR_WME_OUI_SIZE ]; // includes the 3 byte OUI + 1 byte Type
+ tANI_U8 Subtype;
+ tANI_U8 Version;
+ tANI_U8 QoSInfo;
+ tANI_U8 Reserved;
+ tCsrWmeAcParms BestEffort;
+ tCsrWmeAcParms Background;
+ tCsrWmeAcParms Video;
+ tCsrWmeAcParms Voice;
+
+} __ani_attr_packed tCsrWmeParmIe;
+
+typedef __ani_attr_pre_packed struct tagCsrWpaIe
+{
+ tDot11IEHeader IeHeader;
+ tANI_U8 Oui[ CSR_WPA_OUI_SIZE ];
+ tANI_U16 Version;
+ tANI_U8 MulticastOui[ CSR_WPA_OUI_SIZE ];
+ tANI_U16 cUnicastCyphers;
+
+ __ani_attr_pre_packed struct {
+
+ tANI_U8 Oui[ CSR_WPA_OUI_SIZE ];
+
+ } __ani_attr_packed UnicastOui[ 1 ];
+
+} __ani_attr_packed tCsrWpaIe;
+
+typedef __ani_attr_pre_packed struct tagCsrWpaAuthIe
+{
+
+ tANI_U16 cAuthenticationSuites;
+
+ __ani_attr_pre_packed struct {
+
+ tANI_U8 Oui[ CSR_WPA_OUI_SIZE ];
+
+ } __ani_attr_packed AuthOui[ 1 ];
+
+} __ani_attr_packed tCsrWpaAuthIe;
+
+
+typedef __ani_attr_pre_packed struct tagCsrRSNIe
+{
+ tDot11IEHeader IeHeader;
+ tANI_U16 Version;
+ tANI_U8 MulticastOui[ CSR_RSN_OUI_SIZE ];
+ tANI_U16 cUnicastCyphers;
+
+ __ani_attr_pre_packed struct {
+
+ tANI_U8 Oui[ CSR_RSN_OUI_SIZE ];
+
+ } __ani_attr_packed UnicastOui[ 1 ];
+
+} __ani_attr_packed tCsrRSNIe;
+
+typedef __ani_attr_pre_packed struct tagCsrRSNAuthIe
+{
+ tANI_U16 cAuthenticationSuites;
+ __ani_attr_pre_packed struct {
+
+ tANI_U8 Oui[ CSR_RSN_OUI_SIZE ];
+
+ } __ani_attr_packed AuthOui[ 1 ];
+
+} __ani_attr_packed tCsrRSNAuthIe;
+
+typedef __ani_attr_pre_packed struct tagCsrRSNCapabilities
+{
+ tANI_U16 PreAuthSupported:1;
+ tANI_U16 NoPairwise:1;
+ tANI_U16 PTKSAReplayCounter:2;
+ tANI_U16 GTKSAReplayCounter:2;
+ tANI_U16 Reserved:10;
+} __ani_attr_packed tCsrRSNCapabilities;
+
+typedef __ani_attr_pre_packed struct tagCsrRSNPMKIe
+{
+ tANI_U16 cPMKIDs;
+
+ __ani_attr_pre_packed struct {
+
+ tANI_U8 PMKID[ CSR_RSN_PMKID_SIZE ];
+
+ } __ani_attr_packed PMKIDList[ 1 ];
+
+
+} __ani_attr_packed tCsrRSNPMKIe;
+
+typedef __ani_attr_pre_packed struct tCsrIELenInfo
+{
+ tANI_U8 min;
+ tANI_U8 max;
+} __ani_attr_packed tCsrIELenInfo;
+
+#ifdef FEATURE_WLAN_WAPI
+typedef __ani_attr_pre_packed struct tagCsrWapiIe
+{
+ tDot11IEHeader IeHeader;
+ tANI_U16 Version;
+
+ tANI_U16 cAuthenticationSuites;
+ __ani_attr_pre_packed struct {
+
+ tANI_U8 Oui[ CSR_WAPI_OUI_SIZE ];
+
+ } __ani_attr_packed AuthOui[ 1 ];
+
+ tANI_U16 cUnicastCyphers;
+ __ani_attr_pre_packed struct {
+
+ tANI_U8 Oui[ CSR_WAPI_OUI_SIZE ];
+
+ } __ani_attr_packed UnicastOui[ 1 ];
+
+ tANI_U8 MulticastOui[ CSR_WAPI_OUI_SIZE ];
+
+ __ani_attr_pre_packed struct {
+ tANI_U16 PreAuthSupported:1;
+ tANI_U16 Reserved:15;
+ } __ani_attr_packed tCsrWapiCapabilities;
+
+
+} __ani_attr_packed tCsrWapiIe;
+
+typedef __ani_attr_pre_packed struct tagCsrWAPIBKIe
+{
+ tANI_U16 cBKIDs;
+ __ani_attr_pre_packed struct {
+
+ tANI_U8 BKID[ CSR_WAPI_BKID_SIZE ];
+
+ } __ani_attr_packed BKIDList[ 1 ];
+
+
+} __ani_attr_packed tCsrWAPIBKIe;
+#endif /* FEATURE_WLAN_WAPI */
+
+#if defined(__ANI_COMPILER_PRAGMA_PACK_STACK)
+#pragma pack( pop )
+#endif
+
+// Structure used to describe a group of continuous channels and hook it into the
+// corresponding channel list
+typedef struct tagCsrChannelSet
+{
+ tListElem channelListLink;
+ tANI_U8 firstChannel;
+ tANI_U8 interChannelOffset;
+ tANI_U8 numChannels;
+ tANI_U8 txPower;
+}tCsrChannelSet;
+
+
+typedef struct sDot11InfoIBSSParmSet
+{
+ tDot11IEHeader dot11IEHeader;
+ tANI_U8 ATIMWindow;
+}tDot11InfoIBSSParmSet;
+
+
+typedef struct sDot11IECountry
+{
+ tDot11IEHeader dot11IEHeader;
+ tANI_U8 countryString[3];
+ tSirMacChanInfo chanInfo[1];
+}tDot11IECountry;
+
+
+typedef struct sDot11IEExtenedSupportedRates
+{
+ tDot11IEHeader dot11IEHeader;
+ tANI_U8 ExtendedSupportedRates[ CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX ];
+}tDot11IEExtenedSupportedRates;
+
+#define CSR_DOT11_AP_NAME_MAX_LENGTH ( 32 )
+
+typedef struct tagDot11IEAPName
+{
+ tDot11IEHeader dot11IEHeader;
+ tANI_U8 ApName[ CSR_DOT11_AP_NAME_MAX_LENGTH ];
+}tDot11IEAPName;
+
+typedef struct tagDot11IE11HLocalPowerConstraint
+{
+ tDot11IEHeader dot11IEHeader;
+ tANI_U8 localPowerConstraint;
+
+}tDot11IE11HLocalPowerConstraint;
+
+typedef struct tagRoamingTimerInfo
+{
+ tpAniSirGlobal pMac;
+ tANI_U8 sessionId;
+} tCsrTimerInfo;
+
+
+#define CSR_IS_11A_BSS(pBssDesc) ( eSIR_11A_NW_TYPE == (pBssDesc)->nwType )
+#define CSR_IS_BASIC_RATE(rate) ((rate) & CSR_DOT11_BASIC_RATE_MASK)
+#define CSR_IS_QOS_BSS(pIes) ( (pIes)->WMMParams.present || (pIes)->WMMInfoAp.present )
+
+#define CSR_IS_UAPSD_BSS(pIes) \
+ ( ((pIes)->WMMParams.present && ((pIes)->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD)) || \
+ ((pIes)->WMMInfoAp.present && (pIes)->WMMInfoAp.uapsd) )
+
+//This macro returns the total length needed of Tlv with with len bytes of data
+#define GET_TLV_MSG_LEN(len) GET_ROUND_UP((sizeof(tCsrCfgMsgTlvHdr) + (len)), sizeof(tANI_U32))
+
+tANI_BOOLEAN csrGetBssIdBssDesc( tHalHandle hHal, tSirBssDescription *pSirBssDesc, tCsrBssid *pBssId );
+tANI_BOOLEAN csrIsBssIdEqual( tHalHandle hHal, tSirBssDescription *pSirBssDesc1, tSirBssDescription *pSirBssDesc2 );
+
+eCsrMediaAccessType csrGetQoSFromBssDesc( tHalHandle hHal, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes);
+tANI_BOOLEAN csrIsNULLSSID( tANI_U8 *pBssSsid, tANI_U8 len );
+tANI_BOOLEAN csrIsInfraBssDesc( tSirBssDescription *pSirBssDesc );
+tANI_BOOLEAN csrIsIbssBssDesc( tSirBssDescription *pSirBssDesc );
+tANI_BOOLEAN csrIsPrivacy( tSirBssDescription *pSirBssDesc );
+tSirResultCodes csrGetDisassocRspStatusCode( tSirSmeDisassocRsp *pSmeDisassocRsp );
+tSirResultCodes csrGetDeAuthRspStatusCode( tSirSmeDeauthRsp *pSmeRsp );
+tANI_U32 csrGetFragThresh( tHalHandle hHal );
+tANI_U32 csrGetRTSThresh( tHalHandle hHal );
+eCsrPhyMode csrGetPhyModeFromBssDesc( tSirBssDescription *pSirBssDesc );
+tANI_U32 csrGet11hPowerConstraint( tHalHandle hHal, tDot11fIEPowerConstraints *pPowerConstraint );
+tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrRSNIe *pRSNIe );
+tANI_U8 csrConstructWpaIe( tHalHandle hHal, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe );
+#ifdef FEATURE_WLAN_WAPI
+
+tANI_BOOLEAN csrIsProfileWapi( tCsrRoamProfile *pProfile );
+#endif /* FEATURE_WLAN_WAPI */
+//If a WPAIE exists in the profile, just use it. Or else construct one from the BSS
+//Caller allocated memory for pWpaIe and guarrantee it can contain a max length WPA IE
+tANI_U8 csrRetrieveWpaIe( tHalHandle hHal, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe );
+tANI_BOOLEAN csrIsSsidEqual( tHalHandle hHal, tSirBssDescription *pSirBssDesc1,
+ tSirBssDescription *pSirBssDesc2, tDot11fBeaconIEs *pIes2 );
+//Null ssid means match
+tANI_BOOLEAN csrIsSsidInList( tHalHandle hHal, tSirMacSSid *pSsid, tCsrSSIDs *pSsidList );
+tANI_BOOLEAN csrIsProfileWpa( tCsrRoamProfile *pProfile );
+tANI_BOOLEAN csrIsProfileRSN( tCsrRoamProfile *pProfile );
+//This function returns the raw byte array of WPA and/or RSN IE
+tANI_BOOLEAN csrGetWpaRsnIe( tHalHandle hHal, tANI_U8 *pIes, tANI_U32 len,
+ tANI_U8 *pWpaIe, tANI_U8 *pcbWpaIe, tANI_U8 *pRSNIe, tANI_U8 *pcbRSNIe);
+//If a RSNIE exists in the profile, just use it. Or else construct one from the BSS
+//Caller allocated memory for pWpaIe and guarrantee it can contain a max length WPA IE
+tANI_U8 csrRetrieveRsnIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes, tCsrRSNIe *pRsnIe );
+#ifdef FEATURE_WLAN_WAPI
+//If a WAPI IE exists in the profile, just use it. Or else construct one from the BSS
+//Caller allocated memory for pWapiIe and guarrantee it can contain a max length WAPI IE
+tANI_U8 csrRetrieveWapiIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe );
+#endif /* FEATURE_WLAN_WAPI */
+tANI_BOOLEAN csrSearchChannelListForTxPower(tHalHandle hHal, tSirBssDescription *pBssDescription, tCsrChannelSet *returnChannelGroup);
+tANI_BOOLEAN csrRatesIsDot11Rate11bSupportedRate( tANI_U8 dot11Rate );
+tANI_BOOLEAN csrRatesIsDot11Rate11aSupportedRate( tANI_U8 dot11Rate );
+tAniEdType csrTranslateEncryptTypeToEdType( eCsrEncryptionType EncryptType );
+//pIes shall contain IEs from pSirBssDesc. It shall be returned from function csrGetParsedBssDescriptionIEs
+tANI_BOOLEAN csrIsSecurityMatch( tHalHandle hHal, tCsrAuthList *authType, tCsrEncryptionList *pUCEncryptionType, tCsrEncryptionList *pMCEncryptionType,
+ tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes,
+ eCsrAuthType *negotiatedAuthtype, eCsrEncryptionType *negotiatedUCCipher, eCsrEncryptionType *negotiatedMCCipher );
+tANI_BOOLEAN csrIsBSSTypeMatch(eCsrRoamBssType bssType1, eCsrRoamBssType bssType2);
+tANI_BOOLEAN csrIsBssTypeIBSS(eCsrRoamBssType bssType);
+tANI_BOOLEAN csrIsBssTypeWDS(eCsrRoamBssType bssType);
+//ppIes can be NULL. If caller want to get the *ppIes allocated by this function, pass in *ppIes = NULL
+//Caller needs to free the memory in this case
+tANI_BOOLEAN csrMatchBSS( tHalHandle hHal, tSirBssDescription *pBssDesc, tCsrScanResultFilter *pFilter,
+ eCsrAuthType *pNegAuth, eCsrEncryptionType *pNegUc, eCsrEncryptionType *pNegMc,
+ tDot11fBeaconIEs **ppIes);
+
+tANI_BOOLEAN csrIsBssidMatch( tHalHandle hHal, tCsrBssid *pProfBssid, tCsrBssid *BssBssid );
+tANI_BOOLEAN csrMatchBSSToConnectProfile( tHalHandle hHal, tCsrRoamConnectedProfile *pProfile,
+ tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes );
+tANI_BOOLEAN csrRatesIsDot11RateSupported( tHalHandle hHal, tANI_U8 rate );
+tANI_U16 csrRatesFindBestRate( tSirMacRateSet *pSuppRates, tSirMacRateSet *pExtRates, tSirMacPropRateSet *pPropRates );
+tSirBssType csrTranslateBsstypeToMacType(eCsrRoamBssType csrtype);
+
+//Caller allocates memory for pIEStruct
+eHalStatus csrParseBssDescriptionIEs(tHalHandle hHal, tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIEStruct);
+//This function will allocate memory for the parsed IEs to the caller. Caller must free the memory
+//after it is done with the data only if this function succeeds
+eHalStatus csrGetParsedBssDescriptionIEs(tHalHandle hHal, tSirBssDescription *pBssDesc, tDot11fBeaconIEs **ppIEStruct);
+
+tANI_BOOLEAN csrValidateCountryString( tHalHandle hHal, tANI_U8 *pCountryString );
+tSirScanType csrGetScanType(tpAniSirGlobal pMac, tANI_U8 chnId);
+
+tANI_U8 csrToUpper( tANI_U8 ch );
+eHalStatus csrGetPhyModeFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBSSDescription,
+ eCsrPhyMode *pPhyMode, tDot11fBeaconIEs *pIes);
+
+//fForce -- force reassoc regardless of whether there is any change
+//The reason is that for UAPSD-bypass, the code underneath this call determine whether
+//to allow UAPSD. The information in pModProfileFields reflects what the user wants.
+//There may be discrepency in it. UAPSD-bypass logic should decide if it needs to reassoc
+eHalStatus csrReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tCsrRoamModifyProfileFields *pModProfileFields,
+ tANI_U32 *pRoamId, v_BOOL_t fForce);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+tANI_BOOLEAN csrIsProfile11r( tCsrRoamProfile *pProfile );
+tANI_BOOLEAN csrIsAuthType11r( eCsrAuthType AuthType );
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+tANI_BOOLEAN csrIsAuthTypeCCX( eCsrAuthType AuthType );
+tANI_BOOLEAN csrIsProfileCCX( tCsrRoamProfile *pProfile );
+#endif
+
+#endif
+
diff --git a/CORE/SME/inc/measApi.h b/CORE/SME/inc/measApi.h
new file mode 100644
index 0000000..1e9b029
--- /dev/null
+++ b/CORE/SME/inc/measApi.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
diff --git a/CORE/SME/inc/measInternal.h b/CORE/SME/inc/measInternal.h
new file mode 100644
index 0000000..1e9b029
--- /dev/null
+++ b/CORE/SME/inc/measInternal.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
diff --git a/CORE/SME/inc/p2p_Api.h b/CORE/SME/inc/p2p_Api.h
new file mode 100644
index 0000000..13276de
--- /dev/null
+++ b/CORE/SME/inc/p2p_Api.h
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/******************************************************************************
+*
+* Name: p2p_Api.h
+*
+* Description: P2P FSM defines.
+*
+* Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+* Qualcomm Confidential and Proprietary.
+*
+******************************************************************************/
+
+#ifndef __P2P_API_H__
+#define __P2P_API_H__
+
+#include "vos_types.h"
+#include "halTypes.h"
+#include "palTimer.h"
+#include "vos_lock.h"
+
+typedef struct sP2pPsConfig{
+ tANI_U8 opp_ps;
+ tANI_U32 ctWindow;
+ tANI_U8 count;
+ tANI_U32 duration;
+ tANI_U32 interval;
+ tANI_U32 single_noa_duration;
+ tANI_U8 psSelection;
+ tANI_U8 sessionid;
+}tP2pPsConfig,*tpP2pPsConfig;
+
+typedef eHalStatus (*remainOnChanCallback)( tHalHandle, void* context,
+ eHalStatus status );
+
+typedef struct sRemainOnChn{
+ tANI_U8 chn;
+ tANI_U32 duration;
+ remainOnChanCallback callback;
+ void *pCBContext;
+}tRemainOnChn, tpRemainOnChn;
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+
+#define MAX_SOCIAL_CHANNELS 3
+#define P2P_OPERATING_CHANNEL 6
+#define P2P_MAX_GROUP_LIMIT 5
+#define P2P_MAC_ADDRESS_LEN 6
+#define MAX_LISTEN_SEARCH_CYCLE 3
+#define P2P_LISTEN_TIMEOUT_AUTO 500 //0.5 sec
+#define P2P_LISTEN_TIMEOUT_HIGH 200 //0.4 sec
+#define P2P_LISTEN_TIMEOUT 1000 //1 sec
+#define P2P_REMAIN_ON_CHAN_TIMEOUT 300
+#define P2P_REMAIN_ON_CHAN_TIMEOUT_HIGH 1000
+#define P2P_REMAIN_ON_CHAN_TIMEOUT_LOW 100
+#define ACTION_FRAME_RETRY_TIMEOUT 50
+#define P2P_COUNTRY_CODE_LEN 3
+
+#define P2P_CLEAR_POWERSAVE 0
+#define P2P_OPPORTUNISTIC_PS 1
+#define P2P_PERIODIC_NOA 2
+#define P2P_SINGLE_NOA 4
+
+
+/* Wi-Fi Direct Device Discovery Type */
+typedef enum ep2pDiscoverType {
+ /** Driver must perform device discovery only using the scan phase*/
+ WFD_DISCOVER_TYPE_SCAN_ONLY = 1,
+ /** Driver must perform device discovery only using the find phase*/
+ WFD_DISCOVER_TYPE_FIND_ONLY = 2,
+ /** Driver can use either use scan phase or find phase to discovery
+ P2P devices. In our case Driver uses scan phase */
+ WFD_DISCOVER_TYPE_AUTO = 3,
+ /*Scan only social channel*/
+ WFD_DISCOVER_SCAN_ONLY_SOCIAL_CHN,
+ /** If it is set, driver must perform a complete discovery,
+ If it is false, it can do partial discovery.*/
+ WFD_DISCOVER_TYPE_FORCED = 0x80000000
+} ep2pDiscoverType, *ePp2pDiscoverType;
+
+//bit mask for what to discover
+#define QCWLAN_P2P_DISCOVER_DEVICE 0x1
+#define QCWLAN_P2P_DISCOVER_GO 0x2
+#define QCWLAN_P2P_DISCOVER_ANY 0x8
+
+#define P2P_DISCOVER_SCAN_ONLY(t) ( (WFD_DISCOVER_TYPE_SCAN_ONLY == (t)) \
+ || (WFD_DISCOVER_SCAN_ONLY_SOCIAL_CHN == (t)) )
+
+/* Scan Type */
+typedef enum ep2pScanType {
+ P2P_SCAN_TYPE_ACTIVE = 1, /** device should perform active scans for the scan phase of device discovery */
+ P2P_SCAN_TYPE_PASSIVE = 2, /** device should perform passive scanning for the scan phase of device discovery */
+ P2P_SCAN_TYPE_AUTO = 3 /** The selection of the scan type is upto the driver */
+} ep2pScanType, * ePp2pScanType;
+
+/** Listen State Discoverability */
+typedef enum ep2pListenStateDiscoverability {
+ P2P_DEVICE_NOT_DISCOVERABLE, /** Wi-Fi Direct Device Port must not make itself discoverable */
+ P2P_DEVICE_AUTO_AVAILABILITY, /** Wi-Fi Direct Device Port must periodically put itself in the listen state to become discoverable*/
+ P2P_DEVICE_HIGH_AVAILABILITY /** Wi-Fi Direct Device Port must be frequently put itself in the listen state
+ to increase the speed and reliability of remote devices discovering it */
+} ep2pListenStateDiscoverability, * ePp2pListenStateDiscoverability;
+
+typedef enum ep2pOperatingMode {
+ OPERATION_MODE_INVALID,
+ OPERATION_MODE_P2P_DEVICE,
+ OPERATION_MODE_P2P_GROUP_OWNER,
+ OPERATION_MODE_P2P_CLIENT
+}ep2pOperatingMode;
+
+typedef struct _tp2pDiscoverDeviceFilter{
+ tSirMacAddr DeviceID;
+ v_UCHAR_t ucBitmask;
+ tSirMacSSid GroupSSID;
+} tp2pDiscoverDeviceFilter;
+
+typedef struct _tp2pDiscoverRequest {
+ ep2pDiscoverType discoverType;
+ ep2pScanType scanType;
+ tANI_U32 uDiscoverTimeout;
+ tANI_U32 uNumDeviceFilters;
+ tp2pDiscoverDeviceFilter *pDeviceFilters;
+ tANI_BOOLEAN bForceScanLegacyNetworks;
+ tANI_U32 uNumOfLegacySSIDs;
+ tANI_U8 *pLegacySSIDs;
+ tANI_U32 uIELen;
+ tANI_U8 *pIEField;
+} tP2PDiscoverRequest;
+
+typedef enum _eP2PDiscoverStatus {
+ eP2P_DISCOVER_SUCCESS,
+ eP2P_DISCOVER_FAILURE,
+ eP2P_DISCOVER_ABORT,
+ eP2P_DIRECTED_DISCOVER
+} eP2PDiscoverStatus;
+
+typedef eHalStatus (*p2pDiscoverCompleteCallback)(tHalHandle hHal, void *pContext, eP2PDiscoverStatus discoverStatus);
+
+typedef struct sP2PGroupId {
+ tANI_U8 present;
+ tANI_U8 deviceAddress[6];
+ tANI_U8 num_ssid;
+ tANI_U8 ssid[32];
+} tP2PGroupId;
+
+typedef struct sP2PGroupBssid {
+ tANI_U8 present;
+ tANI_U8 P2PGroupBssid[6];
+} tP2PGroupBssid;
+
+typedef struct sP2PChannel {
+ tANI_U8 present;
+ tANI_U8 countryString[P2P_COUNTRY_CODE_LEN];
+ tANI_U8 regulatoryClass;
+ tANI_U8 channel;
+} tP2P_OperatingChannel, tP2P_ListenChannel;
+
+/** Structure contains parameters required for Wi-Fi Direct Device functionality such as device discovery, Group Owner Negotiation */
+typedef enum P2PFrameType {
+ eP2P_INVALID_FRM,
+ eP2P_PROBE_REQ,
+ eP2P_PROBE_RSP,
+ eP2P_GONEGO_REQ,
+ eP2P_GONEGO_RES,
+ eP2P_GONEGO_CNF,
+ eP2P_PROVISION_DISCOVERY_REQUEST,
+ eP2P_PROVISION_DISCOVERY_RESPONSE,
+ eP2P_BEACON,
+ eP2P_GROUP_ID,
+ eP2P_ASSOC_REQ,
+ eP2P_INVITATION_REQ,
+ eP2P_INVITATION_RSP,
+ eP2P_DEVICE_DISCOVERY_REQ,
+ eP2P_DEVICE_DISCOVERY_RSP,
+} eP2PFrameType;
+
+typedef enum P2PRequest {
+ eWFD_DISCOVER_REQUEST,
+ eWFD_DEVICE_ID,
+ eWFD_DEVICE_CAPABILITY,
+ eWFD_GROUP_OWNER_CAPABILITY,
+ eWFD_DEVICE_INFO,
+ eWFD_SECONDARY_DEVICE_TYPE_LIST,
+ eWFD_ADDITIONAL_IE,
+ eWFD_GROUP_ID,
+ eWFD_SEND_GO_NEGOTIATION_REQUEST,
+ eWFD_SEND_GO_NEGOTIATION_RESPONSE,
+ eWFD_SEND_GO_NEGOTIATION_CONFIRMATION,
+ eWFD_SEND_PROVISION_DISCOVERY_REQUEST,
+ eWFD_SEND_PROVISION_DISCOVERY_RESPONSE,
+ eWFD_SEND_INVITATION_REQUEST,
+ eWFD_SEND_INVITATION_RESPONSE,
+ eWFD_OPERATING_CHANNEL,
+ eWFD_LISTEN_CHANNEL
+} eP2PRequest;
+
+typedef struct _p2p_device_capability_config {
+ tANI_BOOLEAN bServiceDiscoveryEnabled;
+ tANI_BOOLEAN bClientDiscoverabilityEnabled;
+ tANI_BOOLEAN bConcurrentOperationSupported;
+ tANI_BOOLEAN bInfrastructureManagementEnabled;
+ tANI_BOOLEAN bDeviceLimitReached;
+ tANI_BOOLEAN bInvitationProcedureEnabled;
+ tANI_U32 WPSVersionsEnabled;
+} tp2p_device_capability_config;
+
+typedef struct _p2p_group_owner_capability_config {
+ tANI_BOOLEAN bPersistentGroupEnabled;
+ tANI_BOOLEAN bIntraBSSDistributionSupported;
+ tANI_BOOLEAN bCrossConnectionSupported;
+ tANI_BOOLEAN bPersistentReconnectSupported;
+ tANI_BOOLEAN bGroupFormationEnabled;
+ tANI_U32 uMaximumGroupLimit;
+} tp2p_group_owner_capability_config;
+
+typedef struct _tP2P_ProvDiscoveryReq {
+ tANI_U8 dialogToken;
+ tANI_U8 PeerDeviceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U32 uSendTimeout;
+ tANI_U8 GroupCapability;
+ tP2PGroupId GroupId;
+ tANI_BOOLEAN bUseGroupID;
+ tANI_U32 uIELength;
+ tANI_U8 *IEdata;
+} tP2P_ProvDiscoveryReq;
+
+typedef struct _tP2P_ProvDiscoveryRes {
+ tANI_U8 dialogToken;
+ tANI_U8 ReceiverDeviceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U32 uSendTimeout;
+ tANI_U32 uIELength;
+ tANI_U8 *IEdata;
+} tP2P_ProvDiscoveryRes;
+
+typedef struct p2p_go_request {
+ tANI_U8 dialogToken;
+ tANI_U8 peerDeviceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U32 uSendTimeout;
+ tANI_U8 GoIntent;
+ tANI_U32 GoTimeout;
+ tANI_U32 ClientTimeout;
+ tANI_U8 IntendedInterfaceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U8 GroupCapability;
+ tANI_U32 uIELength;
+ tANI_U8 *IEdata;
+} tP2P_go_request;
+
+typedef struct p2p_go_confirm {
+ tANI_U8 peerDeviceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U8 dialog_token;
+ tANI_U32 uSendTimeout;
+ tANI_U8 status;
+ tANI_U8 GroupCapability;
+ tP2PGroupId GroupId;
+ tANI_BOOLEAN bUsedGroupId;
+ tANI_U32 uIELength;
+ tANI_U8 *IEdata;
+} tP2P_go_confirm;
+
+typedef struct p2p_go_response {
+ tANI_U8 peerDeviceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U8 dialog_token;
+ tANI_U32 uSendTimeout;
+ tANI_U8 status;
+ tANI_U8 GoIntent;
+ tANI_U32 GoTimeout;
+ tANI_U32 ClientTimeout;
+ tANI_U8 IntendedInterfaceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U8 GroupCapability;
+ tP2PGroupId GroupId;
+ tANI_BOOLEAN bUsedGroupId;
+ tANI_U32 uIELength;
+ tANI_U8 *IEdata;
+} tP2P_go_response;
+
+//Invitation Req parameters
+typedef struct p2p_invitation_request {
+ tANI_U8 DialogToken;
+ tANI_U8 PeerDeviceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U32 uSendTimeout;
+ tANI_U32 GoTimeout;
+ tANI_U32 ClientTimeout;
+ tANI_U8 InvitationFlags;
+ tP2PGroupBssid GroupBSSID;
+ tP2P_OperatingChannel OperatingChannel;
+ tP2PGroupId GroupID;
+ tANI_U32 uIELength;
+ tANI_U8 *IEdata;
+} tP2P_invitation_request;
+
+
+//Invitation Response parameters
+typedef struct p2p_invitation_response {
+ tANI_U8 ReceiverDeviceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U8 DialogToken;
+ void* RequestContext;
+ tANI_U32 uSendTimeout;
+ tANI_U8 status;
+ tANI_U32 GoTimeout;
+ tANI_U32 ClientTimeout;
+ tP2PGroupBssid GroupBSSID;
+ tP2P_OperatingChannel OperatingChannel;
+ tANI_U32 uIELength;
+ tANI_U8 *IEdata;
+} tP2P_invitation_response;
+
+typedef enum eOUISubType {
+ eOUI_P2P_GONEGO_REQ,
+ eOUI_P2P_GONEGO_RES,
+ eOUI_P2P_GONEGO_CNF,
+ eOUI_P2P_INVITATION_REQ,
+ eOUI_P2P_INVITATION_RES,
+ eOUI_P2P_DEVICE_DISCOVERABILITY_REQ,
+ eOUI_P2P_DEVICE_DISCOVERABILITY_RES,
+ eOUI_P2P_PROVISION_DISCOVERY_REQ,
+ eOUI_P2P_PROVISION_DISCOVERY_RES,
+ eOUI_P2P_INVALID
+}eOUISubType;
+
+typedef enum _eP2PPort {
+ eP2PPortDevice,
+ eP2PPortGroupOwner,
+ eP2PPortClient
+} eP2PPort;
+
+typedef enum eListenDiscoverableState {
+ eStateDisabled,
+ eStateEnabled,
+
+}eListenDiscoverableState;
+
+typedef enum P2PRemainOnChnReason
+{
+ eP2PRemainOnChnReasonUnknown,
+ eP2PRemainOnChnReasonDiscovery, //Part of the discovery (search and listen)
+ eP2PRemainOnChnReasonSendFrame, //Found peer and before sending request frame
+ eP2PRemainOnChnReasonListen, //In listen-only mode
+}eP2PRemainOnChnReason;
+
+typedef struct sGroupFormationReq {
+ tCsrBssid deviceAddress;
+ tANI_U8 targetListenChannel;
+ tANI_U8 persistent_group;
+ tANI_U8 group_limit; /* may be internal */
+ tANI_U8 GO_config_timeout;
+ tANI_U8 CL_config_timeout;
+ tANI_U8 GO_intent;
+ tANI_U16 devicePasswdId;
+ tSirMacAddr groupBssid;
+ tSirMacSSid groupSsid;
+}tGroupFormationReq;
+
+typedef struct tP2PConfigParam
+{
+ v_U32_t P2POperatingChannel;
+ v_U32_t P2PListenChannel;
+ v_U32_t P2PPSSelection;
+ v_U32_t P2POpPSCTWindow;
+ v_U32_t P2PNoADuration;
+ v_U32_t P2PNoACount;
+ v_U32_t P2PNoAInterval;
+}tP2PConfigParam;
+
+#endif
+
+typedef struct sp2pContext
+{
+ v_CONTEXT_t vosContext;
+ tHalHandle hHal;
+ tANI_U8 sessionId; //Session id corresponding to P2P. On windows it is same as HDD sessionid not sme sessionid.
+ tANI_U8 SMEsessionId;
+ tANI_U8 probeReqForwarding;
+ tANI_U8 *probeRspIe;
+ tANI_U32 probeRspIeLength;
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ tANI_U8 numClients;
+ tANI_U32 maxGroupLimit;
+ ep2pOperatingMode operatingmode;
+ tANI_U8 state;
+ tANI_U8 socialChannel[MAX_SOCIAL_CHANNELS];
+ tANI_U8 currentSearchIndex;
+ tANI_U8 listenIndex;
+ tANI_U8 dialogToken;
+ tANI_U8 receivedDialogToken;
+ eOUISubType actionFrameOUI;
+ eP2PFrameType actionFrameType;
+ tANI_BOOLEAN actionFrameTimeout;
+ tANI_U8 *pSentActionFrame;
+ tANI_U32 ActionFrameLen;
+ tANI_U32 ActionFrameSendTimeout;
+ eListenDiscoverableState listenDiscoverableState;
+ tPalTimerHandle listenTimerHandler;
+ tPalTimerHandle WPSRegistrarCheckTimerHandler;
+ tANI_U32 WPSRegistrarSet;
+ tANI_U8 bWaitForWPSReady;
+ tANI_U8 bInGroupFormation;
+ tPalTimerHandle discoverTimer;
+ tPalTimerHandle retryActionFrameTimer;
+ tPalTimerHandle actionFrameTimer;
+ tPalTimerHandle nextActionFrameTimer;
+ tANI_U8 peerMacAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U8 selfMacAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U8 ReceiverDeviceAddress[P2P_MAC_ADDRESS_LEN];
+ tANI_U8 listen_search_cycle;
+ ep2pDiscoverType discoverType;
+ ep2pScanType scanType;
+ tANI_U32 uDiscoverTimeout;
+ tp2pDiscoverDeviceFilter *directedDiscoveryFilter;
+ tANI_U32 uNumDeviceFilters;
+ //Number of deviceFilter directedDiscoveryFilter holds
+ tANI_U32 uNumDeviceFilterAllocated;
+ tGroupFormationReq formationReq;
+ tANI_U8 GroupFormationPending;
+ tANI_BOOLEAN PeerFound;
+ tANI_BOOLEAN directedDiscovery;
+ tANI_U32 listenDuration;
+ tANI_U32 expire_time;
+ p2pDiscoverCompleteCallback p2pDiscoverCBFunc;
+ void *pContext;
+ tANI_BOOLEAN bForceScanLegacyNetworks;
+ tANI_U8 *DiscoverReqIeField;
+ tANI_U32 DiscoverReqIeLength;
+ tANI_U8 *GoNegoReqIeField;
+ tANI_U32 GoNegoReqIeLength;
+ tANI_U8 *GoNegoResIeField;
+ tANI_U32 GoNegoResIeLength;
+ tANI_U8 *GoNegoCnfIeField;
+ tANI_U32 GoNegoCnfIeLength;
+ tANI_U8 *ProvDiscReqIeField;
+ tANI_U32 ProvDiscReqIeLength;
+ tANI_U8 *ProvDiscResIeField;
+ tANI_U32 ProvDiscResIeLength;
+ tANI_U8 *InvitationReqIeField;
+ tANI_U32 InvitationReqIeLength;
+ tANI_U8 *InvitationResIeField;
+ tANI_U32 InvitationResIeLength;
+ tANI_U32 DiscoverableCfg;
+ vos_spin_lock_t lState;
+ tANI_U8 *pNextActionFrm;
+ tANI_U32 nNextFrmLen;
+ tANI_U32 nNextFrameTimeOut;
+ eP2PFrameType NextActionFrameType;
+ tANI_U8 ssid[32];
+ v_U32_t P2PListenChannel;
+ v_U32_t P2POperatingChannel;
+ tP2pPsConfig pNoA;
+ tANI_U8 OriginalGroupCapability;
+#endif
+} tp2pContext, *tPp2pContext;
+
+
+eHalStatus sme_RemainOnChannel( tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U8 channel, tANI_U32 duration,
+ remainOnChanCallback callback,
+ void *pContext );
+eHalStatus sme_ReportProbeReq( tHalHandle hHal, tANI_U8 flag );
+eHalStatus sme_updateP2pIe( tHalHandle hHal, void *p2pIe,
+ tANI_U32 p2pIeLength );
+eHalStatus sme_sendAction( tHalHandle hHal, tANI_U8 sessionId,
+ const tANI_U8 *pBuf, tANI_U32 len );
+eHalStatus sme_CancelRemainOnChannel( tHalHandle hHal, tANI_U8 sessionId );
+eHalStatus sme_p2pOpen( tHalHandle hHal );
+eHalStatus p2pStop( tHalHandle hHal );
+eHalStatus sme_p2pClose( tHalHandle hHal );
+eHalStatus sme_p2pSetPs( tHalHandle hHal, tP2pPsConfig * data );
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+eHalStatus p2pRemainOnChannel( tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U8 channel, tANI_U32 duration,
+ remainOnChanCallback callback, void *pContext,
+ eP2PRemainOnChnReason reason);
+#else
+eHalStatus p2pRemainOnChannel( tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U8 channel, tANI_U32 duration,
+ remainOnChanCallback callback, void *pContext);
+#endif
+eHalStatus p2pSendAction( tHalHandle hHal, tANI_U8 sessionId,
+ const tANI_U8 *pBuf, tANI_U32 len );
+eHalStatus p2pCancelRemainOnChannel( tHalHandle hHal, tANI_U8 sessionId );
+eHalStatus p2pSetPs( tHalHandle hHal, tP2pPsConfig *pNoA );
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+eHalStatus p2pRemainOnChannelCallback(tHalHandle halHandle, void *pContext, eHalStatus scan_status);
+eHalStatus P2P_DiscoverRequest(tHalHandle hHal, tANI_U8 SessionID, tP2PDiscoverRequest *pDiscoverRequest,
+ p2pDiscoverCompleteCallback callback, void *pContext);
+tANI_U8 p2pGetDialogToken(tHalHandle hHal, tANI_U8 SessionID, eP2PFrameType actionFrameType);
+eHalStatus P2P_ListenStateDiscoverable(tHalHandle hHal, tANI_U8 sessionId, ep2pListenStateDiscoverability listenState);
+eHalStatus p2pCreateSendActionFrame(tHalHandle hHal, tANI_U8 SessionID,
+ void *p2pactionframe, eP2PFrameType actionFrameType, tANI_U32 timeout);
+eHalStatus p2pScanRequest(tp2pContext *p2pContext, p2pDiscoverCompleteCallback callback, void *pContext);
+void p2pActionFrameTimerHandler(void *pContext);
+void p2pListenDiscoverTimerHandler(void *pContext);
+void p2pDiscoverTimerHandler(void *pContext);
+void p2pRetryActionFrameTimerHandler(void *pContext);
+eHalStatus p2pGrpFormationRemainOnChanRspCallback(tHalHandle halHandle, void *pContext, tANI_U32 scanId, eCsrScanStatus scan_status);
+eHalStatus p2pChangeDefaultConfigParam(tHalHandle hHal, tP2PConfigParam *pParam);
+eHalStatus p2pGetConfigParam(tHalHandle hHal, tP2PConfigParam *pParam);
+eHalStatus p2pPS(tHalHandle hHal, tANI_U8 sessionId);
+eHalStatus p2pCloseSession(tHalHandle hHal, tANI_U8 SessionID);
+eHalStatus p2pSetSessionId(tHalHandle hHal, tANI_U8 SessionID, tANI_U8 SmeSessionId);
+tANI_BOOLEAN p2pIsOperatingChannEqualListenChann(tHalHandle hHal, tANI_U8 SessionID);
+eHalStatus p2pGetListenChannel(tHalHandle hHal, tANI_U8 SessionID, tANI_U8 *channel);
+eHalStatus p2pSetListenChannel(tHalHandle hHal, tANI_U8 SessionID, tANI_U8 channel);
+eHalStatus p2pStopDiscovery(tHalHandle hHal, tANI_U8 SessionID);
+tANI_U8 getP2PSessionIdFromSMESessionId(tHalHandle hHal, tANI_U8 SessionID);
+void p2pCallDiscoverCallback(tp2pContext *p2pContext, eP2PDiscoverStatus statusCode);
+eHalStatus p2pGetResultFilter(tp2pContext *pP2pContext,
+ tCsrScanResultFilter *pFilter);
+#endif//INTERNAL
+#endif //__P2P_API_H__
diff --git a/CORE/SME/inc/pmc.h b/CORE/SME/inc/pmc.h
new file mode 100644
index 0000000..e2e3c7f
--- /dev/null
+++ b/CORE/SME/inc/pmc.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/******************************************************************************
+*
+* Name: pmc.h
+*
+* Description: Power Management Control (PMC) internal definitions.
+*
+* Copyright 2008 (c) Qualcomm, Incorporated.
+ All Rights Reserved.
+* Qualcomm Confidential and Proprietary.
+*
+******************************************************************************/
+
+#ifndef __PMC_H__
+#define __PMC_H__
+
+
+#include "palTimer.h"
+#include "csrLinkList.h"
+#include "pmcApi.h"
+#include "smeInternal.h"
+
+
+//Change PMC_ABORT to no-op for now. We need to define it as VOS_ASSERT(0) once we
+//cleanup the usage.
+#define PMC_ABORT
+
+/* Host power sources. */
+typedef enum ePowerSource
+{
+ AC_POWER, /* host is operating from AC power */
+ BATTERY_POWER /* host is operating from battery power */
+} tPowerSource;
+
+
+/* Power save check routine list entry. */
+typedef struct sPowerSaveCheckEntry
+{
+ tListElem link; /* list links */
+ tANI_BOOLEAN (*checkRoutine) (void *checkContext); /* power save check routine */
+ void *checkContext; /* value to be passed as parameter to routine specified above */
+} tPowerSaveCheckEntry, *tpPowerSaveCheckEntry;
+
+
+/* Device Power State update indication list entry. */
+typedef struct sDeviceStateUpdateIndEntry
+{
+ tListElem link; /* list links */
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState); /* Callback routine to be invoked when pmc changes device state */
+ void *callbackContext; /* value to be passed as parameter to routine specified above */
+} tDeviceStateUpdateIndEntry, *tpDeviceStateUpdateIndEntry;
+
+/* Request full power callback routine list entry. */
+typedef struct sRequestFullPowerEntry
+{
+ tListElem link; /* list links */
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status); /* routine to call when full power is restored */
+ void *callbackContext; /* value to be passed as parameter to routine specified above */
+} tRequestFullPowerEntry, *tpRequestFullPowerEntry;
+
+
+/* Request BMPS callback routine list entry. */
+typedef struct sRequestBmpsEntry
+{
+ tListElem link; /* list links */
+
+ /* routine to call when BMPS request succeeded/failed */
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status);
+
+ /* value to be passed as parameter to routine specified above */
+ void *callbackContext;
+
+} tRequestBmpsEntry, *tpRequestBmpsEntry;
+
+
+/* Start U-APSD callback routine list entry. */
+typedef struct sStartUapsdEntry
+{
+ tListElem link; /* list links */
+
+ /* routine to call when Uapsd Start succeeded/failed*/
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status);
+
+ /* value to be passed as parameter to routine specified above */
+ void *callbackContext;
+
+} tStartUapsdEntry, *tpStartUapsdEntry;
+
+typedef struct sPmcDeferredMsg
+{
+ tListElem link;
+ tpAniSirGlobal pMac;
+ tANI_U16 messageType;
+ tANI_U16 size; //number of bytes in u.data
+ union
+ {
+ tSirPowerSaveCfg powerSaveConfig;
+ tSirWowlAddBcastPtrn wowlAddPattern;
+ tSirWowlDelBcastPtrn wowlDelPattern;
+ tANI_U8 data[1]; //a place holder
+ }u;
+} tPmcDeferredMsg;
+
+
+
+/* Current PMC information for a particular device. */
+typedef struct sPmcInfo
+{
+ tPowerSource powerSource; /* host power source */
+ tPmcSwitchState hwWlanSwitchState; /* Hardware WLAN Switch state */
+ tPmcSwitchState swWlanSwitchState; /* Software WLAN Switch state */
+ tPmcState pmcState; /* PMC state */
+ tANI_BOOLEAN requestFullPowerPending; /* TRUE if a request for full power is pending */
+ tRequestFullPowerReason requestFullPowerReason; /* reason for requesting full power */
+ tPmcImpsConfigParams impsConfig; /* IMPS configuration */
+ tPmcBmpsConfigParams bmpsConfig; /* BMPS configuration */
+ tPmcSmpsConfigParams smpsConfig; /* SMPS configuration */
+ tANI_BOOLEAN impsEnabled; /* TRUE if IMPS is enabled */
+ tANI_BOOLEAN bmpsEnabled; /* TRUE if BMPS is enabled */
+ tANI_BOOLEAN autoBmpsEntryEnabled; /* TRUE if auto BMPS entry is enabled. If set to TRUE, PMC will
+ attempt to put the device into BMPS on entry into full Power */
+ tANI_BOOLEAN bmpsRequestedByHdd; /*TRUE if BMPS mode has been requested by HDD */
+ tANI_BOOLEAN bmpsRequestQueued; /*If a enter BMPS request is queued*/
+ tANI_BOOLEAN smpsEnabled; /* TRUE if SMPS is enabled */
+ tANI_BOOLEAN remainInPowerActiveTillDHCP; /* Remain in Power active till DHCP completes */
+ tANI_U32 remainInPowerActiveThreshold; /*Remain in Power active till DHCP threshold*/
+ tANI_U32 impsPeriod; /* amount of time to remain in IMPS */
+ void (*impsCallbackRoutine) (void *callbackContext, eHalStatus status); /* routine to call when IMPS period
+ has finished */
+ void *impsCallbackContext; /* value to be passed as parameter to routine specified above */
+ tPalTimerHandle hImpsTimer; /* timer to use with IMPS */
+ vos_timer_t hTrafficTimer; /* timer to measure traffic for BMPS */
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ tPalTimerHandle hDiagEvtTimer; /* timer to report PMC state through DIAG event */
+#endif
+ tPalTimerHandle hExitPowerSaveTimer; /* timer for deferred exiting of power save mode */
+ tDblLinkList powerSaveCheckList; /* power save check routine list */
+ tDblLinkList requestFullPowerList; /* request full power callback routine list */
+ tANI_U32 cLastTxUnicastFrames; /* transmit unicast frame count at last BMPS traffic timer expiration */
+ tANI_U32 cLastRxUnicastFrames; /* receive unicast frame count at last BMPS traffic timer expiration */
+
+
+ tANI_BOOLEAN uapsdEnabled; /* TRUE if UAPSD is enabled */
+ tANI_BOOLEAN uapsdSessionRequired; /* TRUE if device should go to UAPSD on entering BMPS*/
+ tDblLinkList requestBmpsList; /* request Bmps callback routine list */
+ tDblLinkList requestStartUapsdList; /* request start Uapsd callback routine list */
+ tANI_BOOLEAN standbyEnabled; /* TRUE if Standby is enabled */
+ void (*standbyCallbackRoutine) (void *callbackContext, eHalStatus status); /* routine to call for standby request */
+ void *standbyCallbackContext;/* value to be passed as parameter to routine specified above */
+ tDblLinkList deviceStateUpdateIndList; /*update device state indication list */
+ tANI_BOOLEAN pmcReady; /*whether eWNI_SME_SYS_READY_IND has been sent to PE or not */
+ tANI_BOOLEAN wowlEnabled; /* TRUE if WoWL is enabled */
+ tANI_BOOLEAN wowlModeRequired; /* TRUE if device should go to WOWL on entering BMPS */
+ void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status); /* routine to call for wowl request */
+ void *enterWowlCallbackContext;/* value to be passed as parameter to routine specified above */
+ tSirSmeWowlEnterParams wowlEnterParams; /* WOWL mode configuration */
+ tDblLinkList deferredMsgList; //The message in here are deferred and DONOT expect response from PE
+ tANI_BOOLEAN rfSuppliesVotedOff; //Whether RF supplies are voted off or not.
+#ifdef FEATURE_WLAN_SCAN_PNO
+ preferredNetworkFoundIndCallback prefNetwFoundCB; /* routine to call for Preferred Network Found Indication */
+ void *preferredNetworkFoundIndCallbackContext;/* value to be passed as parameter to routine specified above */
+#endif // FEATURE_WLAN_SCAN_PNO
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ FilterMatchCountCallback FilterMatchCountCB; /* routine to call for Packet Coalescing Filter Match Count */
+ void *FilterMatchCountCBContext;/* value to be passed as parameter to routine specified above */
+#endif // WLAN_FEATURE_PACKET_FILTERING
+#ifdef WLAN_FEATURE_GTK_OFFLOAD
+ GTKOffloadGetInfoCallback GtkOffloadGetInfoCB; /* routine to call for GTK Offload Information */
+ void *GtkOffloadGetInfoCBContext; /* value to be passed as parameter to routine specified above */
+#endif // WLAN_FEATURE_GTK_OFFLOAD
+
+#ifdef WLAN_WAKEUP_EVENTS
+ void (*wakeReasonIndCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd); /* routine to call for Wake Reason Indication */
+ void *wakeReasonIndCBContext; /* value to be passed as parameter to routine specified above */
+#endif // WLAN_WAKEUP_EVENTS
+} tPmcInfo, *tpPmcInfo;
+
+
+//MACRO
+#define PMC_IS_READY(pMac) ( ((pMac)->pmc.pmcReady) && (STOPPED != (pMac)->pmc.pmcState) )
+
+
+/* Routine definitions. */
+extern eHalStatus pmcEnterLowPowerState (tHalHandle hHal);
+extern eHalStatus pmcExitLowPowerState (tHalHandle hHal);
+extern eHalStatus pmcEnterFullPowerState (tHalHandle hHal);
+extern eHalStatus pmcEnterRequestFullPowerState (tHalHandle hHal, tRequestFullPowerReason fullPowerReason);
+extern eHalStatus pmcEnterRequestImpsState (tHalHandle hHal);
+extern eHalStatus pmcEnterImpsState (tHalHandle hHal);
+extern eHalStatus pmcEnterRequestBmpsState (tHalHandle hHal);
+extern eHalStatus pmcEnterBmpsState (tHalHandle hHal);
+extern eHalStatus pmcEnterRequestStartUapsdState (tHalHandle hHal);
+extern eHalStatus pmcEnterUapsdState (tHalHandle hHal);
+extern eHalStatus pmcEnterRequestStopUapsdState (tHalHandle hHal);
+extern eHalStatus pmcEnterRequestStandbyState (tHalHandle hHal);
+extern eHalStatus pmcEnterStandbyState (tHalHandle hHal);
+extern tANI_BOOLEAN pmcPowerSaveCheck (tHalHandle hHal);
+extern eHalStatus pmcSendPowerSaveConfigMessage (tHalHandle hHal);
+extern eHalStatus pmcSendMessage (tpAniSirGlobal pMac, tANI_U16 messageType, void *pMessageData, tANI_U32 messageSize);
+extern void pmcDoCallbacks (tHalHandle hHal, eHalStatus callbackStatus);
+extern void pmcDoBmpsCallbacks (tHalHandle hHal, eHalStatus callbackStatus);
+extern void pmcDoStartUapsdCallbacks (tHalHandle hHal, eHalStatus callbackStatus);
+extern void pmcDoStandbyCallbacks (tHalHandle hHal, eHalStatus callbackStatus);
+extern eHalStatus pmcStartTrafficTimer (tHalHandle hHal, tANI_U32 expirationTime);
+extern void pmcStopTrafficTimer (tHalHandle hHal);
+extern void pmcImpsTimerExpired (tHalHandle hHal);
+extern void pmcTrafficTimerExpired (tHalHandle hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+extern eHalStatus pmcStartDiagEvtTimer (tHalHandle hHal);
+extern void pmcStopDiagEvtTimer (tHalHandle hHal);
+extern void pmcDiagEvtTimerExpired (tHalHandle hHal);
+#endif
+
+extern void pmcExitPowerSaveTimerExpired (tHalHandle hHal);
+extern tPmcState pmcGetPmcState (tHalHandle hHal);
+extern const char* pmcGetPmcStateStr(tPmcState state);
+extern void pmcDoDeviceStateUpdateCallbacks (tHalHandle hHal, tPmcState state);
+extern eHalStatus pmcRequestEnterWowlState(tHalHandle hHal, tpSirSmeWowlEnterParams wowlEnterParams);
+extern eHalStatus pmcEnterWowlState (tHalHandle hHal);
+extern eHalStatus pmcRequestExitWowlState(tHalHandle hHal);
+extern void pmcDoEnterWowlCallbacks (tHalHandle hHal, eHalStatus callbackStatus);
+//The function will request for full power as well in addition to defer the message
+extern eHalStatus pmcDeferMsg( tpAniSirGlobal pMac, tANI_U16 messageType,
+ void *pData, tANI_U32 size);
+extern eHalStatus pmcIssueCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void *pvParam,
+ tANI_U32 size, tANI_BOOLEAN fPutToListHead );
+extern eHalStatus pmcEnterImpsCheck( tpAniSirGlobal pMac );
+extern eHalStatus pmcEnterBmpsCheck( tpAniSirGlobal pMac );
+extern tANI_BOOLEAN pmcShouldBmpsTimerRun( tpAniSirGlobal pMac );
+#endif
diff --git a/CORE/SME/inc/pmcApi.h b/CORE/SME/inc/pmcApi.h
new file mode 100644
index 0000000..05a7fff
--- /dev/null
+++ b/CORE/SME/inc/pmcApi.h
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/******************************************************************************
+
+*
+
+* Name: pmcApi.h
+
+*
+
+* Description: Power Management Control (PMC) API definitions.
+
+* Copyright 2008 (c) Qualcomm, Incorporated.
+
+* All Rights Reserved.
+
+* Qualcomm Confidential and Proprietary.
+
+*
+
+******************************************************************************/
+
+
+#ifndef __PMC_API_H__
+
+#define __PMC_API_H__
+
+//This timer value determines the default periodicity at which BMPS retries will happen
+//This default value is overwritten typicaly by OS specific registry/INI values.
+#define BMPS_TRAFFIC_TIMER_DEFAULT 5000 //unit = ms
+#define DHCP_REMAIN_POWER_ACTIVE_THRESHOLD 12 // (12 * 5) sec = 60 seconds = 1 min
+
+//This timer value is used when starting the timer right after association. This value
+//should be large enough to allow the auth, DHCP handshake to complete
+#define BMPS_TRAFFIC_TIMER_ALLOW_SECURITY_DHCP 8000 //unit = ms
+
+#define PMC_IS_CHIP_ACCESSIBLE(pmcState) ( (IMPS != (pmcState)) && (REQUEST_IMPS != (pmcState)) && \
+ (STANDBY != (pmcState)) && (REQUEST_STANDBY != (pmcState)) )
+
+
+
+/* Power events that are signaled to PMC. */
+
+typedef enum ePmcPowerEvent
+
+{
+
+ ePMC_SYSTEM_HIBERNATE, /* host is entering hibernation */
+
+ ePMC_SYSTEM_RESUME, /* host is resuming after hibernation */
+
+ ePMC_HW_WLAN_SWITCH_OFF, /* Hardware WLAN Switch has been turned off */
+
+ ePMC_HW_WLAN_SWITCH_ON, /* Hardware WLAN Switch has been turned on */
+
+ ePMC_SW_WLAN_SWITCH_OFF, /* Software WLAN Switch has been turned off */
+
+ ePMC_SW_WLAN_SWITCH_ON, /* Software WLAN Switch has been turned on */
+
+ ePMC_BATTERY_OPERATION, /* host is now operating on battery power */
+
+ ePMC_AC_OPERATION /* host is now operating on AC power */
+
+} tPmcPowerEvent;
+
+
+
+
+/* Power saving modes. */
+
+typedef enum ePmcPowerSavingMode
+
+{
+
+ ePMC_IDLE_MODE_POWER_SAVE, /* Idle Mode Power Save (IMPS) */
+
+ ePMC_BEACON_MODE_POWER_SAVE, /* Beacon Mode Power Save (BMPS) */
+
+ ePMC_SPATIAL_MULTIPLEX_POWER_SAVE, /* Spatial Multiplexing Power Save (SMPS) */
+
+ ePMC_UAPSD_MODE_POWER_SAVE, /* Unscheduled Automatic Power Save Delivery Mode */
+
+ ePMC_STANDBY_MODE_POWER_SAVE, /* Standby Power Save Mode */
+
+ ePMC_WOWL_MODE_POWER_SAVE /* Wake-on-Wireless LAN Power Save Mode */
+
+} tPmcPowerSavingMode;
+
+
+
+
+/* Switch states. */
+
+typedef enum ePmcSwitchState
+
+{
+
+ ePMC_SWITCH_OFF, /* switch off */
+
+ ePMC_SWITCH_ON /* switch on */
+
+} tPmcSwitchState;
+
+
+
+
+/* Device power states. */
+
+typedef enum ePmcPowerState
+
+{
+
+ ePMC_FULL_POWER, /* full power */
+
+ ePMC_LOW_POWER, /* low power */
+
+} tPmcPowerState;
+
+
+
+/* PMC states. */
+
+typedef enum ePmcState
+
+{
+
+ STOPPED, /* PMC is stopped */
+
+ FULL_POWER, /* full power */
+
+ LOW_POWER, /* low power */
+
+ REQUEST_IMPS, /* requesting IMPS */
+
+ IMPS, /* in IMPS */
+
+ REQUEST_BMPS, /* requesting BMPS */
+
+ BMPS, /* in BMPS */
+
+ REQUEST_FULL_POWER, /* requesting full power */
+
+ REQUEST_START_UAPSD, /* requesting Start UAPSD */
+
+ REQUEST_STOP_UAPSD, /* requesting Stop UAPSD */
+
+ UAPSD, /* in UAPSD */
+
+ REQUEST_STANDBY, /* requesting standby mode */
+
+ STANDBY, /* in standby mode */
+
+ REQUEST_ENTER_WOWL, /* requesting enter WOWL */
+
+ REQUEST_EXIT_WOWL, /* requesting exit WOWL */
+
+ WOWL /* Chip in WOWL mode */
+
+} tPmcState;
+
+
+/* Which beacons should be forwarded to the host. */
+
+typedef enum ePmcBeaconsToForward
+
+{
+
+ ePMC_NO_BEACONS, /* none */
+
+ ePMC_BEACONS_WITH_TIM_SET, /* with TIM set */
+
+ ePMC_BEACONS_WITH_DTIM_SET, /* with DTIM set */
+
+ ePMC_NTH_BEACON, /* every Nth beacon */
+
+ ePMC_ALL_BEACONS /* all beacons */
+
+} tPmcBeaconsToForward;
+
+
+
+
+/* The Spatial Mulitplexing Power Save modes. */
+
+typedef enum ePmcSmpsMode
+
+{
+
+ ePMC_DYNAMIC_SMPS, /* dynamic SMPS */
+
+ ePMC_STATIC_SMPS /* static SMPS */
+
+} tPmcSmpsMode;
+
+
+
+
+/* Configuration parameters for Idle Mode Power Save (IMPS). */
+
+typedef struct sPmcImpsConfigParams
+
+{
+
+ tANI_BOOLEAN enterOnAc; /* FALSE if device should enter IMPS only when host operating
+
+ on battery power, TRUE if device should enter always */
+
+} tPmcImpsConfigParams, *tpPmcImpsConfigParams;
+
+
+
+
+/* Configuration parameters for Beacon Mode Power Save (BMPS). */
+
+typedef struct sPmcBmpsConfigParams
+
+{
+
+ tANI_BOOLEAN enterOnAc; /* FALSE if device should enter BMPS only when host operating on
+
+ battery power, TRUE if device should enter always */
+
+ tANI_U32 txThreshold; /* transmit rate under which BMPS should be entered (frames / traffic measurement period) */
+
+ tANI_U32 rxThreshold; /* receive rate under which BMPS should be entered (frames / traffic measurement period) */
+
+ tANI_U32 trafficMeasurePeriod; /* period for BMPS traffic measurement (milliseconds) */
+
+ tANI_U32 bmpsPeriod; /* amount of time in low power (beacon intervals) */
+
+ tPmcBeaconsToForward forwardBeacons; /* which beacons should be forwarded to the host */
+
+ tANI_U32 valueOfN; /* the value of N when forwardBeacons is set to ePMC_NTH_BEACON */
+
+ tANI_BOOLEAN usePsPoll; /* TRUE if PS-POLL should be used to retrieve frames from AP, FALSE if a
+
+ null data frame with the PM bit reset should be used */
+
+ tANI_BOOLEAN setPmOnLastFrame; /* TRUE to keep device in BMPS as much as possible, FALSE otherwise, TRUE means:
+
+ 1) PM bit should be set on last pending transmit data frame
+
+ 2) null frame with PM bit set should be transmitted after last pending receive
+
+ frame has been processed */
+
+ tANI_BOOLEAN enableBeaconEarlyTermination; /* if TRUE, BET feature in RIVA
+ will be enabled, FALSE otherwise, TRUE means:
+ RXP will read the beacon header for the
+ TIM bit & discard the rest if set to 0,
+ while in BMPS */
+ tANI_U8 bcnEarlyTermWakeInterval; /* This specifies how often in terms
+ of LI we will disable BET in order to sync
+ up TSF*/
+
+} tPmcBmpsConfigParams, *tpPmcBmpsConfigParams;
+
+
+
+
+/* Configuration parameters for Spatial Mulitplexing Power Save (SMPS). */
+
+typedef struct sPmcSmpsConfigParams
+
+{
+
+ tPmcSmpsMode mode; /* mode to use */
+
+ tANI_BOOLEAN enterOnAc; /* FALSE if device should enter SMPS only when host operating on
+
+ battery power, TRUE if device should enter always */
+
+} tPmcSmpsConfigParams, *tpPmcSmpsConfigParams;
+
+
+/* Routine definitions. */
+
+extern eHalStatus pmcOpen (tHalHandle hHal);
+
+extern eHalStatus pmcStart (tHalHandle hHal);
+
+extern eHalStatus pmcStop (tHalHandle hHal);
+
+extern eHalStatus pmcClose (tHalHandle hHal );
+
+extern eHalStatus pmcSignalPowerEvent (tHalHandle hHal, tPmcPowerEvent event);
+
+extern eHalStatus pmcSetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams);
+
+extern eHalStatus pmcGetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams);
+
+extern eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode);
+
+extern eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal);
+
+extern eHalStatus pmcStopAutoBmpsTimer (tHalHandle hHal);
+
+extern eHalStatus pmcDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode);
+
+extern eHalStatus pmcQueryPowerState (tHalHandle hHal, tPmcPowerState *pPowerState, tPmcSwitchState *pHwWlanSwitchState,
+
+ tPmcSwitchState *pSwWlanSwitchState);
+
+extern tANI_BOOLEAN pmcIsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode);
+
+extern eHalStatus pmcRequestFullPower (tHalHandle hHal, void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+
+ void *callbackContext, tRequestFullPowerReason fullPowerReason);
+
+extern eHalStatus pmcRequestImps (tHalHandle hHal, tANI_U32 impsPeriod,
+
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+
+ void *callbackContext);
+
+extern eHalStatus pmcRegisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext),
+
+ void *checkContext);
+
+extern eHalStatus pmcDeregisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext));
+
+extern void pmcMessageProcessor (tHalHandle hHal, tSirSmeRsp *pMsg);
+
+
+extern eHalStatus pmcRequestBmps (
+
+ tHalHandle hHal,
+
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+
+ void *callbackContext);
+
+
+extern eHalStatus pmcStartUapsd (
+
+ tHalHandle hHal,
+
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+
+ void *callbackContext);
+
+
+extern eHalStatus pmcStopUapsd (tHalHandle hHal);
+
+
+extern eHalStatus pmcRequestStandby (
+
+ tHalHandle hHal,
+
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+
+ void *callbackContext);
+
+
+extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal,
+
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState),
+
+ void *callbackContext);
+
+
+extern eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal,
+
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState));
+
+
+extern eHalStatus pmcReady(tHalHandle hHal);
+
+
+void pmcDumpInit(tHalHandle hHal);
+
+
+extern eHalStatus pmcWowlAddBcastPattern (
+
+ tHalHandle hHal,
+
+ tpSirWowlAddBcastPtrn pattern);
+
+
+extern eHalStatus pmcWowlDelBcastPattern (
+
+ tHalHandle hHal,
+
+ tpSirWowlDelBcastPtrn pattern);
+
+
+extern eHalStatus pmcEnterWowl (
+
+ tHalHandle hHal,
+
+ void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status),
+
+ void *enterWowlCallbackContext,
+#ifdef WLAN_WAKEUP_EVENTS
+ void (*wakeReasonIndCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd),
+
+ void *wakeReasonIndCBContext,
+#endif // WLAN_WAKEUP_EVENTS
+ tpSirSmeWowlEnterParams wowlEnterParams);
+
+extern eHalStatus pmcExitWowl (tHalHandle hHal);
+
+
+extern eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest);
+
+/* ---------------------------------------------------------------------------
+ \fn pmcSetKeepAlive
+ \brief Set the Keep Alive feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the Keep Alive.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot set the keepalive.
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+extern eHalStatus pmcSetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest);
+
+extern tANI_BOOLEAN pmcValidateConnectState( tHalHandle hHal );
+
+extern tANI_BOOLEAN pmcAllowImps( tHalHandle hHal );
+
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+/*Pref netw found Cb declaration*/
+typedef void(*preferredNetworkFoundIndCallback)(void *callbackContext, tpSirPrefNetworkFoundInd pPrefNetworkFoundInd);
+
+extern eHalStatus pmcSetPreferredNetworkList(tHalHandle hHal, tpSirPNOScanReq pRequest, tANI_U8 sessionId, preferredNetworkFoundIndCallback callbackRoutine, void *callbackContext);
+extern eHalStatus pmcSetRssiFilter(tHalHandle hHal, v_U8_t rssiThreshold);
+#endif // FEATURE_WLAN_SCAN_PNO
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+// Packet Coalescing Filter Match Count Callback declaration
+typedef void(*FilterMatchCountCallback)(void *callbackContext,
+ tpSirRcvFltPktMatchRsp pRcvFltPktMatchRsp);
+extern eHalStatus pmcGetFilterMatchCount(tHalHandle hHal, FilterMatchCountCallback callbackRoutine, void *callbackContext);
+#endif // WLAN_FEATURE_PACKET_FILTERING
+
+#ifdef WLAN_FEATURE_GTK_OFFLOAD
+// GTK Offload Information Callback declaration
+typedef void(*GTKOffloadGetInfoCallback)(void *callbackContext, tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp);
+
+/* ---------------------------------------------------------------------------
+ \fn pmcSetGTKOffload
+ \brief Set GTK offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pGtkOffload - Pointer to the GTK offload request.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot set the offload.
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+extern eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload);
+
+/* ---------------------------------------------------------------------------
+ \fn pmcGetGTKOffload
+ \brief Get GTK offload information.
+ \param hHal - The handle returned by macOpen.
+ \param callbackRoutine - Pointer to the GTK Offload Get Info response callback routine.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot set the offload.
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+extern eHalStatus pmcGetGTKOffload (tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, void *callbackContext);
+#endif // WLAN_FEATURE_GTK_OFFLOAD
+
+#endif
+
diff --git a/CORE/SME/inc/smeInside.h b/CORE/SME/inc/smeInside.h
new file mode 100644
index 0000000..742ac7d
--- /dev/null
+++ b/CORE/SME/inc/smeInside.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+#if !defined( __SMEINSIDE_H )
+#define __SMEINSIDE_H
+
+
+/**=========================================================================
+
+ \file smeInside.h
+
+ \brief prototype for SME structures and APIs used insside SME
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/* $Header$ */
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "vos_status.h"
+#include "vos_lock.h"
+#include "vos_trace.h"
+#include "vos_memory.h"
+#include "vos_types.h"
+#include "sirApi.h"
+#include "csrInternal.h"
+#include "sme_QosApi.h"
+#include "smeQosInternal.h"
+
+
+
+#if defined WLAN_FEATURE_VOWIFI
+#include "sme_RrmApi.h"
+#endif
+
+
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+
+#define SME_TOTAL_COMMAND 20
+
+
+typedef struct sGenericPmcCmd
+{
+ tANI_U32 size; //sizeof the data in the union, if any
+ tRequestFullPowerReason fullPowerReason;
+ tANI_BOOLEAN fReleaseWhenDone; //if TRUE, the command shall not put back to the queue, free te memory instead.
+ union
+ {
+ tExitBmpsInfo exitBmpsInfo;
+ tSirSmeWowlEnterParams enterWowlInfo;
+ }u;
+} tGenericPmcCmd;
+
+
+typedef struct sGenericQosCmd
+{
+ sme_QosWmmTspecInfo tspecInfo;
+ sme_QosEdcaAcType ac;
+ v_U8_t tspec_mask;
+} tGenericQosCmd;
+
+#ifdef WLAN_FEATURE_P2P
+typedef struct sRemainChlCmd
+{
+ tANI_U8 chn;
+ tANI_U8 phyMode;
+ tANI_U32 duration;
+ void* callback;
+ void* callbackCtx;
+}tRemainChlCmd;
+
+typedef struct sNoACmd
+{
+ tP2pPsConfig NoA;
+} tNoACmd;
+#endif
+
+typedef struct tagSmeCmd
+{
+ tListElem Link;
+ eSmeCommandType command;
+ tANI_U32 sessionId;
+ union
+ {
+ tScanCmd scanCmd;
+ tRoamCmd roamCmd;
+ tWmStatusChangeCmd wmStatusChangeCmd;
+ tSetKeyCmd setKeyCmd;
+ tRemoveKeyCmd removeKeyCmd;
+ tGenericPmcCmd pmcCmd;
+ tGenericQosCmd qosCmd;
+#ifdef WLAN_FEATURE_P2P
+ tRemainChlCmd remainChlCmd;
+ tNoACmd NoACmd;
+#endif
+ tAddStaForSessionCmd addStaSessionCmd;
+ tDelStaForSessionCmd delStaSessionCmd;
+ }u;
+}tSmeCmd;
+
+
+
+/*--------------------------------------------------------------------------
+ Internal to SME
+ ------------------------------------------------------------------------*/
+
+//To get a command buffer
+//Return: NULL if there no more command buffer left
+tSmeCmd *smeGetCommandBuffer( tpAniSirGlobal pMac );
+void smePushCommand( tpAniSirGlobal pMac, tSmeCmd *pCmd, tANI_BOOLEAN fHighPriority );
+void smeProcessPendingQueue( tpAniSirGlobal pMac );
+void smeReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCmd);
+void purgeSmeSessionCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId);
+tANI_BOOLEAN smeCommandPending(tpAniSirGlobal pMac);
+tANI_BOOLEAN pmcProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+//this function is used to abort a command where the normal processing of the command
+//is terminated without going through the normal path. it is here to take care of callbacks for
+//the command, if applicable.
+void pmcAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping );
+tANI_BOOLEAN qosProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+
+eHalStatus csrProcessScanCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+eHalStatus csrRoamProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+void csrRoamProcessWmStatusChangeCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+void csrReinitRoamCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+void csrReinitWmStatusChangeCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+void csrReinitSetKeyCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+void csrReinitRemoveKeyCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+eHalStatus csrRoamProcessSetKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+eHalStatus csrRoamProcessRemoveKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+void csrReleaseCommandSetKey(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+void csrReleaseCommandRemoveKey(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+//eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 roamId );
+eHalStatus csrRoamIssueRemoveKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tCsrRoamRemoveKey *pRemoveKey, tANI_U32 roamId );
+eHalStatus csrIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand, tRequestFullPowerReason *pReason,
+ tANI_BOOLEAN *pfNeedPower);
+void csrAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping );
+
+eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme);
+eHalStatus sme_ReleaseGlobalLock( tSmeStruct *psSme);
+
+
+eHalStatus csrProcessAddStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+eHalStatus csrProcessAddStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg);
+eHalStatus csrProcessDelStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+eHalStatus csrProcessDelStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg);
+
+#ifdef WLAN_NS_OFFLOAD
+/* ---------------------------------------------------------------------------
+ \fn pmcSetNSOffload
+ \brief Set the host offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the offload request.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot set the offload.
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest);
+#endif //WLAN_NS_OFFLOAD
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+eHalStatus pmcSetPreferredNetworkList(tHalHandle hHal, tpSirPNOScanReq pRequest, tANI_U8 sessionId, preferredNetworkFoundIndCallback callbackRoutine, void *callbackContext);
+eHalStatus pmcUpdateScanParams(tHalHandle hHal, tCsrConfig *pRequest, tCsrChannel *pChannelList, tANI_U8 b11dResolved);
+eHalStatus pmcSetRssiFilter(tHalHandle hHal, v_U8_t rssiThreshold);
+#endif // FEATURE_WLAN_SCAN_PNO
+eHalStatus pmcSetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams);
+
+tANI_BOOLEAN csrRoamGetConcurrencyConnectStatusForBmps(tpAniSirGlobal pMac);
+#endif //#if !defined( __SMEINSIDE_H )
diff --git a/CORE/SME/inc/smeInternal.h b/CORE/SME/inc/smeInternal.h
new file mode 100644
index 0000000..3d27d9b
--- /dev/null
+++ b/CORE/SME/inc/smeInternal.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+#if !defined( __SMEINTERNAL_H )
+#define __SMEINTERNAL_H
+
+
+/**=========================================================================
+
+ \file smeInternal.h
+
+ \brief prototype for SME internal structures and APIs used for SME and MAC
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/* $Header$ */
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "vos_status.h"
+#include "vos_lock.h"
+#include "vos_trace.h"
+#include "vos_memory.h"
+#include "vos_types.h"
+#include "csrLinkList.h"
+
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+
+// Mask can be only have one bit set
+typedef enum eSmeCommandType
+{
+ eSmeNoCommand = 0,
+ eSmeDropCommand,
+ //CSR
+ eSmeCsrCommandMask = 0x10000, //this is not a command, it is to identify this is a CSR command
+ eSmeCommandScan,
+ eSmeCommandRoam,
+ eSmeCommandWmStatusChange,
+ eSmeCommandSetKey,
+ eSmeCommandRemoveKey,
+ eSmeCommandAddStaSession,
+ eSmeCommandDelStaSession,
+ //PMC
+ eSmePmcCommandMask = 0x20000, //To identify PMC commands
+ eSmeCommandEnterImps,
+ eSmeCommandExitImps,
+ eSmeCommandEnterBmps,
+ eSmeCommandExitBmps,
+ eSmeCommandEnterUapsd,
+ eSmeCommandExitUapsd,
+ eSmeCommandEnterWowl,
+ eSmeCommandExitWowl,
+ eSmeCommandEnterStandby,
+ //QOS
+ eSmeQosCommandMask = 0x40000, //To identify Qos commands
+ eSmeCommandAddTs,
+ eSmeCommandDelTs,
+#ifdef WLAN_FEATURE_P2P
+ eSmeCommandRemainOnChannel,
+ eSmeCommandNoAUpdate,
+#endif
+} eSmeCommandType;
+
+
+typedef enum eSmeState
+{
+ SME_STATE_STOP,
+ SME_STATE_START,
+ SME_STATE_READY,
+} eSmeState;
+
+
+#define SME_IS_START(pMac) (SME_STATE_STOP != (pMac)->sme.state)
+#define SME_IS_READY(pMac) (SME_STATE_READY == (pMac)->sme.state)
+
+
+typedef struct tagSmeStruct
+{
+ eSmeState state;
+ vos_lock_t lkSmeGlobalLock;
+ tANI_U32 totalSmeCmd;
+ void *pSmeCmdBufAddr;
+ tDblLinkList smeCmdActiveList;
+ tDblLinkList smeCmdPendingList;
+ tDblLinkList smeCmdFreeList; //preallocated roam cmd list
+ void (*pTxPerHitCallback) (void *pCallbackContext); /* callback for Tx PER hit to HDD */
+ void *pTxPerHitCbContext;
+} tSmeStruct, *tpSmeStruct;
+
+
+#endif //#if !defined( __SMEINTERNAL_H )
diff --git a/CORE/SME/inc/smeQosInternal.h b/CORE/SME/inc/smeQosInternal.h
new file mode 100644
index 0000000..f318af1
--- /dev/null
+++ b/CORE/SME/inc/smeQosInternal.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+
+#if !defined( __SMEQOSINTERNAL_H )
+#define __SMEQOSINTERNAL_H
+
+
+/**=========================================================================
+
+ \file smeQosInternal.h
+
+ \brief prototype for SME QoS APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/* $Header$ */
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "vos_lock.h"
+#include "vos_trace.h"
+#include "vos_memory.h"
+#include "vos_types.h"
+#include "aniGlobal.h"
+#include "sirApi.h"
+#include "sme_QosApi.h"
+#include "smeInternal.h"
+
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+#define SME_QOS_AP_SUPPORTS_APSD 0x80
+
+/*---------------------------------------------------------------------------
+ Enumeration of the various EDCA Access Categories:
+ Based on AC to ACI mapping in 802.11e spec (identical to WMM)
+---------------------------------------------------------------------------*/
+typedef enum
+{
+ SME_QOS_EDCA_AC_BE = 0, /* Best effort access category */
+ SME_QOS_EDCA_AC_BK = 1, /* Background access category */
+ SME_QOS_EDCA_AC_VI = 2, /* Video access category */
+ SME_QOS_EDCA_AC_VO = 3, /* Voice access category */
+
+ SME_QOS_EDCA_AC_MAX
+} sme_QosEdcaAcType;
+
+
+/*---------------------------------------------------------------------------
+ Enumeration of the various CSR event indication types that would be reported
+ by CSR
+---------------------------------------------------------------------------*/
+typedef enum
+{
+ SME_QOS_CSR_JOIN_REQ = 0,
+ SME_QOS_CSR_ASSOC_COMPLETE,
+ SME_QOS_CSR_REASSOC_REQ,
+ SME_QOS_CSR_REASSOC_COMPLETE,
+ SME_QOS_CSR_REASSOC_FAILURE,
+ SME_QOS_CSR_DISCONNECT_REQ,
+ SME_QOS_CSR_DISCONNECT_IND,
+ SME_QOS_CSR_HANDOFF_ASSOC_REQ,
+ SME_QOS_CSR_HANDOFF_COMPLETE,
+ SME_QOS_CSR_HANDOFF_FAILURE,
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ SME_QOS_CSR_PREAUTH_SUCCESS_IND,
+ SME_QOS_CSR_SET_KEY_SUCCESS_IND,
+#endif
+}sme_QosCsrEventIndType;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+typedef enum
+{
+ SME_QOS_DIAG_ADDTS_REQ = 0,
+ SME_QOS_DIAG_ADDTS_RSP,
+ SME_QOS_DIAG_DELTS
+
+}sme_QosDiagQosEventSubtype;
+
+typedef enum
+{
+ SME_QOS_DIAG_ADDTS_ADMISSION_ACCEPTED = 0,
+ SME_QOS_DIAG_ADDTS_INVALID_PARAMS,
+ SME_QOS_DIAG_ADDTS_RESERVED,
+ SME_QOS_DIAG_ADDTS_REFUSED,
+ SME_QOS_DIAG_USER_REQUESTED,
+ SME_QOS_DIAG_DELTS_IND_FROM_AP,
+
+}sme_QosDiagQosEventReasonCode;
+
+#endif //FEATURE_WLAN_DIAG_SUPPORT
+/*---------------------------------------------------------------------------
+ The association information structure to be passed by CSR after assoc or
+ reassoc is done
+---------------------------------------------------------------------------*/
+typedef struct
+{
+ tSirBssDescription *pBssDesc;
+ tCsrRoamProfile *pProfile;
+} sme_QosAssocInfo;
+
+/*--------------------------------------------------------------------------
+ External APIs for CSR - Internal to SME
+ ------------------------------------------------------------------------*/
+
+/* --------------------------------------------------------------------------
+ \brief sme_QosOpen() - This function must be called before any API call to
+ SME QoS module.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+
+ \return eHalStatus
+----------------------------------------------------------------------------*/
+eHalStatus sme_QosOpen(tpAniSirGlobal pMac);
+
+/* --------------------------------------------------------------------------
+ \brief sme_QosClose() - To close down SME QoS module. There should not be
+ any API call into this module after calling this function until another
+ call of sme_QosOpen.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+
+ \return eHalStatus
+----------------------------------------------------------------------------*/
+eHalStatus sme_QosClose(tpAniSirGlobal pMac);
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosSetParams() - This function is used by HDD to provide the
+ default TSPEC params to SME.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info per AC as defined above, provided by HDD
+
+ \return eHAL_STATUS_SUCCESS - Setparam is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosSetParams(tpAniSirGlobal pMac, sme_QosWmmTspecInfo * pQoSInfo);
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosMsgProcessor() - sme_ProcessMsg() calls this function for the
+ messages that are handled by SME QoS module.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param msg_type - the type of msg passed by PE as defined in wniApi.h
+ \param pMsgBuf - a pointer to a buffer that maps to various structures base
+ on the message type.
+ The beginning of the buffer can always map to tSirSmeRsp.
+
+ \return eHalStatus.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type,
+ void *pMsgBuf);
+
+/*--------------------------------------------------------------------------
+ Internal APIs for CSR
+ ------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosValidateParams() - The SME QoS API exposed to CSR to validate AP
+ capabilities regarding QoS support & any other QoS parameter validation.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pBssDesc - Pointer to the BSS Descriptor information passed down by
+ CSR to PE while issuing the Join request
+
+ \return eHAL_STATUS_SUCCESS - Validation is successful
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosValidateParams(tpAniSirGlobal pMac,
+ tSirBssDescription *pBssDesc);
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosCsrEventInd() - The QoS sub-module in SME expects notifications
+ from CSR when certain events occur as mentioned in sme_QosCsrEventIndType.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param ind - The event occurred of type sme_QosCsrEventIndType.
+ \param pEvent_info - Information related to the event
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosCsrEventInd(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosCsrEventIndType ind,
+ void *pEvent_info);
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosGetACMMask() - The QoS sub-module API to find out on which ACs
+ AP mandates Admission Control (ACM = 1)
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pSirBssDesc - The event occurred of type sme_QosCsrEventIndType.
+ \param pIes - the parsed IE for pSirBssDesc. This can be NULL.
+
+
+ \return a bit mask indicating for which ACs AP has ACM set to 1
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+v_U8_t sme_QosGetACMMask(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes);
+
+/*
+ sme_QosTriggerUapsdChange
+ It trigger a change on UAPSD (either disable/enable UAPSD) on current QoS flows
+*/
+sme_QosStatusType sme_QosTriggerUapsdChange( tpAniSirGlobal pMac );
+
+#ifdef FEATURE_WLAN_CCX
+v_U8_t sme_QosCCxRetrieveTspecInfo(tpAniSirGlobal pMac, v_U8_t sessionId, tTspecInfo *pTspecInfo);
+
+#endif
+
+#endif //#if !defined( __SMEQOSINTERNAL_H )
diff --git a/CORE/SME/inc/smeRrmInternal.h b/CORE/SME/inc/smeRrmInternal.h
new file mode 100644
index 0000000..072a5e0
--- /dev/null
+++ b/CORE/SME/inc/smeRrmInternal.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/*
+ * */
+#if !defined( __SMERRMINTERNAL_H )
+#define __SMERRMINTERNAL_H
+
+
+/**=========================================================================
+
+ \file smeRrmInternal.h
+
+ \brief prototype for SME RRM APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/* $Header$ */
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "vos_lock.h"
+#include "vos_trace.h"
+#include "vos_memory.h"
+#include "vos_types.h"
+#include "palTimer.h"
+#include "rrmGlobal.h"
+
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+typedef struct sRrmConfigParam
+{
+ tANI_U8 rrmEnabled;
+ tANI_U8 maxRandnInterval;
+}tRrmConfigParam, *tpRrmConfigParam;
+
+typedef struct sRrmNeighborReportDesc
+{
+ tListElem List;
+ tSirNeighborBssDescription *pNeighborBssDescription;
+ tANI_U32 roamScore;
+} tRrmNeighborReportDesc, *tpRrmNeighborReportDesc;
+
+
+typedef void (*NeighborReportRspCallback) (void *context, VOS_STATUS vosStatus);
+
+typedef struct sRrmNeighborRspCallbackInfo
+{
+ tANI_U32 timeout; //in ms.. min value is 10 (10ms)
+ NeighborReportRspCallback neighborRspCallback;
+ void *neighborRspCallbackContext;
+} tRrmNeighborRspCallbackInfo, *tpRrmNeighborRspCallbackInfo;
+
+typedef struct sRrmNeighborRequestControlInfo
+{
+ tANI_BOOLEAN isNeighborRspPending; //To check whether a neighbor req is already sent and response pending
+ vos_timer_t neighborRspWaitTimer;
+ tRrmNeighborRspCallbackInfo neighborRspCallbackInfo;
+} tRrmNeighborRequestControlInfo, *tpRrmNeighborRequestControlInfo;
+
+typedef struct sRrmSMEContext
+{
+ tANI_U16 token;
+ tCsrBssid sessionBssId;
+ tANI_U8 regClass;
+ tCsrChannelInfo channelList; //list of all channels to be measured.
+ tANI_U8 currentIndex;
+ tAniSSID ssId; //SSID used in the measuring beacon report.
+ tSirMacAddr bssId; //bssid used for beacon report measurement.
+ tANI_U16 randnIntvl; //Randomization interval to be used in subsequent measurements.
+ tANI_U16 duration;
+ tANI_U16 measMode;
+ tRrmConfigParam rrmConfig;
+ vos_timer_t IterMeasTimer;
+ tDblLinkList neighborReportCache;
+ tRrmNeighborRequestControlInfo neighborReqControlInfo;
+}tRrmSMEContext, *tpRrmSMEContext;
+
+typedef struct sRrmNeighborReq
+{
+ tANI_U8 no_ssid;
+ tSirMacSSid ssid;
+}tRrmNeighborReq, *tpRrmNeighborReq;
+
+#endif //#if !defined( __SMERRMINTERNAL_H )
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
new file mode 100644
index 0000000..c14d3f9
--- /dev/null
+++ b/CORE/SME/inc/sme_Api.h
@@ -0,0 +1,2089 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+#if !defined( __SME_API_H )
+#define __SME_API_H
+
+
+/**=========================================================================
+
+ \file smeApi.h
+
+ \brief prototype for SME APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/* $Header$ */
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "ccmApi.h"
+#include "csrApi.h"
+#include "pmcApi.h"
+#include "vos_mq.h"
+#include "vos_lock.h"
+#include "halTypes.h"
+#include "sirApi.h"
+#include "btcApi.h"
+#include "vos_nvitem.h"
+#include "p2p_Api.h"
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include "halFw.h"
+#endif
+
+
+#if defined WLAN_FEATURE_VOWIFI
+#include "smeRrmInternal.h"
+#endif
+
+/*--------------------------------------------------------------------------
+ Preprocessor definitions and constants
+ ------------------------------------------------------------------------*/
+
+#define SME_SUMMARY_STATS 1
+#define SME_GLOBAL_CLASSA_STATS 2
+#define SME_GLOBAL_CLASSB_STATS 4
+#define SME_GLOBAL_CLASSC_STATS 8
+#define SME_GLOBAL_CLASSD_STATS 16
+#define SME_PER_STA_STATS 32
+
+#define SME_INVALID_COUNTRY_CODE "XX"
+
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+typedef struct _smeConfigParams
+{
+ tCsrConfigParam csrConfig;
+#if defined WLAN_FEATURE_VOWIFI
+ tRrmConfigParam rrmConfig;
+#endif
+#if defined FEATURE_WLAN_CCX
+ tANI_U8 isCcxIniFeatureEnabled;
+#endif
+#if defined WLAN_FEATURE_P2P_INTERNAL
+ tP2PConfigParam p2pConfig;
+#endif
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ tANI_U8 isFastTransitionEnabled;
+#endif
+} tSmeConfigParams, *tpSmeConfigParams;
+
+
+/*-------------------------------------------------------------------------
+ Function declarations and documenation
+ ------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_Open() - Initialze all SME modules and put them at idle state
+
+ The function initializes each module inside SME, PMC, CCM, CSR, etc. . Upon
+ successfully return, all modules are at idle state ready to start.
+
+ smeOpen must be called before any other SME APIs can be involved.
+ smeOpen must be called after macOpen.
+
+ \param hHal - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS - SME is successfully initialized.
+
+ Other status means SME is failed to be initialized
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_Open(tHalHandle hHal);
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_Close() - Release all SME modules and their resources.
+
+ The function release each module in SME, PMC, CCM, CSR, etc. . Upon
+ return, all modules are at closed state.
+
+ No SME APIs can be involved after sme_Close except sme_Open.
+ sme_Close must be called before macClose.
+
+ \param hHal - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS - SME is successfully close.
+
+ Other status means SME is failed to be closed but caller still cannot
+ call any other SME functions except smeOpen.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_Close(tHalHandle hHal);
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_Start() - Put all SME modules at ready state.
+
+ The function starts each module in SME, PMC, CCM, CSR, etc. . Upon
+ successfully return, all modules are ready to run.
+
+ \param hHal - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS - SME is ready.
+
+ Other status means SME is failed to start.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_Start(tHalHandle hHal);
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_Stop() - Stop all SME modules and put them at idle state
+
+ The function stops each module in SME, PMC, CCM, CSR, etc. . Upon
+ return, all modules are at idle state ready to start.
+
+
+ \param hHal - The handle returned by macOpen.
+
+ \param pmcFlag - The flag tells SME if we want to stop PMC or not
+
+ \return eHAL_STATUS_SUCCESS - SME is stopped.
+
+ Other status means SME is failed to stop but caller should still consider
+ SME is stopped.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_Stop(tHalHandle hHal, tANI_BOOLEAN pmcFlag);
+
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_OpenSession() - Open a session for scan/roam operation.
+
+ This is a synchronous API.
+
+
+ \param hHal - The handle returned by macOpen.
+ \param callback - A pointer to the function caller specifies for roam/connect status indication
+ \param pContext - The context passed with callback
+ \param pSelfMacAddr - Caller allocated memory filled with self MAC address (6 bytes)
+ \param pbSessionId - pointer to a caller allocated buffer for returned session ID
+
+ \return eHAL_STATUS_SUCCESS - session is opened. sessionId returned.
+
+ Other status means SME is failed to open the session.
+ eHAL_STATUS_RESOURCES - no more session available.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, void *pContext,
+ tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId);
+
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_CloseSession() - Open a session for scan/roam operation.
+
+ This is a synchronous API.
+
+
+ \param hHal - The handle returned by macOpen.
+
+ \param sessionId - A previous opened session's ID.
+
+ \return eHAL_STATUS_SUCCESS - session is closed.
+
+ Other status means SME is failed to open the session.
+ eHAL_STATUS_INVALID_PARAMETER - session is not opened.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_CloseSession(tHalHandle hHal, tANI_U8 sessionId,
+ csrRoamSessionCloseCallback callback, void *pContext);
+
+
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_UpdateConfig() - Change configurations for all SME moduels
+
+ The function updates some configuration for modules in SME, CCM, CSR, etc
+ during SMEs close -> open sequence.
+
+ Modules inside SME apply the new configuration at the next transaction.
+
+
+ \param hHal - The handle returned by macOpen.
+ \Param pSmeConfigParams - a pointer to a caller allocated object of
+ typedef struct _smeConfigParams.
+
+ \return eHAL_STATUS_SUCCESS - SME update the config parameters successfully.
+
+ Other status means SME is failed to update the config parameters.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_UpdateConfig(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams);
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+/*--------------------------------------------------------------------------
+
+ \brief sme_UpdateChannelConfig() - Update channel configuration in RIVA.
+
+ It is used at driver start up to inform RIVA of the default channel
+ configuration.
+
+ This is a synchronuous call
+
+ \param hHal - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS - SME update the channel config successfully.
+
+ Other status means SME is failed to update the channel config.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_UpdateChannelConfig(tHalHandle hHal);
+
+#endif // FEATURE_WLAN_SCAN_PNLO
+#ifdef WLAN_SOFTAP_FEATURE
+/*--------------------------------------------------------------------------
+
+ \brief sme_set11dinfo() - Set the 11d information about valid channels
+ and there power using information from nvRAM
+ This function is called only for AP.
+
+ This is a synchronuous call
+
+ \param hHal - The handle returned by macOpen.
+ \Param pSmeConfigParams - a pointer to a caller allocated object of
+ typedef struct _smeConfigParams.
+
+ \return eHAL_STATUS_SUCCESS - SME update the config parameters successfully.
+
+ Other status means SME is failed to update the config parameters.
+ \sa
+--------------------------------------------------------------------------*/
+
+eHalStatus sme_set11dinfo(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams);
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_getSoftApDomain() - Get the current regulatory domain of softAp.
+
+ This is a synchronuous call
+
+ \param hHal - The handle returned by HostapdAdapter.
+ \Param v_REGDOMAIN_t - The current Regulatory Domain requested for SoftAp.
+
+ \return eHAL_STATUS_SUCCESS - SME successfully completed the request.
+
+ Other status means, failed to get the current regulatory domain.
+ \sa
+--------------------------------------------------------------------------*/
+
+eHalStatus sme_getSoftApDomain(tHalHandle hHal, v_REGDOMAIN_t *domainIdSoftAp);
+
+eHalStatus sme_setRegInfo(tHalHandle hHal, tANI_U8 *apCntryCode);
+
+#endif
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ChangeConfigParams
+ \brief The SME API exposed for HDD to provide config params to SME during
+ SMEs stop -> start sequence.
+
+ If HDD changed the domain that will cause a reset. This function will
+ provide the new set of 11d information for the new domain. Currrently this
+ API provides info regarding 11d only at reset but we can extend this for
+ other params (PMC, QoS) which needs to be initialized again at reset.
+
+ This is a synchronuous call
+
+ \param hHal - The handle returned by macOpen.
+
+ \Param
+ pUpdateConfigParam - a pointer to a structure (tCsrUpdateConfigParam) that
+ currently provides 11d related information like Country code,
+ Regulatory domain, valid channel list, Tx power per channel, a
+ list with active/passive scan allowed per valid channel.
+
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ChangeConfigParams(tHalHandle hHal,
+ tCsrUpdateConfigParam *pUpdateConfigParam);
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_HDDReadyInd() - SME sends eWNI_SME_SYS_READY_IND to PE to inform that the NIC
+ is ready tio run.
+
+ The function is called by HDD at the end of initialization stage so PE/HAL can enable the NIC
+ to running state.
+
+
+ \param hHal - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS - eWNI_SME_SYS_READY_IND is sent to PE successfully.
+
+ Other status means SME failed to send the message to PE.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_HDDReadyInd(tHalHandle hHal);
+
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_ProcessMsg() - The main message processor for SME.
+
+ The function is called by a message dispatcher when to process a message
+ targeted for SME.
+
+
+ \param hHal - The handle returned by macOpen.
+ \param pMsg - A pointer to a caller allocated object of tSirMsgQ.
+
+ \return eHAL_STATUS_SUCCESS - SME successfully process the message.
+
+ Other status means SME failed to process the message.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg);
+
+v_VOID_t sme_FreeMsg( tHalHandle hHal, vos_msg_t* pMsg );
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanRequest
+ \brief a wrapper function to Request a 11d or full scan from CSR.
+ \param pScanRequestID - pointer to an object to get back the request ID
+ \param callback - a callback function that scan calls upon finish, will not
+ be called if csrScanRequest returns error
+ \param pContext - a pointer passed in for the callback
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanRequest(tHalHandle hHal, tANI_U8 sessionId, tCsrScanRequest *,
+ tANI_U32 *pScanRequestID,
+ csrScanCompleteCallback callback, void *pContext);
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanSetBGScanparams
+ \brief a wrapper function to request CSR to set BG scan params in PE
+ \param pScanReq - BG scan request structure
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanSetBGScanparams(tHalHandle hHal, tANI_U8 sessionId, tCsrBGScanRequest *pScanReq);
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanGetResult
+ \brief a wrapper function to request scan results from CSR.
+ \param pFilter - If pFilter is NULL, all cached results are returned
+ \param phResult - an object for the result.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanGetResult(tHalHandle hHal, tANI_U8 sessionId, tCsrScanResultFilter *pFilter,
+ tScanResultHandle *phResult);
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanFlushResult
+ \brief a wrapper function to request CSR to clear scan results.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanFlushResult(tHalHandle hHal, tANI_U8 sessionId);
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanResultGetFirst
+ \brief a wrapper function to request CSR to returns the first element of
+ scan result.
+ \param hScanResult - returned from csrScanGetResult
+ \return tCsrScanResultInfo * - NULL if no result
+ ---------------------------------------------------------------------------*/
+tCsrScanResultInfo *sme_ScanResultGetFirst(tHalHandle,
+ tScanResultHandle hScanResult);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanResultGetNext
+ \brief a wrapper function to request CSR to returns the next element of
+ scan result. It can be called without calling csrScanResultGetFirst
+ first
+ \param hScanResult - returned from csrScanGetResult
+ \return Null if no result or reach the end
+ ---------------------------------------------------------------------------*/
+tCsrScanResultInfo *sme_ScanResultGetNext(tHalHandle,
+ tScanResultHandle hScanResult);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanResultPurge
+ \brief a wrapper function to request CSR to remove all items(tCsrScanResult)
+ in the list and free memory for each item
+ \param hScanResult - returned from csrScanGetResult. hScanResult is
+ considered gone by
+ calling this function and even before this function reutrns.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanResultPurge(tHalHandle hHal, tScanResultHandle hScanResult);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanGetPMKIDCandidateList
+ \brief a wrapper function to return the PMKID candidate list
+ \param pPmkidList - caller allocated buffer point to an array of
+ tPmkidCandidateInfo
+ \param pNumItems - pointer to a variable that has the number of
+ tPmkidCandidateInfo allocated when retruning, this is
+ either the number needed or number of items put into
+ pPmkidList
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough and pNumItems
+ has the number of tPmkidCandidateInfo.
+ \Note: pNumItems is a number of tPmkidCandidateInfo,
+ not sizeof(tPmkidCandidateInfo) * something
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanGetPMKIDCandidateList(tHalHandle hHal, tANI_U8 sessionId,
+ tPmkidCandidateInfo *pPmkidList,
+ tANI_U32 *pNumItems );
+
+
+/*----------------------------------------------------------------------------
+ \fn sme_RoamRegisterLinkQualityIndCallback
+
+ \brief
+ a wrapper function to allow HDD to register a callback handler with CSR for
+ link quality indications.
+
+ Only one callback may be registered at any time.
+ In order to deregister the callback, a NULL cback may be provided.
+
+ Registration happens in the task context of the caller.
+
+ \param callback - Call back being registered
+ \param pContext - user data
+
+ DEPENDENCIES: After CSR open
+
+ \return eHalStatus
+-----------------------------------------------------------------------------*/
+eHalStatus sme_RoamRegisterLinkQualityIndCallback(tHalHandle hHal, tANI_U8 sessionId,
+ csrRoamLinkQualityIndCallback callback,
+ void *pContext);
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamConnect
+ \brief a wrapper function to request CSR to inititiate an association
+ \param sessionId - the sessionId returned by sme_OpenSession.
+ \param pProfile - can be NULL to join to any open ones
+ \param pRoamId - to get back the request ID
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamConnect(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile *pProfile,
+ tANI_U32 *pRoamId);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamReassoc
+ \brief a wrapper function to request CSR to inititiate a re-association
+ \param pProfile - can be NULL to join the currently connected AP. In that
+ case modProfileFields should carry the modified field(s) which could trigger
+ reassoc
+ \param modProfileFields - fields which are part of tCsrRoamConnectedProfile
+ that might need modification dynamically once STA is up & running and this
+ could trigger a reassoc
+ \param pRoamId - to get back the request ID
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamReassoc(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile *pProfile,
+ tCsrRoamModifyProfileFields modProfileFields,
+ tANI_U32 *pRoamId);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamConnectToLastProfile
+ \brief a wrapper function to request CSR to disconnect and reconnect with
+ the same profile
+ \return eHalStatus. It returns fail if currently connected
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamConnectToLastProfile(tHalHandle hHal, tANI_U8 sessionId);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamDisconnect
+ \brief a wrapper function to request CSR to disconnect from a network
+ \param reason -- To indicate the reason for disconnecting. Currently, only
+ eCSR_DISCONNECT_REASON_MIC_ERROR is meanful.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamDisconnect(tHalHandle hHal, tANI_U8 sessionId, eCsrRoamDisconnectReason reason);
+
+#ifdef WLAN_SOFTAP_FEATURE
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamStopBss
+ \brief a wrapper function to request CSR to stop bss
+ \param sessionId - sessionId of SoftAP
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamStopBss(tHalHandle hHal, tANI_U8 sessionId);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetAssociatedStas
+ \brief To probe the list of associated stations from various modules of CORE stack.
+ \This is an asynchronous API.
+ \param sessionId - sessionId of SoftAP
+ \param modId - Module from whom list of associtated stations is to be probed.
+ If an invalid module is passed then by default VOS_MODULE_ID_PE will be probed
+ \param pUsrContext - Opaque HDD context
+ \param pfnSapEventCallback - Sap event callback in HDD
+ \param pAssocBuf - Caller allocated memory to be filled with associatd stations info
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetAssociatedStas(tHalHandle hHal, tANI_U8 sessionId,
+ VOS_MODULE_ID modId, void *pUsrContext,
+ void *pfnSapEventCallback, tANI_U8 *pAssocStasBuf);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamDisconnectSta
+ \brief To disassociate a station. This is an asynchronous API.
+ \param pPeerMacAddr - Caller allocated memory filled with peer MAC address (6 bytes)
+ \return eHalStatus SUCCESS Roam callback will be called to indicate actual results
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamDisconnectSta(tHalHandle hHal, tANI_U8 sessionId, tANI_U8 *pPeerMacAddr);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamDeauthSta
+ \brief To disassociate a station. This is an asynchronous API.
+ \param hHal - Global structure
+ \param sessionId - sessionId of SoftAP
+ \param pPeerMacAddr - Caller allocated memory filled with peer MAC address (6 bytes)
+ \return eHalStatus SUCCESS Roam callback will be called to indicate actual results
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamDeauthSta(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U8 *pPeerMacAddr);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamTKIPCounterMeasures
+ \brief To start or stop TKIP counter measures. This is an asynchronous API.
+ \param sessionId - sessionId of SoftAP
+ \param bEnable - Flag to start/stop TKIP countermeasures
+ \return eHalStatus SUCCESS Roam callback will be called to indicate actual results
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamTKIPCounterMeasures(tHalHandle hHal, tANI_U8 sessionId, tANI_BOOLEAN bEnable);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetWpsSessionOverlap
+ \brief To get the WPS PBC session overlap information.
+ \This is an asynchronous API.
+ \param sessionId - sessionId of SoftAP
+ \param pUsrContext - Opaque HDD context
+ \param pfnSapEventCallback - Sap event callback in HDD
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetWpsSessionOverlap(tHalHandle hHal, tANI_U8 sessionId,
+ void *pUsrContext, void *pfnSapEventCallback,
+ v_MACADDR_t pRemoveMac);
+#endif
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetConnectState
+ \brief a wrapper function to request CSR to return the current connect state
+ of Roaming
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetConnectState(tHalHandle hHal, tANI_U8 sessionId, eCsrConnectState *pState);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetConnectProfile
+ \brief a wrapper function to request CSR to return the current connect
+ profile. Caller must call csrRoamFreeConnectProfile after it is done
+ and before reuse for another csrRoamGetConnectProfile call.
+ \param pProfile - pointer to a caller allocated structure
+ tCsrRoamConnectedProfile
+ \return eHalStatus. Failure if not connected
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetConnectProfile(tHalHandle hHal, tANI_U8 sessionId,
+ tCsrRoamConnectedProfile *pProfile);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamFreeConnectProfile
+ \brief a wrapper function to request CSR to free and reinitialize the
+ profile returned previously by csrRoamGetConnectProfile.
+ \param pProfile - pointer to a caller allocated structure
+ tCsrRoamConnectedProfile
+ \return eHalStatus.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamFreeConnectProfile(tHalHandle hHal,
+ tCsrRoamConnectedProfile *pProfile);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamSetPMKIDCache
+ \brief a wrapper function to request CSR to return the PMKID candidate list
+ \param pPMKIDCache - caller allocated buffer point to an array of
+ tPmkidCacheInfo
+ \param numItems - a variable that has the number of tPmkidCacheInfo
+ allocated when retruning, this is either the number needed
+ or number of items put into pPMKIDCache
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough and pNumItems has the number of
+ tPmkidCacheInfo.
+ \Note: pNumItems is a number of tPmkidCacheInfo,
+ not sizeof(tPmkidCacheInfo) * something
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamSetPMKIDCache( tHalHandle hHal, tANI_U8 sessionId, tPmkidCacheInfo *pPMKIDCache,
+ tANI_U32 numItems );
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetSecurityReqIE
+ \brief a wrapper function to request CSR to return the WPA or RSN or WAPI IE CSR
+ passes to PE to JOIN request or START_BSS request
+ This is a synchronuous call.
+ \param sessionId - returned by sme_OpenSession.
+ \param pLen - caller allocated memory that has the length of pBuf as input.
+ Upon returned, *pLen has the needed or IE length in pBuf.
+ \param pBuf - Caller allocated memory that contain the IE field, if any,
+ upon return
+ \param secType - Specifies whether looking for WPA/WPA2/WAPI IE
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetSecurityReqIE(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pLen,
+ tANI_U8 *pBuf, eCsrSecurityType secType);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetSecurityRspIE
+ \brief a wrapper function to request CSR to return the WPA or RSN or WAPI IE from
+ the beacon or probe rsp if connected
+ \param sessionId - returned by sme_OpenSession.
+ \param pLen - caller allocated memory that has the length of pBuf as input.
+ Upon returned, *pLen has the needed or IE length in pBuf.
+ \param pBuf - Caller allocated memory that contain the IE field, if any,
+ upon return
+ \param secType - Specifies whether looking for WPA/WPA2/WAPI IE
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetSecurityRspIE(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pLen,
+ tANI_U8 *pBuf, eCsrSecurityType secType);
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetNumPMKIDCache
+ \brief a wrapper function to request CSR to return number of PMKID cache
+ entries
+ \return tANI_U32 - the number of PMKID cache entries
+ ---------------------------------------------------------------------------*/
+tANI_U32 sme_RoamGetNumPMKIDCache(tHalHandle hHal, tANI_U8 sessionId);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetPMKIDCache
+ \brief a wrapper function to request CSR to return PMKID cache from CSR
+ \param pNum - caller allocated memory that has the space of the number of
+ pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the
+ needed or actually number in tPmkidCacheInfo.
+ \param pPmkidCache - Caller allocated memory that contains PMKID cache, if
+ any, upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetPMKIDCache(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pNum,
+ tPmkidCacheInfo *pPmkidCache);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetConfigParam
+ \brief a wrapper function that HDD calls to get the global settings
+ currently maintained by CSR.
+ \param pParam - caller allocated memory
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_GetConfigParam(tHalHandle hHal, tSmeConfigParams *pParam);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetStatistics
+ \brief a wrapper function that client calls to register a callback to get
+ different PHY level statistics from CSR.
+
+ \param requesterId - different client requesting for statistics, HDD, UMA/GAN etc
+ \param statsMask - The different category/categories of stats requester is looking for
+ The order in which you set the bits in the statsMask for requesting
+ different type of stats is:
+
+ eCsrSummaryStats = bit 0
+ eCsrGlobalClassAStats = bit 1
+ eCsrGlobalClassBStats = bit 2
+ eCsrGlobalClassCStats = bit 3
+ eCsrGlobalClassDStats = bit 4
+ eCsrPerStaStats = bit 5
+
+ \param callback - SME sends back the requested stats using the callback
+ \param periodicity - If requester needs periodic update, 0 means it's an one
+ time request
+ \param cache - If requester is happy with cached stats
+ \param staId - The station ID for which the stats is requested for
+ \param pContext - user context to be passed back along with the callback
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_GetStatistics(tHalHandle hHal, eCsrStatsRequesterType requesterId,
+ tANI_U32 statsMask,
+ tCsrStatsCallback callback,
+ tANI_U32 periodicity, tANI_BOOLEAN cache,
+ tANI_U8 staId, void *pContext);
+
+eHalStatus sme_GetRssi(tHalHandle hHal,
+ tCsrRssiCallback callback,
+ tANI_U8 staId, tCsrBssid bssId, void *pContext, void* pVosContext);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_CfgSetInt
+ \brief a wrapper function that HDD calls to set parameters in CFG.
+ \param cfgId - Configuration Parameter ID (type) for STA.
+ \param ccmValue - The information related to Configuration Parameter ID
+ which needs to be saved in CFG
+ \param callback - To be registered by CSR with CCM. Once the CFG done with
+ saving the information in the database, it notifies CCM &
+ then the callback will be invoked to notify.
+ \param toBeSaved - To save the request for future reference
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_CfgSetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 ccmValue,
+ tCcmCfgSetCallback callback, eAniBoolean toBeSaved) ;
+
+/* ---------------------------------------------------------------------------
+ \fn sme_CfgSetStr
+ \brief a wrapper function that HDD calls to set parameters in CFG.
+ \param cfgId - Configuration Parameter ID (type) for STA.
+ \param pStr - Pointer to the byte array which carries the information needs
+ to be saved in CFG
+ \param length - Length of the data to be saved
+ \param callback - To be registered by CSR with CCM. Once the CFG done with
+ saving the information in the database, it notifies CCM &
+ then the callback will be invoked to notify.
+ \param toBeSaved - To save the request for future reference
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_CfgSetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pStr,
+ tANI_U32 length, tCcmCfgSetCallback callback,
+ eAniBoolean toBeSaved) ;
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetModifyProfileFields
+ \brief HDD or SME - QOS calls this function to get the current values of
+ connected profile fields, changing which can cause reassoc.
+ This function must be called after CFG is downloaded and STA is in connected
+ state. Also, make sure to call this function to get the current profile
+ fields before calling the reassoc. So that pModifyProfileFields will have
+ all the latest values plus the one(s) has been updated as part of reassoc
+ request.
+ \param pModifyProfileFields - pointer to the connected profile fields
+ changing which can cause reassoc
+
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetModifyProfileFields(tHalHandle hHal, tANI_U8 sessionId,
+ tCsrRoamModifyProfileFields * pModifyProfileFields);
+
+
+/*--------------------------------------------------------------------------
+ \fn sme_SetConfigPowerSave
+ \brief Wrapper fn to change power save configuration in SME (PMC) module.
+ For BMPS related configuration, this function also updates the CFG
+ and sends a message to FW to pick up the new values. Note: Calling
+ this function only updates the configuration and does not enable
+ the specified power save mode.
+ \param hHal - The handle returned by macOpen.
+ \param psMode - Power Saving mode being modified
+ \param pConfigParams - a pointer to a caller allocated object of type
+ tPmcSmpsConfigParams or tPmcBmpsConfigParams or tPmcImpsConfigParams
+ \return eHalStatus
+ --------------------------------------------------------------------------*/
+eHalStatus sme_SetConfigPowerSave(tHalHandle hHal, tPmcPowerSavingMode psMode,
+ void *pConfigParams);
+
+/*--------------------------------------------------------------------------
+ \fn sme_GetConfigPowerSave
+ \brief Wrapper fn to retireve power save configuration in SME (PMC) module
+ \param hHal - The handle returned by macOpen.
+ \param psMode - Power Saving mode
+ \param pConfigParams - a pointer to a caller allocated object of type
+ tPmcSmpsConfigParams or tPmcBmpsConfigParams or tPmcImpsConfigParams
+ \return eHalStatus
+ --------------------------------------------------------------------------*/
+eHalStatus sme_GetConfigPowerSave(tHalHandle hHal, tPmcPowerSavingMode psMode,
+ void *pConfigParams);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SignalPowerEvent
+ \brief Signals to PMC that a power event has occurred. Used for putting
+ the chip into deep sleep mode.
+ \param hHal - The handle returned by macOpen.
+ \param event - the event that has occurred
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_SignalPowerEvent (
+ tHalHandle hHal,
+ tPmcPowerEvent event);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_EnablePowerSave
+ \brief Enables one of the power saving modes. This API does not cause a
+ device state change. This is purely a configuration API.
+ \param hHal - The handle returned by macOpen.
+ \param psMode - The power saving mode to enable.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_EnablePowerSave (
+ tHalHandle hHal,
+ tPmcPowerSavingMode psMode);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_DisablePowerSave
+ \brief Disables one of the power saving modes.Disabling does not imply
+ that device will be brought out of the current PS mode. This is
+ purely a configuration API.
+ \param hHal - The handle returned by macOpen.
+ \param psMode - The power saving mode to disable.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_DisablePowerSave (
+ tHalHandle hHal,
+ tPmcPowerSavingMode psMode);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_StartAutoBmpsTimer
+ \brief Starts a timer that periodically polls all the registered
+ module for entry into Bmps mode. This timer is started only if BMPS is
+ enabled and whenever the device is in full power.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_StartAutoBmpsTimer ( tHalHandle hHal);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_StopAutoBmpsTimer
+ \brief Stops the Auto BMPS Timer that was started using sme_startAutoBmpsTimer
+ Stopping the timer does not cause a device state change. Only the timer
+ is stopped. If "Full Power" is desired, use the sme_RequestFullPower API
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_StopAutoBmpsTimer ( tHalHandle hHal);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_QueryPowerState
+ \brief Returns the current power state of the device.
+ \param hHal - The handle returned by macOpen.
+ \param pPowerState - pointer to location to return power state
+ \param pSwWlanSwitchState - ptr to location to return SW WLAN Switch state
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_QueryPowerState (
+ tHalHandle hHal,
+ tPmcPowerState *pPowerState,
+ tPmcSwitchState *pSwWlanSwitchState);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_IsPowerSaveEnabled
+ \brief Checks if the device is able to enter a particular power save mode
+ This does not imply that the device is in a particular PS mode
+ \param hHal - The handle returned by macOpen.
+ \param psMode - the power saving mode
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+extern tANI_BOOLEAN sme_IsPowerSaveEnabled(
+ tHalHandle hHal,
+ tPmcPowerSavingMode psMode);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RequestFullPower
+ \brief Request that the device be brought to full power state.
+ Note 1: If "fullPowerReason" specificied in this API is set to
+ eSME_FULL_PWR_NEEDED_BY_HDD, PMC will clear any "buffered wowl" requests
+ and also clear any "buffered BMPS requests by HDD". Assumption is that since
+ HDD is requesting full power, we need to undo any previous HDD requests for
+ BMPS (using sme_RequestBmps) or WoWL (using sme_EnterWoWL). If the reason is
+ specified anything other than above, the buffered requests for BMPS and WoWL
+ will not be cleared.
+ Note 2: Requesting full power (no matter what the fullPowerReason is) doesn't
+ disable the "auto bmps timer" (if it is enabled) or clear any "buffered uapsd
+ request".
+ Note 3: When the device finally enters Full Power PMC will start a timer
+ if any of the following holds true:
+ - Auto BMPS mode is enabled
+ - Uapsd request is pending
+ - HDD's request for BMPS is pending
+ - HDD's request for WoWL is pending
+ On timer expiry PMC will attempt to put the device in BMPS mode if following
+ (in addition to those listed above) holds true:
+ - Polling of all modules through the Power Save Check routine passes
+ - STA is associated to an access point
+ \param hHal - The handle returned by macOpen.
+ \param - callbackRoutine Callback routine invoked in case of success/failure
+ \param - callbackContext - Cookie to be passed back during callback
+ \param - fullPowerReason - Reason why this API is being invoked. SME needs to
+ distinguish between BAP and HDD requests
+ \return eHalStatus - status
+ eHAL_STATUS_SUCCESS - device brought to full power state
+ eHAL_STATUS_FAILURE - device cannot be brought to full power state
+ eHAL_STATUS_PMC_PENDING - device is being brought to full power state,
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_RequestFullPower (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext,
+ tRequestFullPowerReason fullPowerReason);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RequestBmps
+ \brief Request that the device be put in BMPS state. Request will be
+ accepted only if BMPS mode is enabled and power save check routine
+ passes. Only HDD should invoke this API.
+ \param hHal - The handle returned by macOpen.
+ \param - callbackRoutine Callback routine invoked in case of success/failure
+ \param - callbackContext - Cookie to be passed back during callback
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - device is in BMPS state
+ eHAL_STATUS_FAILURE - device cannot be brought to BMPS state
+ eHAL_STATUS_PMC_PENDING - device is being brought to BMPS state
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_RequestBmps (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetDHCPTillPowerActiveFlag
+ \brief Sets/Clears DHCP related flag in PMC to disable/enable auto BMPS
+ entry by PMC
+ \param hHal - The handle returned by macOpen.
+ ---------------------------------------------------------------------------*/
+void sme_SetDHCPTillPowerActiveFlag(tHalHandle hHal, tANI_U8 flag);
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_StartUapsd
+ \brief Request that the device be put in UAPSD state. If the device is in
+ Full Power it will be put in BMPS mode first and then into UAPSD
+ mode.
+ \param hHal - The handle returned by macOpen.
+ \param - callbackRoutine Callback routine invoked in case of success/failure
+ \param - callbackContext - Cookie to be passed back during callback
+ eHAL_STATUS_SUCCESS - device is in UAPSD state
+ eHAL_STATUS_FAILURE - device cannot be brought to UAPSD state
+ eHAL_STATUS_PMC_PENDING - device is being brought to UAPSD state
+ eHAL_STATUS_PMC_DISABLED - UAPSD is disabled or BMPS mode is disabled
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_StartUapsd (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_StopUapsd
+ \brief Request that the device be put out of UAPSD state. Device will be
+ put in in BMPS state after stop UAPSD completes. Buffered requests for
+ UAPSD will be cleared after this.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - device is put out of UAPSD and back in BMPS state
+ eHAL_STATUS_FAILURE - device cannot be brought out of UAPSD state
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_StopUapsd (tHalHandle hHal);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RequestStandby
+ \brief Request that the device be put in standby. It is HDD's responsibility
+ to bring the chip to full power and do a discconnect before calling
+ this API. Request for standby will be rejected if STA is associated
+ to an AP.
+ \param hHal - The handle returned by macOpen.
+ \param - callbackRoutine Callback routine invoked in case of success/failure
+ \param - callbackContext - Cookie to be passed back during callback
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - device is in Standby mode
+ eHAL_STATUS_FAILURE - device cannot be put in standby mode
+ eHAL_STATUS_PMC_PENDING - device is being put in standby mode
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_RequestStandby (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RegisterPowerSaveCheck
+ \brief Register a power save check routine that is called whenever
+ the device is about to enter one of the power save modes.
+ \param hHal - The handle returned by macOpen.
+ \param checkRoutine - Power save check routine to be registered
+ \param callbackContext - Cookie to be passed back during callback
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully registered
+ eHAL_STATUS_FAILURE - not successfully registered
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_RegisterPowerSaveCheck (
+ tHalHandle hHal,
+ tANI_BOOLEAN (*checkRoutine) (void *checkContext), void *checkContext);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_DeregisterPowerSaveCheck
+ \brief Deregister a power save check routine
+ \param hHal - The handle returned by macOpen.
+ \param checkRoutine - Power save check routine to be deregistered
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully deregistered
+ eHAL_STATUS_FAILURE - not successfully deregistered
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_DeregisterPowerSaveCheck (
+ tHalHandle hHal,
+ tANI_BOOLEAN (*checkRoutine) (void *checkContext));
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RegisterDeviceStateUpdateInd
+ \brief Register a callback routine that is called whenever
+ the device enters a new device state (Full Power, BMPS, UAPSD)
+ \param hHal - The handle returned by macOpen.
+ \param callbackRoutine - Callback routine to be registered
+ \param callbackContext - Cookie to be passed back during callback
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully registered
+ eHAL_STATUS_FAILURE - not successfully registered
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_RegisterDeviceStateUpdateInd (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState),
+ void *callbackContext);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_DeregisterDeviceStateUpdateInd
+ \brief Deregister a routine that was registered for device state changes
+ \param hHal - The handle returned by macOpen.
+ \param callbackRoutine - Callback routine to be deregistered
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully deregistered
+ eHAL_STATUS_FAILURE - not successfully deregistered
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_DeregisterDeviceStateUpdateInd (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState));
+
+/* ---------------------------------------------------------------------------
+ \fn sme_WowlAddBcastPattern
+ \brief Add a pattern for Pattern Byte Matching in Wowl mode. Firmware will
+ do a pattern match on these patterns when Wowl is enabled during BMPS
+ mode.
+ \param hHal - The handle returned by macOpen.
+ \param pattern - Pattern to be added
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot add pattern
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_WowlAddBcastPattern (
+ tHalHandle hHal,
+ tpSirWowlAddBcastPtrn pattern);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_WowlDelBcastPattern
+ \brief Delete a pattern that was added for Pattern Byte Matching.
+ \param hHal - The handle returned by macOpen.
+ \param pattern - Pattern to be deleted
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot delete pattern
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_WowlDelBcastPattern (
+ tHalHandle hHal,
+ tpSirWowlDelBcastPtrn pattern);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_EnterWowl
+ \brief This is the API to request entry into WOWL mode.
+ WoWLAN works on top of BMPS mode. If the device is not in BMPS mode,
+ SME will will cache the information that WOWL has been requested and
+ attempt to put the device in BMPS first. On entry into BMPS, SME will
+ enter the WOWL mode.
+ Note 1: After WoWL request is accepted, If module other than HDD requests
+ full power BEFORE WoWL request is completed, PMC will buffer the WoWL request
+ and attempt to put the chip into BMPS+WOWL based on a timer.
+ Note 2: Buffered request for WoWL will be cleared immedisately AFTER "enter Wowl"
+ completes or if HDD requests full power or if sme_ExitWoWL API is invoked.
+ Note 3: Both UAPSD and WOWL work on top of BMPS. On entry into BMPS, SME
+ will give priority to UAPSD and enable only UAPSD if both UAPSD and WOWL
+ are required. Currently there is no requirement or use case to support UAPSD
+ and WOWL at the same time.
+ Note 4. Request for WoWL is rejected if there is a pending UAPSD request.
+ Note 5. Request for WoWL is rejected if BMPS is disabled.
+
+ \param hHal - The handle returned by macOpen.
+ \param enterWowlCallbackRoutine - Callback routine provided by HDD.
+ Used for success/failure notification by SME
+ \param enterWowlCallbackContext - A cookie passed by HDD, that is passed back to HDD
+ at the time of callback.
+ \param wakeReasonIndCB - Callback routine provided by HDD.
+ Used for Wake Reason Indication by SME
+ \param wakeReasonIndCBContext - A cookie passed by HDD, that is passed back to HDD
+ at the time of callback.
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS Device is already in WoWLAN mode
+ eHAL_STATUS_FAILURE Device cannot enter WoWLAN mode.
+ eHAL_STATUS_PMC_PENDING Request accepted. SME will enable WOWL when BMPS
+ mode is entered.
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_EnterWowl (
+ tHalHandle hHal,
+ void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status),
+ void *enterWowlCallbackContext,
+#ifdef WLAN_WAKEUP_EVENTS
+ void (*wakeReasonIndCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd),
+ void *wakeReasonIndCBContext,
+#endif // WLAN_WAKEUP_EVENTS
+ tpSirSmeWowlEnterParams wowlEnterParams);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ExitWowl
+ \brief This is the SME API exposed to HDD to request exit from WoWLAN mode.
+ SME will initiate exit from WoWLAN mode and device will be put in BMPS
+ mode. Any Buffered request for WoWL will be cleared after this API.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Device cannot exit WoWLAN mode. This can happen
+ only if the previous "Enter WOWL" transaction has
+ not even completed.
+ eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode.
+ ---------------------------------------------------------------------------*/
+extern eHalStatus sme_ExitWowl (tHalHandle hHal);
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RoamSetKey
+
+ \brief To set encryption key. This function should be called only when connected
+ This is an asynchronous API.
+
+ \param pSetKeyInfo - pointer to a caller allocated object of tCsrSetContextInfo
+
+ \param pRoamId Upon success return, this is the id caller can use to identify the request in roamcallback
+
+ \return eHalStatus SUCCESS Roam callback will be called indicate actually results
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamSetKey(tHalHandle, tANI_U8 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 *pRoamId);
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RoamRemoveKey
+
+ \brief To set encryption key. This is an asynchronous API.
+
+ \param pRemoveKey - pointer to a caller allocated object of tCsrRoamRemoveKey
+
+ \param pRoamId Upon success return, this is the id caller can use to identify the request in roamcallback
+
+ \return eHalStatus SUCCESS Roam callback will be called indicate actually results
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamRemoveKey(tHalHandle, tANI_U8 sessionId, tCsrRoamRemoveKey *pRemoveKey, tANI_U32 *pRoamId);
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetCountryCode
+
+ \brief To return the current country code. If no country code is applied, default country code is
+ used to fill the buffer.
+ If 11d supported is turned off, an error is return and the last applied/default country code is used.
+ This is a synchronous API.
+
+ \param pBuf - pointer to a caller allocated buffer for returned country code.
+
+ \param pbLen For input, this parameter indicates how big is the buffer.
+ Upon return, this parameter has the number of bytes for country. If pBuf
+ doesn't have enough space, this function returns
+ fail status and this parameter contains the number that is needed.
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetCountryCode(tHalHandle hHal, tANI_U8 *pBuf, tANI_U8 *pbLen);
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_SetCountryCode
+
+ \brief To change the current/default country code.
+ If 11d supported is turned off, an error is return.
+ This is a synchronous API.
+
+ \param pCountry - pointer to a caller allocated buffer for the country code.
+
+ \param pfRestartNeeded A pointer to caller allocated memory, upon successful return, it indicates
+ whether a reset is required.
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_SetCountryCode(tHalHandle hHal, tANI_U8 *pCountry, tANI_BOOLEAN *pfRestartNeeded);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ResetCountryCodeInformation
+ \brief this function is to reset the country code current being used back to EEPROM default
+ this includes channel list and power setting. This is a synchronous API.
+ \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether
+ a restart is needed to apply the change
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_ResetCountryCodeInformation(tHalHandle hHal, tANI_BOOLEAN *pfRestartNeeded);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetSupportedCountryCode
+ \brief this function is to get a list of the country code current being supported
+ \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return,
+ this has the country code list. 3 bytes for each country code. This may be NULL if
+ caller wants to know the needed byte count.
+ \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return,
+ this contains the length of the data in pBuf. If pbuf is NULL, as input, *pbLen should be 0.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetSupportedCountryCode(tHalHandle hHal, tANI_U8 *pBuf, tANI_U32 *pbLen);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetCurrentRegulatoryDomain
+ \brief this function is to get the current regulatory domain. This is a synchronous API.
+ This function must be called after CFG is downloaded and all the band/mode setting already passed into
+ SME. The function fails if 11d support is turned off.
+ \param pDomain - Caller allocated buffer to return the current domain.
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetCurrentRegulatoryDomain(tHalHandle hHal, v_REGDOMAIN_t *pDomain);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetRegulatoryDomain
+ \brief this function is to set the current regulatory domain.
+ This function must be called after CFG is downloaded and all the band/mode setting already passed into
+ SME. This is a synchronous API.
+ \param domainId - indicate the domain (defined in the driver) needs to set to.
+ See v_REGDOMAIN_t for definition
+ \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether
+ a restart is needed to apply the change
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_SetRegulatoryDomain(tHalHandle hHal, v_REGDOMAIN_t domainId, tANI_BOOLEAN *pfRestartNeeded);
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetRegulatoryDomainForCountry
+
+ \brief To return a regulatory domain base on a country code. This is a synchronous API.
+
+ \param pCountry - pointer to a caller allocated buffer for input country code.
+
+ \param pDomainId Upon successful return, it is the domain that country belongs to.
+ If it is NULL, returning success means that the country code is known.
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetRegulatoryDomainForCountry(tHalHandle hHal, tANI_U8 *pCountry, v_REGDOMAIN_t *pDomainId);
+
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetSupportedRegulatoryDomains
+
+ \brief To return a list of supported regulatory domains. This is a synchronous API.
+
+ \param pDomains - pointer to a caller allocated buffer for returned regulatory domains.
+
+ \param pNumDomains For input, this parameter indicates howm many domains pDomains can hold.
+ Upon return, this parameter has the number for supported domains. If pDomains
+ doesn't have enough space for all the supported domains, this function returns
+ fail status and this parameter contains the number that is needed.
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetSupportedRegulatoryDomains(tHalHandle hHal, v_REGDOMAIN_t *pDomains, tANI_U32 *pNumDomains);
+
+//some support functions
+tANI_BOOLEAN sme_Is11dSupported(tHalHandle hHal);
+tANI_BOOLEAN sme_Is11hSupported(tHalHandle hHal);
+tANI_BOOLEAN sme_IsWmmSupported(tHalHandle hHal);
+//Upper layer to get the list of the base channels to scan for passively 11d info from csr
+eHalStatus sme_ScanGetBaseChannels( tHalHandle hHal, tCsrChannelInfo * pChannelInfo );
+
+typedef void ( *tSmeChangeCountryCallback)(void *pContext);
+/* ---------------------------------------------------------------------------
+
+ \fn sme_ChangeCountryCode
+
+ \brief Change Country code from upperlayer during WLAN driver operation.
+ This is a synchronous API.
+
+ \param hHal - The handle returned by macOpen.
+
+ \param pCountry New Country Code String
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_ChangeCountryCode( tHalHandle hHal,
+ tSmeChangeCountryCallback callback,
+ tANI_U8 *pCountry,
+ void *pContext,
+ void* pVosContext );
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_BtcSignalBtEvent
+ \brief API to signal Bluetooth (BT) event to the WLAN driver. Based on the
+ BT event type and the current operating mode of Libra (full power,
+ BMPS, UAPSD etc), appropriate Bluetooth Coexistence (BTC) strategy
+ would be employed.
+ \param hHal - The handle returned by macOpen.
+ \param pBtcBtEvent - Pointer to a caller allocated object of type tSmeBtEvent
+ Caller owns the memory and is responsible for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE BT Event not passed to HAL. This can happen
+ if driver has not yet been initialized or if BTC
+ Events Layer has been disabled.
+ VOS_STATUS_SUCCESS BT Event passed to HAL
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_BtcSignalBtEvent (tHalHandle hHal, tpSmeBtEvent pBtcBtEvent);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_BtcSetConfig
+ \brief API to change the current Bluetooth Coexistence (BTC) configuration
+ This function should be invoked only after CFG download has completed.
+ Calling it after sme_HDDReadyInd is recommended.
+ \param hHal - The handle returned by macOpen.
+ \param pSmeBtcConfig - Pointer to a caller allocated object of type
+ tSmeBtcConfig. Caller owns the memory and is responsible
+ for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE Config not passed to HAL.
+ VOS_STATUS_SUCCESS Config passed to HAL
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_BtcSetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_BtcGetConfig
+ \brief API to retrieve the current Bluetooth Coexistence (BTC) configuration
+ \param hHal - The handle returned by macOpen.
+ \param pSmeBtcConfig - Pointer to a caller allocated object of type tSmeBtcConfig.
+ Caller owns the memory and is responsible for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_BtcGetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetCfgPrivacy
+ \brief API to set configure privacy parameters
+ \param hHal - The handle returned by macOpen.
+ \param pProfile - Pointer CSR Roam profile.
+ \param fPrivacy - This parameter indicates status of privacy
+
+ \return void
+ ---------------------------------------------------------------------------*/
+void sme_SetCfgPrivacy(tHalHandle hHal, tCsrRoamProfile *pProfile, tANI_BOOLEAN fPrivacy);
+
+#if defined WLAN_FEATURE_VOWIFI
+/* ---------------------------------------------------------------------------
+ \fn sme_NeighborReportRequest
+ \brief API to request neighbor report.
+ \param hHal - The handle returned by macOpen.
+ \param pRrmNeighborReq - Pointer to a caller allocated object of type
+ tRrmNeighborReq. Caller owns the memory and is responsible
+ for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_NeighborReportRequest (tHalHandle hHal, tANI_U8 sessionId,
+ tpRrmNeighborReq pRrmNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo);
+#endif
+
+//The following are debug APIs to support direct read/write register/memory
+//They are placed in SME because HW cannot be access when in LOW_POWER state
+//AND not connected. The knowledge and synchronization is done in SME
+
+//sme_DbgReadRegister
+//Caller needs to validate the input values
+VOS_STATUS sme_DbgReadRegister(tHalHandle hHal, v_U32_t regAddr, v_U32_t *pRegValue);
+
+//sme_DbgWriteRegister
+//Caller needs to validate the input values
+VOS_STATUS sme_DbgWriteRegister(tHalHandle hHal, v_U32_t regAddr, v_U32_t regValue);
+
+//sme_DbgReadMemory
+//Caller needs to validate the input values
+//pBuf caller allocated buffer has the length of nLen
+VOS_STATUS sme_DbgReadMemory(tHalHandle hHal, v_U32_t memAddr, v_U8_t *pBuf, v_U32_t nLen);
+
+//sme_DbgWriteMemory
+//Caller needs to validate the input values
+VOS_STATUS sme_DbgWriteMemory(tHalHandle hHal, v_U32_t memAddr, v_U8_t *pBuf, v_U32_t nLen);
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+//sme_GetFwVersion
+VOS_STATUS sme_GetFwVersion (tHalHandle hHal,FwVersionInfo *pVersion);
+#endif
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+VOS_STATUS sme_GetWcnssWlanCompiledVersion(tHalHandle hHal,
+ tSirVersionType *pVersion);
+VOS_STATUS sme_GetWcnssWlanReportedVersion(tHalHandle hHal,
+ tSirVersionType *pVersion);
+VOS_STATUS sme_GetWcnssSoftwareVersion(tHalHandle hHal,
+ tANI_U8 *pVersion,
+ tANI_U32 versionBufferSize);
+VOS_STATUS sme_GetWcnssHardwareVersion(tHalHandle hHal,
+ tANI_U8 *pVersion,
+ tANI_U32 versionBufferSize);
+#endif
+eHalStatus sme_RoamRegisterCallback(tHalHandle hHal,
+ csrRoamCompleteCallback callback,
+ void *pContext);
+
+#ifdef FEATURE_WLAN_WAPI
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamSetBKIDCache
+ \brief The SME API exposed to HDD to allow HDD to provde SME the BKID
+ candidate list.
+ \param hHal - Handle to the HAL. The HAL handle is returned by the HAL after
+ it is opened (by calling halOpen).
+ \param pBKIDCache - caller allocated buffer point to an array of tBkidCacheInfo
+ \param numItems - a variable that has the number of tBkidCacheInfo allocated
+ when retruning, this is the number of items put into pBKIDCache
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough and pNumItems has the number of tBkidCacheInfo.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamSetBKIDCache( tHalHandle hHal, tANI_U32 sessionId, tBkidCacheInfo *pBKIDCache,
+ tANI_U32 numItems );
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetBKIDCache
+ \brief The SME API exposed to HDD to allow HDD to request SME to return its
+ BKID cache.
+ \param hHal - Handle to the HAL. The HAL handle is returned by the HAL after
+ it is opened (by calling halOpen).
+ \param pNum - caller allocated memory that has the space of the number of
+ tBkidCacheInfo as input. Upon returned, *pNum has the needed number of entries
+ in SME cache.
+ \param pBkidCache - Caller allocated memory that contains BKID cache, if any,
+ upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetBKIDCache(tHalHandle hHal, tANI_U32 *pNum,
+ tBkidCacheInfo *pBkidCache);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetNumBKIDCache
+ \brief The SME API exposed to HDD to allow HDD to request SME to return the
+ number of BKID cache entries.
+ \param hHal - Handle to the HAL. The HAL handle is returned by the HAL after
+ it is opened (by calling halOpen).
+ \return tANI_U32 - the number of BKID cache entries.
+ ---------------------------------------------------------------------------*/
+tANI_U32 sme_RoamGetNumBKIDCache(tHalHandle hHal, tANI_U32 sessionId);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanGetBKIDCandidateList
+ \brief a wrapper function to return the BKID candidate list
+ \param pBkidList - caller allocated buffer point to an array of
+ tBkidCandidateInfo
+ \param pNumItems - pointer to a variable that has the number of
+ tBkidCandidateInfo allocated when retruning, this is
+ either the number needed or number of items put into
+ pPmkidList
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough and pNumItems
+ has the number of tBkidCandidateInfo.
+ \Note: pNumItems is a number of tBkidCandidateInfo,
+ not sizeof(tBkidCandidateInfo) * something
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanGetBKIDCandidateList(tHalHandle hHal, tANI_U32 sessionId,
+ tBkidCandidateInfo *pBkidList,
+ tANI_U32 *pNumItems );
+#endif /* FEATURE_WLAN_WAPI */
+
+
+
+#ifdef WLAN_SOFTAP_FEATURE
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RoamUpdateAPWPSIE
+
+ \brief To update AP's WPS IE. This function should be called after SME AP session is created
+ This is an asynchronous API.
+
+ \param pAPWPSIES - pointer to a caller allocated object of tCsrRoamAPWPSIES
+
+ \return eHalStatus – SUCCESS – Roam callback will be called indicate actually results
+
+ FAILURE or RESOURCES – The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+
+eHalStatus sme_RoamUpdateAPWPSIE(tHalHandle, tANI_U8 sessionId, tSirAPWPSIEs *pAPWPSIES);
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RoamUpdateAPWPARSNIEs
+
+ \brief To update AP's WPA/RSN IEs. This function should be called after SME AP session is created
+ This is an asynchronous API.
+
+ \param pAPSirRSNie - pointer to a caller allocated object of tSirRSNie with WPS/RSN IEs
+
+ \return eHalStatus – SUCCESS –
+
+ FAILURE or RESOURCES – The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamUpdateAPWPARSNIEs(tHalHandle hHal, tANI_U8 sessionId, tSirRSNie * pAPSirRSNie);
+
+#endif
+
+/* ---------------------------------------------------------------------------
+ \fn sme_sendBTAmpEvent
+ \brief API to send the btAMPstate to FW
+ \param hHal - The handle returned by macOpen.
+ \param btAmpEvent -- btAMP event
+ \return eHalStatus – SUCCESS –
+
+ FAILURE or RESOURCES – The API finished and failed.
+
+--------------------------------------------------------------------------- */
+
+eHalStatus sme_sendBTAmpEvent(tHalHandle hHal, tSmeBtAmpEvent btAmpEvent);
+
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetHostOffload
+ \brief API to set the host offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the offload request.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetKeepAlive
+ \brief API to set the Keep Alive feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the Keep Alive request.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest);
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_AbortMacScan
+ \brief API to cancel MAC scan.
+ \param hHal - The handle returned by macOpen.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_AbortMacScan(tHalHandle hHal);
+
+/* ----------------------------------------------------------------------------
+ \fn sme_GetOperationChannel
+ \brief API to get current channel on which STA is parked
+ this function gives channel information only of infra station or IBSS station.
+ \param hHal and poiter to memory location
+ \returns eHAL_STATUS_SUCCESS
+ eHAL_STATUS_FAILURE
+-------------------------------------------------------------------------------*/
+eHalStatus sme_GetOperationChannel(tHalHandle hHal, tANI_U32 *pChannel);
+
+#ifdef WLAN_FEATURE_P2P
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RegisterMgtFrame
+
+ \brief To register managment frame of specified type and subtype.
+ \param frameType - type of the frame that needs to be passed to HDD.
+ \param matchData - data which needs to be matched before passing frame
+ to HDD.
+ \param matchDataLen - Length of matched data.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RegisterMgmtFrame(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U16 frameType, tANI_U8* matchData, tANI_U16 matchLen);
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_DeregisterMgtFrame
+
+ \brief To De-register managment frame of specified type and subtype.
+ \param frameType - type of the frame that needs to be passed to HDD.
+ \param matchData - data which needs to be matched before passing frame
+ to HDD.
+ \param matchDataLen - Length of matched data.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_DeregisterMgmtFrame(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U16 frameType, tANI_U8* matchData, tANI_U16 matchLen);
+#endif
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_ConfigureRxpFilter
+
+ \brief
+ SME will pass this request to lower mac to set/reset the filter on RXP for
+ multicast & broadcast traffic.
+
+ \param
+
+ hHal - The handle returned by macOpen.
+
+ filterMask- Currently the API takes a 1 or 0 (set or reset) as filter.
+ Basically to enable/disable the filter (to filter "all" mcbc traffic) based
+ on this param. In future we can use this as a mask to set various types of
+ filters as suggested below:
+ FILTER_ALL_MULTICAST:
+ FILTER_ALL_BROADCAST:
+ FILTER_ALL_MULTICAST_BROADCAST:
+
+
+ \return eHalStatus
+
+
+--------------------------------------------------------------------------- */
+eHalStatus sme_ConfigureRxpFilter( tHalHandle hHal,
+ tpSirWlanSetRxpFilters wlanRxpFilterParam);
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_ConfigureAppsCpuWakeupState
+
+ \brief
+ SME will pass this request to lower mac to dynamically adjusts the listen
+ interval based on the WLAN/MSM activity. This feature is named as
+ Telescopic Beacon wakeup feature.
+
+ \param
+
+ hHal - The handle returned by macOpen.
+
+ isAppsAwake- Depicts the state of the Apps CPU
+
+
+ \return eHalStatus
+
+
+--------------------------------------------------------------------------- */
+eHalStatus sme_ConfigureAppsCpuWakeupState( tHalHandle hHal, tANI_BOOLEAN isAppsAwake);
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+/* ---------------------------------------------------------------------------
+
+ \fn sme_ConfigureSuspendInd
+
+ \brief
+ SME will pass this request to lower mac to Indicate that the wlan needs to
+ be suspended
+
+ \param
+
+ hHal - The handle returned by macOpen.
+
+ wlanSuspendParam- Depicts the wlan suspend params
+
+
+ \return eHalStatus
+
+
+--------------------------------------------------------------------------- */
+eHalStatus sme_ConfigureSuspendInd( tHalHandle hHal,
+ tpSirWlanSuspendParam wlanSuspendParam);
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_ConfigureResumeReq
+
+ \brief
+ SME will pass this request to lower mac to Indicate that the wlan needs to
+ be Resumed
+
+ \param
+
+ hHal - The handle returned by macOpen.
+
+ wlanResumeParam- Depicts the wlan resume params
+
+
+ \return eHalStatus
+
+
+--------------------------------------------------------------------------- */
+eHalStatus sme_ConfigureResumeReq( tHalHandle hHal,
+ tpSirWlanResumeParam wlanResumeParam);
+
+#endif
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetInfraSessionId
+
+ \brief To get the session ID for infra session, if connected
+ This is a synchronous API.
+
+ \param hHal - The handle returned by macOpen.
+
+ \return sessionid, -1 if infra session is not connected
+
+ -------------------------------------------------------------------------------*/
+tANI_S8 sme_GetInfraSessionId(tHalHandle hHal);
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetInfraOperationChannel
+
+ \brief To get the operating channel for infra session, if connected
+ This is a synchronous API.
+
+ \param hHal - The handle returned by macOpen.
+ \param sessionId - the sessionId returned by sme_OpenSession.
+
+ \return operating channel, 0 if infra session is not connected
+
+ -------------------------------------------------------------------------------*/
+tANI_U8 sme_GetInfraOperationChannel( tHalHandle hHal, tANI_U8 sessionId);
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetConcurrentOperationChannel
+
+ \brief To get the operating channel for other concurrent sessions, if connected
+ This is a synchronous API.
+
+ \param hHal - The handle returned by macOpen.
+ \param currentPersona - persona that is trying to come up.
+
+ \return operating channel, 0 if infra session is not connected
+
+ -------------------------------------------------------------------------------*/
+tANI_U8 sme_GetConcurrentOperationChannel( tHalHandle hHal );
+
+/* ---------------------------------------------------------------------------
+ \fn sme_AbortMacScan
+ \brief API to cancel MAC scan.
+ \param hHal - The handle returned by macOpen.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_AbortMacScan(tHalHandle hHal);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetCfgValidChannels
+ \brief API to get valid channel list
+ \param hHal - The handle returned by macOpen.
+ \param aValidChannels - Pointer to the valid channel list
+ \param len - valid channel list length
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_GetCfgValidChannels(tHalHandle hHal, tANI_U8 *aValidChannels, tANI_U32 *len);
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetPreferredNetworkList
+ \brief API to set the Preferred Network List Offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the offload request.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetPreferredNetworkList (tHalHandle hHal, tpSirPNOScanReq pRequest, tANI_U8 sessionId, preferredNetworkFoundIndCallback callbackRoutine, void *callbackContext );
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetRSSIFilter
+ \brief API to set RSSI Filter feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the offload request.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetRSSIFilter(tHalHandle hHal, v_U8_t rssiThreshold);
+
+/******************************************************************************
+*
+* Name: sme_PreferredNetworkFoundInd
+*
+* Description:
+* Invoke Preferred Network Found Indication
+*
+* Parameters:
+* hHal - HAL handle for device
+* pMsg - found network description
+*
+* Returns: eHalStatus
+*
+******************************************************************************/
+eHalStatus sme_PreferredNetworkFoundInd (tHalHandle hHal, void* pMsg);
+#endif // FEATURE_WLAN_SCAN_PNO
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetPowerParams
+ \brief API to set Power Parameters
+ \param hHal - The handle returned by macOpen.
+ \param pwParams - Pointer to the power parameters requested.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetTxPerTracking
+ \brief Set Tx PER tracking configuration parameters
+ \param hHal - The handle returned by macOpen.
+ \param pTxPerTrackingParam - Tx PER configuration parameters
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetTxPerTracking (
+ tHalHandle hHal,
+ void (*pCallbackfn) (void *pCallbackContext),
+ void *pCallbackContext,
+ tpSirTxPerTrackingParam pTxPerTrackingParam);
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+/* ---------------------------------------------------------------------------
+ \fn sme_ReceiveFilterSetFilter
+ \brief API to set 8023 Multicast Address List
+ \param hHal - The handle returned by macOpen.
+ \param pMulticastAddrs - Pointer to the Multicast Address List
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_8023MulticastList(tHalHandle hHal, tpSirRcvFltMcAddrList pMulticastAddrs);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ReceiveFilterSetFilter
+ \brief API to set Receive Packet Filter
+ \param hHal - The handle returned by macOpen.
+ \param pRcvPktFilterCfg - Receive Packet Filter parameter
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ReceiveFilterSetFilter(tHalHandle hHal, tpSirRcvPktFilterCfgType pRcvPktFilterCfg);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetFilterMatchCount
+ \brief API to get D0 PC Filter Match Count
+ \param hHal - The handle returned by macOpen
+ \param callbackRoutine - Callback routine invoked to receive Packet Coalescing Filter Match Count
+ \param callbackContext - Cookie to be passed back during callback
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_GetFilterMatchCount(tHalHandle hHal,
+ FilterMatchCountCallback callbackRoutine,
+ void *callbackContext );
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ReceiveFilterClearFilter
+ \brief API to clear Receive Packet Filter
+ \param hHal - The handle returned by macOpen.
+ \param pRcvFltPktClearParam - Receive Packet Filter Clear parameter
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ReceiveFilterClearFilter(tHalHandle hHal,
+ tpSirRcvFltPktClearParam pRcvFltPktClearParam);
+#endif // WLAN_FEATURE_PACKET_FILTERING
+/* ---------------------------------------------------------------------------
+
+ \fn sme_IsChannelValid
+ \brief To check if the channel is valid for currently established domain
+ This is a synchronous API.
+
+ \param hHal - The handle returned by macOpen.
+ \param channel - channel to verify
+
+ \return TRUE/FALSE, TRUE if channel is valid
+
+ -------------------------------------------------------------------------------*/
+tANI_BOOLEAN sme_IsChannelValid(tHalHandle hHal, tANI_U8 channel);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetFreqBand
+ \brief Used to set frequency band.
+ \param hHal
+ \eBand band value to be configured
+ \- return eHalStatus
+ -------------------------------------------------------------------------*/
+eHalStatus sme_SetFreqBand(tHalHandle hHal, eCsrBand eBand);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetFreqBand
+ \brief Used to get the current band settings.
+ \param hHal
+ \pBand pointer to hold the current band value
+ \- return eHalStatus
+ -------------------------------------------------------------------------*/
+eHalStatus sme_GetFreqBand(tHalHandle hHal, eCsrBand *pBand);
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_SetTxPerTracking
+ \brief Set Tx PER tracking configuration parameters
+ \param hHal - The handle returned by macOpen.
+ \param pTxPerTrackingParam - Tx PER configuration parameters
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetTxPerTracking (
+ tHalHandle hHal,
+ void (*pCallbackfn) (void *pCallbackContext),
+ void *pCallbackContext,
+ tpSirTxPerTrackingParam pTxPerTrackingParam);
+
+#ifdef WLAN_FEATURE_GTK_OFFLOAD
+/* ---------------------------------------------------------------------------
+ \fn sme_SetGTKOffload
+ \brief API to set GTK offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the GTK offload request.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pRequest);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetGTKOffload
+ \brief API to get GTK offload information.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the GTK offload response.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_GetGTKOffload (tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, void *callbackContext );
+#endif // WLAN_FEATURE_GTK_OFFLOAD
+
+#ifdef WLAN_WAKEUP_EVENTS
+eHalStatus sme_WakeReasonIndCallback (tHalHandle hHal, void* pMsg);
+#endif // WLAN_WAKEUP_EVENTS
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetTxPerTracking
+ \brief Set Tx PER tracking configuration parameters
+ \param hHal - The handle returned by macOpen.
+ \param pTxPerTrackingParam - Tx PER configuration parameters
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetTxPerTracking (
+ tHalHandle hHal,
+ void (*pCallbackfn) (void *pCallbackContext),
+ void *pCallbackContext,
+ tpSirTxPerTrackingParam pTxPerTrackingParam);
+
+
+//return frequency for a particular channel
+tANI_U16 sme_ChnToFreq(tANI_U8 chanNum);
+
+tANI_BOOLEAN sme_IsChannelValid(tHalHandle hHal, tANI_U8 channel);
+
+#if defined WLAN_FEATURE_P2P_INTERNAL
+
+eHalStatus sme_p2pResetSession(tHalHandle hHal, tANI_U8 HDDSessionId);
+
+/* ---------------------------------------------------------------------------
+ \fn sme_p2pFlushDeviceList
+ \brief Remove cached P2P result from scan results
+ \param hHal - The handle returned by macOpen.
+ \param HDDSessionId - HDD's sessionId. Currently unused.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_p2pFlushDeviceList(tHalHandle hHal, tANI_U8 HDDSessionId);
+
+eHalStatus sme_p2pGetResultFilter(tHalHandle hHal, tANI_U8 HDDSessionId,
+ tCsrScanResultFilter *pFilter);
+
+#endif //#if defined WLAN_FEATURE_P2P_INTERNAL
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetMaxTxPower
+ \brief Used to set the Maximum Transmit Power dynamically. Note: this
+ setting will not persist over reboots
+ \param hHal
+ \param pBssid BSSID to set the power cap for
+ \param pBssid pSelfMacAddress self MAC Address
+ \param pBssid power to set in dB
+ \- return eHalStatus
+ -------------------------------------------------------------------------*/
+eHalStatus sme_SetMaxTxPower(tHalHandle hHal, tSirMacAddr pBssid,
+ tSirMacAddr pSelfMacAddress, v_S7_t dB);
+
+#ifdef WLAN_SOFTAP_FEATURE
+/* ---------------------------------------------------------------------------
+
+ \fn sme_HideSSID
+
+ \brief Enable/Disables hidden SSID dynamically. Note: this setting will
+ not persist over reboots.
+
+ \param hHal
+ \param sessionId
+ \param ssidHidden 0 - Broadcast SSID, 1 - Disable broadcast SSID
+ \- return eHalStatus
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_HideSSID(tHalHandle hHal, v_U8_t sessionId, v_U8_t ssidHidden);
+#endif
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_SetTmLevel
+ \brief Set Thermal Mitigation Level to RIVA
+ \param hHal - The handle returned by macOpen.
+ \param newTMLevel - new Thermal Mitigation Level
+ \param tmMode - Thermal Mitigation handle mode, default 0
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetTmLevel(tHalHandle hHal, v_U16_t newTMLevel, v_U16_t tmMode);
+
+/*---------------------------------------------------------------------------
+
+ \brief sme_featureCapsExchange() - SME interface to exchange capabilities between
+ Host and FW.
+
+ \param hHal - HAL handle for device
+
+ \return NONE
+
+---------------------------------------------------------------------------*/
+void sme_featureCapsExchange(tHalHandle hHal);
+
+#endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/inc/sme_FTApi.h b/CORE/SME/inc/sme_FTApi.h
new file mode 100644
index 0000000..30465c6
--- /dev/null
+++ b/CORE/SME/inc/sme_FTApi.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+#if !defined( __SME_FTAPI_H )
+#define __SME_FTAPI_H
+
+#include <limFTDefs.h>
+#include <palTimer.h>
+
+/**=========================================================================
+
+ \brief macros and prototype for SME APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+typedef enum eFTIEState
+{
+ eFT_START_READY, // Start before and after 11r assoc
+ eFT_AUTH_REQ_READY, // When we have recvd the 1st or nth auth req
+ eFT_WAIT_AUTH2, // Sent auth1 and waiting auth2
+ eFT_AUTH_COMPLETE, // We are now ready for FT phase, send auth1, recd auth2
+ eFT_REASSOC_REQ_WAIT, // Now we have sent Auth Rsp to the supplicant and waiting
+ // Reassoc Req from the supplicant.
+ eFT_SET_KEY_WAIT, // We have received the Reassoc request from
+ // supplicant. Waiting for the keys.
+} tFTIEStates;
+
+
+typedef struct sFTSMEContext
+{
+ tANI_U8 *auth_ft_ies;
+ tANI_U32 auth_ft_ies_length;
+
+ tANI_U8 *reassoc_ft_ies;
+ tANI_U16 reassoc_ft_ies_length;
+
+ // Pre-Auth info
+ tFTIEStates FTState; // The state of FT in the current 11rAssoc
+ tSirMacAddr preAuthbssId; // BSSID to preauth to
+ tANI_U32 smeSessionId;
+
+ // Saved pFTPreAuthRsp
+ tpSirFTPreAuthRsp psavedFTPreAuthRsp;
+
+ // Time to trigger reassoc once pre-auth is successful
+ tPalTimerHandle preAuthReassocIntvlTimer;
+
+} tftSMEContext, *tpftSMEContext;
+
+/*--------------------------------------------------------------------------
+ Prototype functions
+ ------------------------------------------------------------------------*/
+void sme_FTOpen(tHalHandle hHal);
+void sme_FTClose(tHalHandle hHal);
+void sme_SetFTIEs( tHalHandle hHal, tANI_U8 sessionId, tANI_U8 *ft_ies, tANI_U16 ft_ies_length );
+eHalStatus sme_FTUpdateKey( tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo );
+void csrFTPreAuthRspProcessor( tHalHandle hHal, tpSirFTPreAuthRsp pFTPreAuthRsp );
+void sme_GetFTPreAuthResponse( tHalHandle hHal, tANI_U8 *ft_ies, tANI_U32 ft_ies_ip_len, tANI_U16 *ft_ies_length );
+void sme_GetRICIEs( tHalHandle hHal, tANI_U8 *ric_ies, tANI_U32 ric_ies_ip_len, tANI_U32 *ric_ies_length );
+void sme_PreauthReassocIntvlTimerCallback(void *context);
+
+
+#endif //#if !defined( __SME_FTAPI_H )
diff --git a/CORE/SME/inc/sme_QosApi.h b/CORE/SME/inc/sme_QosApi.h
new file mode 100644
index 0000000..d6614fd
--- /dev/null
+++ b/CORE/SME/inc/sme_QosApi.h
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+
+#if !defined( __SME_QOSAPI_H )
+#define __SME_QOSAPI_H
+
+
+/**=========================================================================
+
+ \file sme_QosApi.h
+
+ \brief prototype for SME QoS APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/* $Header$ */
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "vos_lock.h"
+#include "vos_trace.h"
+#include "vos_memory.h"
+#include "vos_types.h"
+#include "aniGlobal.h"
+#include "sirApi.h"
+
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+ Enumeration of the various QoS status types that would be reported to HDD
+---------------------------------------------------------------------------*/
+typedef enum
+{
+ //async: once PE notifies successful TSPEC negotiation, or CSR notifies for
+ //successful reassoc, notifies HDD with current QoS Params
+ SME_QOS_STATUS_SETUP_SUCCESS_IND = 0,
+ //sync: only when App asked for APSD & it's already set with ACM = 0
+ SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY,
+ //both: sync or async: in case of async notifies HDD with current QoS Params
+ SME_QOS_STATUS_SETUP_FAILURE_RSP,
+ //sync
+ SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP,
+ //sync: AP doesn't support QoS (WMM)
+ SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP,
+ //sync: either req has been sent down to PE or just buffered in SME
+ SME_QOS_STATUS_SETUP_REQ_PENDING_RSP,
+ //async: in case of flow aggregation, if the new TSPEC negotiation is
+ //successful, OR,
+ //notify existing flows that TSPEC is modified with current QoS Params
+ SME_QOS_STATUS_SETUP_MODIFIED_IND,
+ //sync: no APSD asked for & ACM = 0
+ SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP,
+ //async: In case of UAPSD, once PE notifies successful TSPEC negotiation, or
+ //CSR notifies for successful reassoc to SME-QoS, notify HDD if PMC can't
+ //put the module in UAPSD mode right away (eHAL_STATUS_PMC_PENDING)
+ SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING,
+ //async: In case of UAPSD, once PE notifies successful TSPEC negotiation, or
+ //CSR notifies for successful reassoc to SME-QoS, notify HDD if PMC can't
+ //put the module in UAPSD mode at all (eHAL_STATUS_FAILURE)
+ SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED,
+
+ //sync: req has been sent down to PE in case of delts or addts for remain
+ // flows, OR if the AC doesn't have APSD or ACM
+ //async: once the downgrade req for QoS params is successful
+ SME_QOS_STATUS_RELEASE_SUCCESS_RSP = 100,
+ //both: sync or async: in case of async notifies HDD with current QoS Params
+ SME_QOS_STATUS_RELEASE_FAILURE_RSP,
+ //async: AP sent DELTS indication
+ SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
+ //sync: an addts req has been sent down to PE to downgrade the QoS params or
+ // just buffered in SME
+ SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP,
+ //sync
+ SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP,
+
+ //async: for QoS modify request if modification is successful, notifies HDD
+ // with current QoS Params
+ SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND = 200,
+ //sync: only when App asked for APSD & it's already set with ACM = 0
+ SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY,
+ //both: sync or async: in case of async notifies HDD with current QoS Params
+ SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP,
+ //sync: either req has been sent down to PE or just buffered in SME
+ SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP,
+ //sync: no APSD asked for & ACM = 0
+ SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP,
+ //sync
+ SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP,
+ //async: In case of UAPSD, once PE notifies successful TSPEC negotiation, or
+ //CSR notifies for successful reassoc to SME-QoS, notify HDD if PMC can't
+ //put the module in UAPSD mode right away (eHAL_STATUS_PMC_PENDING)
+ SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_PENDING,
+ //async: In case of UAPSD, once PE notifies successful TSPEC negotiation, or
+ //CSR notifies for successful reassoc to SME-QoS, notify HDD if PMC can't
+ //put the module in UAPSD mode at all (eHAL_STATUS_FAILURE)
+ SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED,
+ //sync: STA is handing off to a new AP
+ SME_QOS_STATUS_HANDING_OFF = 300,
+ //async:powersave mode changed by PMC from UAPSD to Full power
+ SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND = 400,
+ //async:powersave mode changed by PMC from Full power to UAPSD
+ SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND,
+
+}sme_QosStatusType;
+
+/*---------------------------------------------------------------------------
+ Enumeration of the various User priority (UP) types
+
+ From 802.1D/802.11e/WMM specifications (all refer to same table)
+---------------------------------------------------------------------------*/
+typedef enum
+{
+ SME_QOS_WMM_UP_BE = 0,
+ SME_QOS_WMM_UP_BK = 1,
+ SME_QOS_WMM_UP_RESV = 2, /* Reserved */
+ SME_QOS_WMM_UP_EE = 3,
+ SME_QOS_WMM_UP_CL = 4,
+ SME_QOS_WMM_UP_VI = 5,
+ SME_QOS_WMM_UP_VO = 6,
+ SME_QOS_WMM_UP_NC = 7,
+
+ SME_QOS_WMM_UP_MAX
+
+}sme_QosWmmUpType;
+
+/*---------------------------------------------------------------------------
+ Enumeration of the various TSPEC directions
+
+ From 802.11e/WMM specifications
+---------------------------------------------------------------------------*/
+
+typedef enum
+{
+ SME_QOS_WMM_TS_DIR_UPLINK = 0,
+ SME_QOS_WMM_TS_DIR_DOWNLINK = 1,
+ SME_QOS_WMM_TS_DIR_RESV = 2, /* Reserved */
+ SME_QOS_WMM_TS_DIR_BOTH = 3,
+
+}sme_QosWmmDirType;
+
+/*---------------------------------------------------------------------------
+ Enumeration of the various TSPEC ack policies.
+
+ From 802.11 WMM specification
+---------------------------------------------------------------------------*/
+
+typedef enum
+{
+ SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK = 0,
+ SME_QOS_WMM_TS_ACK_POLICY_RESV1 = 1,
+ SME_QOS_WMM_TS_ACK_POLICY_RESV2 = 2, /* Reserved */
+ SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK = 3,
+
+}sme_QosWmmAckPolicyType;
+
+/*---------------------------------------------------------------------------
+ TS Info field in the WMM TSPEC
+
+ See suggestive values above
+---------------------------------------------------------------------------*/
+typedef struct
+{
+ v_U8_t burst_size_defn;
+ sme_QosWmmAckPolicyType ack_policy;
+ sme_QosWmmUpType up; /* User priority */
+ v_U8_t psb; /* power-save bit */
+ sme_QosWmmDirType direction; /* Direction */
+ v_U8_t tid; /* TID : To be filled up by SME-QoS */
+} sme_QosWmmTsInfoType;
+
+/*---------------------------------------------------------------------------
+ The WMM TSPEC Element (from the WMM spec)
+---------------------------------------------------------------------------*/
+typedef struct
+{
+ sme_QosWmmTsInfoType ts_info;
+ v_U16_t nominal_msdu_size;
+ v_U16_t maximum_msdu_size;
+ v_U32_t min_service_interval;
+ v_U32_t max_service_interval;
+ v_U32_t inactivity_interval;
+ v_U32_t suspension_interval;
+ v_U32_t svc_start_time;
+ v_U32_t min_data_rate;
+ v_U32_t mean_data_rate;
+ v_U32_t peak_data_rate;
+ v_U32_t max_burst_size;
+ v_U32_t delay_bound;
+ v_U32_t min_phy_rate;
+ v_U16_t surplus_bw_allowance;
+ v_U16_t medium_time;
+} sme_QosWmmTspecInfo;
+
+
+/*--------------------------------------------------------------------------
+ External APIs
+ ------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosCallback() - This is a callback function which is registered
+ per flow while HDD is requesting for QoS. Used for any notification for the
+ flow (i.e. setup success/failure/release) which needs to be sent to HDD. HDD
+ will notify the application in turn, if needed.
+
+ \param hHal - The handle returned by macOpen.
+ \param HDDcontext - A cookie passed by HDD during QoS setup, to be used by SME
+ during any QoS notification (through the callabck) to HDD
+ \param pCurrentQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM
+ TSPEC related info as defined above, fed back to HDD
+ \param status - The status of the flow running on an AC. It could be of
+ sme_QosStatusType
+
+ \return eHAL_STATUS_SUCCESS - Callback invoke successful.
+
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+typedef eHalStatus (*sme_QosCallback)(tHalHandle hHal, void * HDDcontext,
+ sme_QosWmmTspecInfo * pCurrentQoSInfo,
+ sme_QosStatusType status,
+ v_U32_t QosFlowID);
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosSetupReq() - The SME QoS API exposed to HDD to request for QoS
+ on a particular AC. This function should be called after a link has been
+ established, i.e. STA is associated with an AP etc. If the request involves
+ admission control on the requested AC, HDD needs to provide the necessary
+ Traffic Specification (TSPEC) parameters otherwise SME is going to use the
+ default params.
+
+ \param hHal - The handle returned by macOpen.
+ \param sessionId - sessionId returned by sme_OpenSession. Current QOS code doesn't
+ support multiple session. This function returns failure when different
+ sessionId is passed in before calling sme_QosReleaseReq.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info as defined above, provided by HDD
+ \param QoSCallback - The callback which is registered per flow while
+ requesting for QoS. Used for any notification for the
+ flow (i.e. setup success/failure/release) which needs to
+ be sent to HDD
+ \param HDDcontext - A cookie passed by HDD to be used by SME during any QoS
+ notification (through the callabck) to HDD
+ \param UPType - Useful only if HDD or any other upper layer module (BAP etc.)
+ looking for implicit QoS setup, in that
+ case, the pQoSInfo will be NULL & SME will know about the AC
+ (from the UP provided in this param) QoS is requested on
+ \param pQosFlowID - Identification per flow running on each AC generated by
+ SME.
+ It is only meaningful if the QoS setup for the flow is
+ successful
+
+ \return SME_QOS_STATUS_SETUP_SUCCESS - Setup request processed successfully.
+
+ Other status means Setup request failed
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosSetupReq(tHalHandle hHal, tANI_U32 sessionId,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ sme_QosCallback QoSCallback, void * HDDcontext,
+ sme_QosWmmUpType UPType, v_U32_t * pQosFlowID);
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosModifyReq() - The SME QoS API exposed to HDD to request for
+ modification of certain QoS params on a flow running on a particular AC.
+ This function should be called after a link has been established, i.e. STA is
+ associated with an AP etc. & a QoS setup has been succesful for that flow.
+ If the request involves admission control on the requested AC, HDD needs to
+ provide the necessary Traffic Specification (TSPEC) parameters & SME might
+ start the renegotiation process through ADDTS.
+
+ \param hHal - The handle returned by macOpen.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info as defined above, provided by HDD
+ \param QosFlowID - Identification per flow running on each AC generated by
+ SME.
+ It is only meaningful if the QoS setup for the flow has
+ been successful already
+
+ \return SME_QOS_STATUS_SETUP_SUCCESS - Modification request processed
+ successfully.
+
+ Other status means request failed
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosModifyReq(tHalHandle hHal,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ v_U32_t QosFlowID);
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosReleaseReq() - The SME QoS API exposed to HDD to request for
+ releasing a QoS flow running on a particular AC. This function should be
+ called only if a QoS is set up with a valid FlowID. HDD sould invoke this
+ API only if an explicit request for QoS release has come from Application
+
+ \param hHal - The handle returned by macOpen.
+ \param QosFlowID - Identification per flow running on each AC generated by SME
+ It is only meaningful if the QoS setup for the flow is
+ successful
+
+ \return SME_QOS_STATUS_RELEASE_SUCCESS - Release request processed
+ successfully.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosReleaseReq(tHalHandle hHal, v_U32_t QosFlowID);
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosIsTSInfoAckPolicyValid() - The SME QoS API exposed to HDD to
+ check if TS info ack policy field can be set to "HT-immediate block acknowledgement"
+
+ \param pMac - The handle returned by macOpen.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info, provided by HDD
+ \param sessionId - sessionId returned by sme_OpenSession.
+
+ \return VOS_TRUE - Current Association is HT association and so TS info ack policy
+ can be set to "HT-immediate block acknowledgement"
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+v_BOOL_t sme_QosIsTSInfoAckPolicyValid(tpAniSirGlobal pMac,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ v_U8_t sessionId);
+
+#endif //#if !defined( __SME_QOSAPI_H )
diff --git a/CORE/SME/inc/sme_RrmApi.h b/CORE/SME/inc/sme_RrmApi.h
new file mode 100644
index 0000000..9b105b2
--- /dev/null
+++ b/CORE/SME/inc/sme_RrmApi.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+
+#if !defined( __SMERRMAPI_H )
+#define __SMERRMAPI_H
+
+
+/**=========================================================================
+
+ \file sme_RrmApi.h
+
+ \brief prototype for SME RRM APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/* $Header$ */
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "vos_lock.h"
+#include "vos_trace.h"
+#include "vos_memory.h"
+#include "vos_types.h"
+#include "aniGlobal.h"
+#include "sirApi.h"
+#include "smeInternal.h"
+#include "smeRrmInternal.h"
+
+
+//APIs
+eHalStatus sme_RrmMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type,
+ void *pMsgBuf);
+
+VOS_STATUS rrmClose (tpAniSirGlobal pMac);
+VOS_STATUS rrmReady (tpAniSirGlobal pMac);
+VOS_STATUS rrmOpen (tpAniSirGlobal pMac);
+VOS_STATUS rrmChangeDefaultConfigParam(tpAniSirGlobal pMac, tpRrmConfigParam pRrmConfig);
+VOS_STATUS sme_RrmNeighborReportRequest(tpAniSirGlobal pMac, tANI_U8 sessionId, tpRrmNeighborReq pNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo);
+
+tRrmNeighborReportDesc* smeRrmGetFirstBssEntryFromNeighborCache( tpAniSirGlobal pMac);
+tRrmNeighborReportDesc* smeRrmGetNextBssEntryFromNeighborCache( tpAniSirGlobal pMac, tpRrmNeighborReportDesc pBssEntry);
+
+
+#endif
diff --git a/CORE/SME/inc/smsDebug.h b/CORE/SME/inc/smsDebug.h
new file mode 100644
index 0000000..9d91493
--- /dev/null
+++ b/CORE/SME/inc/smsDebug.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+
+
+ \file cssDebug.h
+
+ Define debug log interface for SMS.
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+
+ ========================================================================== */
+
+#ifndef SMS_DEBUG_H__
+#define SMS_DEBUG_H__
+
+//#include <stdio.h>
+//#include <stdarg.h>
+
+#include "utilsApi.h"
+#include "sirDebug.h"
+
+void smsLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...);
+
+#endif // __HAL_DEBUG_H__
diff --git a/CORE/SME/inc/wlan_ps_wow_diag.h b/CORE/SME/inc/wlan_ps_wow_diag.h
new file mode 100644
index 0000000..0291923
--- /dev/null
+++ b/CORE/SME/inc/wlan_ps_wow_diag.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+#ifndef _WLAN_PS_WOW_DIAG_H_
+#define _WLAN_PS_WOW_DIAG_H_
+
+
+#include "vos_diag_core_event.h"
+#include "vos_diag_core_log.h"
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+
+typedef enum
+{
+ WLAN_BMPS_ENTER_REQ =0,
+ WLAN_UAPSD_START_REQ =1,
+ WLAN_UAPSD_STOP_REQ =2,
+ WLAN_ENTER_STANDBY_REQ =3,
+ WLAN_ENTER_DEEP_SLEEP_REQ =4,
+ WLAN_START_BMPS_AUTO_TIMER_REQ =5,
+ WLAN_STOP_BMPS_AUTO_TIMER_REQ =6,
+ WLAN_IMPS_ENTER_REQ =7,
+ WLAN_ENTER_FULL_POWER_REQ =8,
+ WLAN_PMC_CURRENT_STATE =9,
+ WLAN_PS_MODE_ENABLE_REQ =10,
+ WLAN_PS_MODE_DISABLE_REQ =11,
+ WLAN_WINMOB_D_POWER_STATE =12,
+ WLAN_BMPS_DTIM_PERIOD =13,
+ WLAN_BMPS_FINAL_LI =14,
+ WLAN_BMPS_SET_CONFIG =15,
+
+} wlan_ps_evt_subtype_t;
+
+// maps directly to eRequestFullPowerReason
+typedef enum
+{
+ WLAN_MISSED_BEACON_IND_RCVD, /* PE received a MAX_MISSED_BEACON_IND */
+ WLAN_BMPS_STATUS_IND_RCVD, /* PE received a SIR_HAL_BMPS_STATUS_IND */
+ WLAN_BMPS_MODE_DISABLED, /* BMPS mode was disabled by HDD in SME */
+ WLAN_LINK_DISCONNECTED_BY_HDD, /* Link has been disconnected requested by HDD */
+ WLAN_LINK_DISCONNECTED_BY_OTHER,/* Disconnect due to linklost or requested by peer */
+ WLAN_FULL_PWR_NEEDED_BY_HDD, /* HDD request full power for some reason */
+ WLAN_FULL_PWR_NEEDED_BY_BAP, /* BAP request full power for BT_AMP */
+ WLAN_FULL_PWR_NEEDED_BY_CSR, /* CSR requests full power */
+ WLAN_FULL_PWR_NEEDED_BY_QOS, /* QOS requests full power */
+ WLAN_REASON_OTHER /* No specific reason. General reason code */
+
+} wlan_ps_full_power_request_reason_t;
+
+// maps directly to ePmcState
+typedef enum
+{
+ WLAN_PMC_STOPPED, /* PMC is stopped */
+ WLAN_PMC_FULL_POWER, /* full power */
+ WLAN_PMC_LOW_POWER, /* low power */
+ WLAN_PMC_REQUEST_IMPS, /* requesting IMPS */
+ WLAN_PMC_IMPS, /* in IMPS */
+ WLAN_PMC_REQUEST_BMPS, /* requesting BMPS */
+ WLAN_PMC_BMPS, /* in BMPS */
+ WLAN_PMC_REQUEST_FULL_POWER, /* requesting full power */
+ WLAN_PMC_REQUEST_START_UAPSD, /* requesting Start UAPSD */
+ WLAN_PMC_REQUEST_STOP_UAPSD, /* requesting Stop UAPSD */
+ WLAN_PMC_UAPSD, /* in UAPSD */
+ WLAN_PMC_REQUEST_STANDBY, /* requesting standby mode */
+ WLAN_PMC_STANDBY, /* in standby mode */
+ WLAN_PMC_REQUEST_ENTER_WOWL, /* requesting enter WOWL */
+ WLAN_PMC_REQUEST_EXIT_WOWL, /* requesting exit WOWL */
+ WLAN_PMC_WOWL /* Chip in WOWL mode */
+
+} wlan_ps_pmc_current_state_t;
+
+// maps directly to ePmcPowerSavingMode
+typedef enum
+{
+ WLAN_IDLE_MODE_POWER_SAVE, /* Idle Mode Power Save (IMPS) */
+ WLAN_BEACON_MODE_POWER_SAVE, /* Beacon Mode Power Save (BMPS) */
+ WLAN_SPATIAL_MULTIPLEX_POWER_SAVE, /* Spatial Multiplexing Power Save (SMPS) */
+ WLAN_UAPSD_MODE_POWER_SAVE, /* Unscheduled Automatic Power Save Delivery Mode */
+ WLAN_STANDBY_MODE_POWER_SAVE, /* Standby Power Save Mode */
+ WLAN_WOWL_MODE_POWER_SAVE /* Wake-on-Wireless LAN Power Save Mode */
+
+} wlan_ps_enable_disable_ps_mode_t;
+
+typedef enum
+{
+ WLAN_D0,
+ WLAN_D1,
+ WLAN_D2,
+ WLAN_D3,
+ WLAN_D4
+
+} wlan_ps_winmob_d_power_state_t;
+
+typedef enum
+{
+ WLAN_WOW_ENTER_REQ =0,
+ WLAN_WOW_EXIT_REQ =1,
+ WLAN_WOW_DEL_PTRN_REQ =2,
+ WLAN_WOW_WAKEUP = 3
+
+} wlan_ps_wow_evt_subtype_t;
+
+typedef enum
+{
+ WLAN_WOW_TYPE_NONE,
+ WLAN_WOW_TYPE_MAGIC_PKT_ONLY,
+ WLAN_WOW_TYPE_PTRN_BYTE_MATCH_ONLY,
+ WLAN_WOW_TYPE_MAGIC_PKT_PTRN_BYTE_MATCH,
+
+} wlan_ps_wow_type_t;
+
+typedef enum
+{
+ WLAN_WOW_MAGIC_PKT_MATCH,
+ WLAN_WOW_PTRN_BYTE_MATCH
+
+} wlan_ps_wos_wakeup_cause_t;
+
+#endif // FEATURE_WLAN_DIAG_SUPPORT
+
+#endif // _WLAN_PS_WOW_DIAG_H_
+
diff --git a/CORE/SME/src/QoS/sme_Qos.c b/CORE/SME/src/QoS/sme_Qos.c
new file mode 100644
index 0000000..7729594
--- /dev/null
+++ b/CORE/SME/src/QoS/sme_Qos.c
@@ -0,0 +1,7890 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/**=========================================================================
+
+ \file sme_Qos.c
+
+ \brief implementation for SME QoS APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+/* $Header$ */
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include "halInternal.h" //Check if the below include of aniGobal.h is sufficient for Volans too.
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include "aniGlobal.h"
+#endif
+
+#include "smeInside.h"
+#include "vos_diag_core_event.h"
+#include "vos_diag_core_log.h"
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "smsDebug.h"
+#include "utilsParser.h"
+#endif
+#ifdef FEATURE_WLAN_CCX
+#include <csrCcx.h>
+#endif
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+/* TODO : 6Mbps as Cisco APs seem to like only this value; analysis req. */
+#define SME_QOS_MIN_PHY_RATE 0x5B8D80
+#define SME_QOS_SURPLUS_BW_ALLOWANCE 0x2000 /* Ratio of 1.0 */
+/*---------------------------------------------------------------------------
+ Max values to bound tspec params against and avoid rollover
+---------------------------------------------------------------------------*/
+#define SME_QOS_32BIT_MAX 0xFFFFFFFF
+#define SME_QOS_16BIT_MAX 0xFFFF
+#define SME_QOS_16BIT_MSB 0x8000
+/*---------------------------------------------------------------------------
+ Adds y to x, but saturates at 32-bit max to avoid rollover
+---------------------------------------------------------------------------*/
+#define SME_QOS_BOUNDED_U32_ADD_Y_TO_X( _x, _y ) \
+ do \
+ { \
+ (_x) = ( (SME_QOS_32BIT_MAX-(_x))<(_y) ) ? \
+ (SME_QOS_32BIT_MAX) : (_x)+(_y); \
+ } while(0)
+/*---------------------------------------------------------------------------
+ As per WMM spec there could be max 2 TSPEC running on the same AC with
+ different direction. We will refer each TSPEC with an index
+---------------------------------------------------------------------------*/
+#define SME_QOS_TSPEC_INDEX_0 0
+#define SME_QOS_TSPEC_INDEX_1 1
+#define SME_QOS_TSPEC_INDEX_MAX 2
+#define SME_QOS_TSPEC_MASK_BIT_1_SET 1
+#define SME_QOS_TSPEC_MASK_BIT_2_SET 2
+#define SME_QOS_TSPEC_MASK_BIT_1_2_SET 3
+#define SME_QOS_TSPEC_MASK_CLEAR 0
+
+//which key to search on, in the flowlist (1 = flowID, 2 = AC, 4 = reason)
+#define SME_QOS_SEARCH_KEY_INDEX_1 1
+#define SME_QOS_SEARCH_KEY_INDEX_2 2
+#define SME_QOS_SEARCH_KEY_INDEX_3 4
+#define SME_QOS_SEARCH_KEY_INDEX_4 8 // ac + direction
+#define SME_QOS_SEARCH_KEY_INDEX_5 0x10 // ac + tspec_mask
+//special value for searching any Session Id
+#define SME_QOS_SEARCH_SESSION_ID_ANY CSR_ROAM_SESSION_MAX
+#define SME_QOS_ACCESS_POLICY_EDCA 1
+#define SME_QOS_MAX_TID 255
+#define SME_QOS_TSPEC_IE_LENGTH 61
+#define SME_QOS_TSPEC_IE_TYPE 2
+#define SME_QOS_MIN_FLOW_ID 1
+#define SME_QOS_MAX_FLOW_ID 0xFFFFFFFE
+#define SME_QOS_INVALID_FLOW_ID 0xFFFFFFFF
+// per the WMM Specification v1.2 Section 2.2.10
+// The Dialog Token field shall be set [...] to a non-zero value
+#define SME_QOS_MIN_DIALOG_TOKEN 1
+#define SME_QOS_MAX_DIALOG_TOKEN 0xFF
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------
+ Enumeration of the various states in the QoS state m/c
+---------------------------------------------------------------------------*/
+typedef enum
+{
+ SME_QOS_CLOSED = 0,
+ SME_QOS_INIT,
+ SME_QOS_LINK_UP,
+ SME_QOS_REQUESTED,
+ SME_QOS_QOS_ON,
+ SME_QOS_HANDOFF,
+
+}sme_QosStates;
+/*---------------------------------------------------------------------------
+ Enumeration of the various QoS cmds
+---------------------------------------------------------------------------*/
+typedef enum
+{
+ SME_QOS_SETUP_REQ = 0,
+ SME_QOS_RELEASE_REQ,
+ SME_QOS_MODIFY_REQ,
+ SME_QOS_RESEND_REQ,
+ SME_QOS_CMD_MAX
+}sme_QosCmdType;
+/*---------------------------------------------------------------------------
+ Enumeration of the various QoS reason codes to be used in the Flow list
+---------------------------------------------------------------------------*/
+typedef enum
+{
+ SME_QOS_REASON_SETUP = 0,
+ SME_QOS_REASON_RELEASE,
+ SME_QOS_REASON_MODIFY,
+ SME_QOS_REASON_MODIFY_PENDING,
+ SME_QOS_REASON_REQ_SUCCESS,
+ SME_QOS_REASON_MAX
+}sme_QosReasonType;
+
+/*---------------------------------------------------------------------------
+ Table to map user priority passed in as an argument to appropriate Access
+ Category as specified in 802.11e/WMM
+---------------------------------------------------------------------------*/
+sme_QosEdcaAcType sme_QosUPtoACMap[SME_QOS_WMM_UP_MAX] =
+{
+ SME_QOS_EDCA_AC_BE, /* User Priority 0 */
+ SME_QOS_EDCA_AC_BK, /* User Priority 1 */
+ SME_QOS_EDCA_AC_BK, /* User Priority 2 */
+ SME_QOS_EDCA_AC_BE, /* User Priority 3 */
+ SME_QOS_EDCA_AC_VI, /* User Priority 4 */
+ SME_QOS_EDCA_AC_VI, /* User Priority 5 */
+ SME_QOS_EDCA_AC_VO, /* User Priority 6 */
+ SME_QOS_EDCA_AC_VO /* User Priority 7 */
+};
+
+/*---------------------------------------------------------------------------
+ Table to map access category (AC) to appropriate user priority as specified
+ in 802.11e/WMM
+ Note: there is a quantization loss here because 4 ACs are mapped to 8 UPs
+ Mapping is done for consistency
+---------------------------------------------------------------------------*/
+sme_QosWmmUpType sme_QosACtoUPMap[SME_QOS_EDCA_AC_MAX] =
+{
+ SME_QOS_WMM_UP_BE, /* AC BE */
+ SME_QOS_WMM_UP_BK, /* AC BK */
+ SME_QOS_WMM_UP_VI, /* AC VI */
+ SME_QOS_WMM_UP_VO /* AC VO */
+};
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's FLOW Link List structure. This list can hold information per
+ flow/request, like TSPEC params requested, which AC it is running on
+---------------------------------------------------------------------------*/
+typedef struct sme_QosFlowInfoEntry_s
+{
+ tListElem link; /* list links */
+ v_U8_t sessionId;
+ v_U8_t tspec_mask;
+ sme_QosReasonType reason;
+ v_U32_t QosFlowID;
+ sme_QosEdcaAcType ac_type;
+ sme_QosWmmTspecInfo QoSInfo;
+ void * HDDcontext;
+ sme_QosCallback QoSCallback;
+ v_BOOL_t hoRenewal;//set to TRUE while re-negotiating flows after
+ //handoff, will set to FALSE once done with
+ //the process. Helps SME to decide if at all
+ //to notify HDD/LIS for flow renewal after HO
+} sme_QosFlowInfoEntry;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's setup request cmd related information structure.
+---------------------------------------------------------------------------*/
+typedef struct sme_QosSetupCmdInfo_s
+{
+ v_U32_t QosFlowID;
+ sme_QosWmmTspecInfo QoSInfo;
+ void *HDDcontext;
+ sme_QosCallback QoSCallback;
+ sme_QosWmmUpType UPType;
+ v_BOOL_t hoRenewal;//set to TRUE while re-negotiating flows after
+ //handoff, will set to FALSE once done with
+ //the process. Helps SME to decide if at all
+ //to notify HDD/LIS for flow renewal after HO
+} sme_QosSetupCmdInfo;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's modify cmd related information structure.
+---------------------------------------------------------------------------*/
+typedef struct sme_QosModifyCmdInfo_s
+{
+ v_U32_t QosFlowID;
+ sme_QosEdcaAcType ac;
+ sme_QosWmmTspecInfo QoSInfo;
+} sme_QosModifyCmdInfo;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's resend cmd related information structure.
+---------------------------------------------------------------------------*/
+typedef struct sme_QosResendCmdInfo_s
+{
+ v_U8_t tspecMask;
+ sme_QosEdcaAcType ac;
+ sme_QosWmmTspecInfo QoSInfo;
+} sme_QosResendCmdInfo;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's release cmd related information structure.
+---------------------------------------------------------------------------*/
+typedef struct sme_QosReleaseCmdInfo_s
+{
+ v_U32_t QosFlowID;
+} sme_QosReleaseCmdInfo;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's buffered cmd related information structure.
+---------------------------------------------------------------------------*/
+typedef struct sme_QosCmdInfo_s
+{
+ sme_QosCmdType command;
+ tpAniSirGlobal pMac;
+ v_U8_t sessionId;
+ union
+ {
+ sme_QosSetupCmdInfo setupCmdInfo;
+ sme_QosModifyCmdInfo modifyCmdInfo;
+ sme_QosResendCmdInfo resendCmdInfo;
+ sme_QosReleaseCmdInfo releaseCmdInfo;
+ }u;
+} sme_QosCmdInfo;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's buffered cmd List structure. This list can hold information
+ related to any pending cmd from HDD
+---------------------------------------------------------------------------*/
+typedef struct sme_QosCmdInfoEntry_s
+{
+ tListElem link; /* list links */
+ sme_QosCmdInfo cmdInfo;
+} sme_QosCmdInfoEntry;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's Per AC information structure. This can hold information on
+ how many flows running on the AC, the current, previous states the AC is in
+---------------------------------------------------------------------------*/
+typedef struct sme_QosACInfo_s
+{
+ v_U8_t num_flows[SME_QOS_TSPEC_INDEX_MAX];
+ sme_QosStates curr_state;
+ sme_QosStates prev_state;
+ sme_QosWmmTspecInfo curr_QoSInfo[SME_QOS_TSPEC_INDEX_MAX];
+ sme_QosWmmTspecInfo requested_QoSInfo[SME_QOS_TSPEC_INDEX_MAX];
+ v_BOOL_t reassoc_pending;//reassoc requested for APSD
+ //As per WMM spec there could be max 2 TSPEC running on the same AC with
+ //different direction. We will refer each TSPEC with an index
+ v_U8_t tspec_mask_status; //status showing if both the indices are in use
+ v_U8_t tspec_pending;//tspec negotiation going on for which index
+ v_BOOL_t hoRenewal;//set to TRUE while re-negotiating flows after
+ //handoff, will set to FALSE once done with
+ //the process. Helps SME to decide if at all
+ //to notify HDD/LIS for flow renewal after HO
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ v_U8_t ricIdentifier[SME_QOS_TSPEC_INDEX_MAX];
+ /* stores the ADD TS response for each AC. The ADD TS response is formed by
+ parsing the RIC received in the the reassoc response */
+ tSirAddtsRsp addTsRsp[SME_QOS_TSPEC_INDEX_MAX];
+#endif
+
+} sme_QosACInfo;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's Per session information structure. This can hold information
+ on the state of the session
+---------------------------------------------------------------------------*/
+typedef struct sme_QosSessionInfo_s
+{
+ // what is this entry's session id
+ v_U8_t sessionId;
+ // is the session currently active
+ v_BOOL_t sessionActive;
+ // All AC info for this session
+ sme_QosACInfo ac_info[SME_QOS_EDCA_AC_MAX];
+ // Bitmask of the ACs with APSD on
+ // Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored
+ v_U8_t apsdMask;
+ // association information for this session
+ sme_QosAssocInfo assocInfo;
+ // ID assigned to our reassoc request
+ v_U32_t roamID;
+ // maintaining a powersave status in QoS module, to be fed back to PMC at
+ // times through the sme_QosPmcCheckRoutine
+ v_BOOL_t readyForPowerSave;
+ // are we in the process of handing off to a different AP
+ v_BOOL_t handoffRequested;
+ // following reassoc or AddTS has UAPSD already been requested from PMC
+ v_BOOL_t uapsdAlreadyRequested;
+ // commands that are being buffered for this session
+ tDblLinkList bufferedCommandList;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ v_BOOL_t ftHandoffInProgress;
+#endif
+
+} sme_QosSessionInfo;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ Search key union. We can use the flowID, ac type, or reason to find an entry
+ in the flow list
+---------------------------------------------------------------------------*/
+typedef union sme_QosSearchKey_s
+{
+ v_U32_t QosFlowID;
+ sme_QosEdcaAcType ac_type;
+ sme_QosReasonType reason;
+}sme_QosSearchKey;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ We can either use the flowID or the ac type to find an entry in the flow list.
+ The index is a bitmap telling us which key to use. Starting from LSB,
+ bit 0 - Flow ID
+ bit 1 - AC type
+---------------------------------------------------------------------------*/
+typedef struct sme_QosSearchInfo_s
+{
+ v_U8_t sessionId;
+ v_U8_t index;
+ sme_QosSearchKey key;
+ sme_QosWmmDirType direction;
+ v_U8_t tspec_mask;
+}sme_QosSearchInfo;
+/*---------------------------------------------------------------------------
+DESCRIPTION
+ SME QoS module's internal control block.
+---------------------------------------------------------------------------*/
+struct sme_QosCb_s
+{
+ //global Mac pointer
+ tpAniSirGlobal pMac;
+ //All Session Info
+ sme_QosSessionInfo sessionInfo[CSR_ROAM_SESSION_MAX];
+ //All FLOW info
+ tDblLinkList flow_list;
+ //default TSPEC params
+ sme_QosWmmTspecInfo def_QoSInfo[SME_QOS_EDCA_AC_MAX];
+ //counter for assigning Flow IDs
+ v_U32_t nextFlowId;
+ //counter for assigning Dialog Tokens
+ v_U8_t nextDialogToken;
+}sme_QosCb;
+typedef eHalStatus (*sme_QosProcessSearchEntry)(tpAniSirGlobal pMac, tListElem *pEntry);
+/*--------------------------------------------------------------------------
+ Internal function declarations
+ ------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosInternalSetupReq(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ sme_QosCallback QoSCallback,
+ void * HDDcontext,
+ sme_QosWmmUpType UPType,
+ v_U32_t QosFlowID,
+ v_BOOL_t buffered_cmd,
+ v_BOOL_t hoRenewal);
+sme_QosStatusType sme_QosInternalModifyReq(tpAniSirGlobal pMac,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ v_U32_t QosFlowID,
+ v_BOOL_t buffered_cmd);
+sme_QosStatusType sme_QosInternalReleaseReq(tpAniSirGlobal pMac,
+ v_U32_t QosFlowID,
+ v_BOOL_t buffered_cmd);
+sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosWmmTspecInfo *pTspec_Info,
+ sme_QosEdcaAcType ac);
+eHalStatus sme_QosAddTsReq(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosWmmTspecInfo * pTspec_Info,
+ sme_QosEdcaAcType ac);
+eHalStatus sme_QosDelTsReq(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosEdcaAcType ac,
+ v_U8_t tspec_mask);
+eHalStatus sme_QosProcessAddTsRsp(tpAniSirGlobal pMac, void *pMsgBuf);
+eHalStatus sme_QosProcessDelTsInd(tpAniSirGlobal pMac, void *pMsgBuf);
+eHalStatus sme_QosProcessDelTsRsp(tpAniSirGlobal pMac, void *pMsgBuf);
+eHalStatus sme_QosProcessAssocCompleteEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessReassocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessReassocSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessReassocFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessDisconnectEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessJoinReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessHandoffAssocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessHandoffSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessHandoffFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+#ifdef WLAN_FEATURE_VOWIFI_11R
+eHalStatus sme_QosProcessPreauthSuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessSetKeySuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
+eHalStatus sme_QosProcessAggrQosRsp(tpAniSirGlobal pMac, void *pMsgBuf);
+eHalStatus sme_QosFTAggrQosReq( tpAniSirGlobal pMac, v_U8_t sessionId );
+#endif
+eHalStatus sme_QosProcessAddTsSuccessRsp(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ tSirAddtsRspInfo * pRsp);
+eHalStatus sme_QosProcessAddTsFailureRsp(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ tSirAddtsRspInfo * pRsp);
+eHalStatus sme_QosAggregateParams(
+ sme_QosWmmTspecInfo * pInput_Tspec_Info,
+ sme_QosWmmTspecInfo * pCurrent_Tspec_Info,
+ sme_QosWmmTspecInfo * pUpdated_Tspec_Info);
+static eHalStatus sme_QosUpdateParams(v_U8_t sessionId,
+ sme_QosEdcaAcType ac,
+ v_U8_t tspec_mask,
+ sme_QosWmmTspecInfo * pTspec_Info);
+sme_QosWmmUpType sme_QosAcToUp(sme_QosEdcaAcType ac);
+sme_QosEdcaAcType sme_QosUpToAc(sme_QosWmmUpType up);
+v_BOOL_t sme_QosIsACM(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc,
+ sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes);
+tListElem *sme_QosFindInFlowList(sme_QosSearchInfo search_key);
+eHalStatus sme_QosFindAllInFlowList(tpAniSirGlobal pMac,
+ sme_QosSearchInfo search_key,
+ sme_QosProcessSearchEntry fnp);
+static void sme_QosStateTransition(v_U8_t sessionId,
+ sme_QosEdcaAcType ac,
+ sme_QosStates new_state);
+eHalStatus sme_QosBufferCmd(sme_QosCmdInfo *pcmd, v_BOOL_t insert_head);
+static eHalStatus sme_QosProcessBufferedCmd(v_U8_t sessionId);
+eHalStatus sme_QosSaveAssocInfo(sme_QosSessionInfo *pSession, sme_QosAssocInfo *pAssoc_info);
+eHalStatus sme_QosSetupFnp(tpAniSirGlobal pMac, tListElem *pEntry);
+eHalStatus sme_QosModificationNotifyFnp(tpAniSirGlobal pMac, tListElem *pEntry);
+eHalStatus sme_QosModifyFnp(tpAniSirGlobal pMac, tListElem *pEntry);
+eHalStatus sme_QosDelTsIndFnp(tpAniSirGlobal pMac, tListElem *pEntry);
+eHalStatus sme_QosReassocSuccessEvFnp(tpAniSirGlobal pMac, tListElem *pEntry);
+eHalStatus sme_QosAddTsFailureFnp(tpAniSirGlobal pMac, tListElem *pEntry);
+eHalStatus sme_QosAddTsSuccessFnp(tpAniSirGlobal pMac, tListElem *pEntry);
+static v_BOOL_t sme_QosIsRspPending(v_U8_t sessionId, sme_QosEdcaAcType ac);
+static v_BOOL_t sme_QosIsUapsdActive(void);
+void sme_QosPmcFullPowerCallback(void *callbackContext, eHalStatus status);
+void sme_QosPmcStartUapsdCallback(void *callbackContext, eHalStatus status);
+v_BOOL_t sme_QosPmcCheckRoutine(void *callbackContext);
+void sme_QosPmcDeviceStateUpdateInd(void *callbackContext, tPmcState pmcState);
+eHalStatus sme_QosProcessOutOfUapsdMode(tpAniSirGlobal pMac);
+eHalStatus sme_QosProcessIntoUapsdMode(tpAniSirGlobal pMac);
+static eHalStatus sme_QosBufferExistingFlows(tpAniSirGlobal pMac,
+ v_U8_t sessionId);
+static eHalStatus sme_QosDeleteExistingFlows(tpAniSirGlobal pMac,
+ v_U8_t sessionId);
+static void sme_QosCleanupCtrlBlkForHandoff(tpAniSirGlobal pMac,
+ v_U8_t sessionId);
+static eHalStatus sme_QosDeleteBufferedRequests(tpAniSirGlobal pMac,
+ v_U8_t sessionId);
+v_BOOL_t sme_QosValidateRequestedParams(tpAniSirGlobal pMac,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ v_U8_t sessionId);
+
+extern eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme);
+extern eHalStatus sme_ReleaseGlobalLock( tSmeStruct *psSme);
+static eHalStatus qosIssueCommand( tpAniSirGlobal pMac, v_U8_t sessionId,
+ eSmeCommandType cmdType, sme_QosWmmTspecInfo * pQoSInfo,
+ sme_QosEdcaAcType ac, v_U8_t tspec_mask );
+/*
+ sme_QosReRequestAddTS to re-send AddTS for the combined QoS request
+*/
+static sme_QosStatusType sme_QosReRequestAddTS(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ sme_QosEdcaAcType ac,
+ v_U8_t tspecMask);
+static void sme_QosInitACs(tpAniSirGlobal pMac, v_U8_t sessionId);
+static eHalStatus sme_QosRequestReassoc(tpAniSirGlobal pMac, tANI_U8 sessionId,
+ tCsrRoamModifyProfileFields *pModFields,
+ v_BOOL_t fForce );
+static v_U32_t sme_QosAssignFlowId(void);
+static v_U8_t sme_QosAssignDialogToken(void);
+static eHalStatus sme_QosUpdateTspecMask(v_U8_t sessionId,
+ sme_QosSearchInfo search_key,
+ v_U8_t new_tspec_mask);
+/*--------------------------------------------------------------------------
+ External APIs definitions
+ ------------------------------------------------------------------------*/
+/* --------------------------------------------------------------------------
+ \brief sme_QosOpen() - This function must be called before any API call to
+ SME QoS module.
+ \param pMac - Pointer to the global MAC parameter structure.
+
+ \return eHalStatus
+----------------------------------------------------------------------------*/
+eHalStatus sme_QosOpen(tpAniSirGlobal pMac)
+{
+ sme_QosSessionInfo *pSession;
+ v_U8_t sessionId;
+ eHalStatus status;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: initializing SME-QoS module",
+ __FUNCTION__, __LINE__);
+ //init the control block
+ //(note that this will make all sessions invalid)
+ vos_mem_zero(&sme_QosCb, sizeof(sme_QosCb));
+ sme_QosCb.pMac = pMac;
+ sme_QosCb.nextFlowId = SME_QOS_MIN_FLOW_ID;
+ sme_QosCb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN;
+ //init flow list
+ status = csrLLOpen(pMac->hHdd, &sme_QosCb.flow_list);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "%s: %d: cannot initialize Flow List",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
+ {
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pSession->sessionId = sessionId;
+ // initialize the session's per-AC information
+ sme_QosInitACs(pMac, sessionId);
+ // initialize the session's buffered command list
+ status = csrLLOpen(pMac->hHdd, &pSession->bufferedCommandList);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "%s: %d: cannot initialize cmd list for session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ return eHAL_STATUS_FAILURE;
+ }
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ //the routine registered here gets called by PMC whenever the device is about
+ //to enter one of the power save modes. PMC runs a poll with all the
+ //registered modules if device can enter powersave mode or remain full power
+ if(!HAL_STATUS_SUCCESS(
+ pmcRegisterPowerSaveCheck(pMac, sme_QosPmcCheckRoutine, pMac)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "%s: %d: cannot register with pmcRegisterPowerSaveCheck()",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ //the routine registered here gets called by PMC whenever there is a device
+ // state change. PMC might go to full power because of many reasons and this
+ // is the way for PMC to inform all the other registered modules so that
+ // everyone is in sync.
+ if(!HAL_STATUS_SUCCESS(
+ pmcRegisterDeviceStateUpdateInd(pMac, sme_QosPmcDeviceStateUpdateInd, pMac)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "%s: %d: cannot register with pmcRegisterDeviceStateUpdateInd()",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: done initializing SME-QoS module",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_SUCCESS;
+}
+/* --------------------------------------------------------------------------
+ \brief sme_QosClose() - To close down SME QoS module. There should not be
+ any API call into this module after calling this function until another
+ call of sme_QosOpen.
+ \param pMac - Pointer to the global MAC parameter structure.
+
+ \return eHalStatus
+----------------------------------------------------------------------------*/
+eHalStatus sme_QosClose(tpAniSirGlobal pMac)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosEdcaAcType ac;
+ v_U8_t sessionId;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: closing down SME-QoS",
+ __FUNCTION__, __LINE__);
+ // deregister with PMC
+ if(!HAL_STATUS_SUCCESS(
+ pmcDeregisterDeviceStateUpdateInd(pMac, sme_QosPmcDeviceStateUpdateInd)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "%s: %d: cannot deregister with pmcDeregisterDeviceStateUpdateInd()",
+ __FUNCTION__, __LINE__);
+ }
+ if(!HAL_STATUS_SUCCESS(
+ pmcDeregisterPowerSaveCheck(pMac, sme_QosPmcCheckRoutine)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "%s: %d: cannot deregister with pmcDeregisterPowerSaveCheck()",
+ __FUNCTION__, __LINE__);
+ }
+ //cleanup control block
+ //close the flow list
+ csrLLClose(&sme_QosCb.flow_list);
+ // shut down all of the sessions
+ for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
+ {
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if (pSession == NULL)
+ continue;
+
+ sme_QosInitACs(pMac, sessionId);
+ // this session doesn't require UAPSD
+ pSession->apsdMask = 0;
+
+ pSession->uapsdAlreadyRequested = VOS_FALSE;
+ pSession->handoffRequested = VOS_FALSE;
+ pSession->readyForPowerSave = VOS_TRUE;
+ pSession->roamID = 0;
+ //need to clean up buffered req
+ sme_QosDeleteBufferedRequests(pMac, sessionId);
+ //need to clean up flows
+ sme_QosDeleteExistingFlows(pMac, sessionId);
+
+ // Clean up the assoc info if already allocated
+ if (pSession->assocInfo.pBssDesc) {
+ vos_mem_free(pSession->assocInfo.pBssDesc);
+ pSession->assocInfo.pBssDesc = NULL;
+ }
+
+ // close the session's buffered command list
+ csrLLClose(&pSession->bufferedCommandList);
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ sme_QosStateTransition(sessionId, ac, SME_QOS_CLOSED);
+ }
+ pSession->sessionActive = VOS_FALSE;
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: closed down QoS",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosSetupReq() - The SME QoS API exposed to HDD to request for QoS
+ on a particular AC. This function should be called after a link has been
+ established, i.e. STA is associated with an AP etc. If the request involves
+ admission control on the requested AC, HDD needs to provide the necessary
+ Traffic Specification (TSPEC) parameters otherwise SME is going to use the
+ default params.
+
+ \param hHal - The handle returned by macOpen.
+ \param sessionId - sessionId returned by sme_OpenSession.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info as defined above, provided by HDD
+ \param QoSCallback - The callback which is registered per flow while
+ requesting for QoS. Used for any notification for the
+ flow (i.e. setup success/failure/release) which needs to
+ be sent to HDD
+ \param HDDcontext - A cookie passed by HDD to be used by SME during any QoS
+ notification (through the callabck) to HDD
+ \param UPType - Useful only if HDD or any other upper layer module (BAP etc.)
+ looking for implicit QoS setup, in that
+ case, the pQoSInfo will be NULL & SME will know about the AC
+ (from the UP provided in this param) QoS is requested on
+ \param pQosFlowID - Identification per flow running on each AC generated by
+ SME.
+ It is only meaningful if the QoS setup for the flow is
+ successful
+
+ \return eHAL_STATUS_SUCCESS - Setup is successful.
+
+ Other status means Setup request failed
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosSetupReq(tHalHandle hHal, tANI_U32 sessionId,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ sme_QosCallback QoSCallback,
+ void * HDDcontext,
+ sme_QosWmmUpType UPType, v_U32_t * pQosFlowID)
+{
+ sme_QosSessionInfo *pSession;
+ eHalStatus lock_status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ sme_QosStatusType status;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: QoS Setup requested by client on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ lock_status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( !HAL_STATUS_SUCCESS( lock_status ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Unable to obtain lock",
+ __FUNCTION__, __LINE__);
+ return SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ }
+ //Make sure the session is valid
+ if (!CSR_IS_SESSION_VALID( pMac, sessionId ))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Supplied Session ID %d is invalid",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ }
+ else
+ {
+ //Make sure the session is active
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if (!pSession->sessionActive)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Supplied Session ID %d is inactive",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ }
+ else
+ {
+ //Assign a Flow ID
+ *pQosFlowID = sme_QosAssignFlowId();
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: QoS request on session %d assigned Flow ID %d",
+ __FUNCTION__, __LINE__,
+ sessionId, *pQosFlowID);
+ //Call the internal function for QoS setup,
+ // adding a layer of abstraction
+ status = sme_QosInternalSetupReq(pMac, (v_U8_t)sessionId, pQoSInfo,
+ QoSCallback, HDDcontext, UPType,
+ *pQosFlowID, VOS_FALSE, VOS_FALSE);
+ }
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: QoS setup return status on session %d is %d",
+ __FUNCTION__, __LINE__,
+ sessionId, status);
+ return status;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosModifyReq() - The SME QoS API exposed to HDD to request for
+ modification of certain QoS params on a flow running on a particular AC.
+ This function should be called after a link has been established, i.e. STA is
+ associated with an AP etc. & a QoS setup has been succesful for that flow.
+ If the request involves admission control on the requested AC, HDD needs to
+ provide the necessary Traffic Specification (TSPEC) parameters & SME might
+ start the renegotiation process through ADDTS.
+
+ \param hHal - The handle returned by macOpen.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info as defined above, provided by HDD
+ \param QosFlowID - Identification per flow running on each AC generated by
+ SME.
+ It is only meaningful if the QoS setup for the flow has
+ been successful already
+
+ \return SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful.
+
+ Other status means request failed
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosModifyReq(tHalHandle hHal,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ v_U32_t QosFlowID)
+{
+ eHalStatus lock_status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ sme_QosStatusType status;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: QoS Modify requested by client for Flow %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+ lock_status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( !HAL_STATUS_SUCCESS( lock_status ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Unable to obtain lock",
+ __FUNCTION__, __LINE__);
+ return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ }
+ //Call the internal function for QoS modify, adding a layer of abstraction
+ status = sme_QosInternalModifyReq(pMac, pQoSInfo, QosFlowID, VOS_FALSE);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: QoS Modify return status on Flow %d is %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID, status);
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosReleaseReq() - The SME QoS API exposed to HDD to request for
+ releasing a QoS flow running on a particular AC. This function should be
+ called only if a QoS is set up with a valid FlowID. HDD sould invoke this
+ API only if an explicit request for QoS release has come from Application
+
+ \param hHal - The handle returned by macOpen.
+ \param QosFlowID - Identification per flow running on each AC generated by SME
+ It is only meaningful if the QoS setup for the flow is
+ successful
+
+ \return eHAL_STATUS_SUCCESS - Release is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosReleaseReq(tHalHandle hHal, v_U32_t QosFlowID)
+{
+ eHalStatus lock_status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ sme_QosStatusType status;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: QoS Release requested by client for Flow %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+ lock_status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( !HAL_STATUS_SUCCESS( lock_status ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Unable to obtain lock",
+ __FUNCTION__, __LINE__);
+ return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
+ }
+ //Call the internal function for QoS release, adding a layer of abstraction
+ status = sme_QosInternalReleaseReq(pMac, QosFlowID, VOS_FALSE);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: QoS Release return status on Flow %d is %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID, status);
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosSetParams() - This function is used by HDD to provide the
+ default TSPEC params to SME.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info per AC as defined above, provided by HDD
+
+ \return eHAL_STATUS_SUCCESS - Setparam is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosSetParams(tpAniSirGlobal pMac, sme_QosWmmTspecInfo * pQoSInfo)
+{
+ sme_QosEdcaAcType ac;
+ // find the AC
+ ac = sme_QosUpToAc(pQoSInfo->ts_info.up);
+ if(SME_QOS_EDCA_AC_MAX == ac)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Invalid AC %d (via UP %d)",
+ __FUNCTION__, __LINE__,
+ ac, pQoSInfo->ts_info.up );
+ return eHAL_STATUS_FAILURE;
+ }
+ //copy over the default params for this AC
+ sme_QosCb.def_QoSInfo[ac] = *pQoSInfo;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: QoS default params set for AC %d (via UP %d)",
+ __FUNCTION__, __LINE__,
+ ac, pQoSInfo->ts_info.up );
+ return eHAL_STATUS_SUCCESS;
+}
+
+void qosReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ vos_mem_zero( &pCommand->u.qosCmd, sizeof( tGenericQosCmd ) );
+ smeReleaseCommand( pMac, pCommand );
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosMsgProcessor() - sme_ProcessMsg() calls this function for the
+ messages that are handled by SME QoS module.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param msg_type - the type of msg passed by PE as defined in wniApi.h
+ \param pMsgBuf - a pointer to a buffer that maps to various structures base
+ on the message type.
+ The beginning of the buffer can always map to tSirSmeRsp.
+
+ \return eHAL_STATUS_SUCCESS - Validation is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type,
+ void *pMsgBuf)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: msg = %d for QoS",
+ __FUNCTION__, __LINE__, msg_type);
+ //switch on the msg type & make the state transition accordingly
+ switch(msg_type)
+ {
+ case eWNI_SME_ADDTS_RSP:
+ pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
+ if( pEntry )
+ {
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ if( eSmeCommandAddTs == pCommand->command )
+ {
+ status = sme_QosProcessAddTsRsp(pMac, pMsgBuf);
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
+ {
+ qosReleaseCommand( pMac, pCommand );
+ }
+ smeProcessPendingQueue( pMac );
+ }
+ }
+ break;
+ case eWNI_SME_DELTS_RSP:
+ pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
+ if( pEntry )
+ {
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ if( eSmeCommandDelTs == pCommand->command )
+ {
+ status = sme_QosProcessDelTsRsp(pMac, pMsgBuf);
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
+ {
+ qosReleaseCommand( pMac, pCommand );
+ }
+ smeProcessPendingQueue( pMac );
+ }
+ }
+ break;
+ case eWNI_SME_DELTS_IND:
+ status = sme_QosProcessDelTsInd(pMac, pMsgBuf);
+ break;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eWNI_SME_FT_AGGR_QOS_RSP:
+ status = sme_QosProcessAggrQosRsp(pMac, pMsgBuf);
+ break;
+#endif
+
+ default:
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: unknown msg type = %d",
+ __FUNCTION__, __LINE__, msg_type);
+ break;
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosValidateParams() - The SME QoS API exposed to CSR to validate AP
+ capabilities regarding QoS support & any other QoS parameter validation.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pBssDesc - Pointer to the BSS Descriptor information passed down by
+ CSR to PE while issuing the Join request
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosValidateParams(tpAniSirGlobal pMac,
+ tSirBssDescription *pBssDesc)
+{
+ tDot11fBeaconIEs *pIes = NULL;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: validation for QAP & APSD",
+ __FUNCTION__, __LINE__);
+ do
+ {
+ if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes)))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: csrGetParsedBssDescriptionIEs() failed",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ //check if the AP is QAP & it supports APSD
+ if( !CSR_IS_QOS_BSS(pIes) )
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: AP doesn't support QoS",
+ __FUNCTION__, __LINE__);
+
+ break;
+ }
+ if(!(pIes->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD) &&
+ !(pIes->WMMInfoAp.uapsd))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: AP doesn't support APSD",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ status = eHAL_STATUS_SUCCESS;
+ }while(0);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: validated with status = %d",
+ __FUNCTION__, __LINE__, status);
+ if(pIes)
+ {
+ vos_mem_free(pIes);
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosCsrEventInd() - The QoS sub-module in SME expects notifications
+ from CSR when certain events occur as mentioned in sme_QosCsrEventIndType.
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param ind - The event occurred of type sme_QosCsrEventIndType.
+ \param pEvent_info - Information related to the event
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosCsrEventInd(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosCsrEventIndType ind,
+ void *pEvent_info)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On Session %d Event %d received from CSR",
+ __FUNCTION__, __LINE__,
+ sessionId, ind );
+ switch(ind)
+ {
+ case SME_QOS_CSR_ASSOC_COMPLETE:
+ //expecting assoc info in pEvent_info
+ status = sme_QosProcessAssocCompleteEv(pMac, sessionId, pEvent_info);
+ break;
+ case SME_QOS_CSR_REASSOC_REQ:
+ //nothing expected in pEvent_info
+ status = sme_QosProcessReassocReqEv(pMac, sessionId, pEvent_info);
+ break;
+ case SME_QOS_CSR_REASSOC_COMPLETE:
+ //expecting assoc info in pEvent_info
+ status = sme_QosProcessReassocSuccessEv(pMac, sessionId, pEvent_info);
+ break;
+ case SME_QOS_CSR_REASSOC_FAILURE:
+ //nothing expected in pEvent_info
+ status = sme_QosProcessReassocFailureEv(pMac, sessionId, pEvent_info);
+ break;
+ case SME_QOS_CSR_DISCONNECT_REQ:
+ case SME_QOS_CSR_DISCONNECT_IND:
+ //nothing expected in pEvent_info
+ status = sme_QosProcessDisconnectEv(pMac, sessionId, pEvent_info);
+ break;
+ case SME_QOS_CSR_JOIN_REQ:
+ //nothing expected in pEvent_info
+ status = sme_QosProcessJoinReqEv(pMac, sessionId, pEvent_info);
+ break;
+ case SME_QOS_CSR_HANDOFF_ASSOC_REQ:
+ //nothing expected in pEvent_info
+ status = sme_QosProcessHandoffAssocReqEv(pMac, sessionId, pEvent_info);
+ break;
+ case SME_QOS_CSR_HANDOFF_COMPLETE:
+ //nothing expected in pEvent_info
+ status = sme_QosProcessHandoffSuccessEv(pMac, sessionId, pEvent_info);
+ break;
+ case SME_QOS_CSR_HANDOFF_FAILURE:
+ //nothing expected in pEvent_info
+ status = sme_QosProcessHandoffFailureEv(pMac, sessionId, pEvent_info);
+ break;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case SME_QOS_CSR_PREAUTH_SUCCESS_IND:
+ status = sme_QosProcessPreauthSuccessInd(pMac, sessionId, pEvent_info);
+ break;
+#ifdef FEATURE_WLAN_CCX
+ case SME_QOS_CSR_SET_KEY_SUCCESS_IND:
+ status = sme_QosProcessSetKeySuccessInd(pMac, sessionId, pEvent_info);
+ break;
+#endif
+#endif
+ default:
+ //Err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On Session %d Unknown Event %d received from CSR",
+ __FUNCTION__, __LINE__,
+ sessionId, ind );
+ break;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On Session %d processed Event %d with status %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ind, status );
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosGetACMMask() - The QoS sub-module API to find out on which ACs
+ AP mandates Admission Control (ACM = 1)
+ (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored)
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pSirBssDesc - The event occurred of type sme_QosCsrEventIndType.
+
+ \return a bit mask indicating for which ACs AP has ACM set to 1
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+v_U8_t sme_QosGetACMMask(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes)
+{
+ sme_QosEdcaAcType ac;
+ v_U8_t acm_mask = 0;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked",
+ __FUNCTION__, __LINE__);
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ if(sme_QosIsACM(pMac, pSirBssDesc, ac, pIes))
+ {
+ acm_mask = acm_mask | (1 << (SME_QOS_EDCA_AC_VO - ac));
+ }
+
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: mask is %d",
+ __FUNCTION__, __LINE__, acm_mask);
+ return acm_mask;
+}
+/*--------------------------------------------------------------------------
+ Internal function definitions
+ ------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------
+ \brief sme_QosInternalSetupReq() - The SME QoS internal setup request handling
+ function.
+ If the request involves admission control on the requested AC, HDD needs to
+ provide the necessary Traffic Specification (TSPEC) parameters otherwise SME
+ is going to use the default params.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info as defined above, provided by HDD
+ \param QoSCallback - The callback which is registered per flow while
+ requesting for QoS. Used for any notification for the
+ flow (i.e. setup success/failure/release) which needs to
+ be sent to HDD
+ \param HDDcontext - A cookie passed by HDD to be used by SME during any QoS
+ notification (through the callabck) to HDD
+ \param UPType - Useful only if HDD or any other upper layer module (BAP etc.)
+ looking for implicit QoS setup, in that
+ case, the pQoSInfo will be NULL & SME will know about the AC
+ (from the UP provided in this param) QoS is requested on
+ \param QosFlowID - Identification per flow running on each AC generated by
+ SME.
+ It is only meaningful if the QoS setup for the flow is
+ successful
+ \param buffered_cmd - tells us if the cmd was a buffered one or fresh from
+ client
+
+ \return eHAL_STATUS_SUCCESS - Setup is successful.
+
+ Other status means Setup request failed
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosInternalSetupReq(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ sme_QosCallback QoSCallback,
+ void * HDDcontext,
+ sme_QosWmmUpType UPType,
+ v_U32_t QosFlowID,
+ v_BOOL_t buffered_cmd,
+ v_BOOL_t hoRenewal)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosEdcaAcType ac;
+ sme_QosWmmTspecInfo Tspec_Info;
+ sme_QosStates new_state = SME_QOS_CLOSED;
+ sme_QosFlowInfoEntry *pentry = NULL;
+ sme_QosCmdInfo cmd;
+ sme_QosStatusType status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ v_U8_t tmask = 0;
+ v_U8_t new_tmask = 0;
+ sme_QosSearchInfo search_key;
+ v_BOOL_t bufferCommand;
+ eHalStatus hstatus;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d for flow %d",
+ __FUNCTION__, __LINE__,
+ sessionId, QosFlowID);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ // if caller sent an empty TSPEC, fill up with the default one
+ if(!pQoSInfo)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ "%s: %d: caller sent an empty QoS param list, using defaults",
+ __FUNCTION__, __LINE__);
+ // find the AC with UPType passed in
+ ac = sme_QosUpToAc(UPType);
+ if(SME_QOS_EDCA_AC_MAX == ac)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid AC %d from UP %d",
+ __FUNCTION__, __LINE__,
+ ac, UPType);
+
+ return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP;
+ }
+ Tspec_Info = sme_QosCb.def_QoSInfo[ac];
+ }
+ else
+ {
+ // find the AC
+ ac = sme_QosUpToAc(pQoSInfo->ts_info.up);
+ if(SME_QOS_EDCA_AC_MAX == ac)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid AC %d from UP %d",
+ __FUNCTION__, __LINE__,
+ ac, pQoSInfo->ts_info.up);
+
+ return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP;
+ }
+ //validate QoS params
+ if(!sme_QosValidateRequestedParams(pMac, pQoSInfo, sessionId))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid params",
+ __FUNCTION__, __LINE__);
+ return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP;
+ }
+ Tspec_Info = *pQoSInfo;
+ }
+ pACInfo = &pSession->ac_info[ac];
+ // need to vote off powersave for the duration of this request
+ pSession->readyForPowerSave = VOS_FALSE;
+ // assume we won't have to (re)buffer the command
+ bufferCommand = VOS_FALSE;
+ //check to consider the following flowing scenario
+ //Addts request is pending on one AC, while APSD requested on another which
+ //needs a reassoc. Will buffer a request if Addts is pending on any AC,
+ //which will safegaurd the above scenario, & also won't confuse PE with back
+ //to back Addts or Addts followed by Reassoc
+ if(sme_QosIsRspPending(sessionId, ac))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: buffering the setup request for flow %d in state %d "
+ "since another request is pending",
+ __FUNCTION__, __LINE__,
+ QosFlowID, pACInfo->curr_state );
+ bufferCommand = VOS_TRUE;
+ }
+ else
+ {
+ // make sure we are in full power so that we can issue
+ // an AddTS or reassoc if necessary
+ hstatus = pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback,
+ pSession, eSME_REASON_OTHER);
+ if( eHAL_STATUS_PMC_PENDING == hstatus )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: buffering the setup request for flow %d in state %d, "
+ "waiting for full power",
+ __FUNCTION__, __LINE__,
+ QosFlowID, pACInfo->curr_state );
+ bufferCommand = VOS_TRUE;
+ }
+ }
+ if (bufferCommand)
+ {
+ // we need to buffer the command
+ cmd.command = SME_QOS_SETUP_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.setupCmdInfo.HDDcontext = HDDcontext;
+ cmd.u.setupCmdInfo.QoSInfo = Tspec_Info;
+ cmd.u.setupCmdInfo.QoSCallback = QoSCallback;
+ cmd.u.setupCmdInfo.UPType = UPType;
+ cmd.u.setupCmdInfo.hoRenewal = hoRenewal;
+ cmd.u.setupCmdInfo.QosFlowID = QosFlowID;
+ hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't buffer the setup request in state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state );
+ // unable to buffer the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Buffered setup request for flow = %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+ return SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
+ }
+
+ //get into the state m/c to see if the request can be granted
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_LINK_UP:
+ //call the internal qos setup logic to decide on if the
+ // request is NOP, or need reassoc for APSD and/or need to send out ADDTS
+ status = sme_QosSetup(pMac, sessionId, &Tspec_Info, ac);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d with AC %d in state SME_QOS_LINK_UP "
+ "sme_QosSetup returned with status %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, status);
+ if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
+ {
+ // we aren't waiting for a response from the AP
+ // so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ if((SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)||
+ (SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
+ (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
+ {
+ // we received an expected "good" status
+ //create an entry in the flow list
+ pentry = vos_mem_malloc(sizeof(*pentry));
+ if (!pentry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't allocate memory for the new "
+ "entry in the Flow List",
+ __FUNCTION__, __LINE__);
+ return SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ }
+ pentry->ac_type = ac;
+ pentry->HDDcontext = HDDcontext;
+ pentry->QoSCallback = QoSCallback;
+ pentry->hoRenewal = hoRenewal;
+ pentry->QosFlowID = QosFlowID;
+ pentry->sessionId = sessionId;
+ // since we are in state SME_QOS_LINK_UP this must be the
+ // first TSPEC on this AC, so use index 0 (mask bit 1)
+ pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0] = Tspec_Info;
+ if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)
+ {
+ if(pACInfo->tspec_mask_status &&
+ !pACInfo->reassoc_pending)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d with AC %d in state "
+ "SME_QOS_LINK_UP tspec_mask_status is %d "
+ "but should not be set yet",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->tspec_mask_status);
+ //ASSERT
+ VOS_ASSERT(0);
+ vos_mem_free(pentry);
+ return SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ }
+ pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_SET;
+ if(!pACInfo->reassoc_pending)
+ {
+ // we didn't request for reassoc, it must be a tspec negotiation
+ pACInfo->tspec_pending = 1;
+ }
+
+ pentry->reason = SME_QOS_REASON_SETUP;
+ new_state = SME_QOS_REQUESTED;
+ }
+ else
+ {
+ // SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP or
+ // SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY
+ pentry->reason = SME_QOS_REASON_REQ_SUCCESS;
+ new_state = SME_QOS_QOS_ON;
+ pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_SET;
+ pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] = Tspec_Info;
+ if(buffered_cmd && !pentry->hoRenewal)
+ {
+ QoSCallback(pMac, HDDcontext,
+ &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ status,
+ pentry->QosFlowID);
+ }
+ pentry->hoRenewal = VOS_FALSE;
+ }
+ pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0]++;
+
+ //indicate on which index the flow entry belongs to & add it to the
+ //Flow List at the end
+ pentry->tspec_mask = pACInfo->tspec_mask_status;
+ pentry->QoSInfo = Tspec_Info;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Creating entry on session %d at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ sessionId, pentry, QosFlowID);
+ csrLLInsertTail(&sme_QosCb.flow_list, &pentry->link, VOS_TRUE);
+ }
+ else
+ {
+ // unexpected status returned by sme_QosSetup()
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d unexpected status %d "
+ "returned by sme_QosSetup",
+ __FUNCTION__, __LINE__,
+ sessionId, status);
+ new_state = pACInfo->curr_state;
+ if(buffered_cmd && hoRenewal)
+ {
+ QoSCallback(pMac, HDDcontext,
+ &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
+ QosFlowID);
+ }
+ }
+ break;
+ case SME_QOS_HANDOFF:
+ case SME_QOS_REQUESTED:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: Buffering setup request for flow %d in state = %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID, pACInfo->curr_state );
+ //buffer cmd
+ cmd.command = SME_QOS_SETUP_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.setupCmdInfo.HDDcontext = HDDcontext;
+ cmd.u.setupCmdInfo.QoSInfo = Tspec_Info;
+ cmd.u.setupCmdInfo.QoSCallback = QoSCallback;
+ cmd.u.setupCmdInfo.UPType = UPType;
+ cmd.u.setupCmdInfo.hoRenewal = hoRenewal;
+ cmd.u.setupCmdInfo.QosFlowID = QosFlowID;
+ hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d couldn't buffer the setup "
+ "request for flow %d in state = %d",
+ __FUNCTION__, __LINE__,
+ sessionId, QosFlowID, pACInfo->curr_state );
+ // unable to buffer the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ }
+ status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
+ new_state = pACInfo->curr_state;
+ break;
+ case SME_QOS_QOS_ON:
+
+ //check if multiple flows running on the ac
+ if((pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] > 0)||
+ (pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] > 0))
+ {
+ //do we need to care about the case where APSD needed on ACM = 0 below?
+ if(CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) ||
+ sme_QosIsACM(pMac, pSession->assocInfo.pBssDesc, ac, NULL))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: tspec_mask_status = %d for AC = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->tspec_mask_status, ac);
+ if(!pACInfo->tspec_mask_status)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: tspec_mask_status can't be 0 for ac = %d in "
+ "state = %d",
+ __FUNCTION__, __LINE__,
+ ac, pACInfo->curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return status;
+ }
+ /* Flow aggregation */
+ if(SME_QOS_TSPEC_MASK_BIT_1_2_SET != pACInfo->tspec_mask_status)
+ {
+ /* Either of upstream, downstream or bidirectional flows are present */
+ /* If either of new stream or current stream is for bidirecional, aggregate
+ * the new stream with the current streams present and send out aggregated Tspec.*/
+ if((Tspec_Info.ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH) ||
+ (pACInfo->curr_QoSInfo[pACInfo->tspec_mask_status - 1].
+ ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH))
+ {
+ // Aggregate the new stream with the current stream(s).
+ tmask = pACInfo->tspec_mask_status;
+ }
+ /* None of new stream or current (aggregated) streams are for bidirectional.
+ * Check if the new stream direction matches the current stream direction. */
+ else if(pACInfo->curr_QoSInfo[pACInfo->tspec_mask_status - 1].
+ ts_info.direction == Tspec_Info.ts_info.direction)
+ {
+ // Aggregate the new stream with the current stream(s).
+ tmask = pACInfo->tspec_mask_status;
+ }
+ /* New stream is in different direction. */
+ else
+ {
+ // No Aggregation. Mark the 2nd tpsec index also as active.
+ tmask = SME_QOS_TSPEC_MASK_CLEAR;
+ new_tmask = SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~pACInfo->tspec_mask_status;
+ pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_2_SET;
+ }
+ }
+ else
+ {
+ /* Both uplink and downlink streams are present. */
+ /* If new stream is bidirectional, aggregate new stream with all existing
+ * upstreams and downstreams. Send out new aggregated tpsec. */
+ if(Tspec_Info.ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH)
+ {
+ // Only one tspec index (0) will be in use after this aggregation.
+ tmask = SME_QOS_TSPEC_MASK_BIT_1_2_SET;
+ pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_SET;
+ }
+ /* New stream is also uni-directional
+ * Find out the tsepc index with which it needs to be aggregated */
+ else if(pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.direction !=
+ Tspec_Info.ts_info.direction)
+ {
+ // Aggregate with 2nd tspec index
+ tmask = SME_QOS_TSPEC_MASK_BIT_2_SET;
+ }
+ else
+ {
+ // Aggregate with 1st tspec index
+ tmask = SME_QOS_TSPEC_MASK_BIT_1_SET;
+ }
+ }
+ }
+ else
+ {
+ //ACM = 0
+ // We won't be sending a TSPEC to the AP but we still need
+ // to aggregate to calculate trigger frame parameters
+ tmask = SME_QOS_TSPEC_MASK_BIT_1_SET;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: tmask = %d, new_tmask = %d in state = %d",
+ __FUNCTION__, __LINE__,
+ tmask, new_tmask, pACInfo->curr_state );
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: tspec_mask_status = %d for AC = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->tspec_mask_status, ac);
+ if(tmask)
+ {
+ // create the aggregate TSPEC
+ if(tmask != SME_QOS_TSPEC_MASK_BIT_1_2_SET)
+ {
+ hstatus = sme_QosAggregateParams(&Tspec_Info,
+ &pACInfo->curr_QoSInfo[tmask - 1],
+ &pACInfo->requested_QoSInfo[tmask - 1]);
+ }
+ else
+ {
+ /* Aggregate the new bidirectional stream with the existing upstreams and
+ * downstreams in tspec indices 0 and 1. */
+ tmask = SME_QOS_TSPEC_MASK_BIT_1_SET;
+
+ if((hstatus = sme_QosAggregateParams(&Tspec_Info,
+ &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ &pACInfo->requested_QoSInfo[tmask - 1]))
+ == eHAL_STATUS_SUCCESS)
+ {
+ hstatus = sme_QosAggregateParams(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
+ &pACInfo->requested_QoSInfo[tmask - 1],
+ NULL);
+ }
+ }
+
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: failed to aggregate params",
+ __FUNCTION__, __LINE__);
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ }
+ }
+ else
+ {
+ tmask = new_tmask;
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: no flows running for ac = %d while in state = %d",
+ __FUNCTION__, __LINE__,
+ ac, pACInfo->curr_state );
+ //ASSERT
+ VOS_ASSERT(0);
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return status;
+ }
+ //although aggregating, make sure to request on the correct UP
+ pACInfo->requested_QoSInfo[tmask - 1].ts_info.up = Tspec_Info.ts_info.up;
+ status = sme_QosSetup(pMac, sessionId,
+ &pACInfo->requested_QoSInfo[tmask - 1], ac);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON "
+ "sme_QosSetup returned with status %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, status);
+ if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
+ {
+ // we aren't waiting for a response from the AP
+ // so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ if((SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)||
+ (SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
+ (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
+ {
+ // we received an expected "good" status
+ //create an entry in the flow list
+ pentry = (sme_QosFlowInfoEntry *) vos_mem_malloc(sizeof(*pentry));
+ if (!pentry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't allocate memory for the new "
+ "entry in the Flow List",
+ __FUNCTION__, __LINE__);
+ return SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ }
+ pentry->ac_type = ac;
+ pentry->HDDcontext = HDDcontext;
+ pentry->QoSCallback = QoSCallback;
+ pentry->hoRenewal = hoRenewal;
+ pentry->QosFlowID = QosFlowID;
+ pentry->sessionId = sessionId;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Creating flow %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+ if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status)||
+ (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
+ {
+ new_state = pACInfo->curr_state;
+ pentry->reason = SME_QOS_REASON_REQ_SUCCESS;
+ pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] =
+ pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0];
+ if(buffered_cmd && !pentry->hoRenewal)
+ {
+ QoSCallback(pMac, HDDcontext,
+ &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ status,
+ pentry->QosFlowID);
+ }
+ if(SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)
+ {
+ // if we are not in handoff, then notify all flows on
+ // this AC that the aggregate TSPEC may have changed
+ if(!pentry->hoRenewal)
+ {
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
+ search_key.sessionId = sessionId;
+ hstatus = sme_QosFindAllInFlowList(pMac, search_key,
+ sme_QosSetupFnp);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't notify other "
+ "entries on this AC =%d",
+ __FUNCTION__, __LINE__, ac);
+ }
+ }
+ }
+ pentry->hoRenewal = VOS_FALSE;
+ }
+ else
+ {
+ // SME_QOS_STATUS_SETUP_REQ_PENDING_RSP
+ new_state = SME_QOS_REQUESTED;
+ pentry->reason = SME_QOS_REASON_SETUP;
+ //Need this info when addts comes back from PE to know on
+ //which index of the AC the request was from
+ pACInfo->tspec_pending = tmask;
+ }
+ pACInfo->num_flows[tmask - 1]++;
+ //indicate on which index the flow entry belongs to & add it to the
+ //Flow List at the end
+ pentry->tspec_mask = tmask;
+ pentry->QoSInfo = Tspec_Info;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d creating entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ sessionId, pentry, QosFlowID);
+ csrLLInsertTail(&sme_QosCb.flow_list, &pentry->link, VOS_TRUE);
+ }
+ else
+ {
+ // unexpected status returned by sme_QosSetup()
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d unexpected status %d "
+ "returned by sme_QosSetup",
+ __FUNCTION__, __LINE__,
+ sessionId, status);
+ new_state = pACInfo->curr_state;
+ }
+ break;
+ case SME_QOS_CLOSED:
+ case SME_QOS_INIT:
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: setup requested in unexpected state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state);
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ VOS_ASSERT(0);
+ new_state = pACInfo->curr_state;
+ }
+ /* if current state is same as previous no need for transistion,
+ if we are doing reassoc & we are already in handoff state, no need to move
+ to requested state. But make sure to set the previous state as requested
+ state
+ */
+ if((new_state != pACInfo->curr_state)&&
+ (!(pACInfo->reassoc_pending &&
+ (SME_QOS_HANDOFF == pACInfo->curr_state))))
+ {
+ sme_QosStateTransition(sessionId, ac, new_state);
+ }
+
+ if(pACInfo->reassoc_pending &&
+ (SME_QOS_HANDOFF == pACInfo->curr_state))
+ {
+ pACInfo->prev_state = SME_QOS_REQUESTED;
+ }
+ if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
+ (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
+ {
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ }
+ return status;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosInternalModifyReq() - The SME QoS internal function to request
+ for modification of certain QoS params on a flow running on a particular AC.
+ If the request involves admission control on the requested AC, HDD needs to
+ provide the necessary Traffic Specification (TSPEC) parameters & SME might
+ start the renegotiation process through ADDTS.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info as defined above, provided by HDD
+ \param QosFlowID - Identification per flow running on each AC generated by
+ SME.
+ It is only meaningful if the QoS setup for the flow has
+ been successful already
+
+ \return SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful.
+
+ Other status means request failed
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosInternalModifyReq(tpAniSirGlobal pMac,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ v_U32_t QosFlowID,
+ v_BOOL_t buffered_cmd)
+{
+ tListElem *pEntry= NULL;
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosFlowInfoEntry *pNewEntry= NULL;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ sme_QosEdcaAcType ac;
+ sme_QosStates new_state = SME_QOS_CLOSED;
+ sme_QosStatusType status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ sme_QosWmmTspecInfo Aggr_Tspec_Info;
+ sme_QosSearchInfo search_key;
+ sme_QosCmdInfo cmd;
+ v_U8_t sessionId;
+ v_BOOL_t bufferCommand;
+ eHalStatus hstatus;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked for flow %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ //set the key type & the key to be searched in the Flow List
+ search_key.key.QosFlowID = QosFlowID;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_1;
+ search_key.sessionId = SME_QOS_SEARCH_SESSION_ID_ANY;
+ //go through the link list to find out the details on the flow
+ pEntry = sme_QosFindInFlowList(search_key);
+ if(!pEntry)
+ {
+ //Err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: no match found for flowID = %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+ return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP;
+ }
+ // find the AC
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ ac = flow_info->ac_type;
+
+ sessionId = flow_info->sessionId;
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pACInfo = &pSession->ac_info[ac];
+
+ //validate QoS params
+ if(!sme_QosValidateRequestedParams(pMac, pQoSInfo, sessionId))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid params",
+ __FUNCTION__, __LINE__);
+ return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP;
+ }
+ // For modify, make sure that direction, TID and UP are not being altered
+ if((pQoSInfo->ts_info.direction != flow_info->QoSInfo.ts_info.direction) ||
+ (pQoSInfo->ts_info.up != flow_info->QoSInfo.ts_info.up) ||
+ (pQoSInfo->ts_info.tid != flow_info->QoSInfo.ts_info.tid))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Modification of direction/tid/up is not allowed",
+ __FUNCTION__, __LINE__);
+
+ return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP;
+ }
+ // need to vote off powersave for the duration of this request
+ pSession->readyForPowerSave = VOS_FALSE;
+ // assume we won't have to (re)buffer the command
+ bufferCommand = VOS_FALSE;
+ //check to consider the following flowing scenario
+ //Addts request is pending on one AC, while APSD requested on another which
+ //needs a reassoc. Will buffer a request if Addts is pending on any AC,
+ //which will safegaurd the above scenario, & also won't confuse PE with back
+ //to back Addts or Addts followed by Reassoc
+ if(sme_QosIsRspPending(sessionId, ac))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: buffering the modify request for flow %d in state %d "
+ "since another request is pending",
+ __FUNCTION__, __LINE__,
+ QosFlowID, pACInfo->curr_state );
+ bufferCommand = VOS_TRUE;
+ }
+ else
+ {
+ // make sure we are in full power so that we can issue
+ // an AddTS or reassoc if necessary
+ hstatus = pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback,
+ pSession, eSME_REASON_OTHER);
+ if( eHAL_STATUS_PMC_PENDING == hstatus )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: buffering the modify request for flow %d in state %d, "
+ "waiting for full power",
+ __FUNCTION__, __LINE__,
+ QosFlowID, pACInfo->curr_state );
+ bufferCommand = VOS_TRUE;
+ }
+ }
+ if (bufferCommand)
+ {
+ // we need to buffer the command
+ cmd.command = SME_QOS_MODIFY_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.modifyCmdInfo.QosFlowID = QosFlowID;
+ cmd.u.modifyCmdInfo.QoSInfo = *pQoSInfo;
+ hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't buffer the modify request in state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state );
+ // unable to buffer the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Buffered modify request for flow = %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+ return SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
+ }
+ //get into the stat m/c to see if the request can be granted
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_QOS_ON:
+ //save the new params adding a new (duplicate) entry in the Flow List
+ //Once we have decided on OTA exchange needed or not we can delete the
+ //original one from the List
+ pNewEntry = (sme_QosFlowInfoEntry *) vos_mem_malloc(sizeof(*pNewEntry));
+ if (!pNewEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't allocate memory for the new "
+ "entry in the Flow List",
+ __FUNCTION__, __LINE__);
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ }
+ pNewEntry->ac_type = ac;
+ pNewEntry->sessionId = sessionId;
+ pNewEntry->HDDcontext = flow_info->HDDcontext;
+ pNewEntry->QoSCallback = flow_info->QoSCallback;
+ pNewEntry->QosFlowID = flow_info->QosFlowID;
+ pNewEntry->reason = SME_QOS_REASON_MODIFY_PENDING;
+ //since it is a modify request, use the same index on which the flow
+ //entry originally was running & add it to the Flow List at the end
+ pNewEntry->tspec_mask = flow_info->tspec_mask;
+ pNewEntry->QoSInfo = *pQoSInfo;
+ //update the entry from Flow List which needed to be modified
+ flow_info->reason = SME_QOS_REASON_MODIFY;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d creating modified "
+ "entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ sessionId, pNewEntry, pNewEntry->QosFlowID);
+ //add the new entry under construction to the Flow List
+ csrLLInsertTail(&sme_QosCb.flow_list, &pNewEntry->link, VOS_TRUE);
+ //update TSPEC with the new param set
+ hstatus = sme_QosUpdateParams(sessionId,
+ ac, pNewEntry->tspec_mask,
+ &Aggr_Tspec_Info);
+ if(HAL_STATUS_SUCCESS(hstatus))
+ {
+ pACInfo->requested_QoSInfo[pNewEntry->tspec_mask -1] = Aggr_Tspec_Info;
+ //if ACM, send out a new ADDTS
+ status = sme_QosSetup(pMac, sessionId,
+ &pACInfo->requested_QoSInfo[pNewEntry->tspec_mask -1],
+ ac);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON "
+ "sme_QosSetup returned with status %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, status);
+ if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
+ {
+ // we aren't waiting for a response from the AP
+ // so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)
+ {
+ new_state = SME_QOS_REQUESTED;
+ status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
+ pACInfo->tspec_pending = pNewEntry->tspec_mask;
+ }
+ else if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
+ (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
+ {
+ new_state = SME_QOS_QOS_ON;
+
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ //delete the original entry in FLOW list which got modified
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
+ search_key.sessionId = sessionId;
+ hstatus = sme_QosFindAllInFlowList(pMac, search_key,
+ sme_QosModifyFnp);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ }
+ if(SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP != status)
+ {
+ pACInfo->curr_QoSInfo[pNewEntry->tspec_mask -1] =
+ pACInfo->requested_QoSInfo[pNewEntry->tspec_mask -1];
+ if(SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)
+ {
+ status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY;
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
+ search_key.sessionId = sessionId;
+ hstatus = sme_QosFindAllInFlowList(pMac, search_key,
+ sme_QosModificationNotifyFnp);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't notify other "
+ "entries on this AC =%d",
+ __FUNCTION__, __LINE__, ac);
+ }
+ }
+ else if(SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status)
+ {
+ status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP;
+ }
+ }
+ if(buffered_cmd)
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[pNewEntry->tspec_mask -1],
+ status,
+ flow_info->QosFlowID);
+ }
+
+ }
+ else
+ {
+ // unexpected status returned by sme_QosSetup()
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d unexpected status %d "
+ "returned by sme_QosSetup",
+ __FUNCTION__, __LINE__,
+ sessionId, status);
+ new_state = SME_QOS_QOS_ON;
+ }
+ }
+ else
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosUpdateParams() failed",
+ __FUNCTION__, __LINE__);
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ new_state = SME_QOS_LINK_UP;
+ }
+ /* if we are doing reassoc & we are already in handoff state, no need
+ to move to requested state. But make sure to set the previous state
+ as requested state
+ */
+ if(!(pACInfo->reassoc_pending &&
+ (SME_QOS_HANDOFF == pACInfo->curr_state)))
+ {
+ sme_QosStateTransition(sessionId, ac, new_state);
+ }
+ else
+ {
+ pACInfo->prev_state = SME_QOS_REQUESTED;
+ }
+ break;
+ case SME_QOS_HANDOFF:
+ case SME_QOS_REQUESTED:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: Buffering modify request for flow %d in state = %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID, pACInfo->curr_state );
+ //buffer cmd
+ cmd.command = SME_QOS_MODIFY_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.modifyCmdInfo.QosFlowID = QosFlowID;
+ cmd.u.modifyCmdInfo.QoSInfo = *pQoSInfo;
+ hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't buffer the modify request in state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state );
+ // unable to buffer the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ }
+ status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
+ break;
+ case SME_QOS_CLOSED:
+ case SME_QOS_INIT:
+ case SME_QOS_LINK_UP:
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: modify requested in unexpected state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state);
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ break;
+ }
+ if((SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
+ (SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY == status))
+ {
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosInternalReleaseReq() - The SME QoS internal function to request
+ for releasing a QoS flow running on a particular AC.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param QosFlowID - Identification per flow running on each AC generated by SME
+ It is only meaningful if the QoS setup for the flow is
+ successful
+
+ \return eHAL_STATUS_SUCCESS - Release is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosInternalReleaseReq(tpAniSirGlobal pMac,
+ v_U32_t QosFlowID,
+ v_BOOL_t buffered_cmd)
+{
+ tListElem *pEntry= NULL;
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ sme_QosFlowInfoEntry *pDeletedFlow = NULL;
+ sme_QosEdcaAcType ac;
+ sme_QosStates new_state = SME_QOS_CLOSED;
+ sme_QosStatusType status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
+ sme_QosWmmTspecInfo Aggr_Tspec_Info;
+ sme_QosSearchInfo search_key;
+ sme_QosCmdInfo cmd;
+ tCsrRoamModifyProfileFields modifyProfileFields;
+ v_BOOL_t deltsIssued = VOS_FALSE;
+ v_U8_t sessionId;
+ v_BOOL_t bufferCommand;
+ eHalStatus hstatus;
+ v_BOOL_t biDirectionalFlowsPresent = VOS_FALSE;
+ v_BOOL_t uplinkFlowsPresent = VOS_FALSE;
+ v_BOOL_t downlinkFlowsPresent = VOS_FALSE;
+ tListElem *pResult= NULL;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked for flow %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ //set the key type & the key to be searched in the Flow List
+ search_key.key.QosFlowID = QosFlowID;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_1;
+ search_key.sessionId = SME_QOS_SEARCH_SESSION_ID_ANY;
+ //go through the link list to find out the details on the flow
+ pEntry = sme_QosFindInFlowList(search_key);
+
+ if(!pEntry)
+ {
+ //Err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: no match found for flowID = %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+ return SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP;
+ }
+ // find the AC
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ ac = flow_info->ac_type;
+ sessionId = flow_info->sessionId;
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ // need to vote off powersave for the duration of this request
+ pSession->readyForPowerSave = VOS_FALSE;
+ // assume we won't have to (re)buffer the command
+ bufferCommand = VOS_FALSE;
+ //check to consider the following flowing scenario
+ //Addts request is pending on one AC, while APSD requested on another which
+ //needs a reassoc. Will buffer a request if Addts is pending on any AC,
+ //which will safegaurd the above scenario, & also won't confuse PE with back
+ //to back Addts or Addts followed by Reassoc
+ if(sme_QosIsRspPending(sessionId, ac))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: buffering the release request for flow %d in state %d "
+ "since another request is pending",
+ __FUNCTION__, __LINE__,
+ QosFlowID, pACInfo->curr_state );
+ bufferCommand = VOS_TRUE;
+ }
+ else
+ {
+ // make sure we are in full power so that we can issue
+ // a DelTS or reassoc if necessary
+ hstatus = pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback,
+ pSession, eSME_REASON_OTHER);
+ if( eHAL_STATUS_PMC_PENDING == hstatus )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: buffering the release request for flow %d in state %d, "
+ "waiting for full power",
+ __FUNCTION__, __LINE__,
+ QosFlowID, pACInfo->curr_state );
+ bufferCommand = VOS_TRUE;
+ }
+ }
+ if (bufferCommand)
+ {
+ // we need to buffer the command
+ cmd.command = SME_QOS_RELEASE_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.releaseCmdInfo.QosFlowID = QosFlowID;
+ hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't buffer the release request in state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state );
+ // unable to buffer the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Buffered release request for flow = %d",
+ __FUNCTION__, __LINE__,
+ QosFlowID);
+ return SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP;
+ }
+ //get into the stat m/c to see if the request can be granted
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_QOS_ON:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: tspec_mask_status = %d for AC = %d with "
+ "entry tspec_mask = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->tspec_mask_status, ac, flow_info->tspec_mask);
+
+ //check if multiple flows running on the ac
+ if(pACInfo->num_flows[flow_info->tspec_mask - 1] > 1)
+ {
+ //don't want to include the flow in the new TSPEC on which release
+ //is requested
+ flow_info->reason = SME_QOS_REASON_RELEASE;
+
+ /* Check if the flow being released is for bi-diretional.
+ * Following flows may present in the system.
+ * a) bi-directional flows
+ * b) uplink flows
+ * c) downlink flows.
+ * If the flow being released is for bidirectional, splitting of existing
+ * streams into two tspec indices is required in case ff (b), (c) are present
+ * and not (a).
+ * In case if split occurs, all upstreams are aggregated into tspec index 0,
+ * downstreams are aggregaed into tspec index 1 and two tspec requests for
+ * (aggregated) upstream(s) followed by (aggregated) downstream(s) is sent
+ * to AP. */
+ if(flow_info->QoSInfo.ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH)
+ {
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ //set the key type & the key to be searched in the Flow List
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_4;
+ search_key.sessionId = sessionId;
+ search_key.direction = SME_QOS_WMM_TS_DIR_BOTH;
+ pResult = sme_QosFindInFlowList(search_key);
+ if(pResult)
+ biDirectionalFlowsPresent = VOS_TRUE;
+
+ if(!biDirectionalFlowsPresent)
+ {
+ // The only existing bidirectional flow is being released
+
+ // Check if uplink flows exist
+ search_key.direction = SME_QOS_WMM_TS_DIR_UPLINK;
+ pResult = sme_QosFindInFlowList(search_key);
+ if(pResult)
+ uplinkFlowsPresent = VOS_TRUE;
+
+ // Check if downlink flows exist
+ search_key.direction = SME_QOS_WMM_TS_DIR_DOWNLINK;
+ pResult = sme_QosFindInFlowList(search_key);
+ if(pResult)
+ downlinkFlowsPresent = VOS_TRUE;
+
+ if(uplinkFlowsPresent && downlinkFlowsPresent)
+ {
+ // Need to split the uni-directional flows into SME_QOS_TSPEC_INDEX_0 and SME_QOS_TSPEC_INDEX_1
+
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ // Mark all downstream flows as using tspec index 1
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_4;
+ search_key.sessionId = sessionId;
+ search_key.direction = SME_QOS_WMM_TS_DIR_DOWNLINK;
+ sme_QosUpdateTspecMask(sessionId, search_key, SME_QOS_TSPEC_MASK_BIT_2_SET);
+
+ // Aggregate all downstream flows
+ hstatus = sme_QosUpdateParams(sessionId,
+ ac, SME_QOS_TSPEC_MASK_BIT_2_SET,
+ &Aggr_Tspec_Info);
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d buffering the AddTS request "
+ "for AC %d in state %d as Addts is pending "
+ "on other Tspec index of this AC",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+
+ // Buffer the (aggregated) tspec request for downstream flows.
+ // Please note that the (aggregated) tspec for upstream flows is sent
+ // out by the susequent logic.
+ cmd.command = SME_QOS_RESEND_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.resendCmdInfo.ac = ac;
+ cmd.u.resendCmdInfo.tspecMask = SME_QOS_TSPEC_MASK_BIT_2_SET;
+ cmd.u.resendCmdInfo.QoSInfo = Aggr_Tspec_Info;
+ pACInfo->requested_QoSInfo[SME_QOS_TSPEC_MASK_BIT_2_SET - 1] = Aggr_Tspec_Info;
+ if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d unable to buffer the AddTS "
+ "request for AC %d TSPEC %d in state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, SME_QOS_TSPEC_MASK_BIT_2_SET, pACInfo->curr_state);
+
+ // unable to buffer the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+
+ return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ }
+ pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_2_SET;
+
+ }
+ }
+ }
+
+ /* In case of splitting of existing streams,
+ * tspec_mask will be pointing to tspec index 0 and
+ * aggregated tspec for upstream(s) is sent out here. */
+ hstatus = sme_QosUpdateParams(sessionId,
+ ac, flow_info->tspec_mask,
+ &Aggr_Tspec_Info);
+ if(HAL_STATUS_SUCCESS(hstatus))
+ {
+ pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1] = Aggr_Tspec_Info;
+ //if ACM, send out a new ADDTS
+ status = sme_QosSetup(pMac, sessionId,
+ &pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1], ac);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON "
+ "sme_QosSetup returned with status %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, status);
+ if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
+ {
+ // we aren't waiting for a response from the AP
+ // so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)
+ {
+ new_state = SME_QOS_REQUESTED;
+ status = SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP;
+ pACInfo->tspec_pending = flow_info->tspec_mask;
+ }
+ else if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
+ (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
+ {
+ new_state = SME_QOS_QOS_ON;
+ pACInfo->num_flows[flow_info->tspec_mask - 1]--;
+ pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1] =
+ pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1];
+ //delete the entry from Flow List
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Deleting entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ flow_info, QosFlowID);
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ pDeletedFlow = flow_info;
+ if(SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)
+ {
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
+ search_key.sessionId = sessionId;
+ hstatus = sme_QosFindAllInFlowList(pMac, search_key,
+ sme_QosSetupFnp);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't notify other "
+ "entries on this AC =%d",
+ __FUNCTION__, __LINE__, ac);
+ }
+ }
+ status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP;
+ if(buffered_cmd)
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
+ status,
+ flow_info->QosFlowID);
+ }
+ }
+ else
+ {
+ // unexpected status returned by sme_QosSetup()
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d unexpected status %d "
+ "returned by sme_QosSetup",
+ __FUNCTION__, __LINE__,
+ sessionId, status);
+ new_state = SME_QOS_LINK_UP;
+ pACInfo->num_flows[flow_info->tspec_mask - 1]--;
+ pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1] =
+ pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1];
+ //delete the entry from Flow List
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d deleting entry at "
+ "%p with flowID %d",
+ __FUNCTION__, __LINE__,
+ sessionId, flow_info, QosFlowID);
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ pDeletedFlow = flow_info;
+ if(buffered_cmd)
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
+ status,
+ flow_info->QosFlowID);
+ }
+ }
+ }
+ else
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosUpdateParams() failed",
+ __FUNCTION__, __LINE__);
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ new_state = SME_QOS_LINK_UP;
+ if(buffered_cmd)
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
+ status,
+ flow_info->QosFlowID);
+ }
+ }
+ }
+ else
+ {
+ // this is the only flow aggregated in this TSPEC
+ status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP;
+#ifdef FEATURE_WLAN_CCX
+ if (ac == SME_QOS_EDCA_AC_VO)
+ {
+ // Indicate to neighbor roam logic of the new required VO
+ // ac bandwidth requirement.
+ csrNeighborRoamIndicateVoiceBW( pMac, pACInfo->curr_QoSInfo[0].peak_data_rate, FALSE );
+ }
+#endif
+ //check if delts needs to be sent
+ if(CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) ||
+ sme_QosIsACM(pMac, pSession->assocInfo.pBssDesc, ac, NULL))
+ {
+ //check if other TSPEC for this AC is also in use
+ if(SME_QOS_TSPEC_MASK_BIT_1_2_SET != pACInfo->tspec_mask_status)
+ {
+ // this is the only TSPEC active on this AC
+ // so indicate that we no longer require APSD
+ pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
+ //Also update modifyProfileFields.uapsd_mask in CSR for consistency
+ csrGetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields);
+ modifyProfileFields.uapsd_mask = pSession->apsdMask;
+ csrSetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields);
+ if(!pSession->apsdMask)
+ {
+ // this session no longer needs UAPSD
+ // do any sessions still require UAPSD?
+ if (!sme_QosIsUapsdActive())
+ {
+ // No sessions require UAPSD so turn it off
+ // (really don't care when PMC stops it)
+ (void)pmcStopUapsd(pMac);
+ }
+ }
+ }
+ //send delts
+ hstatus = qosIssueCommand(pMac, sessionId, eSmeCommandDelTs,
+ NULL, ac, flow_info->tspec_mask);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosDelTsReq() failed",
+ __FUNCTION__, __LINE__);
+ status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
+ // we won't be waiting for a response from the AP
+ // so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ else
+ {
+ pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET &
+ (~flow_info->tspec_mask);
+ deltsIssued = VOS_TRUE;
+ }
+ }
+ else if(pSession->apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac)))
+ {
+ //reassoc logic
+ csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields);
+ modifyProfileFields.uapsd_mask |= pSession->apsdMask;
+ modifyProfileFields.uapsd_mask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
+ pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
+ if(!pSession->apsdMask)
+ {
+ // this session no longer needs UAPSD
+ // do any sessions still require UAPSD?
+ if (!sme_QosIsUapsdActive())
+ {
+ // No sessions require UAPSD so turn it off
+ // (really don't care when PMC stops it)
+ (void)pmcStopUapsd(pMac);
+ }
+ }
+ hstatus = sme_QosRequestReassoc(pMac, sessionId,
+ &modifyProfileFields, VOS_FALSE);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Reassoc failed",
+ __FUNCTION__, __LINE__);
+ status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
+ // we won't be waiting for a response from the AP
+ // so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ else
+ {
+ pACInfo->reassoc_pending = VOS_FALSE;//no need to wait
+ pACInfo->prev_state = SME_QOS_LINK_UP;
+ pACInfo->tspec_pending = 0;
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: nothing to do for AC = %d",
+ __FUNCTION__, __LINE__, ac);
+ // we won't be waiting for a response from the AP
+ // so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ if(buffered_cmd)
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ NULL,
+ status,
+ flow_info->QosFlowID);
+ }
+ if(SME_QOS_STATUS_RELEASE_FAILURE_RSP == status)
+ {
+ break;
+ }
+
+ if(((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~flow_info->tspec_mask) > 0) &&
+ ((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~flow_info->tspec_mask) <=
+ SME_QOS_TSPEC_INDEX_MAX))
+ {
+ if(pACInfo->num_flows[(SME_QOS_TSPEC_MASK_BIT_1_2_SET &
+ ~flow_info->tspec_mask) - 1] > 0)
+ {
+ new_state = SME_QOS_QOS_ON;
+ }
+ else
+ {
+ new_state = SME_QOS_LINK_UP;
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Exceeded the array bounds of pACInfo->num_flows",
+ __FUNCTION__, __LINE__);
+ VOS_ASSERT (0);
+ return SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP;
+ }
+
+ if(VOS_FALSE == deltsIssued)
+ {
+ vos_mem_zero(&pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
+ sizeof(sme_QosWmmTspecInfo));
+ }
+ vos_mem_zero(&pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1],
+ sizeof(sme_QosWmmTspecInfo));
+ pACInfo->num_flows[flow_info->tspec_mask - 1]--;
+ //delete the entry from Flow List
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d deleting entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ sessionId, flow_info, QosFlowID);
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ pDeletedFlow = flow_info;
+ }
+ /* if we are doing reassoc & we are already in handoff state, no need
+ to move to requested state. But make sure to set the previous state
+ as requested state
+ */
+ if(SME_QOS_HANDOFF != pACInfo->curr_state)
+ {
+ sme_QosStateTransition(sessionId, ac, new_state);
+ }
+ if(pACInfo->reassoc_pending)
+ {
+ pACInfo->prev_state = SME_QOS_REQUESTED;
+ }
+ break;
+ case SME_QOS_HANDOFF:
+ case SME_QOS_REQUESTED:
+ //buffer cmd
+ cmd.command = SME_QOS_RELEASE_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.releaseCmdInfo.QosFlowID = QosFlowID;
+ hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't buffer the release request in state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state );
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
+ }
+ status = SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP;
+ break;
+ case SME_QOS_CLOSED:
+ case SME_QOS_INIT:
+ case SME_QOS_LINK_UP:
+ default:
+ //print error msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: release request in unexpected state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state );
+ //ASSERT
+ VOS_ASSERT(0);
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ break;
+ }
+ // if we deleted a flow, reclaim the memory
+ if (pDeletedFlow)
+ {
+ vos_mem_free(pDeletedFlow);
+ }
+ if((SME_QOS_STATUS_RELEASE_SUCCESS_RSP == status))
+ {
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ }
+ return status;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosSetup() - The internal qos setup function which has the
+ intelligence if the request is NOP, or for APSD and/or need to send out ADDTS.
+ It also does the sanity check for QAP, AP supports APSD etc.
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param sessionId - Session upon which setup is being performed
+ \param pTspec_Info - Pointer to sme_QosWmmTspecInfo which contains the WMM
+ TSPEC related info as defined above
+ \param ac - Enumeration of the various EDCA Access Categories.
+
+ \return SME_QOS_STATUS_SETUP_SUCCESS_RSP if the setup is successful
+ The logic used in the code might be confusing. Trying to cover all the cases
+ here.
+ AP supports App wants ACM = 1 Already set APSD Result
+ | 0 | 0 | 0 | 0 | NO ACM NO APSD
+ | 0 | 0 | 0 | 1 | NO ACM NO APSD/INVALID
+ | 0 | 0 | 1 | 0 | ADDTS
+ | 0 | 0 | 1 | 1 | ADDTS
+ | 0 | 1 | 0 | 0 | FAILURE
+ | 0 | 1 | 0 | 1 | INVALID
+ | 0 | 1 | 1 | 0 | ADDTS
+ | 0 | 1 | 1 | 1 | ADDTS
+ | 1 | 0 | 0 | 0 | NO ACM NO APSD
+ | 1 | 0 | 0 | 1 | NO ACM NO APSD
+ | 1 | 0 | 1 | 0 | ADDTS
+ | 1 | 0 | 1 | 1 | ADDTS
+ | 1 | 1 | 0 | 0 | REASSOC
+ | 1 | 1 | 0 | 1 | NOP: APSD SET ALREADY
+ | 1 | 1 | 1 | 0 | ADDTS
+ | 1 | 1 | 1 | 1 | ADDTS
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosWmmTspecInfo *pTspec_Info,
+ sme_QosEdcaAcType ac)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosStatusType status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ tDot11fBeaconIEs *pIes = NULL;
+ tCsrRoamModifyProfileFields modifyProfileFields;
+ eHalStatus hstatus;
+ if( !CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Session Id %d is invalid",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ return status;
+ }
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if( !pSession->sessionActive )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Session %d is inactive",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ return status;
+ }
+ if(!pSession->assocInfo.pBssDesc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Session %d has an Invalid BSS Descriptor",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ return status;
+ }
+ hstatus = csrGetParsedBssDescriptionIEs(pMac,
+ pSession->assocInfo.pBssDesc,
+ &pIes);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d unable to parse BSS IEs",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ return status;
+ }
+
+ /* success so pIes was allocated */
+
+ if( !CSR_IS_QOS_BSS(pIes) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AP doesn't support QoS",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ vos_mem_free(pIes);
+ //notify HDD through the synchronous status msg
+ return SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP;
+ }
+ if(pTspec_Info->max_service_interval || pTspec_Info->min_service_interval)
+ {
+ pTspec_Info->ts_info.psb = 1;
+ }
+ else
+ {
+ pTspec_Info->ts_info.psb = 0;
+ }
+
+ pACInfo = &pSession->ac_info[ac];
+ do
+ {
+ // is ACM enabled for this AC?
+ if(CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) ||
+ sme_QosIsACM(pMac, pSession->assocInfo.pBssDesc, ac, NULL))
+ {
+ // ACM is enabled for this AC so we must send an AddTS
+ if(pTspec_Info->ts_info.psb &&
+ (!pMac->pmc.uapsdEnabled ))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Request is looking for APSD but PMC doesn't "
+ "have support for APSD",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ if(SME_QOS_MAX_TID == pTspec_Info->ts_info.tid)
+ {
+ //App didn't set TID, generate one
+ pTspec_Info->ts_info.tid =
+ (v_U8_t)(SME_QOS_WMM_UP_NC - pTspec_Info->ts_info.up);
+ }
+ //addts logic
+ hstatus = qosIssueCommand(pMac, sessionId, eSmeCommandAddTs,
+ pTspec_Info, ac, 0);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosAddTsReq() failed",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d AddTS on AC %d is pending",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
+ break;
+ }
+ // ACM is not enabled for this AC
+ // Is the application looking for APSD?
+ if(0 == pTspec_Info->ts_info.psb)
+ {
+ //no, we don't need APSD
+ //but check the case, if the setup is called as a result of a release
+ // or modify which boils down to the fact that APSD was set on this AC
+ // but no longer needed - so we need a reassoc for the above case to
+ // let the AP know
+ if(pSession->apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac)))
+ {
+ // APSD was formerly enabled on this AC but is no longer required
+ // so we must reassociate
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d reassoc needed "
+ "to disable APSD on AC %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields);
+ modifyProfileFields.uapsd_mask |= pSession->apsdMask;
+ modifyProfileFields.uapsd_mask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
+ hstatus = sme_QosRequestReassoc(pMac, sessionId,
+ &modifyProfileFields, VOS_FALSE);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Unable to request reassociation",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d reassociation to enable "
+ "APSD on AC %d is pending",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
+ pACInfo->reassoc_pending = VOS_TRUE;
+ }
+ }
+ else
+ {
+ // we don't need APSD on this AC
+ // and we don't currently have APSD on this AC
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Request is not looking for APSD & Admission "
+ "Control isn't mandatory for the AC",
+ __FUNCTION__, __LINE__);
+ //return success right away
+ status = SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP;
+ }
+ break;
+ }
+ else if(!(pIes->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD) &&
+ !(pIes->WMMInfoAp.uapsd))
+ {
+ // application is looking for APSD but AP doesn't support it
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AP doesn't support APSD",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ break;
+ }
+ else if(pSession->apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac)))
+ {
+ // application is looking for APSD
+ // and it is already enabled on this AC
+ status = SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Request is looking for APSD and it is already "
+ "set for the AC",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ else
+ {
+ // application is looking for APSD
+ // but it is not enabled on this AC
+ // so we need to reassociate
+ if(pMac->pmc.uapsdEnabled)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d reassoc needed "
+ "to enable APSD on AC %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ //reassoc logic
+ // update the UAPSD mask to include the new
+ // AC on which APSD is requested
+ csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields);
+ modifyProfileFields.uapsd_mask |= pSession->apsdMask;
+ modifyProfileFields.uapsd_mask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
+ hstatus = sme_QosRequestReassoc(pMac, sessionId,
+ &modifyProfileFields, VOS_FALSE);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Unable to request reassociation",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d reassociation to enable "
+ "APSD on AC %d is pending",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
+ pACInfo->reassoc_pending = VOS_TRUE;
+ }
+ }
+ else
+ {
+ //err msg: no support for APSD from PMC
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: no support for APSD or BMPS from PMC",
+ __FUNCTION__, __LINE__);
+ }
+ }
+ }while(0);
+
+ vos_mem_free(pIes);
+ return status;
+}
+
+#ifdef FEATURE_WLAN_CCX
+/* This is a dummy function now. But the purpose of me adding this was to
+ * delay the TSPEC processing till SET_KEY completes. This function can be
+ * used to do any SME_QOS processing after the SET_KEY. As of now, it is
+ * not required as we are ok with tspec getting programmed before set_key
+ * as the roam timings are measured without tspec in reassoc!
+ */
+eHalStatus sme_QosProcessSetKeySuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ "########### CCX Set Key Complete #############");
+ return eHAL_STATUS_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosCCXSaveTspecResponse() - This function saves the TSPEC
+ parameters that came along in the TSPEC IE in the reassoc response
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param sessionId - SME session ID
+ \param pTspec - Pointer to the TSPEC IE from the reassoc rsp
+ \param ac - Access Category for which this TSPEC rsp is received
+ \param tspecIndex - flow/direction
+
+ \return eHAL_STATUS_SUCCESS - Release is successful.
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosCCXSaveTspecResponse(tpAniSirGlobal pMac, v_U8_t sessionId, tDot11fIEWMMTSPEC *pTspec, v_U8_t ac, v_U8_t tspecIndex)
+{
+ tpSirAddtsRsp pAddtsRsp = &sme_QosCb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex];
+
+ ac = sme_QosUPtoACMap[pTspec->user_priority];
+
+ vos_mem_zero(pAddtsRsp, sizeof(tSirAddtsRsp));
+
+ pAddtsRsp->messageType = eWNI_SME_ADDTS_RSP;
+ pAddtsRsp->length = sizeof(tSirAddtsRsp);
+ pAddtsRsp->rc = eSIR_SUCCESS;
+ pAddtsRsp->sessionId = sessionId;
+ pAddtsRsp->rsp.dialogToken = 0;
+ pAddtsRsp->rsp.status = eSIR_SUCCESS;
+ pAddtsRsp->rsp.wmeTspecPresent = pTspec->present;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "%s: Copy Tspec to local data structure ac=%d, tspecIdx=%d",
+ __FUNCTION__, ac, tspecIndex);
+
+ if (pAddtsRsp->rsp.wmeTspecPresent)
+ {
+ //Copy TSPEC params received in assoc response to addts response
+ ConvertWMMTSPEC(pMac, &pAddtsRsp->rsp.tspec, pTspec);
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosCCXProcessReassocTspecRsp() - This function processes the
+ WMM TSPEC IE in the reassoc response. Reassoc triggered as part of
+ CCX roaming to another CCX capable AP. If the TSPEC was added before
+ reassoc, as part of Call Admission Control, the reasso req from the
+ STA would carry the TSPEC parameters which were already negotiated
+ with the older AP.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param sessionId - SME session ID
+ \param pEven_info - Pointer to the smeJoinRsp structure
+
+ \return eHAL_STATUS_SUCCESS - Release is successful.
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosCCXProcessReassocTspecRsp(tpAniSirGlobal pMac, v_U8_t sessionId, void* pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ tDot11fIEWMMTSPEC *pTspecIE = NULL;
+ tCsrRoamSession *pCsrSession = CSR_GET_SESSION( pMac, sessionId );
+ tCsrRoamConnectedInfo *pCsrConnectedInfo = &pCsrSession->connectedInfo;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ v_U8_t ac, numTspec, cnt;
+ v_U8_t tspec_flow_index, tspec_mask_status;
+ v_U32_t tspecIeLen;
+
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+ // Get the TSPEC IEs which came along with the reassoc response
+ // from the pbFrames pointer
+ pTspecIE = (tDot11fIEWMMTSPEC *)(pCsrConnectedInfo->pbFrames + pCsrConnectedInfo->nBeaconLength +
+ pCsrConnectedInfo->nAssocReqLength + pCsrConnectedInfo->nAssocRspLength + pCsrConnectedInfo->nRICRspLength);
+
+ // Get the number of tspecs Ies in the frame, the min length
+ // should be atleast equal to the one TSPEC IE
+ tspecIeLen = pCsrConnectedInfo->nTspecIeLength;
+ if (tspecIeLen < sizeof(tDot11fIEWMMTSPEC)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("CCX Tspec IE len %d less than min %d"),
+ tspecIeLen, sizeof(tDot11fIEWMMTSPEC));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ "TspecLen = %d, pbFrames = %p, pTspecIE = %p\n",
+ tspecIeLen, pCsrConnectedInfo->pbFrames, pTspecIE);
+
+ numTspec = (tspecIeLen)/sizeof(tDot11fIEWMMTSPEC);
+ for(cnt=0; cnt<numTspec; cnt++) {
+ ac = sme_QosUpToAc(pTspecIE->user_priority);
+ pACInfo = &pSession->ac_info[ac];
+ tspec_mask_status = pACInfo->tspec_mask_status;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ FL("UP=%d, ac=%d, tspec_mask_status=%x"),
+ pTspecIE->user_priority, ac, tspec_mask_status );
+
+ for (tspec_flow_index = 0; tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++) {
+ if (tspec_mask_status & (1 << tspec_flow_index)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ FL("Found Tspec entry flow = %d AC = %d"),tspec_flow_index, ac);
+ sme_QosCCXSaveTspecResponse(pMac, sessionId, pTspecIE, ac, tspec_flow_index);
+ } else {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ FL("Not found Tspec entry flow = %d AC = %d"),tspec_flow_index, ac);
+ }
+ }
+ // Increment the pointer to point it to the next TSPEC IE
+ pTspecIE++;
+ }
+
+ /* Send the Aggregated QoS request to HAL */
+ status = sme_QosFTAggrQosReq(pMac,sessionId);
+
+ return status;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosCopyTspecInfo() - This function copies the existing TSPEC
+ parameters from the source structure to the destination structure.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pTspec_Info - source structure
+ \param pTspec - destination structure
+
+ \return void
+ --------------------------------------------------------------------------*/
+static void sme_QosCopyTspecInfo(tpAniSirGlobal pMac, sme_QosWmmTspecInfo *pTspec_Info, tSirMacTspecIE* pTspec)
+{
+ /* As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service
+ * Interval, Service Start Time, Suspension Interval and Delay Bound are
+ * all intended for HCCA operation and therefore must be set to zero*/
+ pTspec->delayBound = pTspec_Info->delay_bound;
+ pTspec->inactInterval = pTspec_Info->inactivity_interval;
+ pTspec->length = SME_QOS_TSPEC_IE_LENGTH;
+ pTspec->maxBurstSz = pTspec_Info->max_burst_size;
+ pTspec->maxMsduSz = pTspec_Info->maximum_msdu_size;
+ pTspec->maxSvcInterval = pTspec_Info->max_service_interval;
+ pTspec->meanDataRate = pTspec_Info->mean_data_rate;
+ pTspec->mediumTime = pTspec_Info->medium_time;
+ pTspec->minDataRate = pTspec_Info->min_data_rate;
+ pTspec->minPhyRate = pTspec_Info->min_phy_rate;
+ pTspec->minSvcInterval = pTspec_Info->min_service_interval;
+ pTspec->nomMsduSz = pTspec_Info->nominal_msdu_size;
+ pTspec->peakDataRate = pTspec_Info->peak_data_rate;
+ pTspec->surplusBw = pTspec_Info->surplus_bw_allowance;
+ pTspec->suspendInterval = pTspec_Info->suspension_interval;
+ pTspec->svcStartTime = pTspec_Info->svc_start_time;
+ pTspec->tsinfo.traffic.direction = pTspec_Info->ts_info.direction;
+
+ //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup
+ if (pTspec_Info->ts_info.psb && btcIsReadyForUapsd(pMac)) {
+ pTspec->tsinfo.traffic.psb = pTspec_Info->ts_info.psb;
+ } else {
+ pTspec->tsinfo.traffic.psb = 0;
+ pTspec_Info->ts_info.psb = 0;
+ }
+ pTspec->tsinfo.traffic.tsid = pTspec_Info->ts_info.tid;
+ pTspec->tsinfo.traffic.userPrio = pTspec_Info->ts_info.up;
+ pTspec->tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA;
+ pTspec->tsinfo.traffic.burstSizeDefn = pTspec_Info->ts_info.burst_size_defn;
+ pTspec->tsinfo.traffic.ackPolicy = pTspec_Info->ts_info.ack_policy;
+ pTspec->type = SME_QOS_TSPEC_IE_TYPE;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: up = %d, tid = %d",
+ __FUNCTION__, __LINE__,
+ pTspec_Info->ts_info.up,
+ pTspec_Info->ts_info.tid);
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosCCxRetrieveTspecInfo() - This function is called by CSR
+ when try to create reassoc request message to PE - csrSendSmeReassocReqMsg
+ This functions get the existing tspec parameters to be included
+ in the reassoc request.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param sessionId - SME session ID
+ \param pTspecInfo - Pointer to the structure to carry back the TSPEC parameters
+
+ \return v_U8_t - number of existing negotiated TSPECs
+ --------------------------------------------------------------------------*/
+v_U8_t sme_QosCCxRetrieveTspecInfo(tpAniSirGlobal pMac, v_U8_t sessionId, tTspecInfo *pTspecInfo)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ v_U8_t tspec_mask_status = 0;
+ v_U8_t tspec_pending_status = 0;
+ v_U8_t ac, numTspecs = 0;
+ tTspecInfo *pDstTspec = pTspecInfo;
+
+ //TODO: Check if TSPEC has already been established, if not return
+
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
+ volatile v_U8_t tspec_index = 0;
+
+ pACInfo = &pSession->ac_info[ac];
+ tspec_pending_status = pACInfo->tspec_pending;
+ tspec_mask_status = pACInfo->tspec_mask_status;
+
+ do {
+ if (tspec_mask_status & SME_QOS_TSPEC_MASK_BIT_1_SET) {
+ /* If a tspec status is pending, take requested_QoSInfo for RIC request, else use curr_QoSInfo
+ for the RIC request */
+ if (tspec_pending_status & SME_QOS_TSPEC_MASK_BIT_1_SET) {
+ sme_QosCopyTspecInfo(pMac, &pACInfo->requested_QoSInfo[tspec_index], &pDstTspec->tspec);
+ } else {
+ sme_QosCopyTspecInfo(pMac, &pACInfo->curr_QoSInfo[tspec_index], &pDstTspec->tspec);
+ }
+ pDstTspec->valid = TRUE;
+ numTspecs++;
+ pDstTspec++;
+ }
+ tspec_mask_status >>= 1;
+ tspec_pending_status >>= 1;
+ tspec_index++;
+ } while (tspec_mask_status);
+ }
+
+ return numTspecs;
+}
+
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+
+eHalStatus sme_QosCreateTspecRICIE(tpAniSirGlobal pMac, sme_QosWmmTspecInfo *pTspec_Info,
+ v_U8_t *pRICBuffer, v_U32_t *pRICLength, v_U8_t *pRICIdentifier)
+{
+ tDot11fIERICDataDesc ricIE;
+ tANI_U32 nStatus;
+
+ VOS_ASSERT(NULL != pRICBuffer);
+ VOS_ASSERT(NULL != pRICLength);
+ VOS_ASSERT(NULL != pRICIdentifier);
+
+ vos_mem_zero(&ricIE, sizeof(tDot11fIERICDataDesc));
+
+ ricIE.present = 1;
+ ricIE.RICData.present = 1;
+ ricIE.RICData.resourceDescCount = 1;
+ ricIE.RICData.statusCode = 0;
+ ricIE.RICData.Identifier = sme_QosAssignDialogToken();
+#ifndef USE_80211_WMMTSPEC_FOR_RIC
+ ricIE.TSPEC.present = 1;
+ ricIE.TSPEC.delay_bound = pTspec_Info->delay_bound;
+ ricIE.TSPEC.inactivity_int = pTspec_Info->inactivity_interval;
+ ricIE.TSPEC.burst_size = pTspec_Info->max_burst_size;
+ ricIE.TSPEC.max_msdu_size = pTspec_Info->maximum_msdu_size;
+ ricIE.TSPEC.max_service_int = pTspec_Info->max_service_interval;
+ ricIE.TSPEC.mean_data_rate = pTspec_Info->mean_data_rate;
+ ricIE.TSPEC.medium_time = pTspec_Info->medium_time;
+ ricIE.TSPEC.min_data_rate = pTspec_Info->min_data_rate;
+ ricIE.TSPEC.min_phy_rate = pTspec_Info->min_phy_rate;
+ ricIE.TSPEC.min_service_int = pTspec_Info->min_service_interval;
+ ricIE.TSPEC.size = pTspec_Info->nominal_msdu_size;
+ ricIE.TSPEC.peak_data_rate = pTspec_Info->peak_data_rate;
+ ricIE.TSPEC.surplus_bw_allowance = pTspec_Info->surplus_bw_allowance;
+ ricIE.TSPEC.suspension_int = pTspec_Info->suspension_interval;
+ ricIE.TSPEC.service_start_time = pTspec_Info->svc_start_time;
+ ricIE.TSPEC.direction = pTspec_Info->ts_info.direction;
+ //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup
+ if( pTspec_Info->ts_info.psb && btcIsReadyForUapsd(pMac) )
+ {
+ ricIE.TSPEC.psb = pTspec_Info->ts_info.psb;
+ }
+ else
+ {
+ ricIE.TSPEC.psb = 0;
+ }
+ ricIE.TSPEC.tsid = pTspec_Info->ts_info.tid;
+ ricIE.TSPEC.user_priority = pTspec_Info->ts_info.up;
+ ricIE.TSPEC.access_policy = SME_QOS_ACCESS_POLICY_EDCA;
+
+ *pRICIdentifier = ricIE.RICData.Identifier;
+
+ nStatus = dot11fPackIeRICDataDesc(pMac, &ricIE, pRICBuffer, sizeof(ricIE), pRICLength);
+ if (DOT11F_FAILED(nStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Packing of RIC Data of length %d failed with status %d"),
+ *pRICLength, nStatus);
+ }
+#else // WMM TSPEC
+ /*As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service
+ Interval, Service Start Time, Suspension Interval and Delay Bound are
+ all intended for HCCA operation and therefore must be set to zero*/
+ ricIE.WMMTSPEC.present = 1;
+ ricIE.WMMTSPEC.version = 1;
+ ricIE.WMMTSPEC.delay_bound = pTspec_Info->delay_bound;
+ ricIE.WMMTSPEC.inactivity_int = pTspec_Info->inactivity_interval;
+ ricIE.WMMTSPEC.burst_size = pTspec_Info->max_burst_size;
+ ricIE.WMMTSPEC.max_msdu_size = pTspec_Info->maximum_msdu_size;
+ ricIE.WMMTSPEC.max_service_int = pTspec_Info->max_service_interval;
+ ricIE.WMMTSPEC.mean_data_rate = pTspec_Info->mean_data_rate;
+ ricIE.WMMTSPEC.medium_time = pTspec_Info->medium_time;
+ ricIE.WMMTSPEC.min_data_rate = pTspec_Info->min_data_rate;
+ ricIE.WMMTSPEC.min_phy_rate = pTspec_Info->min_phy_rate;
+ ricIE.WMMTSPEC.min_service_int = pTspec_Info->min_service_interval;
+ ricIE.WMMTSPEC.size = pTspec_Info->nominal_msdu_size;
+ ricIE.WMMTSPEC.peak_data_rate = pTspec_Info->peak_data_rate;
+ ricIE.WMMTSPEC.surplus_bw_allowance = pTspec_Info->surplus_bw_allowance;
+ ricIE.WMMTSPEC.suspension_int = pTspec_Info->suspension_interval;
+ ricIE.WMMTSPEC.service_start_time = pTspec_Info->svc_start_time;
+ ricIE.WMMTSPEC.direction = pTspec_Info->ts_info.direction;
+ //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup
+ if( pTspec_Info->ts_info.psb && btcIsReadyForUapsd(pMac) )
+ {
+ ricIE.WMMTSPEC.psb = pTspec_Info->ts_info.psb;
+ }
+ else
+ {
+ ricIE.WMMTSPEC.psb = 0;
+ }
+ ricIE.WMMTSPEC.tsid = pTspec_Info->ts_info.tid;
+ ricIE.WMMTSPEC.user_priority = pTspec_Info->ts_info.up;
+ ricIE.WMMTSPEC.access_policy = SME_QOS_ACCESS_POLICY_EDCA;
+
+
+ nStatus = dot11fPackIeRICDataDesc(pMac, &ricIE, pRICBuffer, sizeof(ricIE), pRICLength);
+ if (DOT11F_FAILED(nStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Packing of RIC Data of length %d failed with status %d"),
+ *pRICLength, nStatus);
+ }
+#endif /* 80211_TSPEC */
+ *pRICIdentifier = ricIE.RICData.Identifier;
+ return nStatus;
+}
+
+eHalStatus sme_QosProcessFTReassocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ v_U8_t ac, qos_requested = FALSE;
+ v_U8_t tspec_flow_index;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ tListElem *pEntry= NULL;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ FL("Invoked on session %d"), sessionId);
+
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ qos_requested = FALSE;
+
+ for (tspec_flow_index = 0; tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++)
+ {
+ /* Only in the below case, copy the AC's curr QoS Info to requested QoS info */
+ if ((pACInfo->ricIdentifier[tspec_flow_index] && !pACInfo->tspec_pending) ||
+ (pACInfo->tspec_mask_status & (1<<tspec_flow_index)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("Copying the currentQos to requestedQos for AC=%d, flow=%d\n"),
+ ac, tspec_flow_index );
+
+ pACInfo->requested_QoSInfo[tspec_flow_index] = pACInfo->curr_QoSInfo[tspec_flow_index];
+ vos_mem_zero(&pACInfo->curr_QoSInfo[tspec_flow_index], sizeof(sme_QosWmmTspecInfo));
+ qos_requested = TRUE;
+ }
+ }
+
+ // Only if the tspec is required, transition the state to
+ // SME_QOS_REQUESTED for this AC
+ if (qos_requested)
+ {
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_HANDOFF:
+ sme_QosStateTransition(sessionId, ac, SME_QOS_REQUESTED);
+ break;
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("FT Reassoc req event in unexpected state %d"), pACInfo->curr_state);
+ VOS_ASSERT(0);
+ }
+ }
+
+ }
+
+ /* At this point of time, we are disconnected from the old AP, so it is safe
+ * to reset all these session variables */
+ pSession->apsdMask = 0;
+ pSession->uapsdAlreadyRequested = 0;
+ pSession->readyForPowerSave = 0;
+
+ /* Now change reason and HO renewal of all the flow in this session only */
+ pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ "%s: %d: Flow List empty, nothing to update",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ do
+ {
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ if(sessionId == flow_info->sessionId)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Changing FlowID %d reason to SETUP and HO renewal to FALSE",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ flow_info->reason = SME_QOS_REASON_SETUP;
+ flow_info->hoRenewal = eANI_BOOLEAN_TRUE;
+ }
+ pEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
+ } while( pEntry );
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+eHalStatus sme_QosFTAggrQosReq( tpAniSirGlobal pMac, v_U8_t sessionId )
+{
+ tSirAggrQosReq *pMsg = NULL;
+ sme_QosSessionInfo *pSession;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ int i, j = 0;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d", __FUNCTION__, __LINE__,
+ sessionId);
+
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+ pMsg = (tSirAggrQosReq *)vos_mem_malloc(sizeof(tSirAggrQosReq));
+
+ if (!pMsg)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't allocate memory for the msg buffer",
+ __FUNCTION__, __LINE__);
+
+ return eHAL_STATUS_FAILURE;
+ }
+
+ vos_mem_zero(pMsg, sizeof(tSirAggrQosReq));
+
+ pMsg->messageType = pal_cpu_to_be16((v_U16_t)eWNI_SME_FT_AGGR_QOS_REQ);
+ pMsg->length = sizeof(tSirAggrQosReq);
+ pMsg->sessionId = sessionId;
+ pMsg->timeout = 0;
+ pMsg->rspReqd = VOS_TRUE;
+ vos_mem_copy( &pMsg->bssId[ 0 ],
+ &pSession->assocInfo.pBssDesc->bssId[ 0 ],
+ sizeof(tCsrBssid) );
+
+ for( i = 0; i < SME_QOS_EDCA_AC_MAX; i++ )
+ {
+ for( j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++ )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("ac=%d, tspec_mask_staus=%x, tspec_index=%d\n"),
+ i, pSession->ac_info[i].tspec_mask_status, j);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("direction = %d\n"), pSession->ac_info[i].addTsRsp[j].rsp.tspec.tsinfo.traffic.direction);
+ // Check if any flow is active on this AC
+ if ((pSession->ac_info[i].tspec_mask_status) & (1 << j))
+ {
+ tANI_U8 direction = pSession->ac_info[i].addTsRsp[j].rsp.tspec.tsinfo.traffic.direction;
+ if ((direction == SME_QOS_WMM_TS_DIR_UPLINK) ||
+ (direction == SME_QOS_WMM_TS_DIR_BOTH))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ FL("Found tspec entry AC=%d, flow=%d, direction = %d\n"), i, j, direction);
+ pMsg->aggrInfo.aggrAddTsInfo[i].dialogToken =
+ sme_QosAssignDialogToken();
+ pMsg->aggrInfo.aggrAddTsInfo[i].lleTspecPresent =
+ pSession->ac_info[i].addTsRsp[j].rsp.lleTspecPresent;
+ pMsg->aggrInfo.aggrAddTsInfo[i].numTclas =
+ pSession->ac_info[i].addTsRsp[j].rsp.numTclas;
+ vos_mem_copy( pMsg->aggrInfo.aggrAddTsInfo[i].tclasInfo,
+ pSession->ac_info[i].addTsRsp[j].rsp.tclasInfo,
+ SIR_MAC_TCLASIE_MAXNUM );
+ pMsg->aggrInfo.aggrAddTsInfo[i].tclasProc =
+ pSession->ac_info[i].addTsRsp[j].rsp.tclasProc;
+ pMsg->aggrInfo.aggrAddTsInfo[i].tclasProcPresent =
+ pSession->ac_info[i].addTsRsp[j].rsp.tclasProcPresent;
+ pMsg->aggrInfo.aggrAddTsInfo[i].tspec =
+ pSession->ac_info[i].addTsRsp[j].rsp.tspec;
+ pMsg->aggrInfo.aggrAddTsInfo[i].wmeTspecPresent =
+ pSession->ac_info[i].addTsRsp[j].rsp.wmeTspecPresent;
+ pMsg->aggrInfo.aggrAddTsInfo[i].wsmTspecPresent =
+ pSession->ac_info[i].addTsRsp[j].rsp.wsmTspecPresent;
+ pMsg->aggrInfo.tspecIdx |= ( 1 << i );
+
+ // Mark the index for this AC as pending for response, which would be
+ // used to validate the AddTS response from HAL->PE->SME
+ pSession->ac_info[i].tspec_pending = (1<<j);
+ }
+ }
+ }
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "Sending aggregated message to HAL 0x%x\n", pMsg->aggrInfo.tspecIdx);
+
+ if(HAL_STATUS_SUCCESS(palSendMBMessage(pMac->hHdd, pMsg)))
+ {
+ status = eHAL_STATUS_SUCCESS;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: sent down a AGGR QoS req to PE",
+ __FUNCTION__, __LINE__);
+ }
+
+ return status;
+}
+
+eHalStatus sme_QosProcessFTRICResponse(tpAniSirGlobal pMac, v_U8_t sessionId, tDot11fIERICDataDesc *pRicDataDesc, v_U8_t ac, v_U8_t tspecIndex)
+{
+ tANI_U8 i = 0;
+ tpSirAddtsRsp pAddtsRsp
+ = &sme_QosCb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex];
+
+ vos_mem_zero(pAddtsRsp, sizeof(tSirAddtsRsp));
+
+ pAddtsRsp->messageType = eWNI_SME_ADDTS_RSP;
+ pAddtsRsp->length = sizeof(tSirAddtsRsp);
+ pAddtsRsp->rc = pRicDataDesc->RICData.statusCode;
+ pAddtsRsp->sessionId = sessionId;
+ pAddtsRsp->rsp.dialogToken = pRicDataDesc->RICData.Identifier;
+ pAddtsRsp->rsp.status = pRicDataDesc->RICData.statusCode;
+ pAddtsRsp->rsp.wmeTspecPresent = pRicDataDesc->TSPEC.present;
+ if (pAddtsRsp->rsp.wmeTspecPresent)
+ {
+ //Copy TSPEC params received in RIC response to addts response
+ ConvertTSPEC(pMac, &pAddtsRsp->rsp.tspec, &pRicDataDesc->TSPEC);
+ }
+
+ pAddtsRsp->rsp.numTclas = pRicDataDesc->num_TCLAS;
+ if (pAddtsRsp->rsp.numTclas)
+ {
+ for (i = 0; i < pAddtsRsp->rsp.numTclas; i++)
+ {
+ //Copy TCLAS info per index to the addts response
+ ConvertTCLAS(pMac, &pAddtsRsp->rsp.tclasInfo[i], &pRicDataDesc->TCLAS[i]);
+ }
+ }
+
+ pAddtsRsp->rsp.tclasProcPresent = pRicDataDesc->TCLASSPROC.present;
+ if (pAddtsRsp->rsp.tclasProcPresent)
+ pAddtsRsp->rsp.tclasProc = pRicDataDesc->TCLASSPROC.processing;
+
+
+ pAddtsRsp->rsp.schedulePresent = pRicDataDesc->Schedule.present;
+ if (pAddtsRsp->rsp.schedulePresent)
+ {
+ //Copy Schedule IE params to addts response
+ ConvertSchedule(pMac, &pAddtsRsp->rsp.schedule, &pRicDataDesc->Schedule);
+ }
+
+ //Need to check the below portion is a part of WMM TSPEC
+ //Process Delay element
+ if (pRicDataDesc->TSDelay.present)
+ ConvertTSDelay(pMac, &pAddtsRsp->rsp.delay, &pRicDataDesc->TSDelay);
+ //return sme_QosProcessAddTsRsp(pMac, &addtsRsp);
+ return eHAL_STATUS_SUCCESS;
+ }
+eHalStatus sme_QosProcessAggrQosRsp(tpAniSirGlobal pMac, void *pMsgBuf)
+{
+ tpSirAggrQosRsp pAggrRsp = (tpSirAggrQosRsp)pMsgBuf;
+ tSirAddtsRsp addtsRsp;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ int i, j = 0;
+ tANI_U8 sessionId = pAggrRsp->sessionId;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("Received AGGR_QOS resp from LIM"));
+
+ /* Copy over the updated response information for TSPEC of all the ACs */
+ for( i = 0; i < SIR_QOS_NUM_AC_MAX; i++ )
+ {
+ tANI_U8 tspec_mask_status = sme_QosCb.sessionInfo[sessionId].ac_info[i].tspec_mask_status;
+ for( j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++ )
+ {
+ tANI_U8 direction = sme_QosCb.sessionInfo[sessionId].ac_info[i].
+ addTsRsp[j].rsp.tspec.tsinfo.traffic.direction;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("Addts rsp from LIM AC=%d, flow=%d dir=%d, tspecIdx=%x\n"),
+ i, j, direction, pAggrRsp->aggrInfo.tspecIdx);
+ // Check if the direction is Uplink or bi-directional
+ if( ((1<<i) & pAggrRsp->aggrInfo.tspecIdx) &&
+ ((tspec_mask_status) & (1<<j)) &&
+ ((direction == SME_QOS_WMM_TS_DIR_UPLINK) ||
+ (direction == SME_QOS_WMM_TS_DIR_BOTH)))
+ {
+ addtsRsp = sme_QosCb.sessionInfo[sessionId].ac_info[i].addTsRsp[j];
+ addtsRsp.rc = pAggrRsp->aggrInfo.aggrRsp[i].status;
+ addtsRsp.rsp.status = pAggrRsp->aggrInfo.aggrRsp[i].status;
+ addtsRsp.rsp.tspec = pAggrRsp->aggrInfo.aggrRsp[i].tspec;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("%s: Processing Addts rsp from LIM AC=%d, flow=%d\n"), i, j);
+ /* post ADD TS response for each */
+ if (sme_QosProcessAddTsRsp(pMac, &addtsRsp) != eHAL_STATUS_SUCCESS)
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ }
+ }
+ }
+ return status;
+}
+
+
+eHalStatus sme_QosProcessFTReassocRspEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ v_U8_t ac;
+ v_U8_t tspec_flow_index;
+ tDot11fIERICDataDesc *pRicDataDesc = NULL;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tCsrRoamSession *pCsrSession = CSR_GET_SESSION( pMac, sessionId );
+ tCsrRoamConnectedInfo *pCsrConnectedInfo = &pCsrSession->connectedInfo;
+ tANI_U32 ricRspLen = pCsrConnectedInfo->nRICRspLength;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+ pRicDataDesc = (tDot11fIERICDataDesc *)pCsrConnectedInfo->pbFrames + pCsrConnectedInfo->nBeaconLength +
+ pCsrConnectedInfo->nAssocReqLength + pCsrConnectedInfo->nAssocRspLength;
+
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+
+ for (tspec_flow_index = 0; tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++)
+ {
+ /* Only in the below case, copy the AC's curr QoS Info to requested QoS info */
+ if (pACInfo->ricIdentifier[tspec_flow_index])
+ {
+
+ if (!ricRspLen)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("RIC Response not received for AC %d on TSPEC Index %d, RIC Req Identifier = %d"),
+ ac, tspec_flow_index, pACInfo->ricIdentifier[tspec_flow_index]);
+ VOS_ASSERT(0);
+ }
+ else
+ {
+ /* Now we got response for this identifier. Process it. */
+ if (pRicDataDesc->present)
+ {
+ if (pRicDataDesc->RICData.present)
+ {
+ if (pRicDataDesc->RICData.Identifier != pACInfo->ricIdentifier[tspec_flow_index])
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("RIC response order not same as request sent. Request ID = %d, Response ID = %d"),
+ pACInfo->ricIdentifier[tspec_flow_index], pRicDataDesc->RICData.Identifier);
+ VOS_ASSERT(0);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("Processing RIC Response for AC %d, TSPEC Flow index %d with RIC ID %d \n"),
+ ac, tspec_flow_index, pRicDataDesc->RICData.Identifier);
+ status = sme_QosProcessFTRICResponse(pMac, sessionId, pRicDataDesc, ac, tspec_flow_index);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Failed with status %d for AC %d in TSPEC Flow index = %d\n"),
+ status, ac, tspec_flow_index);
+ }
+ }
+ pRicDataDesc++;
+ ricRspLen -= sizeof(tDot11fIERICDataDesc);
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ if (ricRspLen)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("RIC Response still follows despite traversing through all ACs. Remaining len = %d\n"), ricRspLen);
+ VOS_ASSERT(0);
+ }
+
+ /* Send the Aggregated QoS request to HAL */
+ status = sme_QosFTAggrQosReq(pMac,sessionId);
+
+ return status;
+}
+
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosAddTsReq() - To send down the ADDTS request with TSPEC params
+ to PE
+
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param sessionId - Session upon which the TSPEC should be added
+ \param pTspec_Info - Pointer to sme_QosWmmTspecInfo which contains the WMM
+ TSPEC related info as defined above
+ \param ac - Enumeration of the various EDCA Access Categories.
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosAddTsReq(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosWmmTspecInfo * pTspec_Info,
+ sme_QosEdcaAcType ac)
+{
+ tSirAddtsReq *pMsg = NULL;
+ sme_QosSessionInfo *pSession;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+#ifdef FEATURE_WLAN_CCX
+ tCsrRoamSession *pCsrSession = CSR_GET_SESSION( pMac, sessionId );
+#endif
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
+#endif
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d for AC %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pMsg = (tSirAddtsReq *)vos_mem_malloc(sizeof(tSirAddtsReq));
+ if (!pMsg)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't allocate memory for the msg buffer",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_zero(pMsg, sizeof(tSirAddtsReq));
+ pMsg->messageType = pal_cpu_to_be16((v_U16_t)eWNI_SME_ADDTS_REQ);
+ pMsg->length = sizeof(tSirAddtsReq);
+ pMsg->sessionId = sessionId;
+ pMsg->timeout = 0;
+ pMsg->rspReqd = VOS_TRUE;
+ pMsg->req.dialogToken = sme_QosAssignDialogToken();
+ /*As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service
+ Interval, Service Start Time, Suspension Interval and Delay Bound are
+ all intended for HCCA operation and therefore must be set to zero*/
+ pMsg->req.tspec.delayBound = 0;
+ pMsg->req.tspec.inactInterval = pTspec_Info->inactivity_interval;
+ pMsg->req.tspec.length = SME_QOS_TSPEC_IE_LENGTH;
+ pMsg->req.tspec.maxBurstSz = pTspec_Info->max_burst_size;
+ pMsg->req.tspec.maxMsduSz = pTspec_Info->maximum_msdu_size;
+ pMsg->req.tspec.maxSvcInterval = pTspec_Info->max_service_interval;
+ pMsg->req.tspec.meanDataRate = pTspec_Info->mean_data_rate;
+ pMsg->req.tspec.mediumTime = pTspec_Info->medium_time;
+ pMsg->req.tspec.minDataRate = pTspec_Info->min_data_rate;
+ pMsg->req.tspec.minPhyRate = pTspec_Info->min_phy_rate;
+ pMsg->req.tspec.minSvcInterval = pTspec_Info->min_service_interval;
+ pMsg->req.tspec.nomMsduSz = pTspec_Info->nominal_msdu_size;
+ pMsg->req.tspec.peakDataRate = pTspec_Info->peak_data_rate;
+ pMsg->req.tspec.surplusBw = pTspec_Info->surplus_bw_allowance;
+ pMsg->req.tspec.suspendInterval = pTspec_Info->suspension_interval;
+ pMsg->req.tspec.svcStartTime = 0;
+ pMsg->req.tspec.tsinfo.traffic.direction = pTspec_Info->ts_info.direction;
+ //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup
+ if( pTspec_Info->ts_info.psb
+ && btcIsReadyForUapsd(pMac)
+ )
+ {
+ pMsg->req.tspec.tsinfo.traffic.psb = pTspec_Info->ts_info.psb;
+ }
+ else
+ {
+ pMsg->req.tspec.tsinfo.traffic.psb = 0;
+ pTspec_Info->ts_info.psb = 0;
+ }
+ pMsg->req.tspec.tsinfo.traffic.tsid = pTspec_Info->ts_info.tid;
+ pMsg->req.tspec.tsinfo.traffic.userPrio = pTspec_Info->ts_info.up;
+ pMsg->req.tspec.tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA;
+ pMsg->req.tspec.tsinfo.traffic.burstSizeDefn = pTspec_Info->ts_info.burst_size_defn;
+ pMsg->req.tspec.tsinfo.traffic.ackPolicy = pTspec_Info->ts_info.ack_policy;
+ pMsg->req.tspec.type = SME_QOS_TSPEC_IE_TYPE;
+ /*Fill the BSSID pMsg->req.bssId*/
+ if (NULL == pSession->assocInfo.pBssDesc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: BSS descriptor is NULL so we don't send requst to PE",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_copy( &pMsg->bssId[ 0 ],
+ &pSession->assocInfo.pBssDesc->bssId[ 0 ],
+ sizeof(tCsrBssid) );
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: up = %d, tid = %d",
+ __FUNCTION__, __LINE__,
+ pTspec_Info->ts_info.up,
+ pTspec_Info->ts_info.tid);
+#ifdef FEATURE_WLAN_CCX
+ if(pCsrSession->connectedProfile.isCCXAssoc)
+ {
+ pMsg->req.tsrsIE.tsid = pTspec_Info->ts_info.up;
+ pMsg->req.tsrsPresent = 1;
+ }
+#endif
+ if(HAL_STATUS_SUCCESS(palSendMBMessage(pMac->hHdd, pMsg)))
+ {
+ status = eHAL_STATUS_SUCCESS;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: sent down a ADDTS req to PE",
+ __FUNCTION__, __LINE__);
+ //event: EVENT_WLAN_QOS
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ qos.eventId = SME_QOS_DIAG_ADDTS_REQ;
+ qos.reasonCode = SME_QOS_DIAG_USER_REQUESTED;
+ WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
+#endif //FEATURE_WLAN_DIAG_SUPPORT
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosDelTsReq() - To send down the DELTS request with TSPEC params
+ to PE
+
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param sessionId - Session from which the TSPEC should be deleted
+ \param ac - Enumeration of the various EDCA Access Categories.
+ \param tspec_mask - on which tspec per AC, the delts is requested
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosDelTsReq(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosEdcaAcType ac,
+ v_U8_t tspec_mask)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ tSirDeltsReq *pMsg;
+ sme_QosWmmTspecInfo *pTspecInfo;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
+#endif
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d for AC %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ pMsg = (tSirDeltsReq *)vos_mem_malloc(sizeof(tSirDeltsReq));
+ if (!pMsg)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't allocate memory for the msg buffer",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_zero(pMsg, sizeof(tSirDeltsReq));
+ // get pointer to the TSPEC being deleted
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ pTspecInfo = &pACInfo->curr_QoSInfo[tspec_mask - 1];
+ pMsg->messageType = pal_cpu_to_be16((v_U16_t)eWNI_SME_DELTS_REQ);
+ pMsg->length = sizeof(tSirDeltsReq);
+ pMsg->sessionId = sessionId;
+ pMsg->rspReqd = VOS_TRUE;
+ pMsg->req.tspec.delayBound = pTspecInfo->delay_bound;
+ pMsg->req.tspec.inactInterval = pTspecInfo->inactivity_interval;
+ pMsg->req.tspec.length = SME_QOS_TSPEC_IE_LENGTH;
+ pMsg->req.tspec.maxBurstSz = pTspecInfo->max_burst_size;
+ pMsg->req.tspec.maxMsduSz = pTspecInfo->maximum_msdu_size;
+ pMsg->req.tspec.maxSvcInterval = pTspecInfo->max_service_interval;
+ pMsg->req.tspec.meanDataRate = pTspecInfo->mean_data_rate;
+ pMsg->req.tspec.mediumTime = pTspecInfo->medium_time;
+ pMsg->req.tspec.minDataRate = pTspecInfo->min_data_rate;
+ pMsg->req.tspec.minPhyRate = pTspecInfo->min_phy_rate;
+ pMsg->req.tspec.minSvcInterval = pTspecInfo->min_service_interval;
+ pMsg->req.tspec.nomMsduSz = pTspecInfo->nominal_msdu_size;
+ pMsg->req.tspec.peakDataRate = pTspecInfo->peak_data_rate;
+ pMsg->req.tspec.surplusBw = pTspecInfo->surplus_bw_allowance;
+ pMsg->req.tspec.suspendInterval = pTspecInfo->suspension_interval;
+ pMsg->req.tspec.svcStartTime = pTspecInfo->svc_start_time;
+ pMsg->req.tspec.tsinfo.traffic.direction = pTspecInfo->ts_info.direction;
+ pMsg->req.tspec.tsinfo.traffic.psb = pTspecInfo->ts_info.psb;
+ pMsg->req.tspec.tsinfo.traffic.tsid = pTspecInfo->ts_info.tid;
+ pMsg->req.tspec.tsinfo.traffic.userPrio = pTspecInfo->ts_info.up;
+ pMsg->req.tspec.tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA;
+ pMsg->req.tspec.tsinfo.traffic.burstSizeDefn = pTspecInfo->ts_info.burst_size_defn;
+ pMsg->req.tspec.tsinfo.traffic.ackPolicy = pTspecInfo->ts_info.ack_policy;
+ pMsg->req.tspec.type = SME_QOS_TSPEC_IE_TYPE;
+ /*Fill the BSSID pMsg->req.bssId*/
+ if (NULL == pSession->assocInfo.pBssDesc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: BSS descriptor is NULL so we don't send request to PE",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_copy( &pMsg->bssId[ 0 ],
+ &pSession->assocInfo.pBssDesc->bssId[ 0 ],
+ sizeof(tCsrBssid) );
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: up = %d, tid = %d",
+ __FUNCTION__, __LINE__,
+ pTspecInfo->ts_info.up,
+ pTspecInfo->ts_info.tid);
+ vos_mem_zero(&pACInfo->curr_QoSInfo[tspec_mask - 1],
+ sizeof(sme_QosWmmTspecInfo));
+ if(HAL_STATUS_SUCCESS(palSendMBMessage(pMac->hHdd, pMsg)))
+ {
+ status = eHAL_STATUS_SUCCESS;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: sme_QosDelTsReq:Test: sent down a DELTS req to PE",
+ __FUNCTION__, __LINE__);
+ //event: EVENT_WLAN_QOS
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ qos.eventId = SME_QOS_DIAG_DELTS;
+ qos.reasonCode = SME_QOS_DIAG_USER_REQUESTED;
+ WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
+#endif //FEATURE_WLAN_DIAG_SUPPORT
+ }
+
+ return status;
+}
+
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessAddTsRsp() - Function to process the
+ eWNI_SME_ADDTS_RSP came from PE
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pMsgBuf - Pointer to the msg buffer came from PE.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessAddTsRsp(tpAniSirGlobal pMac, void *pMsgBuf)
+{
+ tpSirAddtsRsp paddts_rsp = (tpSirAddtsRsp)pMsgBuf;
+ sme_QosSessionInfo *pSession;
+ v_U8_t sessionId = paddts_rsp->sessionId;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ sme_QosWmmUpType up = (sme_QosWmmUpType)paddts_rsp->rsp.tspec.tsinfo.traffic.userPrio;
+ sme_QosACInfo *pACInfo;
+ sme_QosEdcaAcType ac;
+#endif
+
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d for UP %d",
+ __FUNCTION__, __LINE__,
+ sessionId, up);
+
+ ac = sme_QosUpToAc(up);
+ if(SME_QOS_EDCA_AC_MAX == ac)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid AC %d from UP %d",
+ __FUNCTION__, __LINE__, ac, up);
+
+ return eHAL_STATUS_FAILURE;
+ }
+ pACInfo = &pSession->ac_info[ac];
+ if (SME_QOS_HANDOFF == pACInfo->curr_state)
+ {
+ smsLog(pMac, LOG1, FL("ADDTS Response received for AC %d in HANDOFF State.. Dropping"), ac);
+ pSession->readyForPowerSave = VOS_TRUE;
+ return eHAL_STATUS_SUCCESS;
+ }
+#endif
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
+#endif
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Invoked on session %d with return code %d",
+ __FUNCTION__, __LINE__,
+ sessionId, paddts_rsp->rc);
+ // our outstanding request has been serviced
+ // we can go into powersave
+ pSession->readyForPowerSave = VOS_TRUE;
+ if(paddts_rsp->rc)
+ {
+ //event: EVENT_WLAN_QOS
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ qos.eventId = SME_QOS_DIAG_ADDTS_RSP;
+ qos.reasonCode = SME_QOS_DIAG_ADDTS_REFUSED;
+ WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
+#endif //FEATURE_WLAN_DIAG_SUPPORT
+ status = sme_QosProcessAddTsFailureRsp(pMac, sessionId, &paddts_rsp->rsp);
+ }
+ else
+ {
+ status = sme_QosProcessAddTsSuccessRsp(pMac, sessionId, &paddts_rsp->rsp);
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessDelTsRsp() - Function to process the
+ eWNI_SME_DELTS_RSP came from PE
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pMsgBuf - Pointer to the msg buffer came from PE.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessDelTsRsp(tpAniSirGlobal pMac, void *pMsgBuf)
+{
+ tpSirDeltsRsp pDeltsRsp = (tpSirDeltsRsp)pMsgBuf;
+ sme_QosSessionInfo *pSession;
+ v_U8_t sessionId = pDeltsRsp->sessionId;
+ // msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Invoked on session %d with return code %d",
+ __FUNCTION__, __LINE__,
+ sessionId, pDeltsRsp->rc);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ // our outstanding request has been serviced
+ // we can go into powersave
+ pSession->readyForPowerSave = VOS_TRUE;
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessDelTsInd() - Function to process the
+ eWNI_SME_DELTS_IND came from PE
+
+ Since it's a DELTS indication from AP, will notify all the flows running on
+ this AC about QoS release
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pMsgBuf - Pointer to the msg buffer came from PE.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessDelTsInd(tpAniSirGlobal pMac, void *pMsgBuf)
+{
+ tpSirDeltsRsp pdeltsind = (tpSirDeltsRsp)pMsgBuf;
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ v_U8_t sessionId = pdeltsind->sessionId;
+ sme_QosEdcaAcType ac;
+ sme_QosSearchInfo search_key;
+ sme_QosWmmUpType up = (sme_QosWmmUpType)pdeltsind->rsp.tspec.tsinfo.traffic.userPrio;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
+#endif
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Invoked on session %d for UP %d",
+ __FUNCTION__, __LINE__,
+ sessionId, up);
+ ac = sme_QosUpToAc(up);
+ if(SME_QOS_EDCA_AC_MAX == ac)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid AC %d from UP %d",
+ __FUNCTION__, __LINE__,
+ ac, up);
+ return eHAL_STATUS_FAILURE;
+ }
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pACInfo = &pSession->ac_info[ac];
+
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ //set the key type & the key to be searched in the Flow List
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
+ search_key.sessionId = sessionId;
+ //find all Flows on the perticular AC & delete them, also send HDD indication
+ // through the callback it registered per request
+ if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosDelTsIndFnp)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: no match found for ac = %d",
+ __FUNCTION__, __LINE__,
+ search_key.key.ac_type);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ //clean up the CB
+ vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ sizeof(sme_QosWmmTspecInfo));
+ vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ sizeof(sme_QosWmmTspecInfo));
+ vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
+ sizeof(sme_QosWmmTspecInfo));
+ vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_1],
+ sizeof(sme_QosWmmTspecInfo));
+ pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR;
+ pACInfo->tspec_pending = 0;
+ //event: EVENT_WLAN_QOS
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ qos.eventId = SME_QOS_DIAG_DELTS;
+ qos.reasonCode = SME_QOS_DIAG_DELTS_IND_FROM_AP;
+ WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
+#endif //FEATURE_WLAN_DIAG_SUPPORT
+
+ sme_QosStateTransition(sessionId, ac, SME_QOS_LINK_UP);
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessAssocCompleteEv() - Function to process the
+ SME_QOS_CSR_ASSOC_COMPLETE event indication from CSR
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessAssocCompleteEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_BE;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if(((SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_BE].curr_state)&&
+ (SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_BK].curr_state)&&
+ (SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_VI].curr_state)&&
+ (SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_VO].curr_state)) ||
+ (pSession->handoffRequested))
+ {
+ //get the association info
+ if(!pEvent_info)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: pEvent_info is NULL",
+ __FUNCTION__, __LINE__);
+ return status;
+ }
+ if(!((sme_QosAssocInfo *)pEvent_info)->pBssDesc)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: pBssDesc is NULL",
+ __FUNCTION__, __LINE__);
+ return status;
+ }
+ if((pSession->assocInfo.pBssDesc) &&
+ (csrIsBssidMatch(pMac, (tCsrBssid *)&pSession->assocInfo.pBssDesc->bssId,
+ (tCsrBssid *) &(((sme_QosAssocInfo *)pEvent_info)->pBssDesc->bssId))))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: assoc with the same BSS, no update needed",
+ __FUNCTION__, __LINE__);
+ }
+ else
+ {
+ status = sme_QosSaveAssocInfo(pSession, pEvent_info);
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: wrong state: BE %d, BK %d, VI %d, VO %d",
+ __FUNCTION__, __LINE__,
+ pSession->ac_info[SME_QOS_EDCA_AC_BE].curr_state,
+ pSession->ac_info[SME_QOS_EDCA_AC_BK].curr_state,
+ pSession->ac_info[SME_QOS_EDCA_AC_VI].curr_state,
+ pSession->ac_info[SME_QOS_EDCA_AC_VO].curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ return status;
+ }
+ // the session is active
+ pSession->sessionActive = VOS_TRUE;
+ if(pSession->handoffRequested)
+ {
+ pSession->handoffRequested = VOS_FALSE;
+ //renew all flows
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ status = eHAL_STATUS_SUCCESS;
+ }
+ else
+ {
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_INIT:
+ sme_QosStateTransition(sessionId, ac, SME_QOS_LINK_UP);
+ break;
+ case SME_QOS_LINK_UP:
+ case SME_QOS_REQUESTED:
+ case SME_QOS_QOS_ON:
+ case SME_QOS_HANDOFF:
+ case SME_QOS_CLOSED:
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AC %d is in wrong state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ break;
+ }
+ }
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessReassocReqEv() - Function to process the
+ SME_QOS_CSR_REASSOC_REQ event indication from CSR
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessReassocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosEdcaAcType ac;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if(pSession->ftHandoffInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: no need for state transition, should "
+ "already be in handoff state",
+ __FUNCTION__, __LINE__);
+ VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
+ sme_QosProcessFTReassocReqEv(pMac, sessionId, pEvent_info);
+ return eHAL_STATUS_SUCCESS;
+ }
+#endif
+
+ if(pSession->handoffRequested)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: no need for state transition, should "
+ "already be in handoff state",
+ __FUNCTION__, __LINE__);
+ VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
+
+ //buffer the existing flows to be renewed after handoff is done
+ sme_QosBufferExistingFlows(pMac, sessionId);
+ //clean up the control block partially for handoff
+ sme_QosCleanupCtrlBlkForHandoff(pMac, sessionId);
+ return eHAL_STATUS_SUCCESS;
+ }
+//TBH: Assuming both handoff algo & 11r willn't be enabled at the same time
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if(pSession->ftHandoffInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: no need for state transition, should "
+ "already be in handoff state",
+ __FUNCTION__, __LINE__);
+ VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
+
+ sme_QosProcessFTReassocReqEv(pMac, sessionId, pEvent_info);
+ return eHAL_STATUS_SUCCESS;
+ }
+#endif
+
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_LINK_UP:
+ case SME_QOS_REQUESTED:
+ case SME_QOS_QOS_ON:
+ sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF);
+ break;
+ case SME_QOS_HANDOFF:
+ //This is normal because sme_QosRequestReassoc may already change the state
+ break;
+ case SME_QOS_CLOSED:
+ case SME_QOS_INIT:
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AC %d is in wrong state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ break;
+ }
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessReassocSuccessEv() - Function to process the
+ SME_QOS_CSR_REASSOC_COMPLETE event indication from CSR
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessReassocSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ tpSirSmeJoinRsp pSmeJoinRsp = (tpSirSmeJoinRsp) pEvent_info;
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosEdcaAcType ac, ac_index;
+ sme_QosSearchInfo search_key;
+ sme_QosSearchInfo search_key1;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tListElem *pEntry= NULL;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ // our pending reassociation has completed
+ // we can allow powersave
+ pSession->readyForPowerSave = VOS_TRUE;
+ //get the association info
+ if(!pEvent_info)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: pEvent_info is NULL",
+ __FUNCTION__, __LINE__);
+ return status;
+ }
+ if(!((sme_QosAssocInfo *)pEvent_info)->pBssDesc)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: pBssDesc is NULL",
+ __FUNCTION__, __LINE__);
+ return status;
+ }
+ status = sme_QosSaveAssocInfo(pSession, pEvent_info);
+ if(status)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosSaveAssocInfo() failed",
+ __FUNCTION__, __LINE__);
+ }
+//TBH: Assuming both handoff algo & 11r willn't be enabled at the same time
+ if(pSession->handoffRequested)
+ {
+ pSession->handoffRequested = VOS_FALSE;
+ //renew all flows
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ return eHAL_STATUS_SUCCESS;
+ }
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (pSession->ftHandoffInProgress)
+ {
+ if (csrRoamIs11rAssoc(pMac)) {
+ if (pSmeJoinRsp->parsedRicRspLen) {
+ status = sme_QosProcessFTReassocRspEv(pMac, sessionId, pEvent_info);
+ }
+ }
+#ifdef FEATURE_WLAN_CCX
+ // If CCX association check for TSPEC IEs in the reassoc rsp frame
+ if (csrRoamIsCCXAssoc(pMac)) {
+ if (pSmeJoinRsp->tspecIeLen) {
+ status = sme_QosCCXProcessReassocTspecRsp(pMac, sessionId, pEvent_info);
+ }
+ }
+#endif
+ pSession->ftHandoffInProgress = VOS_FALSE;
+ pSession->handoffRequested = VOS_FALSE;
+ return status;
+ }
+#endif
+
+ pSession->sessionActive = VOS_TRUE;
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_HANDOFF:
+ // return to our previous state
+ sme_QosStateTransition(sessionId, ac, pACInfo->prev_state);
+ //for which ac APSD (hence the reassoc) is requested
+ if(pACInfo->reassoc_pending)
+ {
+ //update the apsd mask in CB - make sure to take care of the case
+ //where we are resetting the bit in apsd_mask
+ if(pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb)
+ {
+ pSession->apsdMask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
+ }
+ else
+ {
+ pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
+ }
+ pACInfo->reassoc_pending = VOS_FALSE;
+ //during setup it gets set as addts & reassoc both gets a pending flag
+ //pACInfo->tspec_pending = 0;
+ sme_QosStateTransition(sessionId, ac, SME_QOS_QOS_ON);
+ // notify HDD with new Service Interval
+ pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] =
+ pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0];
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ //set the key type & the key to be searched in the Flow List
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
+ search_key.sessionId = sessionId;
+ //notify PMC that reassoc is done for APSD on certain AC??
+
+ vos_mem_zero(&search_key1, sizeof(sme_QosSearchInfo));
+ //set the hoRenewal field in control block if needed
+ search_key1.index = SME_QOS_SEARCH_KEY_INDEX_3;
+ search_key1.key.reason = SME_QOS_REASON_SETUP;
+ search_key1.sessionId = sessionId;
+ for(ac_index = SME_QOS_EDCA_AC_BE; ac_index < SME_QOS_EDCA_AC_MAX; ac_index++)
+ {
+ pEntry = sme_QosFindInFlowList(search_key1);
+ if(pEntry)
+ {
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ if(flow_info->ac_type == ac)
+ {
+ pACInfo->hoRenewal = flow_info->hoRenewal;
+ break;
+ }
+ }
+ }
+ //notify HDD the success for the requested flow
+ //notify all the other flows running on the AC that QoS got modified
+ if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosReassocSuccessEvFnp)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: no match found for ac = %d",
+ __FUNCTION__, __LINE__,
+ search_key.key.ac_type);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ pACInfo->hoRenewal = VOS_FALSE;
+ vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ sizeof(sme_QosWmmTspecInfo));
+ }
+ status = eHAL_STATUS_SUCCESS;
+ break;
+ case SME_QOS_INIT:
+ case SME_QOS_CLOSED:
+ //NOP
+ status = eHAL_STATUS_SUCCESS;
+ break;
+ case SME_QOS_LINK_UP:
+ case SME_QOS_REQUESTED:
+ case SME_QOS_QOS_ON:
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AC %d is in wrong state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ break;
+ }
+ }
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ return status;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessReassocFailureEv() - Function to process the
+ SME_QOS_CSR_REASSOC_FAILURE event indication from CSR
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessReassocFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosEdcaAcType ac;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ // our pending reassociation has completed
+ // we can allow powersave
+ pSession->readyForPowerSave = VOS_TRUE;
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_HANDOFF:
+ sme_QosStateTransition(sessionId, ac, SME_QOS_INIT);
+ if(pACInfo->reassoc_pending)
+ {
+ pACInfo->reassoc_pending = VOS_FALSE;
+ }
+ vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ sizeof(sme_QosWmmTspecInfo));
+ vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ sizeof(sme_QosWmmTspecInfo));
+ vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
+ sizeof(sme_QosWmmTspecInfo));
+ vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_1],
+ sizeof(sme_QosWmmTspecInfo));
+ pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR;
+ pACInfo->tspec_pending = 0;
+ pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] = 0;
+ pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] = 0;
+ break;
+ case SME_QOS_INIT:
+ case SME_QOS_CLOSED:
+ //NOP
+ break;
+ case SME_QOS_LINK_UP:
+ case SME_QOS_REQUESTED:
+ case SME_QOS_QOS_ON:
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AC %d is in wrong state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ break;
+ }
+ }
+ //need to clean up flows
+ sme_QosDeleteExistingFlows(pMac, sessionId);
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessHandoffAssocReqEv() - Function to process the
+ SME_QOS_CSR_HANDOFF_ASSOC_REQ event indication from CSR
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessHandoffAssocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ v_U8_t ac;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_LINK_UP:
+ case SME_QOS_REQUESTED:
+ case SME_QOS_QOS_ON:
+ sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF);
+ break;
+ case SME_QOS_HANDOFF:
+ //print error msg
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if(pSession->ftHandoffInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: SME_QOS_CSR_HANDOFF_ASSOC_REQ received in "
+ "SME_QOS_HANDOFF state with FT in progress"
+ , __FUNCTION__, __LINE__);
+ break;
+ }
+#endif
+
+ case SME_QOS_CLOSED:
+ case SME_QOS_INIT:
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AC %d is in wrong state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ break;
+ }
+ }
+ // If FT handoff is in progress, legacy handoff need not be enabled
+ if (!pSession->ftHandoffInProgress) {
+ pSession->handoffRequested = VOS_TRUE;
+ }
+ // this session no longer needs UAPSD
+ pSession->apsdMask = 0;
+ // do any sessions still require UAPSD?
+ if (!sme_QosIsUapsdActive())
+ {
+ // No sessions require UAPSD so turn it off
+ // (really don't care when PMC stops it)
+ (void)pmcStopUapsd(pMac);
+ }
+ pSession->uapsdAlreadyRequested = VOS_FALSE;
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessHandoffSuccessEv() - Function to process the
+ SME_QOS_CSR_HANDOFF_COMPLETE event indication from CSR
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessHandoffSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ v_U8_t ac;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ //go back to original state before handoff
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_HANDOFF:
+ sme_QosStateTransition(sessionId, ac, pACInfo->prev_state);
+ //we will retry for the requested flow(s) with the new AP
+ if(SME_QOS_REQUESTED == pACInfo->curr_state)
+ {
+ pACInfo->curr_state = SME_QOS_LINK_UP;
+ }
+ status = eHAL_STATUS_SUCCESS;
+ break;
+ // FT logic, has already moved it to QOS_REQUESTED state during the
+ // reassoc request event, which would include the Qos (TSPEC) params
+ // in the reassoc req frame
+ case SME_QOS_REQUESTED:
+ break;
+ case SME_QOS_INIT:
+ case SME_QOS_CLOSED:
+ case SME_QOS_LINK_UP:
+ case SME_QOS_QOS_ON:
+ default:
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/* In case of 11r - RIC, we request QoS and Hand-off at the same time hence the
+ state may be SME_QOS_REQUESTED */
+ if( pSession->ftHandoffInProgress )
+ break;
+#endif
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AC %d is in wrong state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ break;
+ }
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessHandoffFailureEv() - Function to process the
+ SME_QOS_CSR_HANDOFF_FAILURE event indication from CSR
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessHandoffFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ v_U8_t ac;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_HANDOFF:
+ sme_QosStateTransition(sessionId, ac, SME_QOS_INIT);
+ //need to clean up flows: TODO
+ vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ sizeof(sme_QosWmmTspecInfo));
+ vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ sizeof(sme_QosWmmTspecInfo));
+ vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
+ sizeof(sme_QosWmmTspecInfo));
+ vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_1],
+ sizeof(sme_QosWmmTspecInfo));
+ pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR;
+ pACInfo->tspec_pending = 0;
+ pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] = 0;
+ pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] = 0;
+ break;
+ case SME_QOS_INIT:
+ case SME_QOS_CLOSED:
+ case SME_QOS_LINK_UP:
+ case SME_QOS_REQUESTED:
+ case SME_QOS_QOS_ON:
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AC %d is in wrong state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ break;
+ }
+ }
+ //no longer in handoff
+ pSession->handoffRequested = VOS_FALSE;
+ //clean up the assoc info
+ if(pSession->assocInfo.pBssDesc)
+ {
+ vos_mem_free(pSession->assocInfo.pBssDesc);
+ pSession->assocInfo.pBssDesc = NULL;
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessDisconnectEv() - Function to process the
+ SME_QOS_CSR_DISCONNECT_REQ or SME_QOS_CSR_DISCONNECT_IND event indication
+ from CSR
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessDisconnectEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if((pSession->handoffRequested)
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/* In case of 11r - RIC, we request QoS and Hand-off at the same time hence the
+ state may be SME_QOS_REQUESTED */
+ && !pSession->ftHandoffInProgress
+#endif
+ )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: no need for state transition, should "
+ "already be in handoff state",
+ __FUNCTION__, __LINE__);
+ VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
+ return eHAL_STATUS_SUCCESS;
+ }
+ sme_QosInitACs(pMac, sessionId);
+ // this session doesn't require UAPSD
+ pSession->apsdMask = 0;
+ // do any sessions still require UAPSD?
+ if (!sme_QosIsUapsdActive())
+ {
+ // No sessions require UAPSD so turn it off
+ // (really don't care when PMC stops it)
+ (void)pmcStopUapsd(pMac);
+ }
+ pSession->uapsdAlreadyRequested = VOS_FALSE;
+ pSession->handoffRequested = VOS_FALSE;
+ pSession->readyForPowerSave = VOS_TRUE;
+ pSession->roamID = 0;
+ //need to clean up buffered req
+ sme_QosDeleteBufferedRequests(pMac, sessionId);
+ //need to clean up flows
+ sme_QosDeleteExistingFlows(pMac, sessionId);
+ //clean up the assoc info
+ if(pSession->assocInfo.pBssDesc)
+ {
+ vos_mem_free(pSession->assocInfo.pBssDesc);
+ pSession->assocInfo.pBssDesc = NULL;
+ }
+ sme_QosCb.sessionInfo[sessionId].sessionActive = VOS_FALSE;
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessJoinReqEv() - Function to process the
+ SME_QOS_CSR_JOIN_REQ event indication from CSR
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessJoinReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosEdcaAcType ac;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if(pSession->handoffRequested)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: no need for state transition, should "
+ "already be in handoff state",
+ __FUNCTION__, __LINE__);
+ VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
+ VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
+ //buffer the existing flows to be renewed after handoff is done
+ sme_QosBufferExistingFlows(pMac, sessionId);
+ //clean up the control block partially for handoff
+ sme_QosCleanupCtrlBlkForHandoff(pMac, sessionId);
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ sme_QosStateTransition(sessionId, ac, SME_QOS_INIT);
+ }
+ //clean up the assoc info if already set
+ if(pSession->assocInfo.pBssDesc)
+ {
+ vos_mem_free(pSession->assocInfo.pBssDesc);
+ pSession->assocInfo.pBssDesc = NULL;
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessPreauthSuccessInd() - Function to process the
+ SME_QOS_CSR_PREAUTH_SUCCESS_IND event indication from CSR
+
+ \param pEvent_info - Pointer to relevant info from CSR.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessPreauthSuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ v_U8_t ac;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_LINK_UP:
+ case SME_QOS_REQUESTED:
+ case SME_QOS_QOS_ON:
+ sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF);
+ break;
+ case SME_QOS_HANDOFF:
+ //print error msg
+ case SME_QOS_CLOSED:
+ case SME_QOS_INIT:
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AC %d is in wrong state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+ //ASSERT
+ VOS_ASSERT(0);
+ break;
+ }
+ }
+
+ pSession->ftHandoffInProgress = VOS_TRUE;
+
+ // Check if its a 11R roaming before preparing the RIC IEs
+ if (csrRoamIs11rAssoc(pMac))
+ {
+ v_U16_t ricOffset = 0;
+ v_U32_t ricIELength = 0;
+ v_U8_t *ricIE;
+ v_U8_t tspec_mask_status = 0;
+ v_U8_t tspec_pending_status = 0;
+
+ /* Any Block Ack info there, should have been already filled by PE and present in this buffer
+ and the ric_ies_length should contain the length of the whole RIC IEs. Filling of TSPEC info
+ should start from this length */
+ ricIE = pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies;
+ ricOffset = pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies_length;
+
+ /* Now we have to process the currentTspeInfo inside this session and create the RIC IEs */
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ volatile v_U8_t tspec_index = 0;
+
+ pACInfo = &pSession->ac_info[ac];
+ tspec_pending_status = pACInfo->tspec_pending;
+ tspec_mask_status = pACInfo->tspec_mask_status;
+ vos_mem_zero(pACInfo->ricIdentifier, SME_QOS_TSPEC_INDEX_MAX);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("AC %d ==> TSPEC status = %d, tspec pending = %d"),
+ ac, tspec_mask_status, tspec_pending_status);
+
+ do
+ {
+ if (tspec_mask_status & 0x1)
+ {
+ /* If a tspec status is pending, take requested_QoSInfo for RIC request, else use curr_QoSInfo
+ for the RIC request */
+ if (tspec_pending_status & 0x1)
+ {
+ status = sme_QosCreateTspecRICIE(pMac, &pACInfo->requested_QoSInfo[tspec_index],
+ ricIE + ricOffset, &ricIELength, &pACInfo->ricIdentifier[tspec_index]);
+ }
+ else
+ {
+ status = sme_QosCreateTspecRICIE(pMac, &pACInfo->curr_QoSInfo[tspec_index],
+ ricIE + ricOffset, &ricIELength, &pACInfo->ricIdentifier[tspec_index]);
+ }
+ }
+ ricOffset += ricIELength;
+ pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies_length += ricIELength;
+
+ tspec_mask_status >>= 1;
+ tspec_pending_status >>= 1;
+ tspec_index++;
+ } while (tspec_mask_status);
+ }
+ }
+ return status;
+}
+
+#endif
+
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessAddTsFailureRsp() - Function to process the
+ Addts request failure response came from PE
+
+ We will notify HDD only for the requested Flow, other Flows running on the AC
+ stay intact
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pRsp - Pointer to the addts response structure came from PE.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessAddTsFailureRsp(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ tSirAddtsRspInfo * pRsp)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosEdcaAcType ac;
+ sme_QosSearchInfo search_key;
+ v_U8_t tspec_pending;
+ sme_QosWmmUpType up = (sme_QosWmmUpType)pRsp->tspec.tsinfo.traffic.userPrio;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d for UP %d",
+ __FUNCTION__, __LINE__,
+ sessionId, up);
+ ac = sme_QosUpToAc(up);
+ if(SME_QOS_EDCA_AC_MAX == ac)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid AC %d from UP %d",
+ __FUNCTION__, __LINE__, ac, up);
+ return eHAL_STATUS_FAILURE;
+ }
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ // is there a TSPEC request pending on this AC?
+ tspec_pending = pACInfo->tspec_pending;
+ if(!tspec_pending)
+ {
+ //ASSERT
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d an AddTS is not pending on AC %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ //set the key type & the key to be searched in the Flow List
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
+ search_key.sessionId = sessionId;
+ if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosAddTsFailureFnp)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d no match found for ac = %d",
+ __FUNCTION__, __LINE__,
+ sessionId, search_key.key.ac_type);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_zero(&pACInfo->requested_QoSInfo[tspec_pending - 1],
+ sizeof(sme_QosWmmTspecInfo));
+
+ if((!pACInfo->num_flows[0])&&
+ (!pACInfo->num_flows[1]))
+ {
+ pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET &
+ (~pACInfo->tspec_pending);
+ sme_QosStateTransition(sessionId, ac, SME_QOS_LINK_UP);
+ }
+ else
+ {
+ sme_QosStateTransition(sessionId, ac, SME_QOS_QOS_ON);
+ }
+ pACInfo->tspec_pending = 0;
+
+ (void)sme_QosProcessBufferedCmd(sessionId);
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosUpdateTspecMask() - Utiltity function to update the tspec.
+ Typical usage while aggregating unidirectional flows into a bi-directional
+ flow on AC which is running multiple flows
+
+ \param sessionId - Session upon which the TSPEC is being updated
+ \param ac - Enumeration of the various EDCA Access Categories.
+ \param old_tspec_mask - on which tspec per AC, the update is requested
+ \param new_tspec_mask - tspec to be set for this AC
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+static eHalStatus sme_QosUpdateTspecMask(v_U8_t sessionId,
+ sme_QosSearchInfo search_key,
+ v_U8_t new_tspec_mask)
+{
+ tListElem *pEntry= NULL, *pNextEntry = NULL;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d for AC %d TSPEC %d",
+ __FUNCTION__, __LINE__,
+ sessionId, search_key.key.ac_type, new_tspec_mask);
+
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+ if (search_key.key.ac_type < SME_QOS_EDCA_AC_MAX)
+ {
+ pACInfo = &pSession->ac_info[search_key.key.ac_type];
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Exceeded the array bounds of pSession->ac_info",
+ __FUNCTION__, __LINE__);
+ VOS_ASSERT (0);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Flow List empty, nothing to update",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+
+ if(search_key.sessionId == flow_info->sessionId)
+ {
+ if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_4)
+ {
+ if((search_key.key.ac_type == flow_info->ac_type) &&
+ (search_key.direction == flow_info->QoSInfo.ts_info.direction))
+ {
+ //msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Flow %d matches",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ pACInfo->num_flows[flow_info->tspec_mask - 1]--;
+ pACInfo->num_flows[new_tspec_mask - 1]++;
+ flow_info->tspec_mask = new_tspec_mask;
+ }
+ }
+ else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_5)
+ {
+ if((search_key.key.ac_type == flow_info->ac_type) &&
+ (search_key.tspec_mask == flow_info->tspec_mask))
+ {
+ //msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Flow %d matches",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ pACInfo->num_flows[flow_info->tspec_mask - 1]--;
+ pACInfo->num_flows[new_tspec_mask - 1]++;
+ flow_info->tspec_mask = new_tspec_mask;
+ }
+ }
+ }
+
+ pEntry = pNextEntry;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessAddTsSuccessRsp() - Function to process the
+ Addts request success response came from PE
+
+ We will notify HDD with addts success for the requested Flow, & for other
+ Flows running on the AC we will send an addts modify status
+
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pRsp - Pointer to the addts response structure came from PE.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessAddTsSuccessRsp(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ tSirAddtsRspInfo * pRsp)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosEdcaAcType ac, ac_index;
+ sme_QosSearchInfo search_key;
+ sme_QosSearchInfo search_key1;
+ v_U8_t tspec_pending;
+ tListElem *pEntry= NULL;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ sme_QosWmmUpType up = (sme_QosWmmUpType)pRsp->tspec.tsinfo.traffic.userPrio;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
+ vos_log_qos_tspec_pkt_type *log_ptr = NULL;
+#endif //FEATURE_WLAN_DIAG_SUPPORT
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d for UP %d",
+ __FUNCTION__, __LINE__,
+ sessionId, up);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ ac = sme_QosUpToAc(up);
+ if(SME_QOS_EDCA_AC_MAX == ac)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid AC %d from UP %d",
+ __FUNCTION__, __LINE__, ac, up);
+ return eHAL_STATUS_FAILURE;
+ }
+ pACInfo = &pSession->ac_info[ac];
+ // is there a TSPEC request pending on this AC?
+ tspec_pending = pACInfo->tspec_pending;
+ if(!tspec_pending)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d an AddTS is not pending on AC %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ //App is looking for APSD or the App which was looking for APSD has been
+ //released, so STA re-negotiated with AP
+ if(pACInfo->requested_QoSInfo[tspec_pending - 1].ts_info.psb)
+ {
+ //update the session's apsd mask
+ pSession->apsdMask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
+ }
+ else
+ {
+ if(((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) > 0) &&
+ ((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) <=
+ SME_QOS_TSPEC_INDEX_MAX))
+ {
+ if(!pACInfo->requested_QoSInfo
+ [(SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) - 1].ts_info.psb)
+ {
+ //update the session's apsd mask
+ pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Exceeded the array bounds of pACInfo->requested_QosInfo",
+ __FUNCTION__, __LINE__);
+ VOS_ASSERT (0);
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+ pACInfo->curr_QoSInfo[tspec_pending - 1] =
+ pACInfo->requested_QoSInfo[tspec_pending - 1];
+ /* Check if the current flow is for bi-directional. If so, update the number of flows
+ * to reflect that all flows are aggregated into tspec index 0. */
+ if((pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1].ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH) &&
+ (pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] > 0))
+ {
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ /* update tspec_mask for all the flows having SME_QOS_TSPEC_MASK_BIT_2_SET to SME_QOS_TSPEC_MASK_BIT_1_SET */
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_5;
+ search_key.sessionId = sessionId;
+ search_key.tspec_mask = SME_QOS_TSPEC_MASK_BIT_2_SET;
+ sme_QosUpdateTspecMask(sessionId, search_key, SME_QOS_TSPEC_MASK_BIT_1_SET);
+ }
+
+ vos_mem_zero(&search_key1, sizeof(sme_QosSearchInfo));
+ //set the horenewal field in control block if needed
+ search_key1.index = SME_QOS_SEARCH_KEY_INDEX_3;
+ search_key1.key.reason = SME_QOS_REASON_SETUP;
+ search_key1.sessionId = sessionId;
+ for(ac_index = SME_QOS_EDCA_AC_BE; ac_index < SME_QOS_EDCA_AC_MAX; ac_index++)
+ {
+ pEntry = sme_QosFindInFlowList(search_key1);
+ if(pEntry)
+ {
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ if(flow_info->ac_type == ac)
+ {
+ pACInfo->hoRenewal = flow_info->hoRenewal;
+ break;
+ }
+ }
+ }
+ vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
+ //set the key type & the key to be searched in the Flow List
+ search_key.key.ac_type = ac;
+ search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
+ search_key.sessionId = sessionId;
+ //notify HDD the success for the requested flow
+ //notify all the other flows running on the AC that QoS got modified
+ if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosAddTsSuccessFnp)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d no match found for ac %d",
+ __FUNCTION__, __LINE__,
+ sessionId, search_key.key.ac_type);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ pACInfo->hoRenewal = VOS_FALSE;
+ vos_mem_zero(&pACInfo->requested_QoSInfo[tspec_pending - 1],
+ sizeof(sme_QosWmmTspecInfo));
+ //event: EVENT_WLAN_QOS
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ qos.eventId = SME_QOS_DIAG_ADDTS_RSP;
+ qos.reasonCode = SME_QOS_DIAG_ADDTS_ADMISSION_ACCEPTED;
+ WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
+ WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_qos_tspec_pkt_type, LOG_WLAN_QOS_TSPEC_C);
+ if(log_ptr)
+ {
+ log_ptr->delay_bound = pACInfo->curr_QoSInfo[tspec_pending - 1].delay_bound;
+ log_ptr->inactivity_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].inactivity_interval;
+ log_ptr->max_burst_size = pACInfo->curr_QoSInfo[tspec_pending - 1].max_burst_size;
+ log_ptr->max_service_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].max_service_interval;
+ log_ptr->maximum_msdu_size = pACInfo->curr_QoSInfo[tspec_pending - 1].maximum_msdu_size;
+ log_ptr->mean_data_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].mean_data_rate;
+ log_ptr->medium_time = pACInfo->curr_QoSInfo[tspec_pending - 1].medium_time;
+ log_ptr->min_data_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].min_data_rate;
+ log_ptr->min_phy_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].min_phy_rate;
+ log_ptr->min_service_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].min_service_interval;
+ log_ptr->nominal_msdu_size = pACInfo->curr_QoSInfo[tspec_pending - 1].nominal_msdu_size;
+ log_ptr->peak_data_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].peak_data_rate;
+ log_ptr->surplus_bw_allowance = pACInfo->curr_QoSInfo[tspec_pending - 1].surplus_bw_allowance;
+ log_ptr->suspension_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].surplus_bw_allowance;
+ log_ptr->suspension_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].suspension_interval;
+ log_ptr->svc_start_time = pACInfo->curr_QoSInfo[tspec_pending - 1].svc_start_time;
+ log_ptr->tsinfo[0] = pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.direction << 5 |
+ pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.tid << 1;
+ log_ptr->tsinfo[1] = pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.up << 11 |
+ pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.psb << 10;
+ log_ptr->tsinfo[2] = 0;
+ }
+ WLAN_VOS_DIAG_LOG_REPORT(log_ptr);
+#endif //FEATURE_WLAN_DIAG_SUPPORT
+#ifdef FEATURE_WLAN_CCX
+ if (ac == SME_QOS_EDCA_AC_VO)
+ {
+ // Indicate to neighbor roam logic of the new required VO
+ // ac bandwidth requirement.
+ csrNeighborRoamIndicateVoiceBW( pMac, pACInfo->curr_QoSInfo[tspec_pending - 1].peak_data_rate, TRUE );
+ }
+#endif
+ pACInfo->tspec_pending = 0;
+
+ sme_QosStateTransition(sessionId, ac, SME_QOS_QOS_ON);
+
+
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ return eHAL_STATUS_SUCCESS;
+
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosAggregateParams() - Utiltity function to increament the TSPEC
+ params per AC. Typical usage while using flow aggregation or deletion of flows
+
+ \param pInput_Tspec_Info - Pointer to sme_QosWmmTspecInfo which contains the
+ WMM TSPEC related info with which pCurrent_Tspec_Info will be updated
+ \param pCurrent_Tspec_Info - Pointer to sme_QosWmmTspecInfo which contains
+ current the WMM TSPEC related info
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosAggregateParams(
+ sme_QosWmmTspecInfo * pInput_Tspec_Info,
+ sme_QosWmmTspecInfo * pCurrent_Tspec_Info,
+ sme_QosWmmTspecInfo * pUpdated_Tspec_Info)
+{
+ sme_QosWmmTspecInfo TspecInfo;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked",
+ __FUNCTION__, __LINE__);
+ if(!pInput_Tspec_Info)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: input is NULL, nothing to aggregate",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ if(!pCurrent_Tspec_Info)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Current is NULL, can't aggregate",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_copy(&TspecInfo, pCurrent_Tspec_Info,
+ sizeof(sme_QosWmmTspecInfo));
+ /*-------------------------------------------------------------------------
+ APSD preference is only meaningful if service interval was set by app
+ -------------------------------------------------------------------------*/
+ if(pCurrent_Tspec_Info->min_service_interval && pInput_Tspec_Info->min_service_interval)
+ {
+ TspecInfo.min_service_interval = VOS_MIN(
+ pCurrent_Tspec_Info->min_service_interval,
+ pInput_Tspec_Info->min_service_interval);
+ }
+ else if(pInput_Tspec_Info->min_service_interval)
+ {
+ TspecInfo.min_service_interval = pInput_Tspec_Info->min_service_interval;
+ }
+ if(pCurrent_Tspec_Info->max_service_interval)
+ {
+ TspecInfo.max_service_interval = VOS_MIN(
+ pCurrent_Tspec_Info->max_service_interval,
+ pInput_Tspec_Info->max_service_interval);
+ }
+ else
+ {
+ TspecInfo.max_service_interval = pInput_Tspec_Info->max_service_interval;
+ }
+ /*-------------------------------------------------------------------------
+ If directions don't match, it must necessarily be both uplink and
+ downlink
+ -------------------------------------------------------------------------*/
+ if(pCurrent_Tspec_Info->ts_info.direction !=
+ pInput_Tspec_Info->ts_info.direction)
+ {
+ TspecInfo.ts_info.direction = SME_QOS_WMM_TS_DIR_BOTH;
+ }
+ /*-------------------------------------------------------------------------
+ Max MSDU size : these sizes are `maxed'
+ -------------------------------------------------------------------------*/
+ TspecInfo.maximum_msdu_size = VOS_MAX(pCurrent_Tspec_Info->maximum_msdu_size,
+ pInput_Tspec_Info->maximum_msdu_size);
+
+ /*-------------------------------------------------------------------------
+ Inactivity interval : these sizes are `maxed'
+ -------------------------------------------------------------------------*/
+ TspecInfo.inactivity_interval = VOS_MAX(pCurrent_Tspec_Info->inactivity_interval,
+ pInput_Tspec_Info->inactivity_interval);
+
+ /*-------------------------------------------------------------------------
+ Delay bounds: min of all values
+ Check on 0: if 0, it means initial value since delay can never be 0!!
+ -------------------------------------------------------------------------*/
+ if(pCurrent_Tspec_Info->delay_bound)
+ {
+ TspecInfo.delay_bound = VOS_MIN(pCurrent_Tspec_Info->delay_bound,
+ pInput_Tspec_Info->delay_bound);
+ }
+ else
+ {
+ TspecInfo.delay_bound = pInput_Tspec_Info->delay_bound;
+ }
+ TspecInfo.max_burst_size = VOS_MAX(pCurrent_Tspec_Info->max_burst_size,
+ pInput_Tspec_Info->max_burst_size);
+
+ /*-------------------------------------------------------------------------
+ Nominal MSDU size also has a fixed bit that needs to be `handled' before
+ aggregation
+ This can be handled only if previous size is the same as new or both have
+ the fixed bit set
+ These sizes are not added: but `maxed'
+ -------------------------------------------------------------------------*/
+ TspecInfo.nominal_msdu_size = VOS_MAX(
+ pCurrent_Tspec_Info->nominal_msdu_size & ~SME_QOS_16BIT_MSB,
+ pInput_Tspec_Info->nominal_msdu_size & ~SME_QOS_16BIT_MSB);
+
+ if( ((pCurrent_Tspec_Info->nominal_msdu_size == 0) ||
+ (pCurrent_Tspec_Info->nominal_msdu_size & SME_QOS_16BIT_MSB)) &&
+ ((pInput_Tspec_Info->nominal_msdu_size == 0) ||
+ (pInput_Tspec_Info->nominal_msdu_size & SME_QOS_16BIT_MSB)))
+ {
+ TspecInfo.nominal_msdu_size |= SME_QOS_16BIT_MSB;
+ }
+
+ /*-------------------------------------------------------------------------
+ Data rates:
+ Add up the rates for aggregation
+ -------------------------------------------------------------------------*/
+ SME_QOS_BOUNDED_U32_ADD_Y_TO_X( TspecInfo.peak_data_rate,
+ pInput_Tspec_Info->peak_data_rate );
+ SME_QOS_BOUNDED_U32_ADD_Y_TO_X( TspecInfo.min_data_rate,
+ pInput_Tspec_Info->min_data_rate );
+ /* mean data rate = peak data rate: aggregate to be flexible on apps */
+ SME_QOS_BOUNDED_U32_ADD_Y_TO_X( TspecInfo.mean_data_rate,
+ pInput_Tspec_Info->mean_data_rate );
+
+ /*-------------------------------------------------------------------------
+ Suspension interval : this is set to the inactivity interval since per
+ spec it is less than or equal to inactivity interval
+ This is not provided by app since we currently don't support the HCCA
+ mode of operation
+ Currently set it to 0 to avoid confusion: Cisco CCX needs ~0; spec
+ requires inactivity interval to be > suspension interval: this could
+ be tricky!
+ -------------------------------------------------------------------------*/
+ TspecInfo.suspension_interval = 0;
+ /*-------------------------------------------------------------------------
+ Remaining parameters do not come from app as they are very WLAN
+ air interface specific
+ Set meaningful values here
+ -------------------------------------------------------------------------*/
+ TspecInfo.medium_time = 0; /* per WMM spec */
+ TspecInfo.min_phy_rate = SME_QOS_MIN_PHY_RATE;
+ TspecInfo.svc_start_time = 0; /* arbitrary */
+ TspecInfo.surplus_bw_allowance += pInput_Tspec_Info->surplus_bw_allowance;
+ if(TspecInfo.surplus_bw_allowance > SME_QOS_SURPLUS_BW_ALLOWANCE)
+ {
+ TspecInfo.surplus_bw_allowance = SME_QOS_SURPLUS_BW_ALLOWANCE;
+ }
+ /* Set ack_policy to block ack even if one stream requests block ack policy */
+ if((pInput_Tspec_Info->ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK) ||
+ (pCurrent_Tspec_Info->ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK))
+ {
+ TspecInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK;
+ }
+
+ if(pInput_Tspec_Info->ts_info.burst_size_defn || pCurrent_Tspec_Info->ts_info.burst_size_defn )
+ {
+ TspecInfo.ts_info.burst_size_defn = 1;
+ }
+ if(pUpdated_Tspec_Info)
+ {
+ vos_mem_copy(pUpdated_Tspec_Info, &TspecInfo,
+ sizeof(sme_QosWmmTspecInfo));
+ }
+ else
+ {
+ vos_mem_copy(pCurrent_Tspec_Info, &TspecInfo,
+ sizeof(sme_QosWmmTspecInfo));
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosUpdateParams() - Utiltity function to update the TSPEC
+ params per AC. Typical usage while deleting flows on AC which is running
+ multiple flows
+
+ \param sessionId - Session upon which the TSPEC is being updated
+ \param ac - Enumeration of the various EDCA Access Categories.
+ \param tspec_mask - on which tspec per AC, the update is requested
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+static eHalStatus sme_QosUpdateParams(v_U8_t sessionId,
+ sme_QosEdcaAcType ac,
+ v_U8_t tspec_mask,
+ sme_QosWmmTspecInfo * pTspec_Info)
+{
+ tListElem *pEntry= NULL, *pNextEntry = NULL;
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ sme_QosWmmTspecInfo Tspec_Info;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: invoked on session %d for AC %d TSPEC %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, tspec_mask);
+ if(!pTspec_Info)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: output is NULL, can't aggregate",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_zero(&Tspec_Info, sizeof(sme_QosWmmTspecInfo));
+ pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Flow List empty, nothing to update",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ //init the TS info field
+ Tspec_Info.ts_info.up = pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.up;
+ Tspec_Info.ts_info.psb = pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.psb;
+ Tspec_Info.ts_info.tid = pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.tid;
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ if((sessionId == flow_info->sessionId) &&
+ (ac == flow_info->ac_type) &&
+ (tspec_mask == flow_info->tspec_mask))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Flow %d matches",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+
+ if((SME_QOS_REASON_RELEASE == flow_info->reason ) ||
+ (SME_QOS_REASON_MODIFY == flow_info->reason))
+ {
+ //msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Skipping Flow %d as it is marked "
+ "for release/modify",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ }
+ else if(!HAL_STATUS_SUCCESS(sme_QosAggregateParams(&flow_info->QoSInfo,
+ &Tspec_Info,
+ NULL)))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosAggregateParams() failed",
+ __FUNCTION__, __LINE__);
+ }
+ }
+ pEntry = pNextEntry;
+ }
+ // return the aggregate
+ *pTspec_Info = Tspec_Info;
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosAcToUp() - Utiltity function to map an AC to UP
+ Note: there is a quantization loss here because 4 ACs are mapped to 8 UPs
+ Mapping is done for consistency
+ \param ac - Enumeration of the various EDCA Access Categories.
+ \return an User Priority
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosWmmUpType sme_QosAcToUp(sme_QosEdcaAcType ac)
+{
+ sme_QosWmmUpType up = SME_QOS_WMM_UP_MAX;
+ if(ac >= 0 && ac < SME_QOS_EDCA_AC_MAX)
+ {
+ up = sme_QosACtoUPMap[ac];
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: ac = %d up = %d returned",
+ __FUNCTION__, __LINE__, ac, up);
+ return up;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosUpToAc() - Utiltity function to map an UP to AC
+ \param up - Enumeration of the various User priorities (UP).
+ \return an Access Category
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+sme_QosEdcaAcType sme_QosUpToAc(sme_QosWmmUpType up)
+{
+ sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_MAX;
+ if(up >= 0 && up < SME_QOS_WMM_UP_MAX)
+ {
+ ac = sme_QosUPtoACMap[up];
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s: %d: up = %d ac = %d returned",
+ __FUNCTION__, __LINE__, up, ac);
+ return ac;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosStateTransition() - The state transition function per AC. We
+ save the previous state also.
+ \param sessionId - Session upon which the state machine is running
+ \param ac - Enumeration of the various EDCA Access Categories.
+ \param new_state - The state FSM is moving to.
+
+ \return None
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+static void sme_QosStateTransition(v_U8_t sessionId,
+ sme_QosEdcaAcType ac,
+ sme_QosStates new_state)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ pACInfo->prev_state = pACInfo->curr_state;
+ pACInfo->curr_state = new_state;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d new state=%d, old state=%d, for AC=%d",
+ __FUNCTION__, __LINE__,
+ sessionId, pACInfo->curr_state, pACInfo->prev_state, ac );
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosFindInFlowList() - Utility function to find an flow entry from
+ the flow_list.
+ \param search_key - We can either use the flowID or the ac type to find the
+ entry in the flow list.
+ A bitmap in sme_QosSearchInfo tells which key to use. Starting from LSB,
+ bit 0 - Flow ID
+ bit 1 - AC type
+ \return the pointer to the entry in the link list
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+tListElem *sme_QosFindInFlowList(sme_QosSearchInfo search_key)
+{
+ tListElem *pEntry= NULL, *pNextEntry = NULL;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Flow List empty, can't search",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ if((search_key.sessionId == flow_info->sessionId) ||
+ (search_key.sessionId == SME_QOS_SEARCH_SESSION_ID_ANY))
+ {
+ if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_1)
+ {
+ if(search_key.key.QosFlowID == flow_info->QosFlowID)
+ {
+ //msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: match found on flowID, ending search",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ }
+ else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_2)
+ {
+ if(search_key.key.ac_type == flow_info->ac_type)
+ {
+ //msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: match found on ac, ending search",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ }
+ else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_3)
+ {
+ if(search_key.key.reason == flow_info->reason)
+ {
+ //msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: match found on reason, ending search",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ }
+ else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_4)
+ {
+ if((search_key.key.ac_type == flow_info->ac_type) &&
+ (search_key.direction == flow_info->QoSInfo.ts_info.direction))
+ {
+ //msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: match found on reason, ending search",
+ __FUNCTION__, __LINE__);
+
+ break;
+ }
+ }
+ }
+ pEntry = pNextEntry;
+ }
+ return pEntry;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosFindAllInFlowList() - Utility function to find an flow entry
+ from the flow_list & act on it.
+ \param search_key - We can either use the flowID or the ac type to find the
+ entry in the flow list.
+ A bitmap in sme_QosSearchInfo tells which key to use. Starting from LSB,
+ bit 0 - Flow ID
+ bit 1 - AC type
+ \param fnp - function pointer specifying the action type for the entry found
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosFindAllInFlowList(tpAniSirGlobal pMac,
+ sme_QosSearchInfo search_key,
+ sme_QosProcessSearchEntry fnp)
+{
+ tListElem *pEntry= NULL, *pNextEntry = NULL;
+ sme_QosSessionInfo *pSession;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Flow List empty, can't search",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
+ if((search_key.sessionId == flow_info->sessionId) ||
+ (search_key.sessionId == SME_QOS_SEARCH_SESSION_ID_ANY))
+ {
+ if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_1)
+ {
+ if(search_key.key.QosFlowID == flow_info->QosFlowID)
+ {
+ //msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: match found on flowID, ending search",
+ __FUNCTION__, __LINE__);
+ status = fnp(pMac, pEntry);
+ if(eHAL_STATUS_FAILURE == status)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Failed to process entry",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ }
+ }
+ else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_2)
+ {
+ if(search_key.key.ac_type == flow_info->ac_type)
+ {
+ //msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: match found on ac, ending search",
+ __FUNCTION__, __LINE__);
+ flow_info->hoRenewal = pSession->ac_info[flow_info->ac_type].hoRenewal;
+ status = fnp(pMac, pEntry);
+ if(eHAL_STATUS_FAILURE == status)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Failed to process entry",
+ __FUNCTION__, __LINE__);
+ break;
+ }
+ }
+ }
+ }
+ pEntry = pNextEntry;
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosIsACM() - Utility function to check if a particular AC
+ mandates Admission Control.
+ \param ac - Enumeration of the various EDCA Access Categories.
+
+ \return VOS_TRUE if the AC mandates Admission Control
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+v_BOOL_t sme_QosIsACM(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc,
+ sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes)
+{
+ v_BOOL_t ret_val = VOS_FALSE;
+ tDot11fBeaconIEs *pIesLocal;
+ if(!pSirBssDesc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: pSirBssDesc is NULL",
+ __FUNCTION__, __LINE__);
+ return VOS_FALSE;
+ }
+
+ if (NULL != pIes)
+ {
+ /* IEs were provided so use them locally */
+ pIesLocal = pIes;
+ }
+ else
+ {
+ /* IEs were not provided so parse them ourselves */
+ if (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal)))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: csrGetParsedBssDescriptionIEs() failed",
+ __FUNCTION__, __LINE__);
+ return VOS_FALSE;
+ }
+
+ /* if success then pIesLocal was allocated */
+ }
+
+ if(CSR_IS_QOS_BSS(pIesLocal))
+ {
+ switch(ac)
+ {
+ case SME_QOS_EDCA_AC_BE:
+ if(pIesLocal->WMMParams.acbe_acm) ret_val = VOS_TRUE;
+ break;
+ case SME_QOS_EDCA_AC_BK:
+ if(pIesLocal->WMMParams.acbk_acm) ret_val = VOS_TRUE;
+ break;
+ case SME_QOS_EDCA_AC_VI:
+ if(pIesLocal->WMMParams.acvi_acm) ret_val = VOS_TRUE;
+ break;
+ case SME_QOS_EDCA_AC_VO:
+ if(pIesLocal->WMMParams.acvo_acm) ret_val = VOS_TRUE;
+ break;
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: unknown AC = %d",
+ __FUNCTION__, __LINE__, ac);
+ //Assert
+ VOS_ASSERT(0);
+ break;
+ }
+ }//IS_QOS_BSS
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: ACM = %d for AC = %d",
+ __FUNCTION__, __LINE__, ret_val, ac );
+ if (NULL == pIes)
+ {
+ /* IEs were allocated locally so free them */
+ vos_mem_free(pIesLocal);
+ }
+ return ret_val;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosBufferExistingFlows() - Utility function to buffer the existing
+ flows in flow_list, so that we can renew them after handoff is done.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+static eHalStatus sme_QosBufferExistingFlows(tpAniSirGlobal pMac,
+ v_U8_t sessionId)
+{
+ tListElem *pEntry= NULL, *pNextEntry = NULL;
+ sme_QosSessionInfo *pSession;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ sme_QosCmdInfo cmd;
+ pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Flow List empty, nothing to buffer",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ if (flow_info->sessionId == sessionId)
+ {
+ if((SME_QOS_REASON_REQ_SUCCESS == flow_info->reason )||
+ (SME_QOS_REASON_SETUP == flow_info->reason ))
+ {
+ cmd.command = SME_QOS_SETUP_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.setupCmdInfo.HDDcontext = flow_info->HDDcontext;
+ cmd.u.setupCmdInfo.QoSInfo = flow_info->QoSInfo;
+ cmd.u.setupCmdInfo.QoSCallback = flow_info->QoSCallback;
+ cmd.u.setupCmdInfo.UPType = SME_QOS_WMM_UP_MAX;//shouldn't be needed
+ cmd.u.setupCmdInfo.QosFlowID = flow_info->QosFlowID;
+ if(SME_QOS_REASON_SETUP == flow_info->reason )
+ {
+ cmd.u.setupCmdInfo.hoRenewal = VOS_FALSE;
+ }
+ else
+ {
+ cmd.u.setupCmdInfo.hoRenewal = VOS_TRUE;//TODO: might need this for modify
+ }
+ if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_TRUE)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't buffer the setup request for "
+ "flow %d in handoff state",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: buffered a setup request for "
+ "flow %d in handoff state",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ }
+ }
+ else if(SME_QOS_REASON_RELEASE == flow_info->reason )
+ {
+ cmd.command = SME_QOS_RELEASE_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.releaseCmdInfo.QosFlowID = flow_info->QosFlowID;
+ if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_TRUE)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't buffer the release request for "
+ "flow %d in handoff state",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: buffered a release request for "
+ "flow %d in handoff state",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ }
+ }
+ else if(SME_QOS_REASON_MODIFY_PENDING == flow_info->reason)
+ {
+ cmd.command = SME_QOS_MODIFY_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.modifyCmdInfo.QosFlowID = flow_info->QosFlowID;
+ cmd.u.modifyCmdInfo.QoSInfo = flow_info->QoSInfo;
+ if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_TRUE)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't buffer the modify request for "
+ "flow %d in handoff state",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: buffered a modify request for "
+ "flow %d in handoff state",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ }
+ }
+ //delete the entry from Flow List
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Deleting original entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ flow_info, flow_info->QosFlowID);
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ vos_mem_free(flow_info);
+ }
+ pEntry = pNextEntry;
+ }
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pSession->uapsdAlreadyRequested = VOS_FALSE;
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosDeleteExistingFlows() - Utility function to Delete the existing
+ flows in flow_list, if we lost connectivity.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+static eHalStatus sme_QosDeleteExistingFlows(tpAniSirGlobal pMac,
+ v_U8_t sessionId)
+{
+ tListElem *pEntry= NULL, *pNextEntry = NULL;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_TRUE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Flow List empty, nothing to delete",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ if (flow_info->sessionId == sessionId)
+ {
+ if((SME_QOS_REASON_REQ_SUCCESS == flow_info->reason )||
+ (SME_QOS_REASON_SETUP == flow_info->reason )||
+ (SME_QOS_REASON_RELEASE == flow_info->reason )||
+ (SME_QOS_REASON_MODIFY == flow_info->reason ))
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ NULL,
+ SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
+ flow_info->QosFlowID);
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Deleting entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ flow_info, flow_info->QosFlowID);
+ //delete the entry from Flow List
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ vos_mem_free(flow_info);
+ }
+ pEntry = pNextEntry;
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosBufferCmd() - Utility function to buffer a request (setup/modify/
+ release) from client while processing another one on the same AC.
+ \param pcmd - a pointer to the cmd structure to be saved inside the buffered
+ cmd link list
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosBufferCmd(sme_QosCmdInfo *pcmd, v_BOOL_t insert_head)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosCmdInfoEntry * pentry = NULL;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Invoked",
+ __FUNCTION__, __LINE__);
+ pentry = (sme_QosCmdInfoEntry *) vos_mem_malloc(sizeof(sme_QosCmdInfoEntry));
+ if (!pentry)
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Memory allocation failure",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ // copy the entire CmdInfo
+ pentry->cmdInfo = *pcmd;
+
+ pSession = &sme_QosCb.sessionInfo[pcmd->sessionId];
+ if(insert_head)
+ {
+ csrLLInsertHead(&pSession->bufferedCommandList, &pentry->link, VOS_TRUE);
+ }
+ else
+ {
+ csrLLInsertTail(&pSession->bufferedCommandList, &pentry->link, VOS_TRUE);
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessBufferedCmd() - Utility function to process a buffered
+ request (setup/modify/release) initially came from the client.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+static eHalStatus sme_QosProcessBufferedCmd(v_U8_t sessionId)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosCmdInfoEntry *pcmd = NULL;
+ tListElem *pEntry= NULL;
+ sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Invoked on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if(!csrLLIsListEmpty( &pSession->bufferedCommandList, VOS_FALSE ))
+ {
+ pEntry = csrLLRemoveHead( &pSession->bufferedCommandList, VOS_TRUE );
+ if(!pEntry)
+ {
+ //Err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: no more buffered commands on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ pSession->readyForPowerSave = VOS_TRUE;
+ return eHAL_STATUS_FAILURE;
+ }
+ pcmd = GET_BASE_ADDR( pEntry, sme_QosCmdInfoEntry, link );
+ switch(pcmd->cmdInfo.command)
+ {
+ case SME_QOS_SETUP_REQ:
+ hdd_status = sme_QosInternalSetupReq(pcmd->cmdInfo.pMac,
+ pcmd->cmdInfo.sessionId,
+ &pcmd->cmdInfo.u.setupCmdInfo.QoSInfo,
+ pcmd->cmdInfo.u.setupCmdInfo.QoSCallback,
+ pcmd->cmdInfo.u.setupCmdInfo.HDDcontext,
+ pcmd->cmdInfo.u.setupCmdInfo.UPType,
+ pcmd->cmdInfo.u.setupCmdInfo.QosFlowID,
+ VOS_TRUE,
+ pcmd->cmdInfo.u.setupCmdInfo.hoRenewal);
+ if(SME_QOS_STATUS_SETUP_FAILURE_RSP == hdd_status)
+ {
+ //Err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosInternalSetupReq failed on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ halStatus = eHAL_STATUS_FAILURE;
+ }
+ break;
+ case SME_QOS_RELEASE_REQ:
+ hdd_status = sme_QosInternalReleaseReq(pcmd->cmdInfo.pMac,
+ pcmd->cmdInfo.u.releaseCmdInfo.QosFlowID,
+ VOS_TRUE);
+ if(SME_QOS_STATUS_RELEASE_FAILURE_RSP == hdd_status)
+ {
+ //Err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosInternalReleaseReq failed on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ halStatus = eHAL_STATUS_FAILURE;
+ }
+ break;
+ case SME_QOS_MODIFY_REQ:
+ hdd_status = sme_QosInternalModifyReq(pcmd->cmdInfo.pMac,
+ &pcmd->cmdInfo.u.modifyCmdInfo.QoSInfo,
+ pcmd->cmdInfo.u.modifyCmdInfo.QosFlowID,
+ VOS_TRUE);
+ if(SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP == hdd_status)
+ {
+ //Err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosInternalModifyReq failed on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ halStatus = eHAL_STATUS_FAILURE;
+ }
+ break;
+ case SME_QOS_RESEND_REQ:
+ hdd_status = sme_QosReRequestAddTS(pcmd->cmdInfo.pMac,
+ pcmd->cmdInfo.sessionId,
+ &pcmd->cmdInfo.u.resendCmdInfo.QoSInfo,
+ pcmd->cmdInfo.u.resendCmdInfo.ac,
+ pcmd->cmdInfo.u.resendCmdInfo.tspecMask);
+ if(SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP == hdd_status)
+ {
+ //Err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: sme_QosReRequestAddTS failed on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ halStatus = eHAL_STATUS_FAILURE;
+ }
+ break;
+ default:
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d unknown cmd = %d",
+ __FUNCTION__, __LINE__,
+ sessionId, pcmd->cmdInfo.command);
+ //ASSERT
+ VOS_ASSERT(0);
+ break;
+ }
+ // buffered command has been processed, reclaim the memory
+ vos_mem_free(pcmd);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: cmd buffer empty",
+ __FUNCTION__, __LINE__);
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ return halStatus;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosDeleteBufferedRequests() - Utility function to Delete the buffered
+ requests in the buffered_cmd_list, if we lost connectivity.
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+static eHalStatus sme_QosDeleteBufferedRequests(tpAniSirGlobal pMac,
+ v_U8_t sessionId)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosCmdInfoEntry *pcmd = NULL;
+ tListElem *pEntry= NULL, *pNextEntry = NULL;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Invoked on session %d",
+ __FUNCTION__, __LINE__, sessionId);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pEntry = csrLLPeekHead( &pSession->bufferedCommandList, VOS_TRUE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Buffered List empty, nothing to delete on session %d",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ return eHAL_STATUS_FAILURE;
+ }
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &pSession->bufferedCommandList, pEntry, VOS_TRUE );
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: deleting entry from buffered List",
+ __FUNCTION__, __LINE__);
+ //delete the entry from Flow List
+ csrLLRemoveEntry(&pSession->bufferedCommandList, pEntry, VOS_TRUE );
+ // reclaim the memory
+ pcmd = GET_BASE_ADDR( pEntry, sme_QosCmdInfoEntry, link );
+ vos_mem_free(pcmd);
+ pEntry = pNextEntry;
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosSaveAssocInfo() - Utility function to save the assoc info in the
+ CB like BSS descritor of the AP, the profile that HDD sent down with the
+ connect request, while CSR notifies for assoc/reassoc success.
+ \param pAssoc_info - pointer to the assoc structure to store the BSS descritor
+ of the AP, the profile that HDD sent down with the
+ connect request
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosSaveAssocInfo(sme_QosSessionInfo *pSession, sme_QosAssocInfo *pAssoc_info)
+{
+ tSirBssDescription *pBssDesc = NULL;
+ v_U32_t bssLen = 0;
+ if(NULL == pAssoc_info)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: pAssoc_info is NULL",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ //clean up the assoc info if already set
+ if(pSession->assocInfo.pBssDesc)
+ {
+ vos_mem_free(pSession->assocInfo.pBssDesc);
+ pSession->assocInfo.pBssDesc = NULL;
+ }
+ bssLen = pAssoc_info->pBssDesc->length +
+ sizeof(pAssoc_info->pBssDesc->length);
+ //save the bss Descriptor
+ pBssDesc = (tSirBssDescription *)vos_mem_malloc(bssLen);
+ if (!pBssDesc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't allocate memory for the bss Descriptor",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_copy(pBssDesc, pAssoc_info->pBssDesc, bssLen);
+ pSession->assocInfo.pBssDesc = pBssDesc;
+ //save the apsd info from assoc
+ if(pAssoc_info->pProfile)
+ {
+ pSession->apsdMask |= pAssoc_info->pProfile->uapsd_mask;
+ }
+ // [TODO] Do we need to update the global APSD bitmap?
+ return eHAL_STATUS_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosSetupFnp() - Utility function (pointer) to notify other entries
+ in FLOW list on the same AC that qos params got modified
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosSetupFnp(tpAniSirGlobal pMac, tListElem *pEntry)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
+ sme_QosEdcaAcType ac;
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Entry is NULL",
+ __FUNCTION__, __LINE__);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ ac = flow_info->ac_type;
+ pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ if(SME_QOS_REASON_REQ_SUCCESS == flow_info->reason)
+ {
+ //notify HDD, only the other Flows running on the AC
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
+ hdd_status,
+ flow_info->QosFlowID);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Entry with flowID = %d getting notified",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosModificationNotifyFnp() - Utility function (pointer) to notify
+ other entries in FLOW list on the same AC that qos params got modified
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosModificationNotifyFnp(tpAniSirGlobal pMac, tListElem *pEntry)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
+ sme_QosEdcaAcType ac;
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Entry is NULL",
+ __FUNCTION__, __LINE__);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ ac = flow_info->ac_type;
+ pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ if(SME_QOS_REASON_REQ_SUCCESS == flow_info->reason)
+ {
+ //notify HDD, only the other Flows running on the AC
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
+ hdd_status,
+ flow_info->QosFlowID);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Entry with flowID = %d getting notified",
+ __FUNCTION__, __LINE__,
+ flow_info->QosFlowID);
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosModifyFnp() - Utility function (pointer) to delete the origianl
+ entry in FLOW list & add the modified one
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosModifyFnp(tpAniSirGlobal pMac, tListElem *pEntry)
+{
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Entry is NULL",
+ __FUNCTION__, __LINE__);
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ switch(flow_info->reason)
+ {
+ case SME_QOS_REASON_MODIFY_PENDING:
+ //set the proper reason code for the new (with modified params) entry
+ flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
+ break;
+ case SME_QOS_REASON_MODIFY:
+ //delete the original entry from Flow List
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Deleting original entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ flow_info, flow_info->QosFlowID);
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ // reclaim the memory
+ vos_mem_free(flow_info);
+ break;
+ default:
+ break;
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosDelTsIndFnp() - Utility function (pointer) to find all Flows on
+ the perticular AC & delete them, also send HDD indication through the callback
+ it registered per request
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosDelTsIndFnp(tpAniSirGlobal pMac, tListElem *pEntry)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ sme_QosEdcaAcType ac;
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Entry is NULL",
+ __FUNCTION__, __LINE__);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ //delete the entry from Flow List
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ ac = flow_info->ac_type;
+ pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
+ SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
+ flow_info->QosFlowID);
+ pACInfo->num_flows[flow_info->tspec_mask - 1]--;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Deleting entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ flow_info, flow_info->QosFlowID);
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ // reclaim the memory
+ vos_mem_free(flow_info);
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosReassocSuccessEvFnp() - Utility function (pointer) to notify HDD
+ the success for the requested flow & notify all the other flows running on the
+ same AC that QoS params got modified
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosReassocSuccessEvFnp(tpAniSirGlobal pMac, tListElem *pEntry)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ v_BOOL_t delete_entry = VOS_FALSE;
+ sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ sme_QosEdcaAcType ac;
+ eHalStatus pmc_status = eHAL_STATUS_FAILURE;
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Entry is NULL",
+ __FUNCTION__, __LINE__);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
+ ac = flow_info->ac_type;
+ pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ switch(flow_info->reason)
+ {
+ case SME_QOS_REASON_SETUP:
+ hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND;
+ delete_entry = VOS_FALSE;
+ flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
+ //check for the case where we had to do reassoc to reset the apsd bit
+ //for the ac - release or modify scenario
+ if(pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb)
+ {
+ // notify PMC as App is looking for APSD. If we already requested
+ // then we don't need to do anything.
+ if(!pSession->uapsdAlreadyRequested)
+ {
+ // this is the first flow to detect we need PMC in UAPSD mode
+
+ pmc_status = pmcStartUapsd(pMac,
+ sme_QosPmcStartUapsdCallback,
+ pSession);
+ // if PMC doesn't return success right away means it is yet to put
+ // the module in BMPS state & later to UAPSD state
+
+ if(eHAL_STATUS_FAILURE == pmc_status)
+ {
+ hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED;
+ //we need to always notify this case
+ flow_info->hoRenewal = VOS_FALSE;
+ }
+ else if(eHAL_STATUS_PMC_PENDING == pmc_status)
+ {
+ // let other flows know PMC has been notified
+ pSession->uapsdAlreadyRequested = VOS_TRUE;
+ }
+ // for any other pmc status we declare success
+ }
+ }
+ break;
+ case SME_QOS_REASON_RELEASE:
+ pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0]--;
+ // fall through
+ case SME_QOS_REASON_MODIFY:
+ delete_entry = VOS_TRUE;
+ break;
+ case SME_QOS_REASON_MODIFY_PENDING:
+ hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND;
+ delete_entry = VOS_FALSE;
+ flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
+ if(pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb)
+ {
+
+ if(!pSession->uapsdAlreadyRequested)
+ {
+ // this is the first flow to detect we need PMC in UAPSD mode
+ pmc_status = pmcStartUapsd(pMac,
+ sme_QosPmcStartUapsdCallback,
+ pSession);
+
+ // if PMC doesn't return success right away means it is yet to put
+ // the module in BMPS state & later to UAPSD state
+ if(eHAL_STATUS_FAILURE == pmc_status)
+ {
+ hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED;
+ // we need to always notify this case
+ flow_info->hoRenewal = VOS_FALSE;
+ }
+ else if(eHAL_STATUS_PMC_PENDING == pmc_status)
+ {
+ pSession->uapsdAlreadyRequested = VOS_TRUE;
+ }
+ // for any other pmc status we declare success
+ }
+ }
+ break;
+ case SME_QOS_REASON_REQ_SUCCESS:
+ hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
+ // fall through
+ default:
+ delete_entry = VOS_FALSE;
+ break;
+ }
+ if(!delete_entry)
+ {
+ if(!flow_info->hoRenewal)
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
+ hdd_status,
+ flow_info->QosFlowID);
+ }
+ else
+ {
+ flow_info->hoRenewal = VOS_FALSE;
+ }
+ }
+ else
+ {
+ //delete the entry from Flow List
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Deleting entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ flow_info, flow_info->QosFlowID);
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ // reclaim the memory
+ vos_mem_free(flow_info);
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosAddTsFailureFnp() - Utility function (pointer),
+ if the Addts request was for for an flow setup request, delete the entry from
+ Flow list & notify HDD
+ if the Addts request was for downgrading of QoS params because of an flow
+ release requested on the AC, delete the entry from Flow list & notify HDD
+ if the Addts request was for change of QoS params because of an flow
+ modification requested on the AC, delete the new entry from Flow list & notify
+ HDD
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosAddTsFailureFnp(tpAniSirGlobal pMac, tListElem *pEntry)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ v_BOOL_t inform_hdd = VOS_FALSE;
+ sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ sme_QosEdcaAcType ac;
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Entry is NULL",
+ __FUNCTION__, __LINE__);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ ac = flow_info->ac_type;
+ pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ switch(flow_info->reason)
+ {
+ case SME_QOS_REASON_SETUP:
+ hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ pACInfo->num_flows[pACInfo->tspec_pending - 1]--;
+ inform_hdd = VOS_TRUE;
+ break;
+ case SME_QOS_REASON_RELEASE:
+ hdd_status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
+ pACInfo->num_flows[pACInfo->tspec_pending - 1]--;
+ inform_hdd = VOS_TRUE;
+ break;
+ case SME_QOS_REASON_MODIFY_PENDING:
+ hdd_status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ inform_hdd = VOS_TRUE;
+ break;
+ case SME_QOS_REASON_MODIFY:
+ flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
+ case SME_QOS_REASON_REQ_SUCCESS:
+ default:
+ inform_hdd = VOS_FALSE;
+ break;
+ }
+ if(inform_hdd)
+ {
+ //notify HDD, only the requested Flow, other Flows running on the AC stay
+ // intact
+ if(!flow_info->hoRenewal)
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1],
+ hdd_status,
+ flow_info->QosFlowID);
+ }
+ else
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1],
+ SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
+ flow_info->QosFlowID);
+ }
+ //delete the entry from Flow List
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Deleting entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ flow_info, flow_info->QosFlowID);
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ // reclaim the memory
+ vos_mem_free(flow_info);
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosAddTsSuccessFnp() - Utility function (pointer),
+ if the Addts request was for for an flow setup request, notify HDD for success
+ for the flow & notify all the other flows running on the same AC that QoS
+ params got modified
+ if the Addts request was for downgrading of QoS params because of an flow
+ release requested on the AC, delete the entry from Flow list & notify HDD
+ if the Addts request was for change of QoS params because of an flow
+ modification requested on the AC, delete the old entry from Flow list & notify
+ HDD for success for the flow & notify all the other flows running on the same
+ AC that QoS params got modified
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
+
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosAddTsSuccessFnp(tpAniSirGlobal pMac, tListElem *pEntry)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+ v_BOOL_t inform_hdd = VOS_FALSE;
+ v_BOOL_t delete_entry = VOS_FALSE;
+ sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
+ sme_QosEdcaAcType ac;
+ eHalStatus pmc_status = eHAL_STATUS_FAILURE;
+ tCsrRoamModifyProfileFields modifyProfileFields;
+
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Entry is NULL",
+ __FUNCTION__, __LINE__);
+ //ASSERT
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ ac = flow_info->ac_type;
+ pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ if(flow_info->tspec_mask != pACInfo->tspec_pending)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: No need to notify the HDD, the ADDTS "
+ "success is not for index = %d of the AC = %d",
+ __FUNCTION__, __LINE__,
+ flow_info->tspec_mask, ac);
+ return eHAL_STATUS_SUCCESS;
+ }
+ switch(flow_info->reason)
+ {
+ case SME_QOS_REASON_SETUP:
+ hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND;
+ flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
+ delete_entry = VOS_FALSE;
+ inform_hdd = VOS_TRUE;
+ // check if App is looking for APSD
+ if(pACInfo->requested_QoSInfo[pACInfo->tspec_pending - 1].ts_info.psb)
+ {
+ // notify PMC as App is looking for APSD. If we already requested
+ // then we don't need to do anything
+ if(!pSession->uapsdAlreadyRequested)
+ {
+ // this is the first flow to detect we need PMC in UAPSD mode
+ pmc_status = pmcStartUapsd(pMac,
+ sme_QosPmcStartUapsdCallback,
+ pSession);
+ // if PMC doesn't return success right away means it is yet to put
+ // the module in BMPS state & later to UAPSD state
+ if(eHAL_STATUS_FAILURE == pmc_status)
+ {
+ hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED;
+ // we need to always notify this case
+ flow_info->hoRenewal = VOS_FALSE;
+ }
+ else if(eHAL_STATUS_PMC_PENDING == pmc_status)
+ {
+ // let other flows know PMC has been notified
+ pSession->uapsdAlreadyRequested = VOS_TRUE;
+ }
+ // for any other pmc status we declare success
+ }
+ }
+ break;
+ case SME_QOS_REASON_RELEASE:
+ pACInfo->num_flows[pACInfo->tspec_pending - 1]--;
+ hdd_status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP;
+ inform_hdd = VOS_TRUE;
+ delete_entry = VOS_TRUE;
+ break;
+ case SME_QOS_REASON_MODIFY:
+ delete_entry = VOS_TRUE;
+ inform_hdd = VOS_FALSE;
+ break;
+ case SME_QOS_REASON_MODIFY_PENDING:
+ hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND;
+ delete_entry = VOS_FALSE;
+ flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
+ inform_hdd = VOS_TRUE;
+ //notify PMC if App is looking for APSD
+ if(pACInfo->requested_QoSInfo[pACInfo->tspec_pending - 1].ts_info.psb)
+ {
+ // notify PMC as App is looking for APSD. If we already requested
+ // then we don't need to do anything.
+ if(!pSession->uapsdAlreadyRequested)
+ {
+ // this is the first flow to detect we need PMC in UAPSD mode
+ pmc_status = pmcStartUapsd(pMac,
+ sme_QosPmcStartUapsdCallback,
+ pSession);
+ // if PMC doesn't return success right away means it is yet to put
+ // the module in BMPS state & later to UAPSD state
+ if(eHAL_STATUS_FAILURE == pmc_status)
+ {
+ hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED;
+ // we need to always notify this case
+ flow_info->hoRenewal = VOS_FALSE;
+ }
+ else if(eHAL_STATUS_PMC_PENDING == pmc_status)
+ {
+ // let other flows know PMC has been notified
+ pSession->uapsdAlreadyRequested = VOS_TRUE;
+ }
+ // for any other pmc status we declare success
+ }
+ }
+ else
+ {
+ if((pACInfo->num_flows[flow_info->tspec_mask - 1] == 1) &&
+ (SME_QOS_TSPEC_MASK_BIT_1_2_SET != pACInfo->tspec_mask_status))
+ {
+ // this is the only TSPEC active on this AC
+ // so indicate that we no longer require APSD
+ pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
+ //Also update modifyProfileFields.uapsd_mask in CSR for consistency
+ csrGetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields);
+ modifyProfileFields.uapsd_mask = pSession->apsdMask;
+ csrSetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields);
+ if(!pSession->apsdMask)
+ {
+ // this session no longer needs UAPSD
+ // do any sessions still require UAPSD?
+ if (!sme_QosIsUapsdActive())
+ {
+ // No sessions require UAPSD so turn it off
+ // (really don't care when PMC stops it)
+ (void)pmcStopUapsd(pMac);
+ }
+ }
+ }
+ }
+ break;
+ case SME_QOS_REASON_REQ_SUCCESS:
+ hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
+ inform_hdd = VOS_TRUE;
+ default:
+ delete_entry = VOS_FALSE;
+ break;
+ }
+ if(inform_hdd)
+ {
+ if(!flow_info->hoRenewal)
+ {
+
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1],
+ hdd_status,
+ flow_info->QosFlowID);
+ }
+ else
+ {
+ flow_info->hoRenewal = VOS_FALSE;
+ }
+ }
+ if(delete_entry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Deleting entry at %p with flowID %d",
+ __FUNCTION__, __LINE__,
+ flow_info, flow_info->QosFlowID);
+ //delete the entry from Flow List
+ csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
+ // reclaim the memory
+ vos_mem_free(flow_info);
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosIsRspPending() - Utility function to check if we are waiting
+ for an AddTS or reassoc response on some AC other than the given AC
+
+ \param sessionId - Session we are interted in
+ \param ac - Enumeration of the various EDCA Access Categories.
+
+ \return boolean
+ TRUE - Response is pending on an AC
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+static v_BOOL_t sme_QosIsRspPending(v_U8_t sessionId, sme_QosEdcaAcType ac)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosEdcaAcType acIndex;
+ v_BOOL_t status = VOS_FALSE;
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ for(acIndex = SME_QOS_EDCA_AC_BE; acIndex < SME_QOS_EDCA_AC_MAX; acIndex++)
+ {
+ if(acIndex == ac)
+ {
+ continue;
+ }
+ pACInfo = &pSession->ac_info[acIndex];
+ if((pACInfo->tspec_pending) || (pACInfo->reassoc_pending))
+ {
+ status = VOS_TRUE;
+ break;
+ }
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosIsUapsdActive() - Function which can be called to determine
+ if any sessions require PMC to be in U-APSD mode.
+ \return boolean
+
+ Returns true if at least one session required PMC to be in U-APSD mode
+ Returns false if no sessions require PMC to be in U-APSD mode
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+static v_BOOL_t sme_QosIsUapsdActive(void)
+{
+ sme_QosSessionInfo *pSession;
+ v_U8_t sessionId;
+ for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
+ {
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if ((pSession->sessionActive) && (pSession->apsdMask))
+ {
+ return VOS_TRUE;
+ }
+ }
+ // no active sessions have U-APSD active
+ return VOS_FALSE;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosPmcFullPowerCallback() - Callback function registered with PMC
+ to notify SME-QoS when it puts the chip into full power
+
+ \param callbackContext - The context passed to PMC during pmcRequestFullPower
+ call.
+ \param status - eHalStatus returned by PMC.
+
+ \return None
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+void sme_QosPmcFullPowerCallback(void *callbackContext, eHalStatus status)
+{
+ sme_QosSessionInfo *pSession = callbackContext;
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ (void)sme_QosProcessBufferedCmd(pSession->sessionId);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: PMC failed to put the chip in Full power",
+ __FUNCTION__, __LINE__);
+ //ASSERT
+ VOS_ASSERT(0);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosPmcStartUAPSDCallback() - Callback function registered with PMC
+ to notify SME-QoS when it puts the chip into UAPSD mode
+
+ \param callbackContext - The context passed to PMC during pmcStartUapsd call.
+ \param status - eHalStatus returned by PMC.
+
+ \return None
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+void sme_QosPmcStartUapsdCallback(void *callbackContext, eHalStatus status)
+{
+ sme_QosSessionInfo *pSession = callbackContext;
+ // NOTE WELL
+ //
+ // In the orignal QoS design the TL module was responsible for
+ // the generation of trigger frames. When that design was in
+ // use, we had to queue up any flows which were waiting for PMC
+ // since we didn't want to notify HDD until PMC had changed to
+ // UAPSD state. Otherwise HDD would provide TL with the trigger
+ // frame parameters, and TL would start trigger frame generation
+ // before PMC was ready. The flows were queued in various places
+ // throughout this module, and they were dequeued here following
+ // a successful transition to the UAPSD state by PMC.
+ //
+ // In the current QoS design the Firmware is responsible for the
+ // generation of trigger frames, but the parameters are still
+ // provided by TL via HDD. The Firmware will be notified of the
+ // change to UAPSD state directly by PMC, at which time it will be
+ // responsible for the generation of trigger frames. Therefore
+ // where we used to queue up flows waiting for PMC to transition
+ // to the UAPSD state, we now always transition directly to the
+ // "success" state so that HDD will immediately provide the trigger
+ // frame parameters to TL, who will in turn plumb them down to the
+ // Firmware. That way the Firmware will have the trigger frame
+ // parameters when it needs them
+ // just note that there is no longer an outstanding request
+ pSession->uapsdAlreadyRequested = VOS_FALSE;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosPmcCheckRoutine() - Function registered with PMC to check with
+ SME-QoS whenever the device is about to enter one of the power
+ save modes. PMC runs a poll with all the registered modules if device can
+ enter powersave mode or remain in full power
+
+ \param callbackContext - The context passed to PMC during registration through
+ pmcRegisterPowerSaveCheck.
+ \return boolean
+
+ SME-QOS returns PMC true or false respectively if it wants to vote for
+ entering power save or not
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+v_BOOL_t sme_QosPmcCheckRoutine(void *callbackContext)
+{
+ sme_QosSessionInfo *pSession;
+ v_U8_t sessionId;
+ for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
+ {
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if ((pSession->sessionActive) &&
+ (!pSession->readyForPowerSave))
+ {
+ return VOS_FALSE;
+ }
+ }
+ // all active sessions have voted for powersave
+ return VOS_TRUE;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosPmcDeviceStateUpdateInd() - Callback function registered with
+ PMC to notify SME-QoS when it changes the power state
+
+ \param callbackContext - The context passed to PMC during registration
+ through pmcRegisterDeviceStateUpdateInd.
+ \param pmcState - Current power state that PMC moved into.
+
+ \return None
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+void sme_QosPmcDeviceStateUpdateInd(void *callbackContext, tPmcState pmcState)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( callbackContext );
+ //check all the entries in Flow list for non-zero service interval, which will
+ //tell us if we need to notify HDD when PMC is out of UAPSD mode or going
+ // back to UAPSD mode
+ switch(pmcState)
+ {
+ case FULL_POWER:
+ status = sme_QosProcessOutOfUapsdMode(pMac);
+ break;
+ case UAPSD:
+ status = sme_QosProcessIntoUapsdMode(pMac);
+ break;
+ default:
+ status = eHAL_STATUS_SUCCESS;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: nothing to process in PMC state %d",
+ __FUNCTION__, __LINE__,
+ pmcState);
+ }
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: ignoring Device(PMC) state change to %d",
+ __FUNCTION__, __LINE__,
+ pmcState);
+ }
+
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessOutOfUapsdMode() - Function to notify HDD when PMC
+ notifies SME-QoS that it moved out of UAPSD mode to FULL power
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessOutOfUapsdMode(tpAniSirGlobal pMac)
+{
+ sme_QosSessionInfo *pSession;
+ tListElem *pEntry= NULL, *pNextEntry = NULL;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+
+ pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Flow List empty, can't search",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
+ //only notify the flows which already successfully setup UAPSD
+ if((flow_info->QoSInfo.max_service_interval ||
+ flow_info->QoSInfo.min_service_interval) &&
+ (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason))
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pSession->ac_info[flow_info->ac_type].curr_QoSInfo[flow_info->tspec_mask - 1],
+ SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND,
+ flow_info->QosFlowID);
+ }
+ pEntry = pNextEntry;
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_QosProcessIntoUapsdMode() - Function to notify HDD when PMC
+ notifies SME-QoS that it is moving into UAPSD mode
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \return eHalStatus
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_QosProcessIntoUapsdMode(tpAniSirGlobal pMac)
+{
+ sme_QosSessionInfo *pSession;
+ tListElem *pEntry= NULL, *pNextEntry = NULL;
+ sme_QosFlowInfoEntry *flow_info = NULL;
+
+ pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
+ if(!pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Flow List empty, can't search",
+ __FUNCTION__, __LINE__);
+ return eHAL_STATUS_FAILURE;
+ }
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
+ flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
+ pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
+ //only notify the flows which already successfully setup UAPSD
+ if((flow_info->QoSInfo.max_service_interval ||
+ flow_info->QoSInfo.min_service_interval) &&
+ (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason))
+ {
+ flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+ &pSession->ac_info[flow_info->ac_type].curr_QoSInfo[flow_info->tspec_mask - 1],
+ SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND,
+ flow_info->QosFlowID);
+ }
+ pEntry = pNextEntry;
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+
+void sme_QosCleanupCtrlBlkForHandoff(tpAniSirGlobal pMac, v_U8_t sessionId)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosEdcaAcType ac;
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ vos_mem_zero(pACInfo->curr_QoSInfo,
+ sizeof(sme_QosWmmTspecInfo) * SME_QOS_TSPEC_INDEX_MAX);
+ vos_mem_zero(pACInfo->requested_QoSInfo,
+ sizeof(sme_QosWmmTspecInfo) * SME_QOS_TSPEC_INDEX_MAX);
+ pACInfo->num_flows[0] = 0;
+ pACInfo->num_flows[1] = 0;
+ pACInfo->reassoc_pending = VOS_FALSE;
+ pACInfo->tspec_mask_status = 0;
+ pACInfo->tspec_pending = VOS_FALSE;
+ pACInfo->hoRenewal = VOS_FALSE;
+ pACInfo->prev_state = SME_QOS_LINK_UP;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_QosIsTSInfoAckPolicyValid() - The SME QoS API exposed to HDD to
+ check if TS info ack policy field can be set to "HT-immediate block acknowledgement"
+
+ \param pMac - The handle returned by macOpen.
+ \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
+ related info, provided by HDD
+ \param sessionId - sessionId returned by sme_OpenSession.
+
+ \return VOS_TRUE - Current Association is HT association and so TS info ack policy
+ can be set to "HT-immediate block acknowledgement"
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+v_BOOL_t sme_QosIsTSInfoAckPolicyValid(tpAniSirGlobal pMac,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ v_U8_t sessionId)
+{
+ tDot11fBeaconIEs *pIes = NULL;
+ sme_QosSessionInfo *pSession;
+ eHalStatus hstatus;
+ if( !CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Session Id %d is invalid",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ return VOS_FALSE;
+ }
+
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+
+ if( !pSession->sessionActive )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Session %d is inactive",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ return VOS_FALSE;
+ }
+
+ if(!pSession->assocInfo.pBssDesc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Session %d has an Invalid BSS Descriptor",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ return VOS_FALSE;
+ }
+
+ hstatus = csrGetParsedBssDescriptionIEs(pMac,
+ pSession->assocInfo.pBssDesc,
+ &pIes);
+ if(!HAL_STATUS_SUCCESS(hstatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d unable to parse BSS IEs",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ return VOS_FALSE;
+ }
+
+ /* success means pIes was allocated */
+
+ if(!pIes->HTCaps.present &&
+ pQoSInfo->ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d HT Caps aren't present but application set ack policy to HT ",
+ __FUNCTION__, __LINE__,
+ sessionId);
+
+ vos_mem_free(pIes);
+ return VOS_FALSE;
+ }
+
+ vos_mem_free(pIes);
+ return VOS_TRUE;
+}
+
+v_BOOL_t sme_QosValidateRequestedParams(tpAniSirGlobal pMac,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ v_U8_t sessionId)
+{
+ v_BOOL_t rc = VOS_FALSE;
+
+ do
+ {
+ if(SME_QOS_WMM_TS_DIR_RESV == pQoSInfo->ts_info.direction) break;
+ if(!sme_QosIsTSInfoAckPolicyValid(pMac, pQoSInfo, sessionId)) break;
+
+ rc = VOS_TRUE;
+ }while(0);
+ return rc;
+}
+
+static eHalStatus qosIssueCommand( tpAniSirGlobal pMac, v_U8_t sessionId,
+ eSmeCommandType cmdType, sme_QosWmmTspecInfo * pQoSInfo,
+ sme_QosEdcaAcType ac, v_U8_t tspec_mask )
+{
+ eHalStatus status = eHAL_STATUS_RESOURCES;
+ tSmeCmd *pCommand = NULL;
+ do
+ {
+ pCommand = smeGetCommandBuffer( pMac );
+ if ( !pCommand )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: fail to get command buffer for command %d",
+ __FUNCTION__, __LINE__, cmdType);
+ break;
+ }
+ pCommand->command = cmdType;
+ pCommand->sessionId = sessionId;
+ switch ( cmdType )
+ {
+ case eSmeCommandAddTs:
+ if( pQoSInfo )
+ {
+ status = eHAL_STATUS_SUCCESS;
+ pCommand->u.qosCmd.tspecInfo = *pQoSInfo;
+ pCommand->u.qosCmd.ac = ac;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: NULL pointer passed",
+ __FUNCTION__, __LINE__);
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ break;
+ case eSmeCommandDelTs:
+ status = eHAL_STATUS_SUCCESS;
+ pCommand->u.qosCmd.ac = ac;
+ pCommand->u.qosCmd.tspec_mask = tspec_mask;
+ break;
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid command type %d",
+ __FUNCTION__, __LINE__, cmdType );
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ break;
+ }
+ } while( 0 );
+ if( HAL_STATUS_SUCCESS( status ) && pCommand )
+ {
+ smePushCommand( pMac, pCommand, eANI_BOOLEAN_FALSE );
+ }
+ else if( pCommand )
+ {
+ qosReleaseCommand( pMac, pCommand );
+ }
+ return( status );
+}
+tANI_BOOLEAN qosProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_BOOLEAN fRemoveCmd = eANI_BOOLEAN_TRUE;
+ do
+ {
+ switch ( pCommand->command )
+ {
+ case eSmeCommandAddTs:
+ status = sme_QosAddTsReq( pMac, (v_U8_t)pCommand->sessionId, &pCommand->u.qosCmd.tspecInfo, pCommand->u.qosCmd.ac);
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
+ }
+ break;
+ case eSmeCommandDelTs:
+ status = sme_QosDelTsReq( pMac, (v_U8_t)pCommand->sessionId, pCommand->u.qosCmd.ac, pCommand->u.qosCmd.tspec_mask );
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ }
+ break;
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: invalid command type %d",
+ __FUNCTION__, __LINE__, pCommand->command );
+ break;
+ }//switch
+ } while(0);
+ return( fRemoveCmd );
+}
+
+/*
+ sme_QosTriggerUapsdChange
+ Invoked by BTC when UAPSD bypass is enabled or disabled
+ We, in turn, must disable or enable UAPSD on all flows as appropriate
+ That may require us to re-add TSPECs or to reassociate
+*/
+sme_QosStatusType sme_QosTriggerUapsdChange( tpAniSirGlobal pMac )
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ v_U8_t ac, tspec1 = 0, tspec2 = 0;
+ v_U8_t uapsd_mask;
+ tDot11fBeaconIEs *pIesLocal;
+ v_U8_t acm_mask;
+ v_BOOL_t fIsUapsdNeeded;
+ v_U8_t sessionId;
+ v_BOOL_t addtsWhenACMNotSet = CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Invoked",
+ __FUNCTION__, __LINE__);
+ for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
+ {
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ if( !pSession->sessionActive )
+ {
+ continue;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Session %d is active",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ if( HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSession->assocInfo.pBssDesc, &pIesLocal)) )
+ {
+ // get the ACM mask
+ acm_mask = sme_QosGetACMMask(pMac, pSession->assocInfo.pBssDesc, pIesLocal);
+ vos_mem_free(pIesLocal);
+ // get the uapsd mask for this session
+ uapsd_mask = pSession->apsdMask;
+ // unmask the bits with ACM on to avoid reassoc on them
+ uapsd_mask &= ~acm_mask;
+ // iterate through the ACs to determine if we need to re-add any TSPECs
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ // Does this AC have QoS active?
+ if( SME_QOS_QOS_ON == pACInfo->curr_state )
+ {
+ // Yes, QoS is active on this AC
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d AC %d has QoS active",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ // Does this AC require ACM?
+ if(( acm_mask & (1 << (SME_QOS_EDCA_AC_VO - ac)) ) || addtsWhenACMNotSet )
+ {
+ // Yes, so we need to re-add any TSPECS
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d AC %d has ACM enabled",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ // Are any TSPECs active?
+ if( pACInfo->tspec_mask_status )
+ {
+ // Yes, at least 1 TSPEC is active. Are they both active?
+ if( SME_QOS_TSPEC_MASK_BIT_1_2_SET == pACInfo->tspec_mask_status )
+ {
+ //both TSPECS are active
+ tspec1 = SME_QOS_TSPEC_MASK_BIT_1_SET;
+ tspec2 = SME_QOS_TSPEC_MASK_BIT_2_SET;
+ }
+ else
+ {
+ // only one TSPEC is active, get its mask
+ tspec1 = SME_QOS_TSPEC_MASK_BIT_1_2_SET & pACInfo->tspec_mask_status;
+ }
+ // Does TSPEC 1 really require UAPSD?
+ fIsUapsdNeeded = (v_BOOL_t)(pACInfo->curr_QoSInfo[tspec1 - 1].max_service_interval ||
+ pACInfo->curr_QoSInfo[tspec1 - 1].min_service_interval);
+ //double check whether we need to do anything
+ if( fIsUapsdNeeded )
+ {
+ pACInfo->requested_QoSInfo[tspec1 - 1] =
+ pACInfo->curr_QoSInfo[tspec1 - 1];
+ sme_QosReRequestAddTS( pMac, sessionId,
+ &pACInfo->requested_QoSInfo[tspec1 - 1],
+ ac,
+ tspec1 );
+ }
+ // Is TSPEC 2 active?
+ if( tspec2 )
+ {
+ // Does TSPEC 2 really require UAPSD?
+ fIsUapsdNeeded = (v_BOOL_t)(pACInfo->curr_QoSInfo[tspec2 - 1].max_service_interval ||
+ pACInfo->curr_QoSInfo[tspec2 - 1].min_service_interval);
+ if( fIsUapsdNeeded )
+ {
+ //No need to inform HDD
+ //pACInfo->hoRenewal = VOS_TRUE;
+ pACInfo->requested_QoSInfo[tspec2 - 1] =
+ pACInfo->curr_QoSInfo[tspec2 - 1];
+ sme_QosReRequestAddTS( pMac, sessionId,
+ &pACInfo->requested_QoSInfo[tspec2 - 1],
+ ac,
+ tspec2);
+ }
+ }
+ }
+ else
+ {
+ // QoS is set, ACM is on, but no TSPECs -- inconsistent state
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d AC %d has QoS enabled and ACM is set, but no TSPEC",
+ __FUNCTION__, __LINE__,
+ sessionId, ac);
+ VOS_ASSERT(0);
+ }
+ }
+ else
+ {
+ //Since ACM bit is not set, there should be only one QoS information for both directions.
+ fIsUapsdNeeded = (v_BOOL_t)(pACInfo->curr_QoSInfo[0].max_service_interval ||
+ pACInfo->curr_QoSInfo[0].min_service_interval);
+ if(fIsUapsdNeeded)
+ {
+ // we need UAPSD on this AC (and we may not currently have it)
+ uapsd_mask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: On session %d AC %d has ACM disabled, uapsd mask now 0x%X",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, uapsd_mask);
+ }
+ }
+ }
+ }
+ // do we need to reassociate?
+ if(uapsd_mask)
+ {
+ tCsrRoamModifyProfileFields modifyProfileFields;
+ //we need to do a reassoc on these AC
+ csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields);
+ if( btcIsReadyForUapsd(pMac) )
+ {
+ modifyProfileFields.uapsd_mask = uapsd_mask;
+ }
+ else
+ {
+ modifyProfileFields.uapsd_mask = 0;
+ }
+ //Do we need to inform HDD?
+ if(!HAL_STATUS_SUCCESS(sme_QosRequestReassoc(pMac, sessionId, &modifyProfileFields, VOS_TRUE)))
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On Session %d Reassoc failed",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ }
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On Session %d failed to parse IEs",
+ __FUNCTION__, __LINE__,
+ sessionId);
+ }
+ }
+ // return status is ignored by BTC
+ return SME_QOS_STATUS_SETUP_SUCCESS_IND;
+}
+
+/*
+ sme_QosReRequestAddTS to re-send AddTS for the combined QoS request
+*/
+static sme_QosStatusType sme_QosReRequestAddTS(tpAniSirGlobal pMac,
+ v_U8_t sessionId,
+ sme_QosWmmTspecInfo * pQoSInfo,
+ sme_QosEdcaAcType ac,
+ v_U8_t tspecMask)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ sme_QosStatusType status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ sme_QosCmdInfo cmd;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Invoked on session %d for AC %d TSPEC %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, tspecMask);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ pACInfo = &pSession->ac_info[ac];
+ // need to vote off powersave for the duration of this request
+ pSession->readyForPowerSave = VOS_FALSE;
+ //call PMC's request for power function
+ // AND
+ //another check is added considering the flowing scenario
+ //Addts reqest is pending on one AC, while APSD requested on another which
+ //needs a reassoc. Will buffer a request if Addts is pending on any AC,
+ //which will safegaurd the above scenario, & also won't confuse PE with back
+ //to back Addts or Addts followed by Reassoc
+ if(sme_QosIsRspPending(sessionId, ac) ||
+ ( eHAL_STATUS_PMC_PENDING == pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback, pSession, eSME_REASON_OTHER)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d buffering the AddTS request "
+ "for AC %d in state %d as Addts is pending "
+ "on other AC or waiting for full power",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, pACInfo->curr_state);
+ //buffer cmd
+ cmd.command = SME_QOS_RESEND_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.resendCmdInfo.ac = ac;
+ cmd.u.resendCmdInfo.tspecMask = tspecMask;
+ cmd.u.resendCmdInfo.QoSInfo = *pQoSInfo;
+ if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: On session %d unable to buffer the AddTS "
+ "request for AC %d TSPEC %d in state %d",
+ __FUNCTION__, __LINE__,
+ sessionId, ac, tspecMask, pACInfo->curr_state);
+ // unable to buffer the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ }
+ return SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
+ }
+ //get into the stat m/c to see if the request can be granted
+ switch(pACInfo->curr_state)
+ {
+ case SME_QOS_QOS_ON:
+ {
+ //if ACM, send out a new ADDTS
+ pACInfo->hoRenewal = VOS_TRUE;
+ status = sme_QosSetup(pMac, sessionId, pQoSInfo, ac);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: sme_QosSetup returned in SME_QOS_QOS_ON state on "
+ "AC %d with status =%d",
+ __FUNCTION__, __LINE__,
+ ac, status);
+ if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
+ {
+ // we aren't waiting for a response from the AP
+ // so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ }
+ if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)
+ {
+ status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
+ pACInfo->tspec_pending = tspecMask;
+ }
+ else if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
+ (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) ||
+ (SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING == status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: UAPSD is setup already status = %d "
+ "returned by sme_QosSetup",
+ __FUNCTION__, __LINE__,
+ status);
+ }
+ else
+ {
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: unexpected status = %d returned by sme_QosSetup",
+ __FUNCTION__, __LINE__,
+ status);
+ }
+ }
+ break;
+ case SME_QOS_HANDOFF:
+ case SME_QOS_REQUESTED:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: Re-Add request in state = %d buffer the request",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state);
+ cmd.command = SME_QOS_RESEND_REQ;
+ cmd.pMac = pMac;
+ cmd.sessionId = sessionId;
+ cmd.u.resendCmdInfo.ac = ac;
+ cmd.u.resendCmdInfo.tspecMask = tspecMask;
+ cmd.u.resendCmdInfo.QoSInfo = *pQoSInfo;
+ if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: couldn't buffer the readd request in state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state );
+ // unable to buffer the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
+ }
+ status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
+ break;
+ case SME_QOS_CLOSED:
+ case SME_QOS_INIT:
+ case SME_QOS_LINK_UP:
+ default:
+ //print error msg,
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: %d: ReAdd request in unexpected state = %d",
+ __FUNCTION__, __LINE__,
+ pACInfo->curr_state );
+ // unable to service the request
+ // nothing is pending so vote powersave back on
+ pSession->readyForPowerSave = VOS_TRUE;
+ // ASSERT?
+ break;
+ }
+ if((SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
+ (SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY == status))
+ {
+ (void)sme_QosProcessBufferedCmd(sessionId);
+ }
+ return (status);
+}
+
+static void sme_QosInitACs(tpAniSirGlobal pMac, v_U8_t sessionId)
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosEdcaAcType ac;
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ vos_mem_zero(&pSession->ac_info[ac], sizeof(sme_QosACInfo));
+ sme_QosStateTransition(sessionId, ac, SME_QOS_INIT);
+ }
+}
+static eHalStatus sme_QosRequestReassoc(tpAniSirGlobal pMac, tANI_U8 sessionId,
+ tCsrRoamModifyProfileFields *pModFields,
+ v_BOOL_t fForce )
+{
+ sme_QosSessionInfo *pSession;
+ sme_QosACInfo *pACInfo;
+ eHalStatus status;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: %d: Invoked on session %d with UAPSD mask 0x%X",
+ __FUNCTION__, __LINE__,
+ sessionId, pModFields->uapsd_mask);
+ pSession = &sme_QosCb.sessionInfo[sessionId];
+ status = csrReassoc(pMac, sessionId, pModFields, &pSession->roamID, fForce);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ //Update the state to Handoff so subsequent requests are queued until
+ // this one is finished
+ sme_QosEdcaAcType ac;
+ for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
+ {
+ pACInfo = &pSession->ac_info[ac];
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "%s: %d: AC[%d] is in state [%d]",
+ __FUNCTION__, __LINE__,
+ ac, pACInfo->curr_state );
+ // If it is already in HANDOFF state, don't do anything since we
+ // MUST preserve the previous state and sme_QosStateTransition
+ // will change the previous state
+ if(SME_QOS_HANDOFF != pACInfo->curr_state)
+ {
+ sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF);
+ }
+ }
+ }
+ return status;
+}
+static v_U32_t sme_QosAssignFlowId(void)
+{
+ v_U32_t flowId;
+ flowId = sme_QosCb.nextFlowId;
+ if (SME_QOS_MAX_FLOW_ID == flowId)
+ {
+ // The Flow ID wrapped. This is obviously not a real life scenario
+ // but handle it to keep the software test folks happy
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "%s: %d: Software Test made the flow counter wrap, "
+ "QoS may no longer be functional",
+ __FUNCTION__, __LINE__);
+ sme_QosCb.nextFlowId = SME_QOS_MIN_FLOW_ID;
+ }
+ else
+ {
+ sme_QosCb.nextFlowId++;
+ }
+ return flowId;
+}
+
+static v_U8_t sme_QosAssignDialogToken(void)
+{
+ v_U8_t token;
+ token = sme_QosCb.nextDialogToken;
+ if (SME_QOS_MAX_DIALOG_TOKEN == token)
+ {
+ // wrap is ok
+ sme_QosCb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN;
+ }
+ else
+ {
+ sme_QosCb.nextDialogToken++;
+ }
+ return token;
+}
+#endif /* WLAN_MDM_CODE_REDUCTION_OPT */
diff --git a/CORE/SME/src/btc/btcApi.c b/CORE/SME/src/btc/btcApi.c
new file mode 100644
index 0000000..36d1fbe
--- /dev/null
+++ b/CORE/SME/src/btc/btcApi.c
@@ -0,0 +1,1941 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/******************************************************************************
+*
+* Name: btcApi.c
+*
+* Description: Routines that make up the BTC API.
+*
+* Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+* Qualcomm Confidential and Proprietary.
+*
+******************************************************************************/
+#include "wlan_qct_wda.h"
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+#include "aniGlobal.h"
+#include "smsDebug.h"
+#include "btcApi.h"
+#include "cfgApi.h"
+#include "pmc.h"
+#include "smeQosInternal.h"
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+#include "vos_diag_core_event.h"
+#include "vos_diag_core_log.h"
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+static void btcLogEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent);
+static void btcRestoreHeartBeatMonitoringHandle(void* hHal);
+static void btcUapsdCheck( tpAniSirGlobal pMac, tpSmeBtEvent pBtEvent );
+VOS_STATUS btcCheckHeartBeatMonitoring(tHalHandle hHal, tpSmeBtEvent pBtEvent);
+static void btcPowerStateCB( v_PVOID_t pContext, tPmcState pmcState );
+static VOS_STATUS btcDeferEvent( tpAniSirGlobal pMac, tpSmeBtEvent pEvent );
+static VOS_STATUS btcDeferDisconnEvent( tpAniSirGlobal pMac, tpSmeBtEvent pEvent );
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+static void btcDiagEventLog (tHalHandle hHal, tpSmeBtEvent pBtEvent);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+/* ---------------------------------------------------------------------------
+ \fn btcOpen
+ \brief API to init the BTC Events Layer
+ \param hHal - The handle returned by macOpen.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE success
+ VOS_STATUS_SUCCESS failure
+ ---------------------------------------------------------------------------*/
+VOS_STATUS btcOpen (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ VOS_STATUS vosStatus;
+ /* Initialize BTC configuartion. */
+ pMac->btc.btcConfig.btcExecutionMode = BTC_SMART_COEXISTENCE;
+ pMac->btc.btcConfig.btcConsBtSlotsToBlockDuringDhcp = 0;
+ pMac->btc.btcConfig.btcA2DPBtSubIntervalsDuringDhcp = BTC_MAX_NUM_ACL_BT_SUB_INTS;
+ pMac->btc.btcConfig.btcBtIntervalMode1 = BTC_BT_INTERVAL_MODE1_DEFAULT;
+ pMac->btc.btcConfig.btcWlanIntervalMode1 = BTC_WLAN_INTERVAL_MODE1_DEFAULT;
+ pMac->btc.btcConfig.btcActionOnPmFail = BTC_START_NEXT;
+ pMac->btc.btcReady = VOS_FALSE;
+ pMac->btc.btcEventState = 0;
+ pMac->btc.btcHBActive = VOS_TRUE;
+
+ vosStatus = vos_timer_init( &pMac->btc.restoreHBTimer,
+ VOS_TIMER_TYPE_SW,
+ btcRestoreHeartBeatMonitoringHandle,
+ (void*) hHal);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcOpen: Fail to init timer");
+ return VOS_STATUS_E_FAILURE;
+ }
+ if( !HAL_STATUS_SUCCESS(pmcRegisterDeviceStateUpdateInd( pMac, btcPowerStateCB, pMac )) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcOpen: Fail to register PMC callback\n");
+ return VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+}
+/* ---------------------------------------------------------------------------
+ \fn btcClose
+ \brief API to exit the BTC Events Layer
+ \param hHal - The handle returned by macOpen.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE success
+ VOS_STATUS_SUCCESS failure
+ ---------------------------------------------------------------------------*/
+VOS_STATUS btcClose (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ VOS_STATUS vosStatus;
+ pMac->btc.btcReady = VOS_FALSE;
+ pMac->btc.btcUapsdOk = VOS_FALSE;
+ vos_timer_stop(&pMac->btc.restoreHBTimer);
+ vosStatus = vos_timer_destroy(&pMac->btc.restoreHBTimer);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcClose: Fail to destroy timer");
+ return VOS_STATUS_E_FAILURE;
+ }
+ if(!HAL_STATUS_SUCCESS(
+ pmcDeregisterDeviceStateUpdateInd(pMac, btcPowerStateCB)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "%s: %d: cannot deregister with pmcDeregisterDeviceStateUpdateInd()",
+ __FUNCTION__, __LINE__);
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn btcReady
+ \brief fn to inform BTC that eWNI_SME_SYS_READY_IND has been sent to PE.
+ This acts as a trigger to send a message to HAL to update the BTC
+ related conig to FW. Note that if HDD configures any power BTC
+ related stuff before this API is invoked, BTC will buffer all the
+ configutaion.
+ \param hHal - The handle returned by macOpen.
+ \return VOS_STATUS
+ ---------------------------------------------------------------------------*/
+VOS_STATUS btcReady (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ v_U32_t cfgVal = 0;
+ v_U8_t i;
+ pMac->btc.btcReady = VOS_TRUE;
+ pMac->btc.btcUapsdOk = VOS_TRUE;
+ for(i=0; i < BT_MAX_SCO_SUPPORT; i++)
+ {
+ pMac->btc.btcScoHandles[i] = BT_INVALID_CONN_HANDLE;
+ }
+
+ // Read heartbeat threshold CFG and save it.
+ ccmCfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &cfgVal);
+ pMac->btc.btcHBCount = (v_U8_t)cfgVal;
+ if (btcSendCfgMsg(hHal, &(pMac->btc.btcConfig)) != VOS_STATUS_SUCCESS)
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+static VOS_STATUS btcSendBTEvent(tpAniSirGlobal pMac, tpSmeBtEvent pBtEvent)
+{
+ vos_msg_t msg;
+ tpSmeBtEvent ptrSmeBtEvent = NULL;
+ switch(pBtEvent->btEventType)
+ {
+ case BT_EVENT_CREATE_SYNC_CONNECTION:
+ case BT_EVENT_SYNC_CONNECTION_UPDATED:
+ if(pBtEvent->uEventParam.btSyncConnection.linkType != BT_SCO &&
+ pBtEvent->uEventParam.btSyncConnection.linkType != BT_eSCO)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "Invalid link type %d for Sync Connection. BT event will be dropped ",
+ __FUNCTION__, pBtEvent->uEventParam.btSyncConnection.linkType);
+ return VOS_STATUS_E_FAILURE;
+ }
+ break;
+ case BT_EVENT_SYNC_CONNECTION_COMPLETE:
+ if((pBtEvent->uEventParam.btSyncConnection.status == BT_CONN_STATUS_SUCCESS) &&
+ ((pBtEvent->uEventParam.btSyncConnection.linkType != BT_SCO && pBtEvent->uEventParam.btSyncConnection.linkType != BT_eSCO) ||
+ (pBtEvent->uEventParam.btSyncConnection.connectionHandle == BT_INVALID_CONN_HANDLE)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "Invalid connection handle %d or link type %d for Sync Connection. BT event will be dropped ",
+ __FUNCTION__,
+ pBtEvent->uEventParam.btSyncConnection.connectionHandle,
+ pBtEvent->uEventParam.btSyncConnection.linkType);
+ return VOS_STATUS_E_FAILURE;
+ }
+ break;
+ case BT_EVENT_MODE_CHANGED:
+ if(pBtEvent->uEventParam.btAclModeChange.mode >= BT_ACL_MODE_MAX)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "Invalid mode %d for ACL Connection. BT event will be dropped ",
+ __FUNCTION__,
+ pBtEvent->uEventParam.btAclModeChange.mode);
+ return VOS_STATUS_E_FAILURE;
+ }
+ break;
+ case BT_EVENT_DEVICE_SWITCHED_OFF:
+ pMac->btc.btcEventState = 0;
+ break;
+ default:
+ break;
+ }
+ ptrSmeBtEvent = vos_mem_malloc(sizeof(tSmeBtEvent));
+ if (NULL == ptrSmeBtEvent)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "Not able to allocate memory for BT event", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ btcLogEvent(pMac, pBtEvent);
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ btcDiagEventLog(pMac, pBtEvent);
+#endif
+ vos_mem_copy(ptrSmeBtEvent, pBtEvent, sizeof(tSmeBtEvent));
+ msg.type = WDA_SIGNAL_BT_EVENT;
+ msg.reserved = 0;
+ msg.bodyptr = ptrSmeBtEvent;
+ if(VOS_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_SIGNAL_BT_EVENT message to WDA", __FUNCTION__);
+ vos_mem_free( ptrSmeBtEvent );
+ return VOS_STATUS_E_FAILURE;
+ }
+ // After successfully posting the message, check if heart beat
+ // monitoring needs to be turned off
+ (void)btcCheckHeartBeatMonitoring(pMac, pBtEvent);
+ //Check whether BTC and UAPSD can co-exist
+ btcUapsdCheck( pMac, pBtEvent );
+ return VOS_STATUS_SUCCESS;
+ }
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+/* ---------------------------------------------------------------------------
+ \fn btcSignalBTEvent
+ \brief API to signal Bluetooth (BT) event to the WLAN driver. Based on the
+ BT event type and the current operating mode of Libra (full power,
+ BMPS, UAPSD etc), appropriate Bluetooth Coexistence (BTC) strategy
+ would be employed.
+ \param hHal - The handle returned by macOpen.
+ \param pBtEvent - Pointer to a caller allocated object of type tSmeBtEvent.
+ Caller owns the memory and is responsible for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE – BT Event not passed to HAL. This can happen
+ if driver has not yet been initialized or if BTC
+ Events Layer has been disabled.
+ VOS_STATUS_SUCCESS – BT Event passed to HAL
+ ---------------------------------------------------------------------------*/
+VOS_STATUS btcSignalBTEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ VOS_STATUS vosStatus;
+ if( NULL == pBtEvent )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "Null pointer for SME BT Event", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ if(( BTC_WLAN_ONLY == pMac->btc.btcConfig.btcExecutionMode ) ||
+ ( BTC_PTA_ONLY == pMac->btc.btcConfig.btcExecutionMode ))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "BTC execution mode not set to BTC_SMART_COEXISTENCE. BT event will be dropped", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ if( pBtEvent->btEventType < 0 || pBtEvent->btEventType >= BT_EVENT_TYPE_MAX )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "Invalid BT event %d being passed. BT event will be dropped",
+ __FUNCTION__, pBtEvent->btEventType);
+ return VOS_STATUS_E_FAILURE;
+ }
+ //Check PMC state to make sure whether we need to defer
+ //If we already have deferred events, defer the new one as well, in case PMC is in transition state
+ if( pMac->btc.fReplayBTEvents || !PMC_IS_CHIP_ACCESSIBLE(pmcGetPmcState( pMac )) )
+ {
+ //We need to defer the event
+ vosStatus = btcDeferEvent(pMac, pBtEvent);
+ if( VOS_IS_STATUS_SUCCESS(vosStatus) )
+ {
+ pMac->btc.fReplayBTEvents = VOS_TRUE;
+ return VOS_STATUS_SUCCESS;
+ }
+ else
+ {
+ return vosStatus;
+ }
+ }
+ btcSendBTEvent(pMac, pBtEvent);
+ return VOS_STATUS_SUCCESS;
+}
+#endif
+/* ---------------------------------------------------------------------------
+ \fn btcCheckHeartBeatMonitoring
+ \brief API to check whether heartbeat monitoring is required to be disabled
+ for specific BT start events which takes significant time to complete
+ during which WLAN misses beacons. To avoid WLAN-MAC from disconnecting
+ for the not enough beacons received we stop the heartbeat timer during
+ this start BT event till the stop of that BT event.
+ \param hHal - The handle returned by macOpen.
+ \param pBtEvent - Pointer to a caller allocated object of type tSmeBtEvent.
+ Caller owns the memory and is responsible for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE Config not passed to HAL.
+ VOS_STATUS_SUCCESS Config passed to HAL
+ ---------------------------------------------------------------------------*/
+VOS_STATUS btcCheckHeartBeatMonitoring(tHalHandle hHal, tpSmeBtEvent pBtEvent)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ VOS_STATUS vosStatus;
+ switch(pBtEvent->btEventType)
+ {
+ // Start events which requires heartbeat monitoring be disabled.
+ case BT_EVENT_INQUIRY_STARTED:
+ pMac->btc.btcEventState |= BT_INQUIRY_STARTED;
+ break;
+ case BT_EVENT_PAGE_STARTED:
+ pMac->btc.btcEventState |= BT_PAGE_STARTED;
+ break;
+ case BT_EVENT_CREATE_ACL_CONNECTION:
+ pMac->btc.btcEventState |= BT_CREATE_ACL_CONNECTION_STARTED;
+ break;
+ case BT_EVENT_CREATE_SYNC_CONNECTION:
+ pMac->btc.btcEventState |= BT_CREATE_SYNC_CONNECTION_STARTED;
+ break;
+ // Stop/done events which indicates heartbeat monitoring can be enabled
+ case BT_EVENT_INQUIRY_STOPPED:
+ pMac->btc.btcEventState &= ~(BT_INQUIRY_STARTED);
+ break;
+ case BT_EVENT_PAGE_STOPPED:
+ pMac->btc.btcEventState &= ~(BT_PAGE_STARTED);
+ break;
+ case BT_EVENT_ACL_CONNECTION_COMPLETE:
+ pMac->btc.btcEventState &= ~(BT_CREATE_ACL_CONNECTION_STARTED);
+ break;
+ case BT_EVENT_SYNC_CONNECTION_COMPLETE:
+ pMac->btc.btcEventState &= ~(BT_CREATE_SYNC_CONNECTION_STARTED);
+ break;
+ default:
+ // Ignore other events
+ return VOS_STATUS_SUCCESS;
+ }
+ // Check if any of the BT start events are active
+ if (pMac->btc.btcEventState) {
+ if (pMac->btc.btcHBActive) {
+ // set heartbeat threshold CFG to zero
+ ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, 0, NULL, eANI_BOOLEAN_FALSE);
+ pMac->btc.btcHBActive = VOS_FALSE;
+ }
+ // Deactivate and active the restore HB timer
+ vos_timer_stop( &pMac->btc.restoreHBTimer);
+ vosStatus= vos_timer_start( &pMac->btc.restoreHBTimer, BT_MAX_EVENT_DONE_TIMEOUT );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcCheckHeartBeatMonitoring: Fail to start timer");
+ return VOS_STATUS_E_FAILURE;
+ }
+ } else {
+ // Restore CFG back to the original value only if it was disabled
+ if (!pMac->btc.btcHBActive) {
+ ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->btc.btcHBCount, NULL, eANI_BOOLEAN_FALSE);
+ pMac->btc.btcHBActive = VOS_TRUE;
+ }
+ // Deactivate the timer
+ vosStatus = vos_timer_stop( &pMac->btc.restoreHBTimer);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcCheckHeartBeatMonitoring: Fail to stop timer");
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+/* ---------------------------------------------------------------------------
+ \fn btcRestoreHeartBeatMonitoringHandle
+ \brief Timer handler to handlet the timeout condition when a specific BT
+ stop event does not come back, in which case to restore back the
+ heartbeat timer.
+ \param hHal - The handle returned by macOpen.
+ \return VOID
+ ---------------------------------------------------------------------------*/
+void btcRestoreHeartBeatMonitoringHandle(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ if( !pMac->btc.btcHBActive )
+ {
+ tPmcState pmcState;
+ //Check PMC state to make sure whether we need to defer
+ pmcState = pmcGetPmcState( pMac );
+ if( PMC_IS_CHIP_ACCESSIBLE(pmcState) )
+ {
+ // Restore CFG back to the original value
+ ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->btc.btcHBCount, NULL, eANI_BOOLEAN_FALSE);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "BT event timeout, restoring back HeartBeat timer");
+ }
+ else
+ {
+ //defer it
+ pMac->btc.btcEventReplay.fRestoreHBMonitor = VOS_TRUE;
+ }
+ }
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn btcSetConfig
+ \brief API to change the current Bluetooth Coexistence (BTC) configuration
+ This function should be invoked only after CFG download has completed.
+ \param hHal - The handle returned by macOpen.
+ \param pSmeBtcConfig - Pointer to a caller allocated object of type
+ tSmeBtcConfig. Caller owns the memory and is responsible
+ for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE Config not passed to HAL.
+ VOS_STATUS_SUCCESS Config passed to HAL
+ ---------------------------------------------------------------------------*/
+VOS_STATUS btcSetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ //Save a copy in the global BTC config
+ vos_mem_copy(&(pMac->btc.btcConfig), pSmeBtcConfig, sizeof(tSmeBtcConfig));
+ //Send the config down only if SME_HddReady has been invoked. If not ready,
+ //BTC config will plumbed down when btcReady is eventually invoked.
+ if(pMac->btc.btcReady)
+ {
+ if(VOS_STATUS_SUCCESS != btcSendCfgMsg(hHal, pSmeBtcConfig))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "Failure to send BTC config down");
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+/* ---------------------------------------------------------------------------
+ \fn btcPostBtcCfgMsg
+ \brief Private API to post BTC config message to HAL
+ \param hHal - The handle returned by macOpen.
+ \param pSmeBtcConfig - Pointer to a caller allocated object of type
+ tSmeBtcConfig. Caller owns the memory and is responsible
+ for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE Config not passed to HAL.
+ VOS_STATUS_SUCCESS Config passed to HAL
+ ---------------------------------------------------------------------------*/
+VOS_STATUS btcSendCfgMsg(tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig)
+{
+ tpSmeBtcConfig ptrSmeBtcConfig = NULL;
+ vos_msg_t msg;
+ if( NULL == pSmeBtcConfig )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcSendCfgMsg: "
+ "Null pointer for BTC Config");
+ return VOS_STATUS_E_FAILURE;
+ }
+ if( pSmeBtcConfig->btcExecutionMode >= BT_EXEC_MODE_MAX )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcSendCfgMsg: "
+ "Invalid BT execution mode %d being set",
+ pSmeBtcConfig->btcExecutionMode);
+ return VOS_STATUS_E_FAILURE;
+ }
+ ptrSmeBtcConfig = vos_mem_malloc(sizeof(tSmeBtcConfig));
+ if (NULL == ptrSmeBtcConfig)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcSendCfgMsg: "
+ "Not able to allocate memory for SME BTC Config");
+ return VOS_STATUS_E_FAILURE;
+ }
+ vos_mem_copy(ptrSmeBtcConfig, pSmeBtcConfig, sizeof(tSmeBtcConfig));
+ msg.type = WDA_BTC_SET_CFG;
+ msg.reserved = 0;
+ msg.bodyptr = ptrSmeBtcConfig;
+ if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcSendCfgMsg: "
+ "Not able to post WDA_BTC_SET_CFG message to WDA");
+ vos_mem_free( ptrSmeBtcConfig );
+ return VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+}
+/* ---------------------------------------------------------------------------
+ \fn btcGetConfig
+ \brief API to retrieve the current Bluetooth Coexistence (BTC) configuration
+ \param hHal - The handle returned by macOpen.
+ \param pSmeBtcConfig - Pointer to a caller allocated object of type
+ tSmeBtcConfig. Caller owns the memory and is responsible
+ for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS btcGetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ if( NULL == pSmeBtcConfig )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcGetConfig: "
+ "Null pointer for BTC Config");
+ return VOS_STATUS_E_FAILURE;
+ }
+ vos_mem_copy(pSmeBtcConfig, &(pMac->btc.btcConfig), sizeof(tSmeBtcConfig));
+ return VOS_STATUS_SUCCESS;
+}
+/*
+ btcFindAclEventHist find a suited ACL event buffer
+ Param: bdAddr - NULL meaning not care.
+ pointer to caller alocated buffer containing the BD address to find a match
+ handle - BT_INVALID_CONN_HANDLE == not care
+ otherwise, a handle to match
+ NOPTE: Either bdAddr or handle can be valid, if both of them are valid, use bdAddr only. If neither
+ bdAddr nor handle is valid, return the next free slot.
+*/
+static tpSmeBtAclEventHist btcFindAclEventHist( tpAniSirGlobal pMac, v_U8_t *bdAddr, v_U16_t handle )
+{
+ int i, j;
+ tpSmeBtAclEventHist pRet = NULL;
+ tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay;
+ for( i = 0; (i < BT_MAX_ACL_SUPPORT) && (NULL == pRet); i++ )
+ {
+ if( NULL != bdAddr )
+ {
+ //try to match addr
+ if( pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx )
+ {
+ for(j = 0; j < pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx; j++)
+ {
+ if( vos_mem_compare(pReplay->btcEventHist.btAclConnectionEvent[i].btAclConnection[j].bdAddr,
+ bdAddr, 6) )
+ {
+ //found it
+ pRet = &pReplay->btcEventHist.btAclConnectionEvent[i];
+ break;
+ }
+ }
+ }
+ }
+ else if( BT_INVALID_CONN_HANDLE != handle )
+ {
+ //try to match handle
+ if( pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx )
+ {
+ for(j = 0; j < pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx; j++)
+ {
+ if( pReplay->btcEventHist.btAclConnectionEvent[i].btAclConnection[j].connectionHandle ==
+ handle )
+ {
+ //found it
+ pRet = &pReplay->btcEventHist.btAclConnectionEvent[i];
+ break;
+ }
+ }
+ }
+ }
+ else if( 0 == pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx )
+ {
+ pRet = &pReplay->btcEventHist.btAclConnectionEvent[i];
+ break;
+ }
+ }
+ return (pRet);
+}
+
+/*
+ btcFindSyncEventHist find a suited SYNC event buffer
+ Param: bdAddr - NULL meaning not care.
+ pointer to caller alocated buffer containing the BD address to find a match
+ handle - BT_INVALID_CONN_HANDLE == not care
+ otherwise, a handle to match
+ NOPTE: Either bdAddr or handle can be valid, if both of them are valid, use bdAddr only. If neither
+ bdAddr nor handle is valid, return the next free slot.
+*/
+static tpSmeBtSyncEventHist btcFindSyncEventHist( tpAniSirGlobal pMac, v_U8_t *bdAddr, v_U16_t handle )
+{
+ int i, j;
+ tpSmeBtSyncEventHist pRet = NULL;
+ tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay;
+ for( i = 0; (i < BT_MAX_SCO_SUPPORT) && (NULL == pRet); i++ )
+ {
+ if( NULL != bdAddr )
+ {
+ //try to match addr
+ if( pReplay->btcEventHist.btSyncConnectionEvent[i].bNextEventIdx )
+ {
+ for(j = 0; j < pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx; j++)
+ {
+ if( vos_mem_compare(pReplay->btcEventHist.btSyncConnectionEvent[i].btSyncConnection[j].bdAddr,
+ bdAddr, 6) )
+ {
+ //found it
+ pRet = &pReplay->btcEventHist.btSyncConnectionEvent[i];
+ break;
+ }
+ }
+ }
+ }
+ else if( BT_INVALID_CONN_HANDLE != handle )
+ {
+ //try to match handle
+ if( pReplay->btcEventHist.btSyncConnectionEvent[i].bNextEventIdx )
+ {
+ for(j = 0; j < pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx; j++)
+ {
+ if( pReplay->btcEventHist.btSyncConnectionEvent[i].btSyncConnection[j].connectionHandle ==
+ handle )
+ {
+ //found it
+ pRet = &pReplay->btcEventHist.btSyncConnectionEvent[i];
+ break;
+ }
+ }
+ }
+ }
+ else if( !pReplay->btcEventHist.btSyncConnectionEvent[i].bNextEventIdx )
+ {
+ pRet = &pReplay->btcEventHist.btSyncConnectionEvent[i];
+ break;
+ }
+ }
+ return (pRet);
+}
+
+/*
+ btcFindDisconnEventHist find a slot for the deferred disconnect event
+ If handle is invlid, it returns a free slot, if any.
+ If handle is valid, it tries to find a match first in case same disconnect event comes down again.
+*/
+static tpSmeBtDisconnectEventHist btcFindDisconnEventHist( tpAniSirGlobal pMac, v_U16_t handle )
+{
+ tpSmeBtDisconnectEventHist pRet = NULL;
+ tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay;
+ int i;
+ if( BT_INVALID_CONN_HANDLE != handle )
+ {
+ for(i = 0; i < BT_MAX_DISCONN_SUPPORT; i++)
+ {
+ if( pReplay->btcEventHist.btDisconnectEvent[i].fValid &&
+ (handle == pReplay->btcEventHist.btDisconnectEvent[i].btDisconnect.connectionHandle) )
+ {
+ pRet = &pReplay->btcEventHist.btDisconnectEvent[i];
+ break;
+ }
+ }
+ }
+ if( NULL == pRet )
+ {
+ //Find a free slot
+ for(i = 0; i < BT_MAX_DISCONN_SUPPORT; i++)
+ {
+ if( !pReplay->btcEventHist.btDisconnectEvent[i].fValid )
+ {
+ pRet = &pReplay->btcEventHist.btDisconnectEvent[i];
+ break;
+ }
+ }
+ }
+ return (pRet);
+}
+
+/*
+ btcFindModeChangeEventHist find a slot for the deferred mopde change event
+ If handle is invalid, it returns a free slot, if any.
+ If handle is valid, it tries to find a match first in case same disconnect event comes down again.
+*/
+tpSmeBtAclModeChangeEventHist btcFindModeChangeEventHist( tpAniSirGlobal pMac, v_U16_t handle )
+{
+ tpSmeBtAclModeChangeEventHist pRet = NULL;
+ tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay;
+ int i;
+ if( BT_INVALID_CONN_HANDLE != handle )
+ {
+ for(i = 0; i < BT_MAX_ACL_SUPPORT; i++)
+ {
+ if( pReplay->btcEventHist.btAclModeChangeEvent[i].fValid &&
+ (handle == pReplay->btcEventHist.btAclModeChangeEvent[i].btAclModeChange.connectionHandle) )
+ {
+ pRet = &pReplay->btcEventHist.btAclModeChangeEvent[i];
+ break;
+ }
+ }
+ }
+ if( NULL == pRet )
+ {
+ //Find a free slot
+ for(i = 0; i < BT_MAX_ACL_SUPPORT; i++)
+ {
+ if( !pReplay->btcEventHist.btAclModeChangeEvent[i].fValid )
+ {
+ pRet = &pReplay->btcEventHist.btAclModeChangeEvent[i];
+ break;
+ }
+ }
+ }
+ return (pRet);
+}
+
+/*
+ btcFindSyncUpdateEventHist find a slot for the deferred SYNC_UPDATE event
+ If handle is invalid, it returns a free slot, if any.
+ If handle is valid, it tries to find a match first in case same disconnect event comes down again.
+*/
+tpSmeBtSyncUpdateHist btcFindSyncUpdateEventHist( tpAniSirGlobal pMac, v_U16_t handle )
+{
+ tpSmeBtSyncUpdateHist pRet = NULL;
+ tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay;
+ int i;
+ if( BT_INVALID_CONN_HANDLE != handle )
+ {
+ for(i = 0; i < BT_MAX_SCO_SUPPORT; i++)
+ {
+ if( pReplay->btcEventHist.btSyncUpdateEvent[i].fValid &&
+ (handle == pReplay->btcEventHist.btSyncUpdateEvent[i].btSyncConnection.connectionHandle) )
+ {
+ pRet = &pReplay->btcEventHist.btSyncUpdateEvent[i];
+ break;
+ }
+ }
+ }
+ if( NULL == pRet )
+ {
+ //Find a free slot
+ for(i = 0; i < BT_MAX_SCO_SUPPORT; i++)
+ {
+ if( !pReplay->btcEventHist.btSyncUpdateEvent[i].fValid )
+ {
+ pRet = &pReplay->btcEventHist.btSyncUpdateEvent[i];
+ break;
+ }
+ }
+ }
+ return (pRet);
+}
+
+/*
+ Call must validate pAclEventHist
+*/
+static void btcReleaseAclEventHist( tpAniSirGlobal pMac, tpSmeBtAclEventHist pAclEventHist )
+{
+ vos_mem_zero( pAclEventHist, sizeof(tSmeBtAclEventHist) );
+}
+
+/*
+ Call must validate pSyncEventHist
+*/
+static void btcReleaseSyncEventHist( tpAniSirGlobal pMac, tpSmeBtSyncEventHist pSyncEventHist )
+{
+ vos_mem_zero( pSyncEventHist, sizeof(tSmeBtSyncEventHist) );
+}
+
+/*To defer a ACL creation event
+ We only support one ACL per BD address.
+ If the last cached event another ACL create event, replace that event with the new event
+ If a completion event with success status code, and the new ACL creation
+ on same address, defer a new disconnect event(fake one), then cache this ACL creation event.
+ Otherwise, save this create event.
+*/
+static VOS_STATUS btcDeferAclCreate( tpAniSirGlobal pMac, tpSmeBtEvent pEvent )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpSmeBtAclEventHist pAclEventHist;
+ tSmeBtAclConnectionParam *pAclEvent;
+ do
+ {
+ //Find a match
+ pAclEventHist = btcFindAclEventHist( pMac, pEvent->uEventParam.btAclConnection.bdAddr,
+ BT_INVALID_CONN_HANDLE );
+ if( NULL == pAclEventHist )
+ {
+ //No cached ACL event on this address
+ //Find a free slot and save it
+ pAclEventHist = btcFindAclEventHist( pMac, NULL, BT_INVALID_CONN_HANDLE );
+ if( NULL != pAclEventHist )
+ {
+ vos_mem_copy(&pAclEventHist->btAclConnection[0], &pEvent->uEventParam.btAclConnection,
+ sizeof(tSmeBtAclConnectionParam));
+ pAclEventHist->btEventType[0] = BT_EVENT_CREATE_ACL_CONNECTION;
+ pAclEventHist->bNextEventIdx = 1;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" failed to find ACL event slot\n"));
+ status = VOS_STATUS_E_RESOURCES;
+ }
+ //done
+ break;
+ }
+ else
+ {
+ //There is history on this BD address
+ VOS_ASSERT(pAclEventHist->bNextEventIdx > 0);
+ pAclEvent = &pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx - 1];
+ if(BT_EVENT_CREATE_ACL_CONNECTION == pAclEventHist->btEventType[pAclEventHist->bNextEventIdx - 1])
+ {
+ //The last cached event is creation, replace it with the new one
+ vos_mem_copy(pAclEvent,
+ &pEvent->uEventParam.btAclConnection,
+ sizeof(tSmeBtAclConnectionParam));
+ //done
+ break;
+ }
+ else if(BT_EVENT_ACL_CONNECTION_COMPLETE ==
+ pAclEventHist->btEventType[pAclEventHist->bNextEventIdx - 1])
+ {
+ //The last cached event is completion, check the status.
+ if(BT_CONN_STATUS_SUCCESS == pAclEvent->status)
+ {
+ tSmeBtEvent btEvent;
+ //The last event we have is success completion event.
+ //Should not get a creation event before creation.
+ smsLog(pMac, LOGE, FL(" Missing disconnect event on handle %d\n"), pAclEvent->connectionHandle);
+ //Fake a disconnect event
+ btEvent.btEventType = BT_EVENT_DISCONNECTION_COMPLETE;
+ btEvent.uEventParam.btDisconnect.connectionHandle = pAclEvent->connectionHandle;
+ btcDeferDisconnEvent(pMac, &btEvent);
+ }
+ }
+ //Need to save the new event
+ if(pAclEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_ACL_DEFERRED)
+ {
+ pAclEventHist->btEventType[pAclEventHist->bNextEventIdx] = BT_EVENT_CREATE_ACL_CONNECTION;
+ vos_mem_copy(&pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx],
+ &pEvent->uEventParam.btAclConnection,
+ sizeof(tSmeBtAclConnectionParam));
+ pAclEventHist->bNextEventIdx++;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" ACL event overflow\n"));
+ VOS_ASSERT(0);
+ }
+ }
+ }while(0);
+ return status;
+}
+
+/*Defer a ACL completion event
+ If there is cached event on this BD address, check completion status.
+ If status is fail and last cached event is creation, remove the creation event and drop
+ this completion event. Otherwise, cache this completion event as the latest one.
+*/
+static VOS_STATUS btcDeferAclComplete( tpAniSirGlobal pMac, tpSmeBtEvent pEvent )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpSmeBtAclEventHist pAclEventHist;
+ do
+ {
+ //Find a match
+ pAclEventHist = btcFindAclEventHist( pMac, pEvent->uEventParam.btAclConnection.bdAddr,
+ BT_INVALID_CONN_HANDLE );
+ if(pAclEventHist)
+ {
+ VOS_ASSERT(pAclEventHist->bNextEventIdx >0);
+ //Found one
+ if(BT_CONN_STATUS_SUCCESS != pEvent->uEventParam.btAclConnection.status)
+ {
+ //If completion fails, and the last one is creation, remove the creation event
+ if(BT_EVENT_CREATE_ACL_CONNECTION == pAclEventHist->btEventType[pAclEventHist->bNextEventIdx-1])
+ {
+ vos_mem_zero(&pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx-1],
+ sizeof(tSmeBtAclConnectionParam));
+ pAclEventHist->bNextEventIdx--;
+ //Done with this event
+ break;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" ACL completion fail but last event(%d) not creation\n"),
+ pAclEventHist->btEventType[pAclEventHist->bNextEventIdx-1]);
+ }
+ }
+ }
+ if( NULL == pAclEventHist )
+ {
+ pAclEventHist = btcFindAclEventHist( pMac, NULL, BT_INVALID_CONN_HANDLE );
+ }
+ if(pAclEventHist)
+ {
+ if(pAclEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_ACL_DEFERRED)
+ {
+ //Save this event
+ pAclEventHist->btEventType[pAclEventHist->bNextEventIdx] = BT_EVENT_ACL_CONNECTION_COMPLETE;
+ vos_mem_copy(&pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx],
+ &pEvent->uEventParam.btAclConnection,
+ sizeof(tSmeBtAclConnectionParam));
+ pAclEventHist->bNextEventIdx++;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" ACL event overflow\n"));
+ VOS_ASSERT(0);
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" cannot find match for failed BT_EVENT_ACL_CONNECTION_COMPLETE of bdAddr (%02X-%02X-%02X-%02X-%02X-%02X)\n"),
+ pEvent->uEventParam.btAclConnection.bdAddr[0],
+ pEvent->uEventParam.btAclConnection.bdAddr[1],
+ pEvent->uEventParam.btAclConnection.bdAddr[2],
+ pEvent->uEventParam.btAclConnection.bdAddr[3],
+ pEvent->uEventParam.btAclConnection.bdAddr[4],
+ pEvent->uEventParam.btAclConnection.bdAddr[5]);
+ status = VOS_STATUS_E_EMPTY;
+ }
+ }while(0);
+ return (status);
+}
+
+/*To defer a SYNC creation event
+ If the last cached event is another SYNC create event, replace
+ that event with the new event.
+ If there is a completion event with success status code, cache a new
+ disconnect event(fake) first, then cache this SYNC creation event.
+ Otherwise, cache this create event.
+*/
+static VOS_STATUS btcDeferSyncCreate( tpAniSirGlobal pMac, tpSmeBtEvent pEvent )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpSmeBtSyncEventHist pSyncEventHist;
+ tSmeBtSyncConnectionParam *pSyncEvent;
+ do
+ {
+ //Find a match
+ pSyncEventHist = btcFindSyncEventHist( pMac, pEvent->uEventParam.btSyncConnection.bdAddr,
+ BT_INVALID_CONN_HANDLE );
+ if( NULL == pSyncEventHist )
+ {
+ //No cached ACL event on this address
+ //Find a free slot and save it
+ pSyncEventHist = btcFindSyncEventHist( pMac, NULL, BT_INVALID_CONN_HANDLE );
+ if( NULL != pSyncEventHist )
+ {
+ vos_mem_copy(&pSyncEventHist->btSyncConnection[0], &pEvent->uEventParam.btSyncConnection,
+ sizeof(tSmeBtSyncConnectionParam));
+ pSyncEventHist->btEventType[0] = BT_EVENT_CREATE_SYNC_CONNECTION;
+ pSyncEventHist->bNextEventIdx = 1;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" failed to find SYNC event slot\n"));
+ status = VOS_STATUS_E_RESOURCES;
+ }
+ //done
+ break;
+ }
+ else
+ {
+ //There is history on this BD address
+ VOS_ASSERT(pSyncEventHist->bNextEventIdx > 0);
+ pSyncEvent = &pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx - 1];
+ if(BT_EVENT_CREATE_SYNC_CONNECTION ==
+ pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx - 1])
+ {
+ //The last cached event is creation, replace it with the new one
+ vos_mem_copy(pSyncEvent,
+ &pEvent->uEventParam.btSyncConnection,
+ sizeof(tSmeBtSyncConnectionParam));
+ //done
+ break;
+ }
+ else if(BT_EVENT_SYNC_CONNECTION_COMPLETE ==
+ pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx - 1])
+ {
+ //The last cached event is completion, check the status.
+ if(BT_CONN_STATUS_SUCCESS == pSyncEvent->status)
+ {
+ tSmeBtEvent btEvent;
+ //The last event we have is success completion event.
+ //Should not get a creation event before creation.
+ smsLog(pMac, LOGE, FL(" Missing disconnect event on handle %d\n"), pSyncEvent->connectionHandle);
+ //Fake a disconnect event
+ btEvent.btEventType = BT_EVENT_DISCONNECTION_COMPLETE;
+ btEvent.uEventParam.btDisconnect.connectionHandle = pSyncEvent->connectionHandle;
+ btcDeferDisconnEvent(pMac, &btEvent);
+ }
+ }
+ //Need to save the new event
+ if(pSyncEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_SCO_DEFERRED)
+ {
+ pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx] = BT_EVENT_CREATE_SYNC_CONNECTION;
+ vos_mem_copy(&pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx],
+ &pEvent->uEventParam.btSyncConnection,
+ sizeof(tSmeBtSyncConnectionParam));
+ pSyncEventHist->bNextEventIdx++;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" SYNC event overflow\n"));
+ }
+ }
+ }while(0);
+ return status;
+}
+
+/*Defer a SYNC completion event
+ If there is cached event on this BD address, check completion status.
+ If status is fail and last cached event is creation, remove te creation event and drop
+ this completion event.
+ Otherwise, cache this completion event as the latest one.
+*/
+static VOS_STATUS btcDeferSyncComplete( tpAniSirGlobal pMac, tpSmeBtEvent pEvent )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpSmeBtSyncEventHist pSyncEventHist;
+ do
+ {
+ //Find a match
+ pSyncEventHist = btcFindSyncEventHist( pMac, pEvent->uEventParam.btSyncConnection.bdAddr,
+ BT_INVALID_CONN_HANDLE );
+ if(pSyncEventHist)
+ {
+ VOS_ASSERT(pSyncEventHist->bNextEventIdx >0);
+ //Found one
+ if(BT_CONN_STATUS_SUCCESS != pEvent->uEventParam.btSyncConnection.status)
+ {
+ //If completion fails, and the last one is creation, remove the creation event
+ if(BT_EVENT_CREATE_SYNC_CONNECTION == pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx-1])
+ {
+ vos_mem_zero(&pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx-1],
+ sizeof(tSmeBtSyncConnectionParam));
+ pSyncEventHist->bNextEventIdx--;
+ //Done with this event
+ break;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" SYNC completion fail but last event(%d) not creation\n"),
+ pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx-1]);
+ }
+ }
+ }
+ if(NULL == pSyncEventHist)
+ {
+ //In case we don't defer the creation event
+ pSyncEventHist = btcFindSyncEventHist( pMac, NULL, BT_INVALID_CONN_HANDLE );
+ }
+ if(pSyncEventHist)
+ {
+ if(pSyncEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_ACL_DEFERRED)
+ {
+ //Save this event
+ pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx] = BT_EVENT_SYNC_CONNECTION_COMPLETE;
+ vos_mem_copy(&pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx],
+ &pEvent->uEventParam.btSyncConnection,
+ sizeof(tSmeBtSyncConnectionParam));
+ pSyncEventHist->bNextEventIdx++;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" SYNC event overflow\n"));
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" cannot find match for BT_EVENT_SYNC_CONNECTION_COMPLETE of bdAddr (%02X-%02X-%02X-%02X-%02X-%02X)\n"),
+ pEvent->uEventParam.btSyncConnection.bdAddr[0],
+ pEvent->uEventParam.btSyncConnection.bdAddr[1],
+ pEvent->uEventParam.btSyncConnection.bdAddr[2],
+ pEvent->uEventParam.btSyncConnection.bdAddr[3],
+ pEvent->uEventParam.btSyncConnection.bdAddr[4],
+ pEvent->uEventParam.btSyncConnection.bdAddr[5]);
+ status = VOS_STATUS_E_EMPTY;
+ }
+ }while(0);
+ return (status);
+}
+
+//return VOS_STATUS_E_EXISTS if the event handle cannot be found
+//VOS_STATUS_SUCCESS if the event is processed
+//Other error status meaning it cannot continue due to other errors
+/*
+ Defer a disconnect event for ACL
+ Check if any history on this event handle.
+ If both ACL_CREATION and ACL_COMPLETION is cached, remove both those events and drop
+ this disconnect event.
+ Otherwise save disconnect event in this ACL's bin.
+ If not ACL match on this handle, not to do anything.
+ Either way, remove any cached MODE_CHANGE event matches this disconnect event's handle.
+*/
+static VOS_STATUS btcDeferDisconnectEventForACL( tpAniSirGlobal pMac, tpSmeBtEvent pEvent )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpSmeBtAclEventHist pAclEventHist;
+ tpSmeBtAclModeChangeEventHist pModeChangeEventHist;
+ v_BOOL_t fDone = VOS_FALSE;
+ int i;
+ pAclEventHist = btcFindAclEventHist( pMac, NULL,
+ pEvent->uEventParam.btDisconnect.connectionHandle );
+ if(pAclEventHist)
+ {
+ if( pAclEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_ACL_DEFERRED)
+ {
+ smsLog(pMac, LOGE, FL(" ACL event history index:%d overflow, resetting to BT_MAX_NUM_EVENT_ACL_DEFERRED\n"), pAclEventHist->bNextEventIdx);
+ pAclEventHist->bNextEventIdx = BT_MAX_NUM_EVENT_ACL_DEFERRED;
+ }
+ //Looking backwords
+ for(i = pAclEventHist->bNextEventIdx - 1; i >= 0; i--)
+ {
+ if( BT_EVENT_ACL_CONNECTION_COMPLETE == pAclEventHist->btEventType[i] )
+ {
+ //make sure we can cancel the link
+ if( (i > 0) && (BT_EVENT_CREATE_ACL_CONNECTION == pAclEventHist->btEventType[i - 1]) )
+ {
+ fDone = VOS_TRUE;
+ if(i == 1)
+ {
+ //All events can be wiped off
+ btcReleaseAclEventHist(pMac, pAclEventHist);
+ break;
+ }
+ //we have both ACL creation and completion, wipe out all of them
+ pAclEventHist->bNextEventIdx = (tANI_U8)(i - 1);
+ vos_mem_zero(&pAclEventHist->btAclConnection[i-1], sizeof(tSmeBtAclConnectionParam));
+ vos_mem_zero(&pAclEventHist->btAclConnection[i], sizeof(tSmeBtAclConnectionParam));
+ break;
+ }
+ }
+ }//for loop
+ if(!fDone)
+ {
+ //Save this disconnect event
+ if(pAclEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_ACL_DEFERRED)
+ {
+ pAclEventHist->btEventType[pAclEventHist->bNextEventIdx] =
+ BT_EVENT_DISCONNECTION_COMPLETE;
+ pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx].connectionHandle =
+ pEvent->uEventParam.btDisconnect.connectionHandle;
+ pAclEventHist->bNextEventIdx++;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" ACL event overflow\n"));
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+ }
+ else
+ {
+ status = VOS_STATUS_E_EXISTS;
+ }
+ //Wipe out the related mode change event if it is there
+ pModeChangeEventHist = btcFindModeChangeEventHist( pMac,
+ pEvent->uEventParam.btDisconnect.connectionHandle );
+ if( pModeChangeEventHist && pModeChangeEventHist->fValid )
+ {
+ pModeChangeEventHist->fValid = VOS_FALSE;
+ }
+ return status;
+}
+
+//This function works the same as btcDeferDisconnectEventForACL except it hanldes SYNC events
+//return VOS_STATUS_E_EXISTS if the event handle cannot be found
+//VOS_STATUS_SUCCESS if the event is processed
+//Other error status meaning it cannot continue due to other errors
+/*
+ Defer a disconnect event for SYNC
+ Check if any SYNC history on this event handle.
+ If yes and if both SYNC_CREATION and SYNC_COMPLETION is cached, remove both those events and drop
+ this disconnect event.
+ Otherwise save disconnect event in this SYNC's bin.
+ If no match found, not to save this event here.
+ Either way, remove any cached SYNC_UPDATE event matches this disconnect event's handle.
+*/
+static VOS_STATUS btcDeferDisconnectEventForSync( tpAniSirGlobal pMac, tpSmeBtEvent pEvent )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpSmeBtSyncEventHist pSyncEventHist;
+ tpSmeBtSyncUpdateHist pSyncUpdateHist;
+ v_BOOL_t fDone = VOS_FALSE;
+ int i;
+ pSyncEventHist = btcFindSyncEventHist( pMac, NULL,
+ pEvent->uEventParam.btDisconnect.connectionHandle );
+ if(pSyncEventHist)
+ {
+ if( pSyncEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_SCO_DEFERRED)
+ {
+ smsLog(pMac, LOGE, FL(" SYNC event history index:%d overflow, resetting to BT_MAX_NUM_EVENT_SCO_DEFERRED\n"), pSyncEventHist->bNextEventIdx);
+ pSyncEventHist->bNextEventIdx = BT_MAX_NUM_EVENT_SCO_DEFERRED;
+ }
+ //Looking backwords
+ for(i = pSyncEventHist->bNextEventIdx - 1; i >= 0; i--)
+ {
+ //if a mode change event exists, drop it
+ if( BT_EVENT_SYNC_CONNECTION_COMPLETE == pSyncEventHist->btEventType[i] )
+ {
+ //make sure we can cancel the link
+ if( (i > 0) && (BT_EVENT_CREATE_SYNC_CONNECTION == pSyncEventHist->btEventType[i - 1]) )
+ {
+ fDone = VOS_TRUE;
+ if(i == 1)
+ {
+ //All events can be wiped off
+ btcReleaseSyncEventHist(pMac, pSyncEventHist);
+ break;
+ }
+ //we have both ACL creation and completion, wipe out all of them
+ pSyncEventHist->bNextEventIdx = (tANI_U8)(i - 1);
+ vos_mem_zero(&pSyncEventHist->btSyncConnection[i-1], sizeof(tSmeBtSyncConnectionParam));
+ vos_mem_zero(&pSyncEventHist->btSyncConnection[i], sizeof(tSmeBtSyncConnectionParam));
+ break;
+ }
+ }
+ }//for loop
+ if(!fDone)
+ {
+ //Save this disconnect event
+ if(pSyncEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_SCO_DEFERRED)
+ {
+ pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx] =
+ BT_EVENT_DISCONNECTION_COMPLETE;
+ pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx].connectionHandle =
+ pEvent->uEventParam.btDisconnect.connectionHandle;
+ pSyncEventHist->bNextEventIdx++;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" SYNC event overflow\n"));
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+ }
+ else
+ {
+ status = VOS_STATUS_E_EXISTS;
+ }
+ //Wipe out the related mode change event if it is there
+ pSyncUpdateHist = btcFindSyncUpdateEventHist( pMac,
+ pEvent->uEventParam.btDisconnect.connectionHandle );
+ if( pSyncUpdateHist && pSyncUpdateHist->fValid )
+ {
+ pSyncUpdateHist->fValid = VOS_FALSE;
+ }
+ return status;
+}
+
+/*
+ Defer a disconnect event.
+ Try to defer it as part of the ACL event first.
+ If no match is found, try SYNC.
+ If still no match found, defer it at DISCONNECT event bin.
+*/
+static VOS_STATUS btcDeferDisconnEvent( tpAniSirGlobal pMac, tpSmeBtEvent pEvent )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpSmeBtDisconnectEventHist pDisconnEventHist;
+ if( BT_INVALID_CONN_HANDLE == pEvent->uEventParam.btDisconnect.connectionHandle )
+ {
+ smsLog( pMac, LOGE, FL(" invalid handle\n") );
+ return (VOS_STATUS_E_INVAL);
+ }
+ //Check ACL first
+ status = btcDeferDisconnectEventForACL(pMac, pEvent);
+ if(!VOS_IS_STATUS_SUCCESS(status))
+ {
+ status = btcDeferDisconnectEventForSync(pMac, pEvent);
+ }
+ if( !VOS_IS_STATUS_SUCCESS(status) )
+ {
+ //Save the disconnect event
+ pDisconnEventHist = btcFindDisconnEventHist( pMac,
+ pEvent->uEventParam.btDisconnect.connectionHandle );
+ if( pDisconnEventHist )
+ {
+ pDisconnEventHist->fValid = VOS_TRUE;
+ vos_mem_copy( &pDisconnEventHist->btDisconnect, &pEvent->uEventParam.btDisconnect,
+ sizeof(tSmeBtDisconnectParam) );
+ status = VOS_STATUS_SUCCESS;
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" cannot find match for BT_EVENT_DISCONNECTION_COMPLETE of handle (%d)\n"),
+ pEvent->uEventParam.btDisconnect.connectionHandle);
+ status = VOS_STATUS_E_EMPTY;
+ }
+ }
+ return (status);
+}
+
+/*
+ btcDeferEvent save the event for possible replay when chip can be accessed
+ This function is called only when in IMPS/Standby state
+*/
+static VOS_STATUS btcDeferEvent( tpAniSirGlobal pMac, tpSmeBtEvent pEvent )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpSmeBtSyncUpdateHist pSyncUpdateHist;
+ tpSmeBtAclModeChangeEventHist pModeChangeEventHist;
+ tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay;
+ switch(pEvent->btEventType)
+ {
+ case BT_EVENT_DEVICE_SWITCHED_ON:
+ //Clear all events first
+ vos_mem_zero( &pReplay->btcEventHist, sizeof(tSmeBtcEventHist) );
+ pReplay->fBTSwitchOn = VOS_TRUE;
+ pReplay->fBTSwitchOff = VOS_FALSE;
+ break;
+ case BT_EVENT_DEVICE_SWITCHED_OFF:
+ //Clear all events first
+ vos_mem_zero( &pReplay->btcEventHist, sizeof(tSmeBtcEventHist) );
+ pReplay->fBTSwitchOff = VOS_TRUE;
+ pReplay->fBTSwitchOn = VOS_FALSE;
+ break;
+ case BT_EVENT_INQUIRY_STARTED:
+ pReplay->btcEventHist.nInquiryEvent++;
+ break;
+ case BT_EVENT_INQUIRY_STOPPED:
+ pReplay->btcEventHist.nInquiryEvent--;
+ break;
+ case BT_EVENT_PAGE_STARTED:
+ pReplay->btcEventHist.nPageEvent++;
+ break;
+ case BT_EVENT_PAGE_STOPPED:
+ pReplay->btcEventHist.nPageEvent--;
+ break;
+ case BT_EVENT_CREATE_ACL_CONNECTION:
+ status = btcDeferAclCreate(pMac, pEvent);
+ break;
+ case BT_EVENT_ACL_CONNECTION_COMPLETE:
+ status = btcDeferAclComplete( pMac, pEvent );
+ break;
+ case BT_EVENT_CREATE_SYNC_CONNECTION:
+ status = btcDeferSyncCreate(pMac, pEvent);
+ break;
+ case BT_EVENT_SYNC_CONNECTION_COMPLETE:
+ status = btcDeferSyncComplete( pMac, pEvent );
+ break;
+ case BT_EVENT_SYNC_CONNECTION_UPDATED:
+ if( BT_INVALID_CONN_HANDLE == pEvent->uEventParam.btDisconnect.connectionHandle )
+ {
+ smsLog( pMac, LOGE, FL(" invalid handle\n") );
+ status = VOS_STATUS_E_INVAL;
+ break;
+ }
+ //Find a match on handle. If not found, get a free slot.
+ pSyncUpdateHist = btcFindSyncUpdateEventHist( pMac,
+ pEvent->uEventParam.btSyncConnection.connectionHandle );
+ if(pSyncUpdateHist)
+ {
+ pSyncUpdateHist->fValid = VOS_TRUE;
+ vos_mem_copy(&pSyncUpdateHist->btSyncConnection, &pEvent->uEventParam.btSyncConnection,
+ sizeof(tSmeBtSyncConnectionParam));
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" cannot find match for BT_EVENT_SYNC_CONNECTION_UPDATED of handle (%d)\n"),
+ pEvent->uEventParam.btSyncConnection.connectionHandle );
+ status = VOS_STATUS_E_EMPTY;
+ }
+ break;
+ case BT_EVENT_DISCONNECTION_COMPLETE:
+ status = btcDeferDisconnEvent( pMac, pEvent );
+ break;
+ case BT_EVENT_MODE_CHANGED:
+ if( BT_INVALID_CONN_HANDLE == pEvent->uEventParam.btDisconnect.connectionHandle )
+ {
+ smsLog( pMac, LOGE, FL(" invalid handle\n") );
+ status = VOS_STATUS_E_INVAL;
+ break;
+ }
+ //Find a match on handle, If not found, return a free slot
+ pModeChangeEventHist = btcFindModeChangeEventHist( pMac,
+ pEvent->uEventParam.btAclModeChange.connectionHandle );
+ if(pModeChangeEventHist)
+ {
+ pModeChangeEventHist->fValid = VOS_TRUE;
+ vos_mem_copy( &pModeChangeEventHist->btAclModeChange,
+ &pEvent->uEventParam.btAclModeChange, sizeof(tSmeBtAclModeChangeParam) );
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" cannot find match for BT_EVENT_MODE_CHANGED of handle (%d)\n"),
+ pEvent->uEventParam.btAclModeChange.connectionHandle);
+ status = VOS_STATUS_E_EMPTY;
+ }
+ break;
+ case BT_EVENT_A2DP_STREAM_START:
+ pReplay->btcEventHist.fA2DPStarted = VOS_TRUE;
+ pReplay->btcEventHist.fA2DPStopped = VOS_FALSE;
+ break;
+ case BT_EVENT_A2DP_STREAM_STOP:
+ pReplay->btcEventHist.fA2DPStopped = VOS_TRUE;
+ pReplay->btcEventHist.fA2DPStarted = VOS_FALSE;
+ break;
+ default:
+ smsLog( pMac, LOGE, FL(" event (%d) is not deferred\n"), pEvent->btEventType );
+ status = VOS_STATUS_E_NOSUPPORT;
+ break;
+ }
+ return (status);
+}
+
+/*
+ Replay all cached events in the following order
+ 1. If BT_SWITCH_OFF event, send it.
+ 2. Send INQUIRY event (START or STOP),if available
+ 3. Send PAGE event (START or STOP), if available
+ 4. Send DISCONNECT events, these DISCONNECT events are not tied to
+ any ACL/SYNC event that we have cached
+ 5. Send ACL events (possible events, CREATION, COMPLETION, DISCONNECT)
+ 6. Send MODE_CHANGE events, if available
+ 7. Send A2DP event(START or STOP), if available
+ 8. Send SYNC events (possible events, CREATION, COMPLETION, DISCONNECT)
+ 9. Send SYNC_UPDATE events, if available
+*/
+static void btcReplayEvents( tpAniSirGlobal pMac )
+{
+ int i, j;
+ tSmeBtEvent btEvent;
+ tpSmeBtAclEventHist pAclHist;
+ tpSmeBtSyncEventHist pSyncHist;
+ tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay;
+ //Always turn on HB monitor first.
+ //It is independent of BT events even though BT event causes this
+ if( pReplay->fRestoreHBMonitor )
+ {
+ pReplay->fRestoreHBMonitor = VOS_FALSE;
+ //Only do it when needed
+ if( !pMac->btc.btcHBActive )
+ {
+ ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->btc.btcHBCount, NULL, eANI_BOOLEAN_FALSE);
+ pMac->btc.btcHBActive = VOS_TRUE;
+ }
+ }
+ if( pMac->btc.fReplayBTEvents )
+ {
+ /*Set the flag to false here so btcSignalBTEvent won't defer any further.
+ This works because SME has it global lock*/
+ pMac->btc.fReplayBTEvents = VOS_FALSE;
+ if( pReplay->fBTSwitchOff )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_DEVICE_SWITCHED_OFF;
+ btcSendBTEvent( pMac, &btEvent );
+ pReplay->fBTSwitchOff = VOS_FALSE;
+ }
+ else if( pReplay->fBTSwitchOn )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_DEVICE_SWITCHED_ON;
+ btcSendBTEvent( pMac, &btEvent );
+ pReplay->fBTSwitchOn = VOS_FALSE;
+ }
+ //Do inquire first
+ if( pReplay->btcEventHist.nInquiryEvent > 0 )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_INQUIRY_STARTED;
+ i = pReplay->btcEventHist.nInquiryEvent;
+ while(i--)
+ {
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ }
+ else if( pReplay->btcEventHist.nInquiryEvent < 0 )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_INQUIRY_STOPPED;
+ i = pReplay->btcEventHist.nInquiryEvent;
+ while(i++)
+ {
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ }
+ //Page
+ if( pReplay->btcEventHist.nPageEvent > 0 )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_PAGE_STARTED;
+ i = pReplay->btcEventHist.nPageEvent;
+ while(i--)
+ {
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ }
+ else if( pReplay->btcEventHist.nPageEvent < 0 )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_PAGE_STOPPED;
+ i = pReplay->btcEventHist.nPageEvent;
+ while(i++)
+ {
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ }
+ //Replay non-completion disconnect events first
+ //Disconnect
+ for( i = 0; i < BT_MAX_DISCONN_SUPPORT; i++ )
+ {
+ if( pReplay->btcEventHist.btDisconnectEvent[i].fValid )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_DISCONNECTION_COMPLETE;
+ vos_mem_copy( &btEvent.uEventParam.btDisconnect,
+ &pReplay->btcEventHist.btDisconnectEvent[i].btDisconnect, sizeof(tSmeBtDisconnectParam) );
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ }
+ //ACL
+ for( i = 0; i < BT_MAX_ACL_SUPPORT; i++ )
+ {
+ if( pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx )
+ {
+ pAclHist = &pReplay->btcEventHist.btAclConnectionEvent[i];
+ //Replay all ACL events for this BD address/handle
+ for(j = 0; j < pAclHist->bNextEventIdx; j++)
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = pAclHist->btEventType[j];
+ if(BT_EVENT_DISCONNECTION_COMPLETE != btEvent.btEventType)
+ {
+ //It must be CREATE or CONNECTION_COMPLETE
+ vos_mem_copy( &btEvent.uEventParam.btAclConnection,
+ &pAclHist->btAclConnection[j], sizeof(tSmeBtAclConnectionParam) );
+ }
+ else
+ {
+ btEvent.uEventParam.btDisconnect.connectionHandle = pAclHist->btAclConnection[j].connectionHandle;
+ }
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ }
+ }
+ //Mode change
+ for( i = 0; i < BT_MAX_ACL_SUPPORT; i++ )
+ {
+ if( pReplay->btcEventHist.btAclModeChangeEvent[i].fValid )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_MODE_CHANGED;
+ vos_mem_copy( &btEvent.uEventParam.btAclModeChange,
+ &pReplay->btcEventHist.btAclModeChangeEvent[i].btAclModeChange, sizeof(tSmeBtAclModeChangeParam) );
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ }
+ //A2DP
+ if( pReplay->btcEventHist.fA2DPStarted )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_A2DP_STREAM_START;
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ else if( pReplay->btcEventHist.fA2DPStopped )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_A2DP_STREAM_STOP;
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ //SCO
+ for( i = 0; i < BT_MAX_SCO_SUPPORT; i++ )
+ {
+ if( pReplay->btcEventHist.btSyncConnectionEvent[i].bNextEventIdx )
+ {
+ pSyncHist = &pReplay->btcEventHist.btSyncConnectionEvent[i];
+ //Replay all SYNC events for this BD address/handle
+ for(j = 0; j < pSyncHist->bNextEventIdx; j++)
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = pSyncHist->btEventType[j];
+ if(BT_EVENT_DISCONNECTION_COMPLETE != btEvent.btEventType)
+ {
+ //Must be CREATION or CONNECTION_COMPLETE
+ vos_mem_copy( &btEvent.uEventParam.btSyncConnection,
+ &pSyncHist->btSyncConnection[j], sizeof(tSmeBtSyncConnectionParam) );
+ }
+ else
+ {
+ btEvent.uEventParam.btDisconnect.connectionHandle = pSyncHist->btSyncConnection[j].connectionHandle;
+ }
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ }
+ }
+ //SYNC update
+ for( i = 0; i < BT_MAX_SCO_SUPPORT; i++ )
+ {
+ if( pReplay->btcEventHist.btSyncUpdateEvent[i].fValid )
+ {
+ vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) );
+ btEvent.btEventType = BT_EVENT_SYNC_CONNECTION_UPDATED;
+ vos_mem_copy( &btEvent.uEventParam.btSyncConnection,
+ &pReplay->btcEventHist.btSyncUpdateEvent[i].btSyncConnection,
+ sizeof(tSmeBtSyncConnectionParam) );
+ btcSendBTEvent( pMac, &btEvent );
+ }
+ }
+ //Clear all events
+ vos_mem_zero( &pReplay->btcEventHist, sizeof(tSmeBtcEventHist) );
+ }
+}
+
+static void btcPowerStateCB( v_PVOID_t pContext, tPmcState pmcState )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(pContext);
+ if( FULL_POWER == pmcState )
+ {
+ btcReplayEvents( pMac );
+ }
+}
+
+/* ---------------------------------------------------------------------------
+ \fn btcLogEvent
+ \brief API to log the the current Bluetooth event
+ \param hHal - The handle returned by macOpen.
+ \param pSmeBtcConfig - Pointer to a caller allocated object of type
+ tSmeBtEvent. Caller owns the memory and is responsible
+ for freeing it.
+ \return None
+ ---------------------------------------------------------------------------*/
+static void btcLogEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent)
+{
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "Bluetooth Event %d received", __FUNCTION__, pBtEvent->btEventType);
+ switch(pBtEvent->btEventType)
+ {
+ case BT_EVENT_CREATE_SYNC_CONNECTION:
+ case BT_EVENT_SYNC_CONNECTION_COMPLETE:
+ case BT_EVENT_SYNC_CONNECTION_UPDATED:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "SCO Connection: "
+ "connectionHandle = %d status = %d linkType %d "
+ "scoInterval %d scoWindow %d retransmisisonWindow = %d ",
+ pBtEvent->uEventParam.btSyncConnection.connectionHandle,
+ pBtEvent->uEventParam.btSyncConnection.status,
+ pBtEvent->uEventParam.btSyncConnection.linkType,
+ pBtEvent->uEventParam.btSyncConnection.scoInterval,
+ pBtEvent->uEventParam.btSyncConnection.scoWindow,
+ pBtEvent->uEventParam.btSyncConnection.retransmisisonWindow);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "BD ADDR = "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ pBtEvent->uEventParam.btSyncConnection.bdAddr[5],
+ pBtEvent->uEventParam.btSyncConnection.bdAddr[4],
+ pBtEvent->uEventParam.btSyncConnection.bdAddr[3],
+ pBtEvent->uEventParam.btSyncConnection.bdAddr[2],
+ pBtEvent->uEventParam.btSyncConnection.bdAddr[1],
+ pBtEvent->uEventParam.btSyncConnection.bdAddr[0]);
+ break;
+ case BT_EVENT_CREATE_ACL_CONNECTION:
+ case BT_EVENT_ACL_CONNECTION_COMPLETE:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "ACL Connection: "
+ "connectionHandle = %d status = %d ",
+ pBtEvent->uEventParam.btAclConnection.connectionHandle,
+ pBtEvent->uEventParam.btAclConnection.status);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "BD ADDR = "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ pBtEvent->uEventParam.btAclConnection.bdAddr[5],
+ pBtEvent->uEventParam.btAclConnection.bdAddr[4],
+ pBtEvent->uEventParam.btAclConnection.bdAddr[3],
+ pBtEvent->uEventParam.btAclConnection.bdAddr[2],
+ pBtEvent->uEventParam.btAclConnection.bdAddr[1],
+ pBtEvent->uEventParam.btAclConnection.bdAddr[0]);
+ break;
+ case BT_EVENT_MODE_CHANGED:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "ACL Mode change : "
+ "connectionHandle %d mode %d ",
+ pBtEvent->uEventParam.btAclModeChange.connectionHandle,
+ pBtEvent->uEventParam.btAclModeChange.mode);
+ break;
+ case BT_EVENT_DISCONNECTION_COMPLETE:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "Disconnect Event : "
+ "connectionHandle %d ", pBtEvent->uEventParam.btAclModeChange.connectionHandle);
+ break;
+ default:
+ break;
+ }
+ }
+
+/*
+ Caller can check whether BTC's current event allows UAPSD. This doesn't affect
+ BMPS.
+ return: VOS_TRUE -- BTC is ready for UAPSD
+ VOS_FALSE -- certain BT event is active, cannot enter UAPSD
+*/
+v_BOOL_t btcIsReadyForUapsd( tHalHandle hHal )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ return( pMac->btc.btcUapsdOk );
+}
+
+/*
+ Base on the BT event, this function sets the flag on whether to allow UAPSD
+ At this time, we are only interested in SCO and A2DP.
+ A2DP tracking is through BT_EVENT_A2DP_STREAM_START and BT_EVENT_A2DP_STREAM_STOP
+ SCO is through BT_EVENT_SYNC_CONNECTION_COMPLETE and BT_EVENT_DISCONNECTION_COMPLETE
+ BT_EVENT_DEVICE_SWITCHED_OFF overwrites them all
+*/
+void btcUapsdCheck( tpAniSirGlobal pMac, tpSmeBtEvent pBtEvent )
+{
+ v_U8_t i;
+ v_BOOL_t fLastUapsdState = pMac->btc.btcUapsdOk, fMoreSCO = VOS_FALSE;
+ switch( pBtEvent->btEventType )
+ {
+ case BT_EVENT_DISCONNECTION_COMPLETE:
+ if( (VOS_FALSE == pMac->btc.btcUapsdOk) &&
+ BT_INVALID_CONN_HANDLE != pBtEvent->uEventParam.btDisconnect.connectionHandle )
+ {
+ //Check whether all SCO connections are gone
+ for(i=0; i < BT_MAX_SCO_SUPPORT; i++)
+ {
+ if( (BT_INVALID_CONN_HANDLE != pMac->btc.btcScoHandles[i]) &&
+ (pMac->btc.btcScoHandles[i] != pBtEvent->uEventParam.btDisconnect.connectionHandle) )
+ {
+ //We still have outstanding SCO connection
+ fMoreSCO = VOS_TRUE;
+ }
+ else if( pMac->btc.btcScoHandles[i] == pBtEvent->uEventParam.btDisconnect.connectionHandle )
+ {
+ pMac->btc.btcScoHandles[i] = BT_INVALID_CONN_HANDLE;
+ }
+ }
+ if( !fMoreSCO && !pMac->btc.fA2DPUp )
+ {
+ //All SCO is disconnected
+ pMac->btc.btcUapsdOk = VOS_TRUE;
+ smsLog( pMac, LOGE, "BT event (DISCONNECTION) happens, UAPSD-allowed flag (%d) change to TRUE \n",
+ pBtEvent->btEventType, pMac->btc.btcUapsdOk );
+ }
+ }
+ break;
+ case BT_EVENT_DEVICE_SWITCHED_OFF:
+ smsLog( pMac, LOGE, "BT event (DEVICE_OFF) happens, UAPSD-allowed flag (%d) change to TRUE \n",
+ pBtEvent->btEventType, pMac->btc.btcUapsdOk );
+ //Clean up SCO
+ for(i=0; i < BT_MAX_SCO_SUPPORT; i++)
+ {
+ pMac->btc.btcScoHandles[i] = BT_INVALID_CONN_HANDLE;
+ }
+ pMac->btc.fA2DPUp = VOS_FALSE;
+ pMac->btc.btcUapsdOk = VOS_TRUE;
+ break;
+ case BT_EVENT_A2DP_STREAM_STOP:
+ smsLog( pMac, LOGE, "BT event (A2DP_STREAM_STOP) happens, UAPSD-allowed flag (%d) \n",
+ pMac->btc.btcUapsdOk );
+ pMac->btc.fA2DPUp = VOS_FALSE;
+ //Check whether SCO is on
+ for(i=0; i < BT_MAX_SCO_SUPPORT; i++)
+ {
+ if(pMac->btc.btcScoHandles[i] != BT_INVALID_CONN_HANDLE)
+ {
+ break;
+ }
+ }
+ if( BT_MAX_SCO_SUPPORT == i )
+ {
+ pMac->btc.fA2DPTrafStop = VOS_TRUE;
+ smsLog( pMac, LOGE, "BT_EVENT_A2DP_STREAM_STOP: UAPSD-allowed flag is now %d\n",
+ pMac->btc.btcUapsdOk );
+ }
+ break;
+
+ case BT_EVENT_MODE_CHANGED:
+ smsLog( pMac, LOGE, "BT event (BT_EVENT_MODE_CHANGED) happens, Mode (%d) UAPSD-allowed flag (%d)\n",
+ pBtEvent->uEventParam.btAclModeChange.mode, pMac->btc.btcUapsdOk );
+ if(pBtEvent->uEventParam.btAclModeChange.mode == BT_ACL_SNIFF)
+ {
+ //Check whether SCO is on
+ for(i=0; i < BT_MAX_SCO_SUPPORT; i++)
+ {
+ if(pMac->btc.btcScoHandles[i] != BT_INVALID_CONN_HANDLE)
+ {
+ break;
+ }
+ }
+ if( BT_MAX_SCO_SUPPORT == i )
+ {
+ if(VOS_TRUE == pMac->btc.fA2DPTrafStop)
+ {
+ pMac->btc.btcUapsdOk = VOS_TRUE;
+ pMac->btc.fA2DPTrafStop = VOS_FALSE;
+ }
+ smsLog( pMac, LOGE, "BT_EVENT_MODE_CHANGED with Mode:%d UAPSD-allowed flag is now %d\n",
+ pBtEvent->uEventParam.btAclModeChange.mode,pMac->btc.btcUapsdOk );
+ }
+ }
+ break;
+ case BT_EVENT_CREATE_SYNC_CONNECTION:
+ {
+ pMac->btc.btcUapsdOk = VOS_FALSE;
+ smsLog( pMac, LOGE, "BT_EVENT_CREATE_SYNC_CONNECTION (%d) happens, UAPSD-allowed flag (%d) change to FALSE \n",
+ pBtEvent->btEventType, pMac->btc.btcUapsdOk );
+ }
+ break;
+ case BT_EVENT_SYNC_CONNECTION_COMPLETE:
+ //Make sure it is a success
+ if( BT_CONN_STATUS_FAIL != pBtEvent->uEventParam.btSyncConnection.status )
+ {
+ //Save te handle for later use
+ for( i = 0; i < BT_MAX_SCO_SUPPORT; i++)
+ {
+ VOS_ASSERT(BT_INVALID_CONN_HANDLE != pBtEvent->uEventParam.btSyncConnection.connectionHandle);
+ if( (BT_INVALID_CONN_HANDLE == pMac->btc.btcScoHandles[i]) &&
+ (BT_INVALID_CONN_HANDLE != pBtEvent->uEventParam.btSyncConnection.connectionHandle))
+ {
+ pMac->btc.btcScoHandles[i] = pBtEvent->uEventParam.btSyncConnection.connectionHandle;
+ break;
+ }
+ }
+
+ if( i >= BT_MAX_SCO_SUPPORT )
+ {
+ smsLog(pMac, LOGE, FL("Too many SCO, ignore this one\n"));
+ }
+ }
+ else
+ {
+ //Check whether SCO is on
+ for(i=0; i < BT_MAX_SCO_SUPPORT; i++)
+ {
+ if(pMac->btc.btcScoHandles[i] != BT_INVALID_CONN_HANDLE)
+ {
+ break;
+ }
+ }
+ /*If No Other Sco/A2DP is ON reenable UAPSD*/
+ if( (BT_MAX_SCO_SUPPORT == i) && !pMac->btc.fA2DPUp)
+ {
+ pMac->btc.btcUapsdOk = VOS_TRUE;
+ }
+ smsLog(pMac, LOGE, FL("TSYNC complete failed\n"));
+ }
+ break;
+ case BT_EVENT_A2DP_STREAM_START:
+ smsLog( pMac, LOGE, "BT_EVENT_A2DP_STREAM_START (%d) happens, UAPSD-allowed flag (%d) change to FALSE \n",
+ pBtEvent->btEventType, pMac->btc.btcUapsdOk );
+ pMac->btc.fA2DPTrafStop = VOS_FALSE;
+ pMac->btc.btcUapsdOk = VOS_FALSE;
+ pMac->btc.fA2DPUp = VOS_TRUE;
+ break;
+ default:
+ //No change for these events
+ smsLog( pMac, LOGE, "BT event (%d) happens, UAPSD-allowed flag (%d) no change \n",
+ pBtEvent->btEventType, pMac->btc.btcUapsdOk );
+ break;
+ }
+ if(fLastUapsdState != pMac->btc.btcUapsdOk)
+ {
+ sme_QosTriggerUapsdChange( pMac );
+ }
+}
+
+/* ---------------------------------------------------------------------------
+ \fn btcHandleCoexInd
+ \brief API to handle Coex indication from WDI
+ \param pMac - The handle returned by macOpen.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE success
+ eHAL_STATUS_SUCCESS failure
+ ---------------------------------------------------------------------------*/
+eHalStatus btcHandleCoexInd(tHalHandle hHal, void* pMsg)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirSmeCoexInd *pSmeCoexInd = (tSirSmeCoexInd *)pMsg;
+
+ if (NULL == pMsg)
+ {
+ smsLog(pMac, LOGE, "in %s msg ptr is NULL\n", __FUNCTION__);
+ status = eHAL_STATUS_FAILURE;
+ }
+ else
+ {
+ // DEBUG
+ smsLog(pMac, LOG1, "Coex indication in %s(), type %d",
+ __FUNCTION__, pSmeCoexInd->coexIndType);
+
+ // suspend heartbeat monitoring
+ if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_DISABLE_HB_MONITOR)
+ {
+ // set heartbeat threshold CFG to zero
+ ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, 0, NULL, eANI_BOOLEAN_FALSE);
+ pMac->btc.btcHBActive = VOS_FALSE;
+ }
+
+ // resume heartbeat monitoring
+ else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_ENABLE_HB_MONITOR)
+ {
+ if (!pMac->btc.btcHBActive)
+ {
+ ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->btc.btcHBCount, NULL, eANI_BOOLEAN_FALSE);
+ pMac->btc.btcHBActive = VOS_TRUE;
+ }
+ }
+
+ // unknown indication type
+ else
+ {
+ smsLog(pMac, LOGE, "unknown Coex indication type in %s()", __FUNCTION__);
+ }
+ }
+
+ return(status);
+}
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+/* ---------------------------------------------------------------------------
+ \fn btcDiagEventLog
+ \brief API to log the the current Bluetooth event
+ \param hHal - The handle returned by macOpen.
+ \param pSmeBtcConfig - Pointer to a caller allocated object of type
+ tSmeBtEvent. Caller owns the memory and is responsible
+ for freeing it.
+ \return None
+ ---------------------------------------------------------------------------*/
+static void btcDiagEventLog (tHalHandle hHal, tpSmeBtEvent pBtEvent)
+{
+ //vos_event_wlan_btc_type *log_ptr = NULL;
+ WLAN_VOS_DIAG_EVENT_DEF(btDiagEvent, vos_event_wlan_btc_type);
+ {
+ btDiagEvent.eventId = pBtEvent->btEventType;
+ switch(pBtEvent->btEventType)
+ {
+ case BT_EVENT_CREATE_SYNC_CONNECTION:
+ case BT_EVENT_SYNC_CONNECTION_COMPLETE:
+ case BT_EVENT_SYNC_CONNECTION_UPDATED:
+ btDiagEvent.connHandle = pBtEvent->uEventParam.btSyncConnection.connectionHandle;
+ btDiagEvent.connStatus = pBtEvent->uEventParam.btSyncConnection.status;
+ btDiagEvent.linkType = pBtEvent->uEventParam.btSyncConnection.linkType;
+ btDiagEvent.scoInterval = pBtEvent->uEventParam.btSyncConnection.scoInterval;
+ btDiagEvent.scoWindow = pBtEvent->uEventParam.btSyncConnection.scoWindow;
+ btDiagEvent.retransWindow = pBtEvent->uEventParam.btSyncConnection.retransmisisonWindow;
+ vos_mem_copy(btDiagEvent.btAddr, pBtEvent->uEventParam.btSyncConnection.bdAddr,
+ sizeof(btDiagEvent.btAddr));
+ break;
+ case BT_EVENT_CREATE_ACL_CONNECTION:
+ case BT_EVENT_ACL_CONNECTION_COMPLETE:
+ btDiagEvent.connHandle = pBtEvent->uEventParam.btAclConnection.connectionHandle;
+ btDiagEvent.connStatus = pBtEvent->uEventParam.btAclConnection.status;
+ vos_mem_copy(btDiagEvent.btAddr, pBtEvent->uEventParam.btAclConnection.bdAddr,
+ sizeof(btDiagEvent.btAddr));
+ break;
+ case BT_EVENT_MODE_CHANGED:
+ btDiagEvent.connHandle = pBtEvent->uEventParam.btAclModeChange.connectionHandle;
+ btDiagEvent.mode = pBtEvent->uEventParam.btAclModeChange.mode;
+ break;
+ case BT_EVENT_DISCONNECTION_COMPLETE:
+ btDiagEvent.connHandle = pBtEvent->uEventParam.btAclModeChange.connectionHandle;
+ break;
+ default:
+ break;
+ }
+ }
+ WLAN_VOS_DIAG_EVENT_REPORT(&btDiagEvent, EVENT_WLAN_BTC);
+}
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
diff --git a/CORE/SME/src/ccm/ccmApi.c b/CORE/SME/src/ccm/ccmApi.c
new file mode 100644
index 0000000..ac50aff
--- /dev/null
+++ b/CORE/SME/src/ccm/ccmApi.c
@@ -0,0 +1,1124 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+#include "palTypes.h"
+#include "wniApi.h" /* WNI_CFG_SET_REQ */
+#include "sirParams.h" /* tSirMbMsg */
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include "halHddApis.h" /* palAllocateMemory */
+#endif
+#include "smsDebug.h" /* smsLog */
+#include "cfgApi.h"
+#include "ccmApi.h"
+#include "logDump.h"
+
+//#define CCM_DEBUG
+#undef CCM_DEBUG
+
+#define CCM_DEBUG2
+//#undef CCM_DEBUG2
+
+#define CFGOBJ_ALIGNTO 4
+#define CFGOBJ_ALIGN(len) ( ((len)+CFGOBJ_ALIGNTO-1) & ~(CFGOBJ_ALIGNTO-1) )
+
+#define CFGOBJ_ID_SIZE 4 /* 4 bytes for cfgId */
+#define CFGOBJ_LEN_SIZE 4 /* 4 bytes for length */
+#define CFGOBJ_INTEGER_VALUE_SIZE 4 /* 4 bytes for integer value */
+
+#define CFG_UPDATE_MAGIC_DWORD 0xabab
+
+#define halHandle2HddHandle(hHal) ( (NULL == (hHal)) ? 0 : ((tpAniSirGlobal)(hHal))->hHdd )
+
+static void ccmComplete(tHddHandle hHdd, void *done)
+{
+ if (done)
+ {
+ (void)palSemaphoreGive(hHdd, done);
+ }
+}
+
+static void ccmWaitForCompletion(tHddHandle hHdd, void *done)
+{
+ if (done)
+ {
+ (void)palSemaphoreTake(hHdd, done);
+ }
+}
+
+static tANI_U32 * encodeCfgReq(tHddHandle hHdd, tANI_U32 *pl, tANI_U32 cfgId, tANI_S32 length, void *pBuf, tANI_U32 value, tANI_U32 type)
+{
+ *pl++ = pal_cpu_to_be32(cfgId) ;
+ *pl++ = pal_cpu_to_be32(length) ;
+ if (type == CCM_INTEGER_TYPE)
+ {
+ *pl++ = pal_cpu_to_be32(value) ;
+ }
+ else
+ {
+ palCopyMemory(hHdd, (void *)pl, (void *)pBuf, length);
+ pl += (CFGOBJ_ALIGN(length) / CFGOBJ_ALIGNTO);
+ }
+ return pl ;
+}
+
+/*
+ * CCM_STRING_TYPE CCM_INTEGER_TYPE
+ * |<-------- 4 ----->| |<-------- 4 ----->|
+ * +----------+ <-- msg --> +----------+
+ * |type | |type |
+ * +----------+ +----------+
+ * |msgLen=24 | |msgLen=16 |
+ * +----------+----------+ +----------+----------+
+ * | cfgId | | cfgId |
+ * +---------------------+ +---------------------+
+ * | length=11 | | length=4 |
+ * +---------------------+ +---------------------+
+ * | | | value |
+ * | | +---------------------+
+ * | |
+ * | +----+
+ * | |////| <- padding to 4-byte boundary
+ * +----------------+----+
+ */
+static eHalStatus sendCfg(tpAniSirGlobal pMac, tHddHandle hHdd, tCfgReq *req, tANI_BOOLEAN fRsp)
+{
+ tSirMbMsg *msg;
+ eHalStatus status;
+ tANI_S16 msgLen = (tANI_U16)(4 + /* 4 bytes for msg header */
+ CFGOBJ_ID_SIZE +
+ CFGOBJ_LEN_SIZE +
+ CFGOBJ_ALIGN(req->length)) ;
+
+ status = palAllocateMemory(hHdd, (void **)&msg, msgLen);
+ if (status == eHAL_STATUS_SUCCESS)
+ {
+ if( fRsp )
+ {
+ msg->type = pal_cpu_to_be16(WNI_CFG_SET_REQ);
+ }
+ else
+ {
+ msg->type = pal_cpu_to_be16(WNI_CFG_SET_REQ_NO_RSP);
+ }
+ msg->msgLen = pal_cpu_to_be16(msgLen);
+ (void)encodeCfgReq(hHdd, msg->data, req->cfgId, req->length, req->ccmPtr, req->ccmValue, req->type) ;
+
+ status = palSendMBMessage(hHdd, msg) ;
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog( pMac, LOGW, FL("palSendMBMessage() failed\n"));
+ //No need to free msg. palSendMBMessage frees it.
+ status = eHAL_STATUS_FAILURE ;
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, FL("palAllocateMemory(len=%d)\n"), msgLen );
+ }
+
+ return status ;
+}
+
+static tCfgReq * allocateCfgReq(tHddHandle hHdd, tANI_U32 type, tANI_S32 length)
+{
+ tCfgReq *req ;
+ tANI_S32 alloc_len = sizeof(tCfgReq) ;
+
+ if (type == CCM_STRING_TYPE)
+ {
+ alloc_len += length ;
+ }
+
+ if (palAllocateMemory(hHdd, (void **)&req, alloc_len) != eHAL_STATUS_SUCCESS)
+ {
+ return NULL ;
+ }
+
+ req->ccmPtr = (req+1);
+
+ return req ;
+}
+
+static void freeCfgReq(tHddHandle hHdd, tCfgReq *req)
+{
+ palFreeMemory(hHdd, (void*)req) ;
+}
+
+static void add_req_tail(tCfgReq *req, struct ccmlink *q)
+{
+ if (q->tail)
+ {
+ q->tail->next = req;
+ q->tail = req ;
+ }
+ else
+ {
+ q->head = q->tail = req ;
+ }
+}
+
+static void del_req(tCfgReq *req, struct ccmlink *q)
+{
+ q->head = req->next ;
+ req->next = NULL ;
+ if (q->head == NULL)
+ {
+ q->tail = NULL ;
+ }
+}
+
+static void purgeReqQ(tHalHandle hHal)
+{
+ tHddHandle hHdd = halHandle2HddHandle(hHal);
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tCfgReq *req, *tmp ;
+
+ for (req = pMac->ccm.reqQ.head; req; req = tmp)
+ {
+ /* loop thru reqQ and invoke callback to return failure */
+ smsLog(pMac, LOGW, FL("deleting cfgReq, cfgid=%d\n"), (int)req->cfgId);
+
+ tmp = req->next ;
+
+ if (req->callback)
+ {
+ req->callback(hHal, eHAL_STATUS_FAILURE);
+ }
+ palSpinLockTake(hHdd, pMac->ccm.lock);
+ del_req(req, &pMac->ccm.reqQ);
+ palSpinLockGive(hHdd, pMac->ccm.lock);
+ freeCfgReq(hHdd, req);
+ }
+ return ;
+}
+
+static void sendQueuedReqToMacSw(tpAniSirGlobal pMac, tHddHandle hHdd)
+{
+ tCfgReq *req ;
+
+ /* Send the head req */
+ req = pMac->ccm.reqQ.head ;
+ if (req)
+ {
+ if (req->state == eCCM_REQ_QUEUED)
+ {
+ /* Send WNI_CFG_SET_REQ */
+ req->state = eCCM_REQ_SENT;
+ if (sendCfg(pMac, hHdd, req, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog( pMac, LOGW, FL("sendCfg() failed\n"));
+ palSpinLockTake(hHdd, pMac->ccm.lock);
+ del_req(req, &pMac->ccm.reqQ) ;
+ palSpinLockGive(hHdd, pMac->ccm.lock);
+ if (req->callback)
+ {
+ req->callback((tHalHandle)pMac, WNI_CFG_OTHER_ERROR) ;
+ }
+
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("ccmComplete(%p)\n"), req->done);
+#endif
+ ccmComplete(hHdd, req->done);
+
+ freeCfgReq(hHdd, req);
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, FL("reqState is not eCCM_REQ_QUEUED, is %d\n"), req->state );
+ }
+ }
+
+ return ;
+}
+
+static eHalStatus cfgSetSub(tpAniSirGlobal pMac, tHddHandle hHdd, tANI_U32 cfgId, tANI_U32 type,
+ tANI_S32 length, void *ccmPtr, tANI_U32 ccmValue,
+ tCcmCfgSetCallback callback, eAniBoolean toBeSaved, void *sem, tCfgReq **r)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tCfgReq *req ;
+
+ do
+ {
+ *r = NULL ;
+
+ if (pMac->ccm.state == eCCM_STOPPED)
+ {
+ status = eHAL_STATUS_FAILURE ;
+ break ;
+ }
+
+ req = allocateCfgReq(hHdd, type, length);
+ if (req == NULL)
+ {
+ status = eHAL_STATUS_FAILED_ALLOC ;
+ break ;
+ }
+
+ req->next = NULL ;
+ req->cfgId = (tANI_U16)cfgId ;
+ req->type = (tANI_U8)type ;
+ req->state = eCCM_REQ_QUEUED ;
+ req->toBeSaved = !!toBeSaved ;
+ req->length = length ;
+ req->done = sem ;
+ req->callback = callback ;
+ if (type == CCM_INTEGER_TYPE)
+ {
+ req->ccmValue = ccmValue ;
+ }
+ else
+ {
+ palCopyMemory(hHdd, (void*)req->ccmPtr, (void*)ccmPtr, length);
+ }
+
+ palSpinLockTake(hHdd, pMac->ccm.lock);
+
+ add_req_tail(req, &pMac->ccm.reqQ);
+ /* If this is the first req on the queue, send it to MAC SW */
+ if ((pMac->ccm.replay.started == 0) && (pMac->ccm.reqQ.head == req))
+ {
+ /* Send WNI_CFG_SET_REQ */
+ req->state = eCCM_REQ_SENT;
+ palSpinLockGive(hHdd, pMac->ccm.lock);
+ status = sendCfg(pMac, hHdd, req, eANI_BOOLEAN_TRUE) ;
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog( pMac, LOGW, FL("sendCfg() failed\n"));
+ palSpinLockTake(hHdd, pMac->ccm.lock);
+ del_req(req, &pMac->ccm.reqQ);
+ palSpinLockGive(hHdd, pMac->ccm.lock);
+ freeCfgReq(hHdd, req);
+ break ;
+ }
+ else
+ {
+ palSpinLockTake(hHdd, pMac->ccm.lock);
+ if(req != pMac->ccm.reqQ.head)
+ {
+ //We send the request and it must be done already
+ req = NULL;
+ }
+ palSpinLockGive(hHdd, pMac->ccm.lock);
+ }
+ }
+ else
+ {
+ palSpinLockGive(hHdd, pMac->ccm.lock);
+ }
+ *r = req ;
+
+ } while(0) ;
+
+ return status;
+}
+
+static eHalStatus cfgSet(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 type, tANI_S32 length, void * ccmPtr, tANI_U32 ccmValue, tCcmCfgSetCallback callback, eAniBoolean toBeSaved)
+{
+ tHddHandle hHdd = halHandle2HddHandle(hHal);
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status;
+ tCfgReq *req ;
+
+ if (pal_in_interrupt())
+ {
+#ifdef CCM_DEBUG2
+ smsLog(pMac, LOGE, FL("WNI_CFG_%s (%d 0x%x), in_interrupt()=TRUE\n"), gCfgParamName[cfgId], (int)cfgId, (int)cfgId);
+#endif
+ status = cfgSetSub(pMac, hHdd, cfgId, type, length, ccmPtr, ccmValue, callback, toBeSaved, NULL, &req);
+ }
+ else
+ {
+ void *sem ;
+
+#ifdef CCM_DEBUG2
+ smsLog(pMac, LOGE, FL("WNI_CFG_%s (%d 0x%x), in_interrupt()=FALSE\n"), gCfgParamName[cfgId], (int)cfgId, (int)cfgId);
+#endif
+ pal_local_bh_disable() ;
+
+ status = palMutexAllocLocked( hHdd, &sem ) ;
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("mutex alloc failed\n"));
+ sem = NULL;
+ }
+ else
+ {
+ status = cfgSetSub(pMac, hHdd, cfgId, type, length, ccmPtr, ccmValue, callback, toBeSaved, sem, &req);
+ if ((status != eHAL_STATUS_SUCCESS) || (req == NULL))
+ {
+ //Either it fails to send or the req is finished already
+ palSemaphoreFree( hHdd, sem );
+ sem = NULL;
+ }
+ }
+
+ pal_local_bh_enable() ;
+
+ if ((status == eHAL_STATUS_SUCCESS) && (sem != NULL))
+ {
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("ccmWaitForCompletion(%p)\n"), req->done);
+#endif
+ ccmWaitForCompletion(hHdd, sem);
+
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("free(%p)\n"), req->done);
+#endif
+ palSemaphoreFree( hHdd, sem ) ;
+ }
+ }
+
+ return status ;
+}
+
+eHalStatus ccmOpen(tHalHandle hHal)
+{
+ tHddHandle hHdd = halHandle2HddHandle(hHal);
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ (void)palZeroMemory(hHdd, &pMac->ccm, sizeof(tCcm)) ;
+ return palSpinLockAlloc(hHdd, &pMac->ccm.lock);
+}
+
+eHalStatus ccmClose(tHalHandle hHal)
+{
+ tHddHandle hHdd = halHandle2HddHandle(hHal);
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U32 i ;
+ tCfgReq *req ;
+
+ ccmStop(hHal);
+
+ /* Go thru comp[] to free all saved requests */
+ for (i = 0 ; i < CFG_PARAM_MAX_NUM ; ++i)
+ {
+ if ((req = pMac->ccm.comp[i]) != NULL)
+ {
+ freeCfgReq(hHdd, req);
+ }
+ }
+
+ return palSpinLockFree(hHdd, pMac->ccm.lock);
+}
+
+/* This function executes in (Linux) softirq context */
+void ccmCfgCnfMsgHandler(tHalHandle hHal, void *m)
+{
+ tHddHandle hHdd = halHandle2HddHandle(hHal);
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tSirMbMsg *msg = (tSirMbMsg *)m ;
+ tANI_U32 result, cfgId ;
+ tCfgReq *req, *old ;
+
+#if 0
+ if (pMac->ccm.state != eCCM_STARTED)
+ {
+ return ;
+ }
+#endif
+
+ result = pal_be32_to_cpu(msg->data[0]);
+ cfgId = pal_be32_to_cpu(msg->data[1]);
+
+ if (pMac->ccm.replay.started && cfgId == CFG_UPDATE_MAGIC_DWORD)
+ {
+ pMac->ccm.replay.in_progress = 1 ;
+ return ;
+ }
+
+ if (pMac->ccm.replay.in_progress)
+ {
+ /* save error code */
+ if (!CCM_IS_RESULT_SUCCESS(result))
+ {
+ pMac->ccm.replay.result = result ;
+ }
+
+ if (--pMac->ccm.replay.nr_param == 0)
+ {
+ pMac->ccm.replay.in_progress = 0 ;
+
+ if (pMac->ccm.replay.callback)
+ {
+ pMac->ccm.replay.callback(hHal, pMac->ccm.replay.result);
+ }
+
+ pMac->ccm.replay.started = 0 ;
+
+ /* Wake up the sleeping process */
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("ccmComplete(%p)\n"), pMac->ccm.replay.done);
+#endif
+ ccmComplete(hHdd, pMac->ccm.replay.done);
+ //Let go with the rest of the set CFGs waiting.
+ sendQueuedReqToMacSw(pMac, hHdd);
+ }
+ }
+ else
+ {
+ /*
+ * Try to match this response with the request.
+ * What if i could not find the req entry ???
+ */
+ req = pMac->ccm.reqQ.head ;
+ if (req)
+ {
+
+ if (req->cfgId == cfgId && req->state == eCCM_REQ_SENT)
+ {
+ palSpinLockTake(hHdd, pMac->ccm.lock);
+ del_req(req, &pMac->ccm.reqQ);
+ palSpinLockGive(hHdd, pMac->ccm.lock);
+ req->state = eCCM_REQ_DONE ;
+
+ if (result == WNI_CFG_NEED_RESTART ||
+ result == WNI_CFG_NEED_RELOAD)
+ {
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("need restart/reload, cfgId=%d\n"), req->cfgId) ;
+#endif
+ //purgeReqQ(hHal);
+ }
+
+ /* invoke callback */
+ if (req->callback)
+ {
+#ifdef CCM_DEBUG
+ req->callback(hHal, cfgId) ;
+#else
+ req->callback(hHal, result) ;
+#endif
+ }
+
+ /* Wake up the sleeping process */
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("cfgId=%ld, calling ccmComplete(%p)\n"), cfgId, req->done);
+#endif
+ ccmComplete(hHdd, req->done);
+
+ /* move the completed req from reqQ to comp[] */
+ if (req->toBeSaved && (CCM_IS_RESULT_SUCCESS(result)))
+ {
+ if ((old = pMac->ccm.comp[cfgId]) != NULL)
+ {
+ freeCfgReq(hHdd, old) ;
+ }
+ pMac->ccm.comp[cfgId] = req ;
+ }
+ else
+ {
+ freeCfgReq(hHdd, req) ;
+ }
+ sendQueuedReqToMacSw(pMac, hHdd);
+ }
+ else
+ {
+ smsLog( pMac, LOGW, FL("can not match RSP with REQ, rspcfgid=%d result=%d reqcfgid=%d reqstate=%d\n"),
+ (int)cfgId, (int)result, req->cfgId, req->state);
+
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("ccmComplete(%p)\n"), req->done);
+#endif
+ }
+
+ }
+ }
+
+ return ;
+}
+
+void ccmStart(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ pMac->ccm.state = eCCM_STARTED ;
+
+#if defined(ANI_LOGDUMP)
+ ccmDumpInit(hHal);
+#endif //#if defined(ANI_LOGDUMP)
+
+ return ;
+}
+
+void ccmStop(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ pMac->ccm.state = eCCM_STOPPED ;
+
+ pal_local_bh_disable() ;
+ purgeReqQ(hHal);
+ pal_local_bh_enable() ;
+
+ return ;
+}
+
+eHalStatus ccmCfgSetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 ccmValue, tCcmCfgSetCallback callback, eAniBoolean toBeSaved)
+{
+ if( callback || toBeSaved)
+ {
+ //we need to sychronous this one
+ return cfgSet(hHal, cfgId, CCM_INTEGER_TYPE, sizeof(tANI_U32), NULL, ccmValue, callback, toBeSaved);
+ }
+ else
+ {
+ //Simply push to CFG and not waiting for the response
+ tCfgReq req;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ req.callback = NULL;
+ req.next = NULL;
+ req.cfgId = ( tANI_U16 )cfgId;
+ req.length = sizeof( tANI_U32 );
+ req.type = CCM_INTEGER_TYPE;
+ req.ccmPtr = NULL;
+ req.ccmValue = ccmValue;
+ req.toBeSaved = toBeSaved;
+ req.state = eCCM_REQ_SENT;
+
+ return ( sendCfg( pMac, pMac->hHdd, &req, eANI_BOOLEAN_FALSE ) );
+ }
+}
+
+eHalStatus ccmCfgSetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pStr, tANI_U32 length, tCcmCfgSetCallback callback, eAniBoolean toBeSaved)
+{
+ if( callback || toBeSaved )
+ {
+ //we need to sychronous this one
+ return cfgSet(hHal, cfgId, CCM_STRING_TYPE, length, pStr, 0, callback, toBeSaved);
+ }
+ else
+ {
+ //Simply push to CFG and not waiting for the response
+ tCfgReq req;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ req.callback = NULL;
+ req.next = NULL;
+ req.cfgId = ( tANI_U16 )cfgId;
+ req.length = length;
+ req.type = CCM_STRING_TYPE;
+ req.ccmPtr = pStr;
+ req.ccmValue = 0;
+ req.toBeSaved = toBeSaved;
+ req.state = eCCM_REQ_SENT;
+
+ return ( sendCfg( pMac, pMac->hHdd, &req, eANI_BOOLEAN_FALSE ) );
+ }
+}
+
+eHalStatus ccmCfgGetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 *pValue)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_SUCCESS ;
+ tCfgReq *req = pMac->ccm.comp[cfgId] ;
+
+ if (req && req->state == eCCM_REQ_DONE)
+ {
+ *pValue = req->ccmValue ;
+ }
+ else
+ {
+ if (wlan_cfgGetInt(pMac, (tANI_U16)cfgId, pValue) != eSIR_SUCCESS)
+ status = eHAL_STATUS_FAILURE;
+ }
+
+ return status ;
+}
+
+eHalStatus ccmCfgGetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pBuf, tANI_U32 *pLength)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tHddHandle hHdd = halHandle2HddHandle(hHal);
+ eHalStatus status = eHAL_STATUS_SUCCESS ;
+ tCfgReq *req = pMac->ccm.comp[cfgId] ;
+
+ if (req && req->state == eCCM_REQ_DONE && (tANI_U32)req->length <= *pLength)
+ {
+ *pLength = req->length ;
+ palCopyMemory(hHdd, (void*)pBuf, (void*)req->ccmPtr, req->length);
+ }
+ else
+ {
+ if (wlan_cfgGetStr(pMac, (tANI_U16)cfgId, pBuf, pLength) != eSIR_SUCCESS)
+ status = eHAL_STATUS_FAILURE;
+ }
+
+ return status ;
+}
+
+/*
+ * Loop thru comp[] and form an ANI message which contains all completed cfgIds.
+ * The message begins with an INTEGER parameter (cfgId=CFG_UPDATE_MAGIC_DWORD)
+ * to mark the start of the message.
+ */
+static eHalStatus cfgUpdate(tpAniSirGlobal pMac, tHddHandle hHdd, tCcmCfgSetCallback callback)
+{
+ tANI_U32 i, *pl ;
+ tCfgReq *req ;
+ tSirMbMsg *msg ;
+ eHalStatus status ;
+ tANI_S16 msgLen = 4 + /* 4 bytes for msg header */
+ /* for CFG_UPDATE_MAGIC_DWORD */
+ CFGOBJ_ID_SIZE +
+ CFGOBJ_LEN_SIZE +
+ CFGOBJ_INTEGER_VALUE_SIZE ;
+
+ if (pMac->ccm.state == eCCM_STOPPED || pMac->ccm.replay.started)
+ {
+ status = eHAL_STATUS_FAILURE ;
+ goto end ;
+ }
+
+ palSpinLockTake(hHdd, pMac->ccm.lock);
+
+ pMac->ccm.replay.started = 1 ;
+ pMac->ccm.replay.nr_param = 0 ;
+
+ palSpinLockGive(hHdd, pMac->ccm.lock);
+
+ /* Calculate message length */
+ for (i = 0 ; i < CFG_PARAM_MAX_NUM ; ++i)
+ {
+ if ((req = pMac->ccm.comp[i]) != NULL)
+ {
+ msgLen += (tANI_S16)(CFGOBJ_ID_SIZE + CFGOBJ_LEN_SIZE + CFGOBJ_ALIGN(req->length)) ;
+ pMac->ccm.replay.nr_param += 1 ;
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("cfgId=%d\n"), req->cfgId);
+#endif
+ }
+ }
+
+ if (pMac->ccm.replay.nr_param == 0)
+ {
+ if (callback)
+ {
+ callback((tHalHandle)pMac, WNI_CFG_SUCCESS) ;
+ }
+ status = eHAL_STATUS_SUCCESS ;
+ goto end ;
+ }
+
+ pMac->ccm.replay.in_progress = 0 ;
+ pMac->ccm.replay.result = WNI_CFG_SUCCESS ;
+ pMac->ccm.replay.callback = callback ;
+ pMac->ccm.replay.done = NULL ;
+
+ status = palAllocateMemory(hHdd, (void **)&msg, msgLen) ;
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ pMac->ccm.replay.started = 0 ;
+ goto end ;
+ }
+
+ msg->type = pal_cpu_to_be16(WNI_CFG_SET_REQ);
+ msg->msgLen = pal_cpu_to_be16(msgLen);
+
+ /* Encode the starting cfgId */
+ pl = encodeCfgReq(hHdd, msg->data, CFG_UPDATE_MAGIC_DWORD, 4, NULL, 0, CCM_INTEGER_TYPE) ;
+
+ /* Encode the saved cfg requests */
+ for (i = 0 ; i < CFG_PARAM_MAX_NUM ; ++i)
+ {
+ if ((req = pMac->ccm.comp[i]) != NULL)
+ {
+ pl = encodeCfgReq(hHdd, pl, req->cfgId, req->length, req->ccmPtr, req->ccmValue, req->type) ;
+ }
+ }
+
+ status = palSendMBMessage(hHdd, msg) ;
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGW, FL("palSendMBMessage() failed. status=%d\n"), status);
+ pMac->ccm.replay.started = 0 ;
+ //No need to free msg. palSendMBMessage frees it.
+ goto end ;
+ }
+
+ end:
+ return status ;
+}
+
+eHalStatus ccmCfgUpdate(tHalHandle hHal, tCcmCfgSetCallback callback)
+{
+ tHddHandle hHdd = halHandle2HddHandle(hHal);
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status ;
+
+ pal_local_bh_disable() ;
+
+ status = cfgUpdate(pMac, hHdd, callback) ;
+ if (status == eHAL_STATUS_SUCCESS)
+ {
+ if (pMac->ccm.replay.nr_param == 0)
+ {
+ /* there is nothing saved at comp[], so we are done! */
+ pMac->ccm.replay.started = 0 ;
+ }
+ else
+ {
+ /* we have sent update message to MAC SW */
+ void *sem ;
+
+ status = palMutexAllocLocked( hHdd, &sem ) ;
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("mutex alloc failed\n"));
+ pMac->ccm.replay.started = 0 ;
+ }
+ else
+ {
+ pMac->ccm.replay.done = sem ;
+ }
+ }
+ }
+
+ pal_local_bh_enable() ;
+
+ /* Waiting here ... */
+ if (status == eHAL_STATUS_SUCCESS && pMac->ccm.replay.done)
+ {
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("ccmWaitForCompletion(%p)\n"), pMac->ccm.replay.done);
+#endif
+ ccmWaitForCompletion(hHdd, pMac->ccm.replay.done);
+
+#ifdef CCM_DEBUG
+ smsLog(pMac, LOGW, FL("free(%p)\n"), pMac->ccm.replay.done);
+#endif
+ palSemaphoreFree( hHdd, pMac->ccm.replay.done) ;
+ }
+
+ return status ;
+}
+
+#if 0
+///////////////////////////////////////////////////////////////////
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+extern struct net_device * hdd_dev[];
+
+typedef struct pal_netdev_priv_s
+{
+ // pointer to the PCI device structure for this device
+ struct pci_dev *pci_dev;
+
+ // TAURUS has three BAR registers
+
+ // BAR0 is a fixed window for the PIF registers
+ volatile void *win0_addr;
+ tANI_U32 win0_size;
+
+ // BAR1 is a movable window for all other registers
+ volatile void *win1_addr;
+ tANI_U32 win1_size;
+ tANI_U32 win1_current;
+
+ // BAR2 is a movable window for all other memory
+ volatile void *win2_addr;
+ tANI_U32 win2_size;
+ tANI_U32 win2_current;
+
+
+} pal_netdev_priv_t;
+
+typedef struct hdd_stats_s {
+ /* Stats on the MAC SW messages sent to applications */
+ ulong stats_mac_rx_mbx_tot_cnt;
+ ulong stats_mac_rx_mbx_success_cnt;
+ ulong stats_mac_rx_mbx_drop_cnt;
+
+ /* Stats on messages sent to the MAC SW messages from applications */
+ ulong stats_mac_tx_mbx_tot_cnt;
+ ulong stats_mac_tx_mbx_success_cnt;
+ ulong stats_mac_tx_mbx_drop_cnt;
+} hdd_stats_t;
+
+/* HDD Driver Private Data structure */
+typedef struct hdd_netdev_priv_s
+{
+ tANI_U32 magic_head;
+
+ // chipset-specific private data
+ pal_netdev_priv_t ANI_CHIPSET;
+
+ tHalHandle halHandle;
+
+#ifdef ANI_BUS_TYPE_PCI
+ struct pci_dev *pci_dev;
+ struct pci_device_id * pPciDevId;
+#endif // ANI_BUS_TYPE_PCI
+
+ // Queued EAPOL frame destination.
+ tANI_U32 eapol_pid;
+
+ unsigned int num_xmit;
+
+ /*
+ * Various frequently used variables that pertain to this
+ * instance of the driver
+ */
+ tANI_U32 rx_buf_sz; /* Based on MTU+extra headroom needed.*/
+ tANI_U32 td_enqueue_nested;
+
+ /*
+ * Flag set by MAC SW to indicate a TD ring is desired
+ */
+ int td_flush;
+
+ int selectiveFlush;
+
+ spinlock_t lock;
+
+ /* Stats */
+ struct net_device_stats stats;
+ int curr_acc_cat;
+#ifdef LX5280
+ unsigned short rtl_pvid; //VLAN id this Interface belongs to
+ int rtl_extPortNum; //ext port used in RTL865x driver
+ int rtl_linkId[16];//link ID of each interface for RTL865x driver
+ int rtl_wdsActive;
+#endif
+ tANI_U16 lport; /* switch logical port */
+
+ /* management and control */
+ tANI_U32 status;
+ tANI_U32 msg_enable;
+ tANI_U32 radio_id; /* Unit # of this device */
+
+ int ap_flag; /*
+ * indicates if the Radio is in AP
+ * or BP mode.
+ */
+
+ /* NAPI Polling suport */
+ struct timer_list oom_timer; /* Out of memory timer. */
+
+ struct timer_list reset_req_timer;/*
+ * Timer started when a Reset
+ * request is sent to WSM. Cleared
+ * when a subsequent Radio Disable
+ * Request is received.
+ */
+
+ struct tasklet_struct *rx_tasklet;
+ struct tasklet_struct *tx_tasklet;
+
+ tANI_U32 learn_mode_frame_cnt; /*
+ * Data Frames forwarded to MAC SW
+ * when Polaris is in learn mode
+ */
+
+ tANI_U32 mgmt_ctl_frames; /* MGMT/CTL Frames forwarded to MAC SW */
+
+ tANI_U32 nir; /* total number of times the ISR has
+ * been invoked.*/
+ tANI_U32 stats_dummy_pkt_requeue_cnt;
+ tANI_U32 stats_rx_td_dummy_pkt_cnt;/* TD Dummy pkts that were after HIF loopback */
+ tANI_U32 stats_rx_tm_dummy_pkt_cnt;/* TM Dummy pkts that were after HIF loopback */
+ tANI_U32 stats_td_dummy_pkt_cnt; /* Dummy pkts that were succesfully
+ * put on the TD ring and that
+ * were picked up by the HIF
+ */
+
+ tANI_U32 stats_mac_dummy_pkt_drop_cnt;/* Number of dummy pkts dropped by the HDD
+ * due to any reason
+ */
+ tANI_U32 stats_wns_l2update_cnt;
+ tANI_U32 stats_app_hif_wr_pkt_cnt;
+ hdd_stats_t hdd_stats;
+
+ tANI_U32 stats_reset_req_timer_cnt; /*
+ * Number of times the
+ * Reset Req Timer expired
+ */
+
+#ifdef TCP_PROFILE
+ unsigned int pv_current_ip_proto;
+ unsigned int pv_current_ip_byte;
+ unsigned int pv_current_ack_seq;
+ unsigned int pv_current_seq;
+ unsigned int pv_rtt;
+ unsigned int pv_sent_seq;
+ unsigned int pv_p_ts;
+ unsigned int pv_tfpl_ts;
+#endif
+ tANI_U32 stats_mac_reset_cnt; /* MAC SW Reset Requests */
+ tANI_U32 stats_mac_reset_eof_sof;
+ tANI_U32 stats_mac_reset_bmu;
+ tANI_U32 stats_mac_reset_pdu_low;
+ tANI_U32 stats_mac_reset_user;
+ tANI_U32 stats_mac_reset_wd_timeout;
+ tANI_U32 stats_mac_reset_unspecified;
+
+ tANI_U32 stats_wd_timeout_cnt;
+ tANI_U32 stats_radio_enable_cnt;
+ tANI_U32 stats_radio_disable_cnt;
+
+#ifdef PLM_EXTRA_STATS
+ tANI_U32 stats_tx_xmit_refilled; /* Pkts xmit-filled */
+ tANI_U32 stats_tx_queue_stop;
+ tANI_U32 stats_tx_queue_start;
+
+ tANI_U32 stats_alloc_fail;
+ tANI_U32 stats_poll_starts;
+ tANI_U32 stats_poll_pkts;
+ tANI_U32 stats_poll_exit_done;
+ tANI_U32 stats_poll_exit_not_done;
+ tANI_U32 stats_poll_exit_oom;
+ tANI_U32 stats_poll_exit_done_rx_pending;
+ tANI_U32 stats_poll_zero_rx;
+
+#ifdef CONFIG_PROC_FS
+#ifdef ANI_USE_TASKLET
+ struct proc_dir_entry *proc_driver_dir; // for /proc/net/drivers
+#endif
+ struct proc_dir_entry *proc_ent_dir; // for the directory itself
+
+ struct proc_dir_entry *proc_ent_stats;
+ struct proc_dir_entry *proc_ent_np_dump;
+ struct proc_dir_entry *proc_ent_ring;
+ char proc_fname_stats[32];
+ char proc_fname_np_dump[32];
+ char proc_fname_ring[32];
+
+ /* Setting Debug levels */
+ struct proc_dir_entry * proc_ent_dbg;
+ char proc_fname_dbg[32];
+
+ /* For bypass flags */
+ struct proc_dir_entry * proc_ent_bypass;
+ char proc_fname_bypass[32];
+
+ int sir_dump_cmd; // Dump SIR command
+ int sir_dump_arg1; // Dump SIR argument 1
+ int sir_dump_arg2; // Dump SIR argument 2
+ int sir_dump_arg3; // Dump SIR argument 3
+ int sir_dump_arg4; // Dump SIR argument 4
+ struct proc_dir_entry * proc_ent_sir_dump;
+ char proc_fname_sir_dump[32];
+
+ eHalStatus status ;
+ struct proc_dir_entry * proc_ent_eeprom_info;
+ char proc_fname_eeprom_info[32];
+
+#endif /* ifdef CONFIG_PROC_FS */
+
+ tANI_U32 rx_small_skb_failure;
+
+ unsigned long open_time; /* jiffies for last open */
+#endif /* PLM_EXTRA_STATS */
+
+ int mac_down;
+ tANI_U32 rx_mac_msg_cnt;
+ tANI_U32 tx_mac_msg_cnt;
+
+ int mbx_sent;
+
+ tANI_U32 bypass; // Used to various types of bypasses
+ // in the driver
+
+ /*
+ * this table is initialized once for all by poldrv and so is not in
+ * mac_param struct
+ */
+ t_mac_block_table * mac_block_table;
+ struct sk_buff_head mac_list;
+#if defined(ASICDXE_PROFILE) && defined(LX5280)
+ tANI_U32 num_of_reg_switches;
+#endif
+ tANI_U32 magic_tail;
+} hdd_netdev_priv_t;
+
+static void ccm_callback(tHalHandle hHal, tANI_S32 cfgId)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ smsLog(pMac, LOGW, FL("cfgId = %d\n"), cfgId);
+}
+
+static void ccm_callback2(tHalHandle hHal, tANI_S32 result)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ smsLog(pMac, LOGW, FL("result = %d\n"), result);
+}
+
+void ccm_test(void)
+{
+ tHalHandle hHal ;
+ tpAniSirGlobal pMac;
+ eHalStatus status ;
+ struct net_device *dev;
+ hdd_netdev_priv_t *np;
+ char str[80] = {1} ;
+
+ dev = hdd_dev[0];
+ np = (hdd_netdev_priv_t *)dev->priv;
+ hHal = np->halHandle ;
+ pMac = PMAC_STRUCT( hHal );
+
+ smsLog(pMac, LOGW, "ccmStart()\n");
+ ccmStart(hHal) ;
+
+ status = ccmCfgUpdate(hHal, ccm_callback2) ;
+ smsLog(pMac, LOGW, "ccmCfgUpdate(): status=%d\n", status);
+
+ status = ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, 100, ccm_callback, 1) ;
+ smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_FRAGMENTATION_THRESHOLD = %d): status=%d\n",
+ WNI_CFG_FRAGMENTATION_THRESHOLD, status);
+
+ status = ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, 100, ccm_callback, 1) ;
+ smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_RTS_THRESHOLD = %d): status=%d\n",
+ WNI_CFG_RTS_THRESHOLD, status);
+
+ /* this cfgid causes reload */
+ status = ccmCfgSetInt(hHal, WNI_CFG_MIMO_ENABLED, 1, ccm_callback, 1) ;
+ smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_MIMO_ENABLED = %d): status=%d\n",
+ WNI_CFG_MIMO_ENABLED, status);
+
+ status = ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, 100, ccm_callback, 1) ;
+ smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_SHORT_RETRY_LIMIT = %d): status=%d\n",
+ WNI_CFG_SHORT_RETRY_LIMIT, status);
+
+ status = ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, 100, ccm_callback, 1) ;
+ smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_LONG_RETRY_LIMIT = %d): status=%d\n",
+ WNI_CFG_LONG_RETRY_LIMIT, status);
+
+ /* this cfgid causes restart */
+ status = ccmCfgSetStr(hHal, WNI_CFG_EDCA_WME_ACVI, str, sizeof(str), ccm_callback, 1) ;
+ smsLog(pMac, LOGW, "ccmCfgSetStr(WNI_CFG_EDCA_WME_ACVI = %d): status=%d\n",
+ WNI_CFG_EDCA_WME_ACVI, status);
+
+ mdelay(100);
+
+ smsLog(pMac, LOGW, "ccmStop()\n");
+ ccmStop(hHal);
+ status = ccmCfgUpdate(hHal, ccm_callback2) ;
+ smsLog(pMac, LOGW, "ccmCfgUpdate(): status=%d\n", status);
+
+ smsLog(pMac, LOGW, "ccmStart()\n");
+ ccmStart(hHal) ;
+ status = ccmCfgUpdate(hHal, ccm_callback2) ;
+ smsLog(pMac, LOGW, "ccmCfgUpdate(): status=%d\n", status);
+}
+#endif
diff --git a/CORE/SME/src/ccm/ccmLogDump.c b/CORE/SME/src/ccm/ccmLogDump.c
new file mode 100644
index 0000000..975bf68
--- /dev/null
+++ b/CORE/SME/src/ccm/ccmLogDump.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/*============================================================================
+ccmLogDump.c
+
+Implements the dump commands specific to the ccm module.
+
+Copyright (c) 2007 QUALCOMM Incorporated.
+All Rights Reserved.
+Qualcomm Confidential and Proprietary
+ ============================================================================*/
+
+
+#include "aniGlobal.h"
+#include "logDump.h"
+
+#if defined(ANI_LOGDUMP)
+
+static tDumpFuncEntry ccmMenuDumpTable[] = {
+
+ {0, "CCM (861-870)", NULL},
+ //{861, "CCM: CCM testing ", dump_ccm}
+
+};
+
+void ccmDumpInit(tHalHandle hHal)
+{
+ logDumpRegisterTable( (tpAniSirGlobal) hHal, &ccmMenuDumpTable[0],
+ sizeof(ccmMenuDumpTable)/sizeof(ccmMenuDumpTable[0]) );
+}
+
+#endif //#if defined(ANI_LOGDUMP)
+
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
new file mode 100644
index 0000000..e1c81a0
--- /dev/null
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -0,0 +1,15084 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+
+
+ \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"
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include "halMsgApi.h" //for HAL_STA_INVALID_IDX.
+#endif
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include "halPhyApi.h"
+#include "halInternal.h"
+#endif
+
+#include "palApi.h"
+#include "csrInsideApi.h"
+#include "smsDebug.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"
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+#include "csrNeighborRoam.h"
+#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */
+
+#ifdef FEATURE_WLAN_CCX
+#include "csrCcx.h"
+#endif /* FEATURE_WLAN_CCX */
+
+#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
+#define CSR_IBSS_JOIN_TIMEOUT_PERIOD ( 1 * PAL_TIMER_TO_SEC_UNIT ) // 1 second
+#define CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD ( 50 * PAL_TIMER_TO_SEC_UNIT ) // 50 seconds, for WPA, WPA2, CCKM
+#define CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD ( 120 * PAL_TIMER_TO_SEC_UNIT ) // 120 seconds, for WPS
+/*---------------------------------------------------------------------------
+ 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)
+/*--------------------------------------------------------------------------
+ Static Type declarations
+ ------------------------------------------------------------------------*/
+static tChannelListWithPower csrRoamPowerTableFromEeprom[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+static tChannelListWithPower csrRoamPowerTableFromEeprom40MHz[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+static tCsrRoamSession csrRoamRoamSession[CSR_ROAM_SESSION_MAX];
+
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+#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:
+ n = AUTH_WPA2_EAP;
+ break;
+
+ case eCSR_AUTH_TYPE_RSN_PSK:
+ 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, tDot11fBeaconIEs *pIes);
+static tAniCBSecondaryMode 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 csrRoamStartIbssJoinTimer(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 interval);
+eHalStatus csrRoamStopIbssJoinTimer(tpAniSirGlobal pMac, tANI_U32 sessionId);
+static void csrRoamIbssJoinTimerHandler(void *pv);
+eHalStatus csrRoamStartWaitForKeyTimer(tpAniSirGlobal pMac, tANI_U32 interval);
+eHalStatus csrRoamStopWaitForKeyTimer(tpAniSirGlobal pMac);
+static void csrRoamWaitForKeyTimeOutHandler(void *pv);
+
+static eHalStatus CsrInit11dInfo(tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo);
+static eHalStatus csrRoamFreeConnectedInfo( tpAniSirGlobal pMac, tCsrRoamConnectedInfo *pConnectedInfo );
+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);
+
+static void csrRoamLinkUp(tpAniSirGlobal pMac, tCsrBssid bssid);
+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);
+
+#ifdef WLAN_SOFTAP_FEATURE
+static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile,tANI_U8 operationChn, eCsrBand *pBand );
+#else
+static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, eCsrPhyMode phyModeIn, tANI_U8 operationChn, eCsrBand *pBand );
+#endif
+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 tlStats);
+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
+extern void SysProcessMmhMsg(tpAniSirGlobal pMac, tSirMsgQ* pMsg);
+
+extern void btampEstablishLogLinkHdlr(void* pMsg);
+
+static void csrSerDesUnpackDiassocRsp(tANI_U8 *pBuf, tSirSmeDisassocRsp *pRsp);
+
+//Initialize global variables
+static void csrRoamInitGlobals(tpAniSirGlobal pMac)
+{
+ if(pMac)
+ {
+ pMac->roam.powerTableFromEeprom = csrRoamPowerTableFromEeprom;
+ pMac->roam.powerTableFromEeprom40MHz = csrRoamPowerTableFromEeprom40MHz;
+ pMac->roam.roamSession = csrRoamRoamSession;
+ }
+ return;
+}
+
+
+static void csrRoamDeInitGlobals(tpAniSirGlobal pMac)
+{
+ if(pMac)
+ {
+ pMac->roam.powerTableFromEeprom = NULL;
+ pMac->roam.powerTableFromEeprom40MHz = NULL;
+ pMac->roam.roamSession = NULL;
+ }
+ return;
+}
+
+eHalStatus csrOpen(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ static uNvTables nvTables;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+
+ v_REGDOMAIN_t regId;
+ 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;
+
+ vosStatus = vos_nv_readDefaultCountryTable( &nvTables );
+ if ( VOS_IS_STATUS_SUCCESS(vosStatus) )
+ {
+ palCopyMemory( pMac->hHdd, 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\n") );
+ //hardcoded for now
+ pMac->scan.countryCodeDefault[0] = 'U';
+ pMac->scan.countryCodeDefault[1] = 'S';
+ pMac->scan.countryCodeDefault[2] = 'I';
+ //status = eHAL_STATUS_SUCCESS;
+ }
+ smsLog( pMac, LOGE, FL(" country Code from nvRam %s\n"), pMac->scan.countryCodeDefault );
+
+ csrGetRegulatoryDomainForCountry(pMac, pMac->scan.countryCodeDefault, ®Id);
+
+ WDA_SetRegDomain(pMac, regId);
+ pMac->scan.domainIdDefault = regId;
+ pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault;
+
+ status = palCopyMemory(pMac->hHdd, pMac->scan.countryCodeCurrent,
+ pMac->scan.countryCodeDefault, WNI_CFG_COUNTRY_CODE_LEN);
+ status = csrInitGetChannels( pMac );
+
+ }while(0);
+
+ return (status);
+}
+
+
+#ifdef WLAN_SOFTAP_FEATURE
+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, LOGW, FL(" Invalid country Code Pointer\n") );
+ return eHAL_STATUS_FAILURE;
+ }
+
+ smsLog( pMac, LOGW, FL(" country Code %s\n"), 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 = strlen(apCntryCode);
+
+ status = csrGetRegulatoryDomainForCountry(pMac, apCntryCode, ®Id);
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog( pMac, LOGE, FL(" fail to get regId for country Code %s\n"), apCntryCode );
+ return status;
+ }
+
+ status = WDA_SetRegDomain(hHal, regId);
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog( pMac, LOGE, FL(" fail to get regId for country Code %s\n"), apCntryCode );
+ return status;
+ }
+
+ pMac->scan.domainIdDefault = regId;
+ pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault;
+
+ /* Clear CC field */
+ palFillMemory( pMac->hHdd,
+ pMac->scan.countryCodeDefault,
+ WNI_CFG_COUNTRY_CODE_LEN,
+ 0 );
+ /* Copy 2 or 3 bytes country code */
+ palCopyMemory( pMac->hHdd, 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)
+ {
+ palFillMemory( pMac->hHdd,
+ pMac->scan.countryCodeDefault + 2,
+ 1,
+ 0x20 );
+ }
+
+ status = palCopyMemory(pMac->hHdd, 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;
+
+ palCopyMemory( pMac->hHdd, 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;
+}
+#endif
+
+eHalStatus csrClose(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ csrStop(pMac);
+ csrRoamClose(pMac);
+ csrScanClose(pMac);
+ csrLLClose(&pMac->roam.statsClientReqList);
+ csrLLClose(&pMac->roam.peStatsReqList);
+ csrLLClose(&pMac->roam.roamCmdPendingList);
+
+ /* DeInit Globals */
+ csrRoamDeInitGlobals(pMac);
+
+ 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 \n");
+ break;
+ }
+ }while(0);
+
+#if defined(ANI_LOGDUMP)
+ csrDumpInit(pMac);
+#endif //#if defined(ANI_LOGDUMP)
+
+ return (status);
+}
+
+
+eHalStatus csrStop(tpAniSirGlobal pMac)
+{
+ tANI_U32 sessionId;
+ tANI_U32 i;
+
+ for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++)
+ {
+ csrRoamCloseSession(pMac, sessionId, 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;
+ csrResetCountryInformation(pMac, eANI_BOOLEAN_TRUE);
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ csrRoamStateChange( pMac, eCSR_ROAMING_STATE_STOP ,i );
+ pMac->roam.curSubState[i] = eCSR_ROAM_SUBSTATE_NONE;
+ }
+
+ 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);
+ /* HDD issues the init scan */
+ csrScanStartResultAgingTimer(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\n",
+ 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);
+ //Enable channel bonding at init; for 2.4 Ghz we will update this CFG at start BSS or join
+ ccmCfgSetInt(pMac, WNI_CFG_CHANNEL_BONDING_MODE, WNI_CFG_CHANNEL_BONDING_MODE_ENABLE, 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;
+
+ 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 = palTimerAlloc(pMac->hHdd, &pMac->roam.hTimerWaitForKey, csrRoamWaitForKeyTimeOutHandler,
+ &pMac->roam.WaitForKeyTimerInfo);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("cannot allocate memory for WaitForKey time out timer\n"));
+ break;
+ }
+
+ status = palTimerAlloc(pMac->hHdd, &pMac->roam.tlStatsReqInfo.hTlStatsTimer, csrRoamTlStatsTimerHandler, pMac);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("cannot allocate memory for summary Statistics timer\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+ }while (0);
+
+ return (status);
+}
+
+
+eHalStatus csrRoamClose(tpAniSirGlobal pMac)
+{
+ tANI_U32 sessionId;
+
+ for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++)
+ {
+ csrRoamCloseSession(pMac, sessionId, TRUE, NULL, NULL);
+ }
+
+ palTimerStop(pMac->hHdd, pMac->roam.hTimerWaitForKey);
+ palTimerFree(pMac->hHdd, pMac->roam.hTimerWaitForKey);
+
+ palTimerStop(pMac->hHdd, pMac->roam.tlStatsReqInfo.hTlStatsTimer);
+ palTimerFree(pMac->hHdd, pMac->roam.tlStatsReqInfo.hTlStatsTimer);
+
+ 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( 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(pProfile)
+ {
+ if(pSession->pConnectBssDesc)
+ {
+ do
+ {
+ size = pSession->pConnectBssDesc->length + sizeof(pSession->pConnectBssDesc->length);
+ if(size)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pProfile->pBssDesc, size);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palCopyMemory(pMac->hHdd, pProfile->pBssDesc, pSession->pConnectBssDesc, size);
+ }
+ 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;
+ palCopyMemory(pMac->hHdd, &pProfile->bssid, &pSession->connectedProfile.bssid, sizeof(tCsrBssid));
+ palCopyMemory(pMac->hHdd, &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_CCX
+ pProfile->isCCXAssoc = pSession->connectedProfile.isCCXAssoc;
+
+ if (csrIsAuthTypeCCX(pSession->connectedProfile.AuthType))
+ {
+ palCopyMemory( pMac->hHdd, pProfile->ccxCckmInfo.krk,
+ pSession->connectedProfile.ccxCckmInfo.krk, CSR_KRK_KEY_LEN );
+ pProfile->ccxCckmInfo.reassoc_req_num=
+ pSession->connectedProfile.ccxCckmInfo.reassoc_req_num;
+ pProfile->ccxCckmInfo.krk_plumbed =
+ pSession->connectedProfile.ccxCckmInfo.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))
+ {
+ if(pProfile)
+ {
+ status = csrRoamCopyConnectProfile(pMac, sessionId, pProfile);
+ }
+ }
+
+ return (status);
+}
+
+eHalStatus csrRoamFreeConnectProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ if(pProfile->pBssDesc)
+ {
+ palFreeMemory(pMac->hHdd, pProfile->pBssDesc);
+ }
+ palZeroMemory(pMac->hHdd, pProfile, sizeof(tCsrRoamConnectedProfile));
+ pProfile->AuthType = eCSR_AUTH_TYPE_UNKNOWN;
+ return (status);
+}
+
+
+static eHalStatus csrRoamFreeConnectedInfo( tpAniSirGlobal pMac, tCsrRoamConnectedInfo *pConnectedInfo )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ if( pConnectedInfo->pbFrames )
+ {
+ palFreeMemory( pMac->hHdd, 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_CCX
+ pConnectedInfo->nTspecIeLength = 0;
+#endif
+
+
+ return ( status );
+}
+
+
+
+
+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)
+{
+ palZeroMemory(pMac->hHdd, &pCommand->u.setKeyCmd, sizeof(tSetKeyCmd));
+}
+
+
+void csrReinitRemoveKeyCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ palZeroMemory(pMac->hHdd, &pCommand->u.removeKeyCmd, sizeof(tRemoveKeyCmd));
+}
+
+
+void csrReleaseCommandSetKey(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ csrReinitSetKeyCmd(pMac, pCommand);
+ csrReleaseCommand( pMac, pCommand );
+}
+
+void csrReleaseCommandRemoveKey(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ csrReinitRemoveKeyCmd(pMac, pCommand);
+ csrReleaseCommand( pMac, pCommand );
+}
+
+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 droping the scan command
+ smsLog( pMac, LOGW, "%s: Drop scan reason %d callback 0x%X\n",
+ __FUNCTION__, pCommand->u.scanCmd.reason, (unsigned int)pCommand->u.scanCmd.callback);
+ if (NULL != pCommand->u.scanCmd.callback)
+ {
+ smsLog( pMac, LOGW, "%s callback scan requester\n", __FUNCTION__);
+ 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\n", pCommand->command );
+ csrReleaseCommand( pMac, pCommand );
+ break;
+ }
+ }
+}
+
+
+
+void csrRoamSubstateChange( tpAniSirGlobal pMac, eCsrRoamSubState NewSubstate, tANI_U32 sessionId)
+{
+ smsLog( pMac, LOG1, " CSR RoamSubstate: [ %d <== %d ]\n", NewSubstate, pMac->roam.curSubState[sessionId]);
+
+
+ if(pMac->roam.curSubState[sessionId] == NewSubstate)
+ {
+ return;
+ }
+ pMac->roam.curSubState[sessionId] = NewSubstate;
+}
+
+
+eCsrRoamState csrRoamStateChange( tpAniSirGlobal pMac, eCsrRoamState NewRoamState, tANI_U8 sessionId)
+{
+ eCsrRoamState PreviousState;
+
+ smsLog( pMac, LOG1, "CSR RoamState: [ %d <== %d ]\n", NewRoamState, 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_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)CSR_BEST_RSSI_VALUE - (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_FALSE;
+ 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_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.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.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
+#endif
+
+ pMac->roam.configParam.addTSWhenACMIsOff = 0;
+ pMac->roam.configParam.fScanTwice = eANI_BOOLEAN_FALSE;
+}
+
+eCsrBand csrGetCurrentBand(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ return pMac->roam.configParam.bandCapability;
+}
+
+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\n",
+ 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\n",
+ 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)\n", eBand);
+ pMac->roam.configParam.eBand = eBand;
+ pMac->roam.configParam.bandCapability = eBand;
+ csrScanGetSupportedChannels( pMac );
+ status = csrInitGetChannels( pMac );
+ if (eHAL_STATUS_SUCCESS == status)
+ csrInitChannelList( hHal );
+ return status;
+}
+
+eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ 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.channelBondingMode24GHz = pParam->channelBondingMode24GHz;
+ pMac->roam.configParam.channelBondingMode5GHz = 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;
+
+ //if HDD passed down non zero values then only update,
+ //otherwise keep using the defaults
+ if(pParam->nActiveMaxChnTime)
+ {
+ pMac->roam.configParam.nActiveMaxChnTime = pParam->nActiveMaxChnTime;
+ }
+ if(pParam->nActiveMinChnTime)
+ {
+ pMac->roam.configParam.nActiveMinChnTime = pParam->nActiveMinChnTime;
+ }
+ if(pParam->nPassiveMaxChnTime)
+ {
+ pMac->roam.configParam.nPassiveMaxChnTime = pParam->nPassiveMaxChnTime;
+ }
+ if(pParam->nPassiveMinChnTime)
+ {
+ pMac->roam.configParam.nPassiveMinChnTime = pParam->nPassiveMinChnTime;
+ }
+ //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;
+#ifdef WLAN_SOFTAP_FEATURE
+ pMac->roam.configParam.uCfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(NULL, pMac->roam.configParam.phyMode,
+ pMac->roam.configParam.ProprietaryRatesEnabled);
+#else
+ pMac->roam.configParam.uCfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(pMac->roam.configParam.phyMode,
+ pMac->roam.configParam.ProprietaryRatesEnabled);
+#endif
+ //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;
+ }
+
+ csrAssignRssiForCategory(pMac, 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;
+ }
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ palCopyMemory( pMac->hHdd, &pMac->roam.configParam.csr11rConfig, &pParam->csr11rConfig, sizeof(tCsr11rConfigParams) );
+ smsLog( pMac, LOG1, "IsFTResourceReqSupp = %d\n", pMac->roam.configParam.csr11rConfig.IsFTResourceReqSupported);
+#endif
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ pMac->roam.configParam.isFastTransitionEnabled = pParam->isFastTransitionEnabled;
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+ pMac->roam.configParam.isCcxIniFeatureEnabled = pParam->isCcxIniFeatureEnabled;
+#endif
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ palCopyMemory( pMac->hHdd, &pMac->roam.configParam.neighborRoamConfig, &pParam->neighborRoamConfig, sizeof(tCsrNeighborRoamConfigParams) );
+
+ smsLog( pMac, LOG1, "nNeighborScanTimerPerioid = %d\n", pMac->roam.configParam.neighborRoamConfig.nNeighborScanTimerPeriod);
+ smsLog( pMac, LOG1, "nNeighborReassocRssiThreshold = %d\n", pMac->roam.configParam.neighborRoamConfig.nNeighborReassocRssiThreshold);
+ smsLog( pMac, LOG1, "nNeighborLookupRssiThreshold = %d\n", pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold);
+ smsLog( pMac, LOG1, "nNeighborScanMinChanTime = %d\n", pMac->roam.configParam.neighborRoamConfig.nNeighborScanMinChanTime);
+ smsLog( pMac, LOG1, "nNeighborScanMaxChanTime = %d\n", pMac->roam.configParam.neighborRoamConfig.nNeighborScanMaxChanTime);
+ smsLog( pMac, LOG1, "nMaxNeighborRetries = %d\n", pMac->roam.configParam.neighborRoamConfig.nMaxNeighborRetries);
+ smsLog( pMac, LOG1, "nNeighborResultsRefreshPeriod = %d\n", pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod);
+
+ {
+ int i;
+ smsLog( pMac, LOG1, FL("Num of Channels in CFG Channel List: %d\n"), 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] );
+ }
+ smsLog( pMac, LOG1, "\n");
+ }
+#endif
+
+ pMac->roam.configParam.addTSWhenACMIsOff = pParam->addTSWhenACMIsOff;
+ pMac->scan.fValidateList = pParam->fValidateList;
+ pMac->scan.fEnableBypass11d = pParam->fEnableBypass11d;
+ pMac->scan.fEnableDFSChnlScan = pParam->fEnableDFSChnlScan;
+ pMac->roam.configParam.fScanTwice = pParam->fScanTwice;
+ }
+
+ return status;
+}
+
+
+eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+
+ 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 = pMac->roam.configParam.channelBondingMode24GHz;
+ pParam->channelBondingMode5GHz = 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;
+
+ //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->fScanTwice = pMac->roam.configParam.fScanTwice;
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ palCopyMemory( pMac->hHdd, &pParam->neighborRoamConfig, &pMac->roam.configParam.neighborRoamConfig, sizeof(tCsrNeighborRoamConfigParams) );
+#endif
+
+ csrSetChannels(pMac, pParam);
+
+ 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\n"), 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 )
+ {
+ palZeroMemory( pMac->hHdd, &pChannelList->channelList[ cChannels ],
+ sizeof( pChannelList->channelList[ 0 ] ) * ( pChannelList->numChannels - cChannels ) );
+
+ }
+
+ 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 )
+ {
+ palZeroMemory( pMac->hHdd, &pChannelList->channelList[ cChannels ],
+ sizeof( pChannelList->channelList[ 0 ] ) * ( pChannelList->numChannels - cChannels ) );
+ }
+
+ pChannelList->numChannels = cChannels;
+ }
+ }
+
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+#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;
+}
+#endif
+
+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 \n"));
+ 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++)
+ {
+#ifdef FEATURE_WLAN_INTEGRATED_SOC /* Need to fix this while dealing with NV item */
+ pMac->scan.base20MHzChannels.channelList[ Index ] = pMac->scan.defaultPowerTable[ Index ].chanId;
+#else
+ pMac->scan.base20MHzChannels.channelList[ Index ] = Index + 1;
+ pMac->scan.defaultPowerTable[Index].chanId = Index + 1;
+ pMac->scan.defaultPowerTable[Index].pwr = 25;
+#endif
+ }
+ 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);
+ // Apply the base channel list, power info, and set the Country code...
+ csrApplyChannelPowerCountryInfo( pMac, &pMac->scan.base20MHzChannels, pMac->scan.countryCodeCurrent );
+
+ 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;
+
+ if(!ps11dinfo)
+ {
+ return (status);
+ }
+
+ if ( ps11dinfo->Channels.numChannels && ( WNI_CFG_VALID_CHANNEL_LIST_LEN >= ps11dinfo->Channels.numChannels ) )
+ {
+ pMac->scan.base20MHzChannels.numChannels = ps11dinfo->Channels.numChannels;
+ status = palCopyMemory(pMac->hHdd, pMac->scan.base20MHzChannels.channelList,
+ ps11dinfo->Channels.channelList, ps11dinfo->Channels.numChannels);
+ if(!HAL_STATUS_SUCCESS(status)) return (status);
+ }
+ else
+ {
+ //No change
+ return (eHAL_STATUS_SUCCESS);
+ }
+
+ //legacy maintenance
+ status = palCopyMemory(pMac->hHdd, pMac->scan.countryCodeDefault,
+ ps11dinfo->countryCode, WNI_CFG_COUNTRY_CODE_LEN);
+ if(!HAL_STATUS_SUCCESS(status)) return (status);
+
+ //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])
+ {
+ status = palCopyMemory(pMac->hHdd, pMac->scan.countryCodeCurrent,
+ ps11dinfo->countryCode, WNI_CFG_COUNTRY_CODE_LEN);
+ if(!HAL_STATUS_SUCCESS(status)) return (status);
+ }
+
+ // need to add the max power channel list
+ if(HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd, (void **)&pChanInfo, sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN)))
+ {
+ palZeroMemory(pMac->hHdd, pChanInfo, sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN);
+ 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 );
+ }
+ palFreeMemory(pMac->hHdd, 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 );
+ }
+
+ }
+
+ return (status);
+}
+
+//pCommand may be NULL
+//Pass in sessionId in case pCommand is NULL. sessionId is not used in case pCommand is not NULL.
+void csrRoamRemoveDuplicateCommand(tpAniSirGlobal pMac, tANI_U32 sessionId, 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( &pMac->sme.smeCmdPendingList );
+ pEntry = csrLLPeekHead( &pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK );
+ while( pEntry )
+ {
+ pNextEntry = csrLLNext( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK );
+ pDupCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+
+ // Remove the previous command if..
+ // - the new roam command is for the same RoamReason...
+ // - the new roam command is a NewProfileList.
+ // - the new roam command is a Forced Dissoc
+ // - the new roam command is from an 802.11 OID (OID_SSID or OID_BSSID).
+ if (
+ (pCommand && ( pCommand->sessionId == pDupCommand->sessionId ) &&
+ ((pCommand->command == pDupCommand->command) &&
+ (pCommand->u.roamCmd.roamReason == pDupCommand->u.roamCmd.roamReason ||
+ eCsrForcedDisassoc == pCommand->u.roamCmd.roamReason ||
+ eCsrHddIssued == pCommand->u.roamCmd.roamReason)))
+ ||
+ //below the pCommand is NULL
+ ( (sessionId == pDupCommand->sessionId) && (eCsrRoamCommandRoam == pDupCommand->command) &&
+ ((eCsrForcedDisassoc == eRoamReason) ||
+ (eCsrHddIssued == eRoamReason))
+ )
+ )
+ {
+ smsLog(pMac, LOGW, FL(" roamReason = %d\n"), pDupCommand->u.roamCmd.roamReason);
+ // Remove the 'stale' roam command from the pending list...
+ if(csrLLRemoveEntry( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK ))
+ {
+ csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK);
+ }
+ }
+ pEntry = pNextEntry;
+ }
+ csrLLUnlock( &pMac->sme.smeCmdPendingList );
+
+ 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);
+}
+
+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;
+
+ if( CSR_IS_SESSION_VALID( pMac, sessionId) )
+ {
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "Session ID:%d is not valid\n", sessionId);
+ VOS_ASSERT(0);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if(eCSR_ROAM_ASSOCIATION_COMPLETION == u1 && pRoamInfo)
+ {
+ smsLog(pMac, LOGW, " Assoc complete result = %d statusCode = %d reasonCode = %d\n", u2, pRoamInfo->statusCode, pRoamInfo->reasonCode);
+ }
+
+ if ( (pSession == NULL) ||
+ (eANI_BOOLEAN_FALSE == pSession->sessionActive) )
+ {
+ smsLog(pMac, LOG1, "Session ID is not valid\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ 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: eCSR_ROAM_ASSOCIATION_COMPLETION,
+ // eCSR_ROAM_LOSTLINK, eCSR_ROAM_DISASSOCIATED,
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ palZeroMemory(pMac->hHdd, &connectionStatus, sizeof(vos_event_wlan_status_payload_type));
+ if((eCSR_ROAM_ASSOCIATION_COMPLETION == u1) && (eCSR_ROAM_RESULT_ASSOCIATED == u2))
+ {
+ 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);
+ palCopyMemory(pMac->hHdd, connectionStatus.ssid, pRoamInfo->u.pConnectedProfile->SSID.ssId, 6);
+ connectionStatus.reason = eCSR_REASON_UNSPECIFIED;
+ WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+#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 );
+
+ //Restore AC weight in case we change it
+ if ( csrIsConnStateConnectedInfra( pMac, sessionId ) )
+ {
+ smsLog(pMac, LOGE, FL(" restore AC weights (%d-%d-%d-%d)\n"), 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;
+ palCopyMemory(pMac->hHdd, &bssId, pNeighborRoamInfo->csrNeighborRoamProfile.BSSIDs.bssid, sizeof(tSirMacAddr));
+
+ } else
+#endif
+ if(pSession->pConnectBssDesc)
+ {
+ palCopyMemory(pMac->hHdd, &bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid));
+ }
+
+
+ smsLog( pMac, LOGE, "CSR Attempting to Disassociate Bssid= %02x-%02x-%02x-%02x-%02x-%02x subState = %d\n",
+ bssId[ 0 ], bssId[ 1 ], bssId[ 2 ],
+ bssId[ 3 ], bssId[ 4 ], bssId[ 5 ], NewSubstate );
+
+ 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)
+ {
+ //Tush-QoS: notify QoS module that disassoc happening
+ sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_DISCONNECT_REQ, NULL);
+ }
+#endif
+ }
+
+ return (status);
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+
+
+
+/* ---------------------------------------------------------------------------
+ \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,
+ tANI_U8 *pPeerMacAddr,
+ 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\n"), 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 pPeerMacAddr - MAC of associated station to delete
+ \param reason - reason code, be one of the tSirMacReasonCodes
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus csrRoamIssueDeauthStaCmd( tpAniSirGlobal pMac,
+ tANI_U32 sessionId,
+ tANI_U8 *pPeerMacAddr,
+ 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 = eCsrForcedDeauthSta;
+ 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\n"), 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\n");
+ return (status);
+ }
+
+ if (pSession->pConnectBssDesc)
+ {
+ palCopyMemory(pMac->hHdd, &bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid));
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "csrRoamIssueTkipCounterMeasures:Connected BSS Description in CSR Session not found\n");
+ return (status);
+ }
+
+ smsLog( pMac, LOG2, "CSR issuing tkip counter measures for Bssid = %02x-%02x-%02x-%02x-%02x-%02x, Enable = %d\n",
+ bssId[ 0 ], bssId[ 1 ], bssId[ 2 ],
+ bssId[ 3 ], bssId[ 4 ], bssId[ 5 ] , 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\n");
+ return (status);
+ }
+
+ if(pSession->pConnectBssDesc)
+ {
+ palCopyMemory( pMac->hHdd, &bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid) );
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "csrRoamGetAssociatedStas:Connected BSS Description in CSR Session not found\n");
+ return (status);
+ }
+
+ smsLog( pMac, LOG2, "CSR getting associated stations for Bssid = %02x-%02x-%02x-%02x-%02x-%02x\n",
+ bssId[ 0 ], bssId[ 1 ], bssId[ 2 ],
+ bssId[ 3 ], bssId[ 4 ], bssId[ 5 ] );
+
+ 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\n");
+ return (status);
+ }
+
+ if(pSession->pConnectBssDesc)
+ {
+ palCopyMemory( pMac->hHdd, &bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid) );
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "csrRoamGetWpsSessionOverlap:Connected BSS Description in CSR Session not found\n");
+ return (status);
+ }
+
+ smsLog( pMac, LOG2, "CSR getting WPS Session Overlap for Bssid = %02x-%02x-%02x-%02x-%02x-%02x\n",
+ bssId[ 0 ], bssId[ 1 ], bssId[ 2 ],
+ bssId[ 3 ], bssId[ 4 ], bssId[ 5 ] );
+
+ status = csrSendMBGetWPSPBCSessions( pMac, sessionId, bssId, pUsrContext, pfnSapEventCallback, pRemoveMac);
+
+ return (status);
+}
+
+#endif
+
+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->pConnectBssDesc)
+ {
+ palCopyMemory(pMac->hHdd, &bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid));
+ }
+
+ smsLog( pMac, LOG2, "CSR Attempting to Deauth Bssid= %02x-%02x-%02x-%02x-%02x-%02x\n",
+ bssId[ 0 ], bssId[ 1 ], bssId[ 2 ],
+ bssId[ 3 ], bssId[ 4 ], bssId[ 5 ] );
+
+ csrRoamSubstateChange( pMac, NewSubstate, sessionId);
+
+ status = csrSendMBDeauthReqMsg( pMac, sessionId, bssId, eSIR_MAC_DISASSOC_LEAVING_BSS_REASON );
+
+ 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 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)
+ {
+ status = palAllocateMemory( pMac->hHdd, (void **)&pSession->pConnectBssDesc, size);
+ }
+ if ( HAL_STATUS_SUCCESS(status) && pSession->pConnectBssDesc )
+ {
+ palCopyMemory( pMac->hHdd, 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;
+
+#if defined(VOSS_ENABLED)
+ VOS_ASSERT( pIes != NULL );
+#endif
+
+ do
+ {
+ palCopyMemory(pMac->hHdd, &pBssConfig->BssCap, &pBssDesc->capabilityInfo, sizeof(tSirMacCapabilityInfo));
+ //get qos
+ pBssConfig->qosType = csrGetQoSFromBssDesc(pMac, pBssDesc, pIes);
+ //get SSID
+ if(pIes->SSID.present)
+ {
+ palCopyMemory(pMac->hHdd, &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\n");
+ //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\n");
+ 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\n");
+ //force it
+ if(eCSR_BAND_24 == pBssConfig->eBand)
+ {
+ pBssConfig->uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
+ }
+ else
+ {
+ pBssConfig->uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
+ }
+ }
+
+ //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;
+ }
+
+ //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;
+ }
+ //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 x the 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);
+ }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
+ palCopyMemory(pMac->hHdd, &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];
+ }
+
+#ifdef WLAN_SOFTAP_FEATURE
+ pBssConfig->uCfgDot11Mode = csrRoamGetPhyModeBandForBss(pMac, pProfile, operationChannel,
+ &pBssConfig->eBand);
+#else
+
+ pBssConfig->uCfgDot11Mode = csrRoamGetPhyModeBandForBss(pMac, (eCsrPhyMode)pProfile->phyMode, operationChannel,
+ &pBssConfig->eBand);
+#endif
+ //QOS
+ //Is this correct to always set to this //***
+
+ if ( pBssConfig->BssCap.ess == 1 )
+ {
+#ifdef WLAN_SOFTAP_FEATURE
+ /*For Softap case enable WMM*/
+ if(CSR_IS_INFRA_AP(pProfile) && (eCsrRoamWmmNoQos != pMac->roam.configParam.WMMSupportMode )){
+ qAPisEnabled = TRUE;
+ }
+ else
+#endif
+ 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 prefered 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;
+ }
+ //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\n");
+
+ break;
+ }
+ //check if the AP is QAP & it supports APSD
+ if( CSR_IS_QOS_BSS(pIes) )
+ {
+ return eHAL_STATUS_SUCCESS;
+ }
+ } while (0);
+
+ 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:
+
+ // 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] )
+ {
+ palCopyMemory( pMac->hHdd, 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] )
+ {
+ palCopyMemory( pMac->hHdd, 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] )
+ {
+ palCopyMemory( pMac->hHdd, 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] )
+ {
+ palCopyMemory( pMac->hHdd, 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:
+
+ // 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] )
+ {
+ palCopyMemory( pMac->hHdd, 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] )
+ {
+ palCopyMemory( pMac->hHdd, 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] )
+ {
+ palCopyMemory( pMac->hHdd, 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] )
+ {
+ palCopyMemory( pMac->hHdd, 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_WEP40:
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ 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;
+
+ status = ccmCfgSetInt(pMac, WNI_CFG_QOS_ENABLED, QoSEnabled, NULL, eANI_BOOLEAN_FALSE);
+ status = ccmCfgSetInt(pMac, WNI_CFG_WME_ENABLED, WmeEnabled, NULL, eANI_BOOLEAN_FALSE);
+
+ return (status);
+}
+
+static eHalStatus csrGetRateSet( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, eCsrPhyMode phyMode, tSirBssDescription *pBssDesc,
+ tDot11fBeaconIEs *pIes, tSirMacRateSet *pOpRateSet, tSirMacRateSet *pExRateSet)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ int i;
+ eCsrCfgDot11Mode cfgDot11Mode;
+ tANI_U8 *pDstRate;
+
+ palZeroMemory(pMac->hHdd, pOpRateSet, sizeof(tSirMacRateSet));
+ palZeroMemory(pMac->hHdd, pExRateSet, sizeof(tSirMacRateSet));
+
+#if defined(VOSS_ENABLED)
+ VOS_ASSERT( pIes != NULL );
+#endif
+
+ 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 ] ) )
+ {
+ *pDstRate++ = pIes->SuppRates.rates[ i ];
+ pOpRateSet->numRates++;;
+ }
+ }
+ }
+
+ 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 = pExRateSet->rate;
+ if(pIes->ExtSuppRates.present)
+ {
+ for ( i = 0; i < pIes->ExtSuppRates.num_rates; i++ )
+ {
+ if ( csrRatesIsDot11RateSupported( pMac, pIes->ExtSuppRates.rates[ i ] ) )
+ {
+ *pDstRate++ = pIes->ExtSuppRates.rates[ i ];
+ pExRateSet->numRates++;
+ }
+ }
+ }
+ }
+ }//Parsing BSSDesc
+ else
+ {
+ smsLog(pMac, LOGE, FL("failed to parse BssDesc\n"));
+ }
+ 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;
+
+#if defined(VOSS_ENABLED)
+ VOS_ASSERT( pIes != NULL );
+#endif
+
+ 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);
+ }
+ palCopyMemory( pMac->hHdd, 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\n"));
+ }
+}
+
+
+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];
+ }
+
+#ifdef WLAN_SOFTAP_FEATURE
+ cfgDot11Mode = csrRoamGetPhyModeBandForBss( pMac, pProfile, operationChannel, &eBand );
+#else
+ cfgDot11Mode = csrRoamGetPhyModeBandForBss( pMac, (eCsrPhyMode)pProfile->phyMode, operationChannel, &eBand );
+#endif
+ // 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);
+ palCopyMemory( pMac->hHdd, 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);
+ palCopyMemory( pMac->hHdd, 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);
+ palCopyMemory( pMac->hHdd, 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);
+ palCopyMemory( pMac->hHdd, OperationalRates,
+ DefaultSupportedRates11b.supportedRateSet.rate,
+ OperationalRatesLength );
+
+ // 11a rates go in the Extended rate set.
+ ExtendedOperationalRatesLength = DefaultSupportedRates11a.supportedRateSet.numRates *
+ sizeof(*DefaultSupportedRates11a.supportedRateSet.rate);
+ palCopyMemory( pMac->hHdd, ExtendedOperationalRates,
+ DefaultSupportedRates11a.supportedRateSet.rate,
+ ExtendedOperationalRatesLength );
+
+ // populate proprietary rates if user allows them
+ if ( pMac->roam.configParam.ProprietaryRatesEnabled )
+ {
+ ProprietaryOperationalRatesLength = DefaultSupportedPropRates.numPropRates *
+ sizeof(*DefaultSupportedPropRates.propRate);
+ palCopyMemory( pMac->hHdd, 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\n");
+ return;
+ }
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ sessionId = pCommand->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);
+}
+
+
+//pIes may be NULL
+eHalStatus csrRoamSetBssConfigCfg(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tSirBssDescription *pBssDesc, tBssConfigParam *pBssConfig,
+ tDot11fBeaconIEs *pIes)
+{
+ 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;
+ csrApplyCountryInformation( pMac, TRUE );
+ }
+ }
+
+ //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);
+
+#ifdef WLAN_SOFTAP_FEATURE
+ //11d
+ ccmCfgSetInt(pMac, WNI_CFG_11D_ENABLED,
+ ((pBssConfig->f11hSupport) ? pBssConfig->f11hSupport : pProfile->ieee80211d),
+ NULL, eANI_BOOLEAN_FALSE);
+#endif
+ /*//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))
+ {
+ channel = pProfile->operationChannel;
+ }
+ else
+ {
+ if(pBssDesc)
+ {
+ channel = pBssDesc->channelId;
+ }
+ }
+ if(0 != channel)
+ {
+ if(CSR_IS_CHANNEL_24GHZ(channel))
+ {//for now if we are on 2.4 Ghz, CB will be always disabled
+ cfgCb = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
+ }
+ else
+ {
+ //cfgCb = pBssConfig->cbMode;
+ cfgCb = pMac->roam.configParam.channelBondingMode5GHz;
+ }
+ }
+ 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 );
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pBssConfig, sizeof(tBssConfigParam));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pBssConfig, sizeof(tBssConfigParam));
+ status = csrRoamPrepareBssConfig(pMac, pProfile, pBssDesc, pBssConfig, pIes);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ pSession->bssParams.uCfgDot11Mode = pBssConfig->uCfgDot11Mode;
+ //For IBSS, we need to prepare some more information
+ if( csrIsBssTypeIBSS(pProfile->BSSType) || CSR_IS_WDS( pProfile )
+#ifdef WLAN_SOFTAP_FEATURE
+ || CSR_IS_INFRA_AP(pProfile)
+#endif
+ )
+ {
+ csrRoamPrepareBssParams(pMac, sessionId, pProfile, pBssDesc, 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);
+ }
+ }
+ }
+ 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 )
+#ifdef WLAN_SOFTAP_FEATURE
+ || CSR_IS_INFRA_AP(pProfile)
+#endif
+ )
+ {
+ // Set parameters for this Bss.
+ status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile, pBssDesc, pBssConfig, pIes);
+ }
+ }
+ }
+ }//Success getting BSS config info
+ palFreeMemory(pMac->hHdd, 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( 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 authType = %d encryType = %d\n"), pProfile->AuthType, pProfile->EncryptionType);
+ if(csrRoamIsSameProfileKeys(pMac, &pSession->connectedProfile, pProfile))
+ {
+ eRoamState = eCsrReassocToSelfNoCapChange;
+ }
+ else
+ {
+ tBssConfigParam bssConfig;
+
+ //The key changes
+ palZeroMemory(pMac->hHdd, &bssConfig, sizeof(bssConfig));
+ status = csrRoamPrepareBssConfig(pMac, pProfile, pBssDesc, &bssConfig, pIesLocal);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ pSession->bssParams.uCfgDot11Mode = bssConfig.uCfgDot11Mode;
+ //Reapply the config including Keys so reassoc is happening.
+ status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile, pBssDesc, &bssConfig, pIesLocal);
+ 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, LOGW, FL(" fail to issue disassociate\n"));
+ eRoamState = eCsrStopRoaming;
+ }
+ }
+ }
+ else
+ {
+ // note: we used to pre-auth here with open authentication networks but that was not working so well.
+ // we had a lot of join timeouts when testing at Samsung. removing this step helped associations
+ // work much better.
+ //
+ //
+ // 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 )
+ {
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+ }
+
+ return( eRoamState );
+}
+
+
+eHalStatus csrRoamShouldRoam(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tSirBssDescription *pBssDesc, tANI_U32 roamId)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tCsrRoamInfo roamInfo;
+
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ 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 prefered 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;
+ }
+ 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 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;
+
+ do
+ {
+ // Check for Cardbus eject condition, before trying to Roam to any BSS
+ //***if( !balIsCardPresent(pAdapter) ) break;
+
+ 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.
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ 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_sessions_running() && !csrIsValidMcConcurrentSession(pMac, sessionId))
+ {
+ concurrentChannel =
+ csrGetConcurrentOperationChannel(pMac);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, "%s: "
+ " csr Concurrent Channel = %d", __FUNCTION__, 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 ((vos_concurrent_sessions_running()) &&
+ csrIsAnySessionInConnectState( pMac ))
+ {
+ pMac->roam.configParam.concurrencyEnabled = 1;
+ }
+
+ if (!concurrentChannel)
+ {
+
+ if(HAL_STATUS_SUCCESS(csrRoamShouldRoam(pMac,
+ sessionId, &pScanResult->Result.BssDescriptor,
+ pCommand->u.roamCmd.roamId)))
+ {
+ //Ok to roam this
+ break;
+ }
+ }
+ 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)
+ {
+ 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);
+ }
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(roamInfo));
+ 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\n"));
+ 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);
+ pCommand->u.roamCmd.roamProfile.uapsd_mask &= ~(acm_mask);
+#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
+
+ }
+ else
+ {
+ pCommand->u.roamCmd.roamProfile.uapsd_mask = 0;
+ }
+ if( pIesLocal && !pScanResult->Result.pvIes)
+ {
+ palFreeMemory(pMac->hHdd, 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))
+#ifdef WLAN_SOFTAP_FEATURE
+ || (CSR_IS_INFRA_AP(pProfile))
+#endif
+ )
+ {
+ // 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\n"));
+ 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);
+ 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
+ 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;
+
+ smsLog(pMac, LOG2, FL("is called\n"));
+ //***if( hddIsRadioStateOn( pAdapter ) )
+ {
+ // Attept to join a Bss...
+ RoamState = csrRoamJoinNextBss( pMac, pCommand, eANI_BOOLEAN_FALSE );
+
+ // if nothing to join..
+ if ( eCsrStopRoaming == 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\n"), 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\n"), status);
+ //roam command is completed by caller in the failed case
+ fComplete = eANI_BOOLEAN_TRUE;
+ }
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ 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\n"), status);
+ //roam command is completed by caller in the failed case
+ fComplete = eANI_BOOLEAN_TRUE;
+ }
+ }
+#endif
+ else
+ {
+ fComplete = eANI_BOOLEAN_TRUE;
+ }
+ if(fComplete)
+ {
+ // ... otherwise, we can complete the Roam command here.
+ 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;
+ tCsrScanResult *pScanResult = NULL;
+ tSirBssDescription *pBssDesc = NULL;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ sessionId = pCommand->sessionId;
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ if(CSR_IS_ROAMING(pSession) && pSession->fCancelRoaming)
+ {
+ //the roaming is cancelled. Simply complete the command
+ smsLog(pMac, LOG1, FL(" Roam command cancelled\n"));
+ 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\n"));
+ 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 );
+
+ switch ( pCommand->u.roamCmd.roamReason )
+ {
+ case eCsrForcedDisassoc:
+ csrFreeRoamProfile(pMac, sessionId);
+ status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, FALSE );
+ 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:
+ csrFreeRoamProfile(pMac, sessionId);
+ status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, TRUE );
+ break;
+
+ case eCsrForcedDeauth:
+ csrFreeRoamProfile(pMac, sessionId);
+ status = csrRoamProcessDisassocDeauth( pMac, pCommand, FALSE, FALSE );
+ 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\n"));
+ }
+ 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\n"));
+ csrRoamIssueReassociate( pMac, sessionId, pSession->pConnectBssDesc, pIes,
+ &pCommand->u.roamCmd.roamProfile );
+ palFreeMemory(pMac->hHdd, pIes);
+ pIes = NULL;
+ }
+ }
+ break;
+ }
+
+ case eCsrCapsChange:
+ smsLog(pMac, LOGE, FL("received eCsrCapsChange \n"));
+ csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId );
+ status = csrRoamIssueDisassociate( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, FALSE);
+ break;
+
+ case eCsrSmeIssuedFTReassoc:
+ smsLog(pMac, LOGE, FL("received FT Reassoc Req \n"));
+ 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;
+
+ default:
+ csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId );
+
+ if( pCommand->u.roamCmd.fUpdateCurRoamProfile )
+ {
+ //Remember the roaming profile
+ csrFreeRoamProfile(pMac, sessionId);
+ if(HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd, (void **)&pSession->pCurRoamProfile, sizeof(tCsrRoamProfile))))
+ {
+ palZeroMemory(pMac->hHdd, pSession->pCurRoamProfile, sizeof(tCsrRoamProfile));
+ 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 );
+ break;
+ }
+
+ return (status);
+}
+
+
+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
+ palZeroMemory(pMac->hHdd, &pCommand->u.roamCmd, sizeof(tRoamCmd));
+}
+
+
+void csrReinitWmStatusChangeCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ palZeroMemory(pMac->hHdd, &pCommand->u.wmStatusChangeCmd, sizeof(tWmStatusChangeCmd));
+}
+
+void csrRoamComplete( tpAniSirGlobal pMac, eCsrRoamCompleteResult Result, void *Context )
+{
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+ tANI_BOOLEAN fReleaseCommand = eANI_BOOLEAN_TRUE;
+
+ smsLog( pMac, LOG2, "roamQ: Roam Completion ...\n" );
+
+ 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\n",
+ pCommand->u.roamCmd.roamReason );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGE, " **********csrRoamComplete fail to release command reason %d\n",
+ pCommand->u.roamCmd.roamReason );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: Roam Completion called but ROAM command is not ACTIVE ...\n" );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: Roam Completion called but NO commands are ACTIVE ...\n" );
+ }
+
+ if( fReleaseCommand )
+ {
+ smeProcessPendingQueue( pMac );
+ }
+}
+
+
+void csrResetPMKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ palZeroMemory( pMac->hHdd, &(pSession->PmkidCandidateInfo[0]), sizeof(tPmkidCandidateInfo) * CSR_MAX_PMKID_ALLOWED );
+ pSession->NumPmkidCandidate = 0;
+}
+
+#ifdef FEATURE_WLAN_WAPI
+void csrResetBKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+ palZeroMemory( pMac->hHdd, &(pSession->BkidCandidateInfo[0]), sizeof(tBkidCandidateInfo) * CSR_MAX_BKID_ALLOWED );
+ pSession->NumBkidCandidate = 0;
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+extern tANI_U8 csrWpaOui[][ CSR_WPA_OUI_SIZE ];
+
+
+
+static 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((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 */
+ )
+ {
+
+ if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) )
+ {
+ smsLog(pMac, LOGE, FL(" cannot parse IEs\n"));
+ }
+ 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 */
+ (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_count * 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
+ if(HAL_STATUS_SUCCESS((status = palAllocateMemory(pMac->hHdd, (void **)&pSession->pWpaRsnRspIE, nIeLen + 2))))
+ {
+ pSession->pWpaRsnRspIE[0] = DOT11F_EID_RSN;
+ pSession->pWpaRsnRspIE[1] = (tANI_U8)nIeLen;
+ //copy upto akm_suites
+ pIeBuf = pSession->pWpaRsnRspIE + 2;
+ palCopyMemory(pMac->hHdd, pIeBuf, &pIesLocal->RSN.version, 8);
+ pIeBuf += 8;
+ if( pIesLocal->RSN.pwise_cipher_suite_count )
+ {
+ //copy pwise_cipher_suites
+ palCopyMemory(pMac->hHdd, pIeBuf, pIesLocal->RSN.pwise_cipher_suites,
+ pIesLocal->RSN.pwise_cipher_suite_count * 4);
+ pIeBuf += pIesLocal->RSN.pwise_cipher_suite_count * 4;
+ }
+ palCopyMemory(pMac->hHdd, pIeBuf, &pIesLocal->RSN.akm_suite_count, 2);
+ pIeBuf += 2;
+ if( pIesLocal->RSN.akm_suite_count )
+ {
+ //copy akm_suites
+ palCopyMemory(pMac->hHdd, pIeBuf, pIesLocal->RSN.akm_suites,
+ pIesLocal->RSN.akm_suite_count * 4);
+ pIeBuf += pIesLocal->RSN.akm_suite_count * 4;
+ }
+ //copy the rest
+ palCopyMemory(pMac->hHdd, pIeBuf, pIesLocal->RSN.akm_suites +
+ pIesLocal->RSN.akm_suite_count * 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
+ if(HAL_STATUS_SUCCESS((status = palAllocateMemory(pMac->hHdd, (void **)&pSession->pWpaRsnRspIE, nIeLen + 2))))
+ {
+ pSession->pWpaRsnRspIE[0] = DOT11F_EID_WPA;
+ pSession->pWpaRsnRspIE[1] = (tANI_U8)nIeLen;
+ pIeBuf = pSession->pWpaRsnRspIE + 2;
+ //Copy WPA OUI
+ palCopyMemory(pMac->hHdd, pIeBuf, &csrWpaOui[1], 4);
+ pIeBuf += 4;
+ palCopyMemory(pMac->hHdd, pIeBuf, &pIesLocal->WPA.version, 8 +
+ pIesLocal->WPA.unicast_cipher_count * 4);
+ pIeBuf += 8 + pIesLocal->WPA.unicast_cipher_count * 4;
+ palCopyMemory(pMac->hHdd, 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
+ if(HAL_STATUS_SUCCESS((status = palAllocateMemory(pMac->hHdd, (void **)&pSession->pWapiRspIE, nIeLen + 2))))
+ {
+ pSession->pWapiRspIE[0] = DOT11F_EID_WAPI;
+ pSession->pWapiRspIE[1] = (tANI_U8)nIeLen;
+ pIeBuf = pSession->pWapiRspIE + 2;
+ //copy upto akm_suite_count
+ palCopyMemory(pMac->hHdd, pIeBuf, &pIesLocal->WAPI.version, 4);
+ pIeBuf += 4;
+ if( pIesLocal->WAPI.akm_suite_count )
+ {
+ //copy akm_suites
+ palCopyMemory(pMac->hHdd, pIeBuf, pIesLocal->WAPI.akm_suites,
+ pIesLocal->WAPI.akm_suite_count * 4);
+ pIeBuf += pIesLocal->WAPI.akm_suite_count * 4;
+ }
+ palCopyMemory(pMac->hHdd, pIeBuf, &pIesLocal->WAPI.unicast_cipher_suite_count, 2);
+ pIeBuf += 2;
+
+ if( pIesLocal->WAPI.unicast_cipher_suite_count )
+ {
+ //copy pwise_cipher_suites
+ palCopyMemory(pMac->hHdd, pIeBuf, pIesLocal->WAPI.unicast_cipher_suites,
+ pIesLocal->WAPI.unicast_cipher_suite_count * 4);
+ pIeBuf += pIesLocal->WAPI.unicast_cipher_suite_count * 4;
+ }
+ //gp_cipher_suite + preauth + reserved + bkid_count
+ palCopyMemory(pMac->hHdd, pIeBuf, &pIesLocal->WAPI.multicast_cipher_suite, 8);
+ pIeBuf += 8;
+ if( pIesLocal->WAPI.bkid_count )
+ {
+ //copy akm_suites
+ palCopyMemory(pMac->hHdd, 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
+ palFreeMemory(pMac->hHdd, 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)\n"), 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_CCX
+//Returns whether the current association is a CCX assoc or not
+tANI_BOOLEAN csrRoamIsCCXAssoc(tpAniSirGlobal pMac)
+{
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ return csrNeighborRoamIsCCXAssoc(pMac);
+#else
+ return eANI_BOOLEAN_FALSE;
+#endif
+}
+#endif
+
+//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;
+#ifdef WLAN_SOFTAP_FEATURE
+ tSirSmeStartBssRsp *pSmeStartBssRsp = NULL;
+#endif
+
+
+ smsLog( pMac, LOG1, FL("Processing ROAM results...\n"));
+
+ switch( Result )
+ {
+ case eCsrJoinSuccess:
+ // reset the IDLE timer
+ // !!
+ // !! fall through to the next CASE statement here is intentional !!
+ // !!
+ case eCsrReassocSuccess:
+ if(eCsrReassocSuccess == Result)
+ {
+ ind_qos = SME_QOS_CSR_REASSOC_COMPLETE;
+ }
+ else
+ {
+ 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\n"));
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(roamInfo));
+ //always free the memory here
+ if(pSession->pWpaRsnRspIE)
+ {
+ pSession->nWpaRsnRspIeLength = 0;
+ palFreeMemory(pMac->hHdd, pSession->pWpaRsnRspIE);
+ pSession->pWpaRsnRspIE = NULL;
+ }
+
+#ifdef FEATURE_WLAN_WAPI
+ if(pSession->pWapiRspIE)
+ {
+ pSession->nWapiRspIeLength = 0;
+ palFreeMemory(pMac->hHdd, 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 );
+ 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)
+ {
+ palCopyMemory(pMac->hHdd, &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 );
+ palCopyMemory(pMac->hHdd, &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_CCX
+ roamInfo.isCCXAssoc = pSession->connectedProfile.isCCXAssoc;
+#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\n") );
+ 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
+ {
+ //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\n") );
+ 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_CCX
+ len += pJoinRsp->tspecIeLen;
+#endif
+ if(len)
+ {
+ if(HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd,
+ (void **)&pSession->connectedInfo.pbFrames, len)))
+ {
+ if(HAL_STATUS_SUCCESS( palCopyMemory(pMac->hHdd,
+ 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_CCX
+ pSession->connectedInfo.nTspecIeLength = pJoinRsp->tspecIeLen;
+#endif
+ roamInfo.nAssocReqLength = pJoinRsp->assocReqLength;
+ roamInfo.nAssocRspLength = pJoinRsp->assocRspLength;
+ roamInfo.nBeaconLength = pJoinRsp->beaconLength;
+ roamInfo.pbFrames = pSession->connectedInfo.pbFrames;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "%s: Copying of memory failed for %d bytes !!!\n",
+ __FUNCTION__, len);
+ palFreeMemory( pMac->hHdd, pSession->connectedInfo.pbFrames );
+ pSession->connectedInfo.pbFrames = NULL;
+ }
+ }
+ }
+ 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;
+ }
+ 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;
+ }
+ }
+#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;
+
+#ifdef FEATURE_WLAN_UAPSD_FW_TRG_FRAMES
+ //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\n",
+ pSession->connectedProfile.modifyProfileFields.uapsd_mask);
+ pmcStartUapsd( pMac, NULL, NULL );
+ }
+#endif
+
+ roamInfo.u.pConnectedProfile = &pSession->connectedProfile;
+ if( pSession->bRefAssocStartCnt > 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_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\n");
+ }
+
+ 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))
+ {
+ 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\n"));
+ status = eHAL_STATUS_FAILURE;
+#ifdef WLAN_SOFTAP_FEATURE
+ pSmeStartBssRsp = (tSirSmeStartBssRsp *)Context;
+#endif
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ if( CSR_IS_IBSS( pProfile ) )
+ {
+ pSession->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED;
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ else if (CSR_IS_INFRA_AP(pProfile))
+ {
+ pSession->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED;
+ }
+#endif
+ else
+ {
+ pSession->connectState = eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED;
+ }
+ if( !CSR_IS_WDS_STA( pProfile ) )
+ {
+ csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId );
+#ifdef WLAN_SOFTAP_FEATURE
+ pSirBssDesc = &pSmeStartBssRsp->bssDescription;
+#else
+ pSirBssDesc = (tSirBssDescription *)Context;
+#endif
+ if( !HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs( pMac, pSirBssDesc, &pIes )) )
+ {
+ smsLog(pMac, LOG2, FL("cannot parse IBSS IEs\n"));
+ 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;
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ if (!CSR_IS_INFRA_AP(pProfile))
+#endif
+ {
+ pScanResult = csrScanAppendBssDescription( pMac, pSirBssDesc, pIes );
+ }
+ csrRoamSaveConnectedBssDesc(pMac, sessionId, pSirBssDesc);
+ csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile);
+ csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo );
+ if(pSirBssDesc)
+ {
+ csrRoamSaveConnectedInfomation(pMac, sessionId, pProfile, pSirBssDesc, pIes);
+ palCopyMemory(pMac->hHdd, &roamInfo.bssid, &pSirBssDesc->bssId, sizeof(tCsrBssid));
+ }
+ //We are doen with the IEs so free it
+ palFreeMemory(pMac->hHdd, 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)
+ {
+ palCopyMemory(pMac->hHdd, 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.
+
+#ifdef WLAN_SOFTAP_FEATURE
+ if( CSR_IS_ENC_TYPE_STATIC( pProfile->negotiatedUCEncryptionType ) && !CSR_IS_INFRA_AP( pSession->pCurRoamProfile ))
+ {
+#else
+ if( CSR_IS_ENC_TYPE_STATIC( pProfile->negotiatedUCEncryptionType ))
+ {
+#endif
+ // 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 );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGE, " StartBSS for WDS station with no BssDesc\n" );
+ 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;
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ if( CSR_IS_INFRA_AP( pProfile ) )
+ {
+ roamStatus = eCSR_ROAM_INFRA_IND;
+ roamResult = eCSR_ROAM_RESULT_INFRA_STARTED;
+ }
+#endif
+
+ //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
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
+ roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
+ if(CSR_INVALID_SCANRESULT_HANDLE == pCommand->u.roamCmd.hBSSList)
+ {
+ //We start the IBSS (didn't find any matched IBSS out there)
+ roamInfo.pBssDesc = pSirBssDesc;
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ roamInfo.staId = (tANI_U8)pSmeStartBssRsp->staId;
+#endif
+ csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, roamStatus, roamResult );
+ }
+
+ csrScanCancelIdleScan(pMac);
+ //Only use this timer for ibss. BAP has its own timer for WDS
+ if( CSR_IS_IBSS( pProfile) && CSR_INVALID_SCANRESULT_HANDLE != pCommand->u.roamCmd.hBSSList)
+ {
+ //start the join IBSS timer
+ csrRoamStartIbssJoinTimer(pMac, sessionId, CSR_IBSS_JOIN_TIMEOUT_PERIOD); //interval
+ pSession->ibss_join_pending = TRUE;
+ }
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ //Already sent join_req for the WDS station
+ fReleaseCommand = eANI_BOOLEAN_FALSE;
+ }
+ else 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;
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ if( CSR_IS_INFRA_AP( pProfile ) )
+ {
+ roamStatus = eCSR_ROAM_INFRA_IND;
+ roamResult = eCSR_ROAM_RESULT_INFRA_START_FAILED;
+ }
+#endif
+ if(Context)
+ {
+ pSirBssDesc = (tSirBssDescription *)Context;
+ }
+ else
+ {
+ pSirBssDesc = NULL;
+ }
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ 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\n"));
+ csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId );
+ csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId );
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ roamInfo.pBssDesc = pSession->pConnectBssDesc;
+ if( roamInfo.pBssDesc )
+ {
+ palCopyMemory(pMac->hHdd, &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\n"));
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(roamInfo));
+
+ //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 )
+ {
+ palCopyMemory(pMac->hHdd, &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;
+#if defined(VOSS_ENABLED)
+ VOS_ASSERT( roamInfo.staId != 0 );
+#endif
+ 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\n"));
+ csrFreeConnectBssDesc(pMac, sessionId);
+ csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile);
+ csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo );
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ 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:
+ default:
+ {
+ smsLog(pMac, LOGW, FL("receives no association indication\n"));
+ 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 eCsrSmeIssuedAssocToSimilarAP:
+ case eCsrHddIssued:
+ csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId );
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss;
+ roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
+ roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
+
+ /* 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))
+ {
+ csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.roamCmd.roamId, eCSR_ROAM_DISASSOCIATED, eCSR_ROAM_RESULT_FORCED);
+ /* Should indicate neighbor roam algorithm about the connect failure here */
+ csrNeighborRoamIndicateConnect(pMac, (tANI_U8)sessionId, VOS_STATUS_E_FAILURE);
+ }
+ else
+#endif
+ {
+ if(pSession->bRefAssocStartCnt > 0)
+ {
+ pSession->bRefAssocStartCnt--;
+ csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
+ eCSR_ROAM_ASSOCIATION_COMPLETION,
+ eCSR_ROAM_RESULT_FAILURE);
+ }
+ }
+ smsLog(pMac, LOG1, FL(" roam(reason %d) failed\n"), pCommand->u.roamCmd.roamReason);
+#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);
+#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);
+ csrScanStartIdleScan(pMac);
+ break;
+ case eCsrForcedIbssLeave:
+ 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;
+#ifdef WLAN_SOFTAP_FEATURE
+ 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);
+ if( CSR_IS_SESSION_VALID(pMac, sessionId) )
+ {
+ pSession = CSR_GET_SESSION(pMac, sessionId);
+ if (!pSession)
+ break;
+
+ if ( CSR_IS_INFRA_AP(&pSession->connectedProfile) )
+ {
+ roamInfo.u.pConnectedProfile = &pSession->connectedProfile;
+ palCopyMemory(pMac->hHdd, 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);
+ }
+ }
+ break;
+#endif
+ 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
+ {
+ palZeroMemory(pMac->hHdd, pDstProfile, sizeof(tCsrRoamProfile));
+ if(pSrcProfile->BSSIDs.numOfBSSIDs)
+ {
+ size = sizeof(tCsrBssid) * pSrcProfile->BSSIDs.numOfBSSIDs;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstProfile->BSSIDs.bssid, size);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->BSSIDs.numOfBSSIDs = pSrcProfile->BSSIDs.numOfBSSIDs;
+ palCopyMemory(pMac->hHdd, pDstProfile->BSSIDs.bssid, pSrcProfile->BSSIDs.bssid, size);
+ }
+ if(pSrcProfile->SSIDs.numOfSSIDs)
+ {
+ size = sizeof(tCsrSSIDInfo) * pSrcProfile->SSIDs.numOfSSIDs;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstProfile->SSIDs.SSIDList, size);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->SSIDs.numOfSSIDs = pSrcProfile->SSIDs.numOfSSIDs;
+ palCopyMemory(pMac->hHdd, pDstProfile->SSIDs.SSIDList, pSrcProfile->SSIDs.SSIDList, size);
+ }
+ if(pSrcProfile->nWPAReqIELength)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstProfile->pWPAReqIE, pSrcProfile->nWPAReqIELength);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->nWPAReqIELength = pSrcProfile->nWPAReqIELength;
+ palCopyMemory(pMac->hHdd, pDstProfile->pWPAReqIE, pSrcProfile->pWPAReqIE, pSrcProfile->nWPAReqIELength);
+ }
+ if(pSrcProfile->nRSNReqIELength)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstProfile->pRSNReqIE, pSrcProfile->nRSNReqIELength);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->nRSNReqIELength = pSrcProfile->nRSNReqIELength;
+ palCopyMemory(pMac->hHdd, pDstProfile->pRSNReqIE, pSrcProfile->pRSNReqIE, pSrcProfile->nRSNReqIELength);
+ }
+#ifdef FEATURE_WLAN_WAPI
+ if(pSrcProfile->nWAPIReqIELength)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstProfile->pWAPIReqIE, pSrcProfile->nWAPIReqIELength);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->nWAPIReqIELength = pSrcProfile->nWAPIReqIELength;
+ palCopyMemory(pMac->hHdd, pDstProfile->pWAPIReqIE, pSrcProfile->pWAPIReqIE, pSrcProfile->nWAPIReqIELength);
+ }
+#endif /* FEATURE_WLAN_WAPI */
+
+ if(pSrcProfile->nAddIEScanLength)
+ {
+ status = palAllocateMemory(pMac->hHdd,
+ (void **)&pDstProfile->pAddIEScan, pSrcProfile->nAddIEScanLength);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->nAddIEScanLength = pSrcProfile->nAddIEScanLength;
+ palCopyMemory(pMac->hHdd, pDstProfile->pAddIEScan, pSrcProfile->pAddIEScan,
+ pSrcProfile->nAddIEScanLength);
+ }
+
+ if(pSrcProfile->nAddIEAssocLength)
+ {
+ status = palAllocateMemory(pMac->hHdd,
+ (void **)&pDstProfile->pAddIEAssoc, pSrcProfile->nAddIEAssocLength);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->nAddIEAssocLength = pSrcProfile->nAddIEAssocLength;
+ palCopyMemory(pMac->hHdd, pDstProfile->pAddIEAssoc, pSrcProfile->pAddIEAssoc,
+ pSrcProfile->nAddIEAssocLength);
+ }
+
+ if(pSrcProfile->ChannelInfo.ChannelList)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstProfile->ChannelInfo.ChannelList, pSrcProfile->ChannelInfo.numOfChannels);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->ChannelInfo.numOfChannels = pSrcProfile->ChannelInfo.numOfChannels;
+ palCopyMemory(pMac->hHdd, 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;
+ 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->uapsd_mask = pSrcProfile->uapsd_mask;
+
+ pDstProfile->beaconInterval = pSrcProfile->beaconInterval;
+#ifdef WLAN_SOFTAP_FEATURE
+ 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;
+#endif
+
+ palCopyMemory(pMac->hHdd, &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
+ {
+ palZeroMemory(pMac->hHdd, pDstProfile, sizeof(tCsrRoamProfile));
+ if(pSrcProfile->bssid)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstProfile->BSSIDs.bssid, sizeof(tCsrBssid));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->BSSIDs.numOfBSSIDs = 1;
+ palCopyMemory(pMac->hHdd, pDstProfile->BSSIDs.bssid, pSrcProfile->bssid, sizeof(tCsrBssid));
+ }
+ if(pSrcProfile->SSID.ssId)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstProfile->SSIDs.SSIDList, sizeof(tCsrSSIDInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pDstProfile->SSIDs.numOfSSIDs = 1;
+ pDstProfile->SSIDs.SSIDList[0].handoffPermitted = pSrcProfile->handoffPermitted;
+ pDstProfile->SSIDs.SSIDList[0].ssidHidden = pSrcProfile->ssidHidden;
+ palCopyMemory(pMac->hHdd, &pDstProfile->SSIDs.SSIDList[0].SSID, &pSrcProfile->SSID, sizeof(tSirMacSSid));
+ }
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstProfile->ChannelInfo.ChannelList, 1);
+ 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;
+ palCopyMemory(pMac->hHdd, &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 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\n") );
+ status = eHAL_STATUS_RESOURCES;
+ }
+ else
+ {
+ if( fClearScan )
+ {
+ csrScanCancelIdleScan(pMac);
+ csrScanAbortMacScanNotForConnect(pMac);
+ }
+ 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\n"), 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\n") );
+ status = eHAL_STATUS_RESOURCES;
+ }
+ else
+ {
+ csrScanCancelIdleScan(pMac);
+ csrScanAbortMacScanNotForConnect(pMac);
+ 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\n"), status );
+ csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_FAILURE, eANI_BOOLEAN_FALSE);
+ csrReleaseCommandRoam( pMac, pCommand );
+ }
+ }
+
+ return (status);
+}
+
+
+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\n"));
+ 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;
+ }
+
+ smsLog(pMac, LOG1, FL("called BSSType = %d authtype = %d encryType = %d\n"),
+ pProfile->BSSType, pProfile->AuthType.authType[0], pProfile->EncryptionType.encryptionType[0]);
+
+ if( CSR_IS_WDS( pProfile ) &&
+ !HAL_STATUS_SUCCESS( status = csrIsBTAMPAllowed( pMac, pProfile->operationChannel ) ) )
+ {
+ return status;
+ }
+ csrRoamCancelRoaming(pMac, sessionId);
+ csrScanRemoveFreshScanCommand(pMac, sessionId);
+ csrScanCancelIdleScan(pMac);
+ //Only abort the scan if it is not used for other roam/connect purpose
+ csrScanAbortMacScan(pMac);
+
+#ifdef WLAN_SOFTAP_FEATURE
+ if (!vos_concurrent_sessions_running() && (VOS_STA_SAP_MODE == pProfile->csrPersona))//In case of AP mode we do not want idle mode scan
+ {
+ csrScanDisable(pMac);
+ }
+#endif
+
+ 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, LOGW, FL("is called with BSSList\n"));
+ status = csrRoamConnectWithBSSList(pMac, sessionId, pProfile, hBssListIn, pRoamId);
+ if(pRoamId)
+ {
+ roamId = *pRoamId;
+ }
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ fCallCallback = eANI_BOOLEAN_TRUE;
+ }
+ }
+ else
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ //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;
+ }
+ else
+ {
+ pScanFilter->bWPSAssociation = 0;
+ }
+
+ do
+ {
+ if( (pProfile && CSR_IS_WDS_AP( pProfile ) )
+#ifdef WLAN_SOFTAP_FEATURE
+ || (pProfile && CSR_IS_INFRA_AP ( pProfile ))
+#endif
+ )
+ {
+ //This can be start right away
+ status = csrRoamIssueConnect(pMac, sessionId, pProfile, NULL, eCsrHddIssued,
+ roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ fCallCallback = eANI_BOOLEAN_TRUE;
+ }
+
+ break;
+ }
+ status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
+ smsLog(pMac, LOGE, "************ csrScanGetResult Status ********* %d\n", 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))
+ {
+ 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\n", status);
+ fCallCallback = eANI_BOOLEAN_TRUE;
+ }
+ }
+ else
+ {
+ //scan for this SSID
+ status = csrScanForSSID(pMac, sessionId, pProfile, roamId);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ fCallCallback = eANI_BOOLEAN_TRUE;
+ }
+ }
+ }
+ 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
+
+ palFreeMemory(pMac->hHdd, 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 = %d authtype = %d encryType = %d\n"), pProfile->BSSType, pProfile->AuthType.authType[0], pProfile->EncryptionType.encryptionType[0]);
+ csrRoamCancelRoaming(pMac, sessionId);
+ csrScanRemoveFreshScanCommand(pMac, sessionId);
+ csrScanCancelIdleScan(pMac);
+ csrScanAbortMacScanNotForConnect(pMac);
+ 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\n"));
+ }
+ }
+ else if(!palEqualMemory(pMac->hHdd, &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\n"));
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOG1, FL("Not connected! No need to reassoc\n"));
+ }
+
+ 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 );
+
+ do
+ {
+ if(pSession->pCurRoamProfile)
+ {
+ csrScanCancelIdleScan(pMac);
+ csrScanAbortMacScanNotForConnect(pMac);
+ //We have to make a copy of pCurRoamProfile because it will be free inside csrRoamIssueConnect
+ status = palAllocateMemory(pMac->hHdd, (void **)&pProfile, sizeof(tCsrRoamProfile));
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ palZeroMemory(pMac->hHdd, pProfile, sizeof(tCsrRoamProfile));
+ status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile);
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ 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);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ }
+ }//We have a profile
+ else
+ {
+ smsLog(pMac, LOGW, FL("cannot find a roaming profile\n"));
+ break;
+ }
+ }while(0);
+ if(pScanFilter)
+ {
+ csrFreeScanFilter(pMac, pScanFilter);
+ palFreeMemory(pMac->hHdd, pScanFilter);
+ }
+ if(NULL != pProfile)
+ {
+ csrReleaseProfile(pMac, pProfile);
+ palFreeMemory(pMac->hHdd, 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\n"));
+ 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;
+
+ // 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, LOGE, FL(" restore AC weights (%d-%d-%d-%d)\n"), 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;
+ }
+ if( fDisassoc )
+ {
+ status = csrRoamIssueDisassociate( pMac, sessionId, NewSubstate, fMICFailure );
+ }
+ 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;
+ }
+ }
+ 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;
+ tANI_BOOLEAN fHighPriority = eANI_BOOLEAN_FALSE;
+
+ do
+ {
+ smsLog( pMac, LOGE, FL(" reason = %d\n"), reason );
+ pCommand = csrGetCommandBuffer( pMac );
+ if ( !pCommand )
+ {
+ smsLog( pMac, LOGE, FL(" fail to get command buffer\n") );
+ 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;
+ 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:
+ fHighPriority = eANI_BOOLEAN_TRUE;
+ 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, fHighPriority);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), 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\n"), status );
+ csrReleaseCommandRoam( pMac, pCommand );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" fail to get command buffer\n") );
+ 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 );
+#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\n"));
+ status = csrRoamIssueDisassociateCmd(pMac, sessionId, reason);
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrRoamDisconnect(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason)
+{
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ csrRoamCancelRoaming(pMac, sessionId);
+ pSession->ibss_join_pending = FALSE;
+ csrRoamStopIbssJoinTimer(pMac, sessionId);
+ csrRoamRemoveDuplicateCommand(pMac, sessionId, NULL, eCsrForcedDisassoc);
+
+ return (csrRoamDisconnectInternal(pMac, sessionId, reason));
+}
+
+
+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;
+
+ palZeroMemory(pMac->hHdd, &pSession->connectedProfile, sizeof(tCsrRoamConnectedProfile));
+ 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;
+ palCopyMemory(pMac->hHdd, &pConnectProfile->Keys, &pProfile->Keys, sizeof(tCsrKeys));
+ //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
+#ifdef FEATURE_WLAN_CCX
+ if ((csrIsProfileCCX(pProfile) || ((pIesTemp->CCXVersion.present) && ((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA)))) && (!(csrIsProfile11r( pProfile ))) && (pMac->roam.configParam.isCcxIniFeatureEnabled))
+ {
+ pConnectProfile->isCCXAssoc = 1;
+ }
+#endif
+ //save ssid
+ if( NULL == pIesTemp )
+ {
+ status = csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesTemp);
+ }
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ if(pIesTemp->SSID.present)
+ {
+ pConnectProfile->SSID.length = pIesTemp->SSID.num_ssid;
+ palCopyMemory(pMac->hHdd, 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) )
+ {
+ pConnectProfile->qap = TRUE;
+ }
+ else
+ {
+ pConnectProfile->qap = FALSE;
+ }
+
+ if ( NULL == pIes )
+ {
+ //Free memory if it allocated locally
+ palFreeMemory(pMac->hHdd, 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) &&
+ palEqualMemory(pMac->hHdd, 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;
+
+ //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);
+ }
+
+ 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 );
+ }
+ else
+ {
+ tANI_U32 roamId = 0;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pSmeJoinRsp->sessionId );
+
+ //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%08lX [%d]\n", 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= %02x-%02x-%02x-%02x-%02x-%02x\n",
+ pSirBssDesc->bssId[ 0 ],pSirBssDesc->bssId[ 1 ],pSirBssDesc->bssId[ 2 ],
+ pSirBssDesc->bssId[ 3 ],pSirBssDesc->bssId[ 4 ],pSirBssDesc->bssId[ 5 ] );
+
+ // 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 );
+
+ 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 );
+
+ smsLog(pMac, LOGE, FL(" calling csrSendSmeReassocReqMsg\n"));
+
+ // attempt to Join this BSS...
+ return csrSendSmeReassocReqMsg( pMac, sessionId, pSirBssDesc, pIes, pProfile );
+}
+
+
+
+void csrRoamReissueRoamCommand(tpAniSirGlobal pMac)
+{
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+ tCsrRoamInfo roamInfo;
+ tANI_U32 sessionId;
+ tCsrRoamSession *pSession;
+
+ 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( pCommand->u.roamCmd.fStopWds )
+ {
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss;
+ roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
+ roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
+#ifdef WLAN_SOFTAP_FEATURE
+ if (CSR_IS_WDS(&pSession->connectedProfile)){
+#endif
+ 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);
+#ifdef WLAN_SOFTAP_FEATURE
+ }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);
+ }
+
+#endif
+
+
+ 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\n");
+ csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
+ }
+ }
+ else if(eCsrStopRoaming == csrRoamJoinNextBss(pMac, pCommand, eANI_BOOLEAN_TRUE))
+ {
+ smsLog(pMac, LOGW, " Failed to reissue join command after disassociated\n");
+ csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGW, " Command is not roaming after disassociated\n");
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, " Disassoc rsp cannot continue because no command is available\n");
+ }
+}
+
+
+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);
+ }
+ 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\n") );
+ 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 \n") );
+ }
+ 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\n") );
+ 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\n"), 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;
+
+ if(NULL == pEntry)
+ {
+ smsLog(pMac, LOGW, " CFG_CNF with active list empty\n");
+ return;
+ }
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ sessionId = pCommand->sessionId;
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+ if(CSR_IS_ROAMING(pSession) && pSession->fCancelRoaming)
+ {
+ //the roaming is cancelled. Simply complete the command
+ smsLog(pMac, LOGW, FL(" Roam command cancelled\n"));
+ csrRoamComplete(pMac, eCsrNothingToJoin, NULL);
+ }
+ else
+ {
+ if ( CCM_IS_RESULT_SUCCESS(result) )
+ {
+ smsLog(pMac, LOG2, "Cfg sequence complete\n");
+ // 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);
+ pBssDesc = &pScanResult->Result.BssDescriptor;
+ }
+ if ( csrIsBssTypeIBSS( pCommand->u.roamCmd.roamProfile.BSSType ) ||
+ CSR_IS_WDS( &pCommand->u.roamCmd.roamProfile )
+#ifdef WLAN_SOFTAP_FEATURE
+ || CSR_IS_INFRA_AP(&pCommand->u.roamCmd.roamProfile)
+#endif
+ )
+ {
+ if(!HAL_STATUS_SUCCESS(csrRoamIssueStartBss( pMac, sessionId,
+ &pSession->bssParams, &pCommand->u.roamCmd.roamProfile,
+ pBssDesc, pCommand->u.roamCmd.roamId )))
+ {
+ smsLog(pMac, LOGW, " CSR start BSS failed\n");
+ //We need to complete the command
+ csrRoamComplete(pMac, eCsrStartBssFailure, NULL);
+ }
+ }
+ else
+ {
+ if (!pCommand->u.roamCmd.pRoamBssEntry)
+ {
+ smsLog(pMac, LOGW, " pRoamBssEntry is NULL\n");
+ //We need to complete the command
+ csrRoamComplete(pMac, eCsrJoinFailure, NULL);
+ return;
+ }
+ // If we are roaming TO an Infrastructure BSS...
+ VOS_ASSERT(pScanResult != NULL);
+ if ( csrIsInfraBssDesc( pBssDesc ) )
+ {
+ tDot11fBeaconIEs *pIesLocal = (tDot11fBeaconIEs *)pScanResult->Result.pvIes;
+
+ if(pIesLocal || (HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal))) )
+ {
+ // ..and currently in an Infrastructure connection....
+ if( csrIsConnStateConnectedInfra( pMac, sessionId ) )
+ {
+ // ...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 CCX and 11r handoff whereas other legacy roaming should
+ * use join request */
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (csrRoamIsHandoffInProgress(pMac) &&
+ csrRoamIs11rAssoc(pMac))
+ {
+ status = csrRoamIssueReassociate(pMac, sessionId, pBssDesc,
+ (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ), &pCommand->u.roamCmd.roamProfile);
+ }
+ else
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+ if (csrRoamIsHandoffInProgress(pMac) &&
+ csrRoamIsCCXAssoc(pMac))
+ {
+ // Now serialize the reassoc command.
+ status = csrRoamIssueReassociateCmd(pMac, sessionId);
+ }
+ else
+#endif
+ // else we are not connected and attempting to Join. Issue the
+ // Join request.
+ {
+ 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
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+ }
+ }//if ( csrIsInfraBssDesc( pBssDesc ) )
+ else
+ {
+ smsLog(pMac, LOGW, FL(" found BSSType mismatching the one in BSS description\n"));
+ }
+ }//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 )
+{
+ //No one is sending eWNI_SME_AUTH_REQ to PE.
+ smsLog(pMac, LOGW, FL("is no-op\n"));
+ if ( eSIR_SME_SUCCESS == pSmeAuthRsp->statusCode )
+ {
+ smsLog( pMac, LOGW, "CSR SmeAuthReq Successful\n" );
+ // 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%08lX [%d]\n", 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;
+
+ if ( eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode )
+ {
+ smsLog( pMac, LOGW, "CSR SmeReassocReq Successful\n" );
+ 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);
+ }
+ 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%08lX [%d]\n", pSmeJoinRsp->statusCode, pSmeJoinRsp->statusCode );
+ result = eCsrReassocFailure;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if ((eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE == pSmeJoinRsp->statusCode) ||
+ (eSIR_SME_FT_REASSOC_FAILURE == 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);
+ }
+ }
+#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;
+ tSirSmeDisassocRsp SmeDisassocRsp;
+
+ csrSerDesUnpackDiassocRsp((tANI_U8 *)pSmeRsp, &SmeDisassocRsp);
+ sessionId = SmeDisassocRsp.sessionId;
+ statusCode = SmeDisassocRsp.statusCode;
+
+ smsLog( pMac, LOG2, "csrRoamRoamingStateDisassocRspProcessor sessionId %d\n", sessionId);
+
+ if ( csrIsConnStateInfra( pMac, sessionId ) )
+ {
+ pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
+ }
+
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+ if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_NO_JOIN( pMac, sessionId ) )
+ {
+ 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\n" );
+ //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 ) )
+ {
+ smsLog( pMac, LOGE, "CSR SmeDisassocReq due to HO\n" );
+#if defined (WLAN_FEATURE_NEIGHBOR_ROAMING)
+ 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, " ********csrRoamRoamingStateDisassocRspProcessor fail to remove cmd reason %d\n",
+ pCommand->u.roamCmd.roamReason );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: Roam Completion called but ROAM command is not ACTIVE ...\n" );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: Roam Completion called but NO commands are ACTIVE ...\n" );
+ }
+
+ //notify HDD for handoff, providing the BSSID too
+ roamInfo.reasonCode = eCsrRoamReasonBetterAP;
+
+ palCopyMemory(pMac->hHdd, roamInfo.bssid, pMac->roam.neighborRoamInfo.csrNeighborRoamProfile.BSSIDs.bssid, sizeof(tSirMacAddr));
+
+ csrRoamCallCallback(pMac,sessionId, &roamInfo, 0, eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE);
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ status = csrRoamPrepareFilterFromProfile(pMac, &pMac->roam.neighborRoamInfo.csrNeighborRoamProfile, pScanFilter);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL(" csrRoamPrepareFilterFromProfile fail to create scan filter\n"));
+ }
+
+ status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ //copy over the connected profile to apply the same for this connection as well
+ if(HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd, (void **)&pCurRoamProfile, sizeof(tCsrRoamProfile))))
+ {
+ palZeroMemory(pMac->hHdd, pCurRoamProfile, sizeof(tCsrRoamProfile));
+ 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))
+ {
+ //msg
+ fCallCallback = eANI_BOOLEAN_TRUE;
+ }
+ /* Notify sub-modules like QoS etc. that handoff happening */
+ sme_QosCsrEventInd(pMac, sessionId, SME_QOS_CSR_HANDOFF_ASSOC_REQ, NULL);
+ palFreeMemory(pMac->hHdd, pCurRoamProfile);
+ }
+ else
+ {
+ //msg
+ smsLog( pMac, LOGE,"csrRoamRoamingStateDisassocRspProcessor: csrScanGetResult failed");
+ // should have asserted, sending up roam complete instead. Let upper layer
+ // decide what to do next
+ csrCallRoamingCompletionCallback(pMac, pSession, &roamInfo, 0, eCSR_ROAM_RESULT_FAILURE);
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" fail to allocate memory for scan filter\n"));
+ csrCallRoamingCompletionCallback(pMac, pSession, &roamInfo, 0, eCSR_ROAM_RESULT_FAILURE);
+ }
+ if( pScanFilter )
+ {
+ csrFreeScanFilter(pMac, pScanFilter);
+ palFreeMemory( pMac->hHdd, pScanFilter );
+ }
+
+
+#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\n" );
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "SmeDisassocReq failed with statusCode= 0x%08lX\n", statusCode );
+ }
+ //We are not done yet. Get the data and continue roaming
+ csrRoamReissueRoamCommand(pMac);
+ }
+
+}
+
+
+static void csrRoamRoamingStateDeauthRspProcessor( tpAniSirGlobal pMac, tSirSmeDeauthRsp *pSmeRsp )
+{
+ tSirResultCodes statusCode;
+
+ //No one is sending eWNI_SME_DEAUTH_REQ to PE.
+ smsLog(pMac, LOGW, FL("is no-op\n"));
+ statusCode = csrGetDeAuthRspStatusCode( pSmeRsp );
+ 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\n" );
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "SmeDeauthReq failed with statusCode= 0x%08lX\n", 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\n" );
+ result = eCsrStartBssSuccess;
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "SmeStartBssReq failed with statusCode= 0x%08lX\n", pSmeStartBssRsp->statusCode );
+ //Let csrRoamComplete decide what to do
+ result = eCsrStartBssFailure;
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ csrRoamComplete( pMac, result, pSmeStartBssRsp);
+#else
+ csrRoamComplete( pMac, result, &pSmeStartBssRsp->bssDescription );
+#endif
+}
+
+
+/*
+ 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, "Message %d[0x%04X] received in substate %d\n",
+ pSmeRsp->messageType, pSmeRsp->messageType,
+ pMac->roam.curSubState[pSmeRsp->sessionId] );
+#if defined ANI_PRODUCT_TYPE_AP
+ pSmeRsp->messageType = pal_be16_to_cpu(pSmeRsp->messageType);
+ pSmeRsp->length = pal_be16_to_cpu(pSmeRsp->length);
+ pSmeRsp->statusCode = pal_be32_to_cpu(pSmeRsp->statusCode);
+#else
+ pSmeRsp->messageType = (pSmeRsp->messageType);
+ pSmeRsp->length = (pSmeRsp->length);
+ pSmeRsp->statusCode = (pSmeRsp->statusCode);
+#endif
+ 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, LOGE, FL("eWNI_SME_DISASSOC_RSP subState = %d\n"), pMac->roam.curSubState[pSmeRsp->sessionId]);
+ csrRoamRoamingStateDisassocRspProcessor( pMac, (tSirSmeDisassocRsp *)pSmeRsp );
+ }
+ 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\n");
+ palZeroMemory( pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo) );
+ roamInfo.staId = (tANI_U8)pIbssPeerInd->staId;
+ roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig;
+ roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig;
+ palCopyMemory(pMac->hHdd, &roamInfo.peerMac, pIbssPeerInd->peerAddr, sizeof(tCsrBssid));
+ csrRoamCallCallback(pMac, sessionId, &roamInfo, 0,
+ eCSR_ROAM_CONNECT_STATUS_UPDATE,
+ eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED);
+ break;
+
+ default:
+ smsLog( pMac, LOG1, "Unexpected message type = %d[0x%X] received in substate %d\n",
+ pSmeRsp->messageType, pSmeRsp->messageType,
+ 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, LOGW, FL("Stats rsp from PE\n"));
+ csrRoamStatsRspProcessor( pMac, pSirMsg );
+ break;
+#ifdef WLAN_SOFTAP_FEATURE
+ case eWNI_SME_UPPER_LAYER_ASSOC_CNF:
+ {
+ tCsrRoamSession *pSession;
+ tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf;
+ tCsrRoamInfo roamInfo;
+ tCsrRoamInfo *pRoamInfo = NULL;
+ tANI_U32 sessionId;
+ eHalStatus status;
+
+ smsLog( pMac, LOG1, FL("ASSOCIATION confirmation can be given to upper layer \n"));
+
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ pRoamInfo = &roamInfo;
+
+ pUpperLayerAssocCnf = (tSirSmeAssocIndToUpperLayerCnf *)pMsgBuf;
+ status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pUpperLayerAssocCnf->bssId, &sessionId );
+ pSession = CSR_GET_SESSION(pMac, sessionId);
+
+ 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;
+
+ palCopyMemory(pMac->hHdd, pRoamInfo->peerMac, pUpperLayerAssocCnf->peerMacAddr, sizeof(tSirMacAddr));
+ palCopyMemory(pMac->hHdd, &pRoamInfo->bssid, pUpperLayerAssocCnf->bssId, sizeof(tCsrBssid));
+
+ pRoamInfo->wmmEnabledSta = pUpperLayerAssocCnf->wmmEnabledSta;
+
+ 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;
+#endif
+
+ 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
+ palCopyMemory( pMac->hHdd, &setKey.peerMac, bssId, sizeof(tCsrBssid) );
+ setKey.paeRole = paeRole; //0 for supplicant
+ setKey.keyId = keyId; // Kye index
+ setKey.keyLength = keyLength;
+ if( keyLength )
+ {
+ palCopyMemory( pMac->hHdd, 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_CCX
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+#endif /* FEATURE_WLAN_CCX */
+
+ do
+ {
+ pCommand = csrGetCommandBuffer(pMac);
+ if(NULL == pCommand)
+ {
+ smsLog( pMac, LOGE, FL(" fail to get command buffer\n") );
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ 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\n", pSetKey->keyLength );
+ break;
+ }
+
+ pCommand->u.setKeyCmd.keyLength = CSR_WEP40_KEY_LEN;
+ palCopyMemory( pMac->hHdd, 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\n", pSetKey->keyLength );
+ break;
+ }
+
+ pCommand->u.setKeyCmd.keyLength = CSR_WEP104_KEY_LEN;
+ palCopyMemory( pMac->hHdd, 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\n", pSetKey->keyLength );
+ break;
+ }
+ pCommand->u.setKeyCmd.keyLength = CSR_TKIP_KEY_LEN;
+ palCopyMemory( pMac->hHdd, 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\n", pSetKey->keyLength );
+ break;
+ }
+ pCommand->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN;
+ palCopyMemory( pMac->hHdd, 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\n", pSetKey->keyLength );
+ break;
+ }
+ pCommand->u.setKeyCmd.keyLength = CSR_WAPI_KEY_LEN;
+ palCopyMemory( pMac->hHdd, pCommand->u.setKeyCmd.Key, pSetKey->Key, CSR_WAPI_KEY_LEN );
+ }
+#endif /* FEATURE_WLAN_WAPI */
+#ifdef FEATURE_WLAN_CCX
+ 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\n", pSetKey->keyLength );
+ break;
+ }
+ palCopyMemory( pMac->hHdd, pSession->ccxCckmInfo.krk, pSetKey->Key, CSR_KRK_KEY_LEN );
+ pSession->ccxCckmInfo.reassoc_req_num=1;
+ pSession->ccxCckmInfo.krk_plumbed = eANI_BOOLEAN_TRUE;
+ status = eHAL_STATUS_SUCCESS;
+ break;
+ }
+#endif /* FEATURE_WLAN_CCX */
+#ifdef WLAN_FEATURE_11W
+ //Check for 11w BIP
+ else if ( eCSR_ENCRYPT_TYPE_AES_CMAC == pSetKey->encType )
+ {
+ tANI_U16 count = 0;
+ if ( pSetKey->keyLength < CSR_AES_KEY_LEN )
+ {
+ smsLog( pMac, LOGW, "Invalid AES/CCMP keylength [= %d] in SetContext call\n", pSetKey->keyLength );
+ break;
+ }
+ pCommand->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN;
+ palCopyMemory( pMac->hHdd, 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
+ palCopyMemory( pMac->hHdd, &pCommand->u.setKeyCmd.peerMac, &pSetKey->peerMac, sizeof(tCsrBssid) );
+ pCommand->u.setKeyCmd.paeRole = pSetKey->paeRole; //0 for supplicant
+ pCommand->u.setKeyCmd.keyId = pSetKey->keyId;
+ palCopyMemory( pMac->hHdd, 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\n"), status );
+ }
+ } while (0);
+
+ // Free the command if there has been a failure, or it is a
+ // "local" operation like the set CCX CCKM KRK key.
+ if( (!HAL_STATUS_SUCCESS( status ) && ( NULL != pCommand ))
+#ifdef FEATURE_WLAN_CCX
+ || ( eCSR_ENCRYPT_TYPE_KRK == pSetKey->encType )
+#endif /* FEATURE_WLAN_CCX */
+ )
+ {
+ 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\n") );
+ status = eHAL_STATUS_CSR_WRONG_STATE;
+ break;
+ }
+ pCommand = csrGetCommandBuffer(pMac);
+ if(NULL == pCommand)
+ {
+ smsLog( pMac, LOGE, FL(" fail to get command buffer\n") );
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ pCommand->command = eSmeCommandRemoveKey;
+ pCommand->sessionId = (tANI_U8)sessionId;
+ pCommand->u.removeKeyCmd.roamId = roamId;
+ pCommand->u.removeKeyCmd.encType = pRemoveKey->encType;
+ palCopyMemory( pMac->hHdd, &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=%02x, %02x, %02x, %02x, %02x, %02x\n"),
+ pRemoveKey->encType, pRemoveKey->keyId,
+ pCommand->u.removeKeyCmd.peerMac[0],
+ pCommand->u.removeKeyCmd.peerMac[1],
+ pCommand->u.removeKeyCmd.peerMac[2],
+ pCommand->u.removeKeyCmd.peerMac[3],
+ pCommand->u.removeKeyCmd.peerMac[4],
+ pCommand->u.removeKeyCmd.peerMac[5]);
+
+ status = csrQueueSmeCommand(pMac, pCommand, fImediate);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), 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(eCSR_ENCRYPT_TYPE_NONE != edType)
+ {
+ palZeroMemory(pMac->hHdd, &setKeyEvent, sizeof(vos_event_wlan_security_payload_type));
+ if( *(( tANI_U8 *)&pCommand->u.setKeyCmd.peerMac) & 0x01 )
+ {
+ setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_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_PTK_REQ;
+ setKeyEvent.encryptionModeUnicast = (v_U8_t)diagEncTypeFromCSRType(pCommand->u.setKeyCmd.encType);
+ setKeyEvent.encryptionModeMulticast = (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType);
+ }
+ palCopyMemory( pMac->hHdd, setKeyEvent.bssid, pSession->connectedProfile.bssid, 6 );
+ if(CSR_IS_ENC_TYPE_STATIC(edType))
+ {
+ 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\n") );
+ //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\n"), 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(eCSR_ENCRYPT_TYPE_NONE != edType)
+ {
+ if( *(( tANI_U8 *)&pCommand->u.setKeyCmd.peerMac) & 0x01 )
+ {
+ setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_RSP;
+ }
+ else
+ {
+ setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_PTK_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);
+
+ palZeroMemory(pMac->hHdd, &removeKeyEvent, sizeof(vos_event_wlan_security_payload_type));
+ 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);
+ palCopyMemory( pMac->hHdd, 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) )
+ {
+ status = palAllocateMemory( pMac->hHdd, (void **)&pMsg, wMsgLen );
+ }
+ else
+ {
+ smsLog( pMac, LOGW, FL(" wrong state not allowed to set key\n") );
+ //Set the error status so error handling kicks in below
+ status = eHAL_STATUS_CSR_WRONG_STATE;
+ }
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ palZeroMemory(pMac->hHdd, pMsg, wMsgLen);
+ 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
+ palCopyMemory( pMac->hHdd, p, &pMac->roam.roamSession[sessionId].connectedProfile.bssid, sizeof(tSirMacAddr) );
+ p += sizeof(tSirMacAddr);
+ // peerMacAddr
+ palCopyMemory( pMac->hHdd, 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 \n"), 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;
+
+ do
+ {
+ if(pProfile->BSSIDs.numOfBSSIDs)
+ {
+ size = sizeof(tCsrBssid) * pProfile->BSSIDs.numOfBSSIDs;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter->BSSIDs.bssid, size);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pScanFilter->BSSIDs.numOfBSSIDs = pProfile->BSSIDs.numOfBSSIDs;
+ palCopyMemory(pMac->hHdd, 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;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter->SSIDs.SSIDList, size);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ palCopyMemory(pMac->hHdd, 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)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter->ChannelInfo.ChannelList, sizeof(*pScanFilter->ChannelInfo.ChannelList) * pProfile->ChannelInfo.numOfChannels);
+ 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\n"), pProfile->ChannelInfo.ChannelList[index]);
+ }
+
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ else
+ {
+ smsLog(pMac, LOGW, FL("Channel list empty\n"));
+ status = eHAL_STATUS_FAILURE;
+ break;
+ }
+ pScanFilter->uapsd_mask = pProfile->uapsd_mask;
+ 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;
+
+ if( pProfile->countryCode[0] )
+ {
+ //This causes the matching function to use countryCode as one of the criteria.
+ palCopyMemory( pMac->hHdd, 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
+
+ }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\n") );
+ 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 )
+ {
+ palCopyMemory( pMac->hHdd, &pCommand->u.wmStatusChangeCmd.u.DisassocIndMsg, pSmeRsp,
+ sizeof( pCommand->u.wmStatusChangeCmd.u.DisassocIndMsg ) );
+ }
+ else
+ {
+ palCopyMemory( pMac->hHdd, &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 \n") );
+ 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\n"));
+ return;
+ }
+
+ if(NULL != pGetRssiReq->rssiCallback)
+ {
+ ((tCsrRssiCallback)(pGetRssiReq->rssiCallback))(rssi, pGetRssiReq->staId, pGetRssiReq->pDevContext);
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL("pGetRssiReq->rssiCallback is NULL\n"));
+ return;
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL("pGetRssiReq is NULL\n"));
+ }
+ return;
+}
+
+void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg )
+{
+ tSirSmeAssocInd *pAssocInd;
+ tSirSmeDisassocInd *pDisassocInd;
+ tSirSmeDeauthInd *pDeauthInd;
+ 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;
+
+#if defined ANI_PRODUCT_TYPE_AP
+ pSirMsg->messageType = pal_be16_to_cpu(pSirMsg->messageType);
+ pSirMsg->length = pal_be16_to_cpu(pSirMsg->length);
+ pSirMsg->statusCode = pal_be32_to_cpu(pSirMsg->statusCode);
+#else
+ pSirMsg->messageType = (pSirMsg->messageType);
+ pSirMsg->length = (pSirMsg->length);
+ pSirMsg->statusCode = (pSirMsg->statusCode);
+#endif
+
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(roamInfo));
+
+ switch( pSirMsg->messageType )
+ {
+ case eWNI_SME_ASSOC_IND:
+ {
+ tCsrRoamSession *pSession;
+ smsLog( pMac, LOG1, FL("ASSOCIATION Indication from SME\n"));
+ pAssocInd = (tSirSmeAssocInd *)pSirMsg;
+ status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pAssocInd->bssId, &sessionId );
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ pSession = CSR_GET_SESSION(pMac, sessionId);
+
+ 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;
+
+ palCopyMemory(pMac->hHdd, pRoamInfo->peerMac, pAssocInd->peerMacAddr, sizeof(tSirMacAddr));
+ palCopyMemory(pMac->hHdd, &pRoamInfo->bssid, pAssocInd->bssId, sizeof(tCsrBssid));
+#ifdef WLAN_SOFTAP_FEATURE
+ pRoamInfo->wmmEnabledSta = pAssocInd->wmmEnabledSta;
+ if(CSR_IS_WDS_AP( pRoamInfo->u.pConnectedProfile))
+#endif
+ status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND);//Sta
+#ifdef WLAN_SOFTAP_FEATURE
+ if(CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile))
+ {
+ 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;
+ }
+ 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
+ }
+#endif
+ /* 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);
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ 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);
+ }
+#endif
+ }
+ }
+ break;
+
+ case eWNI_SME_DISASSOC_IND:
+ smsLog( pMac, LOGE, FL("DISASSOCIATION Indication from MAC\n"));
+
+ // 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
+ pDisassocInd = (tSirSmeDisassocInd *)pSirMsg;
+ status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pDisassocInd->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 CCX and 11r FT connections ONLY.
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (csrRoamIs11rAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac)))
+ {
+ csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
+ }
+#endif
+#ifdef FEATURE_WLAN_CCX
+ if (csrRoamIsCCXAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac)))
+ {
+ csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
+ }
+#endif
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ 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 );
+#ifdef WLAN_SOFTAP_FEATURE
+ if(CSR_IS_INFRA_AP(&pSession->connectedProfile))
+ {
+
+ pRoamInfo = &roamInfo;
+
+ pRoamInfo->statusCode = pDisassocInd->statusCode;
+ pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
+
+ pRoamInfo->staId = (tANI_U8)pDisassocInd->staId;
+
+ palCopyMemory(pMac->hHdd, pRoamInfo->peerMac, pDisassocInd->peerMacAddr, sizeof(tSirMacAddr));
+ palCopyMemory(pMac->hHdd, &pRoamInfo->bssid, pDisassocInd->bssId, sizeof(tCsrBssid));
+
+ status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_DISASSOC_IND);
+ }
+#endif
+ }
+ break;
+
+ case eWNI_SME_DEAUTH_IND:
+ smsLog( pMac, LOG1, FL("DEAUTHENTICATION Indication from MAC\n"));
+ 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 CCX and 11r FT connections ONLY.
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (csrRoamIs11rAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac)))
+ {
+ csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
+ }
+#endif
+#ifdef FEATURE_WLAN_CCX
+ if (csrRoamIsCCXAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac)))
+ {
+ csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
+ }
+#endif
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ 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, eCsrDeauthenticated, pSirMsg );
+#ifdef WLAN_SOFTAP_FEATURE
+ if(CSR_IS_INFRA_AP(&pSession->connectedProfile))
+ {
+
+ pRoamInfo = &roamInfo;
+
+ pRoamInfo->statusCode = pDeauthInd->statusCode;
+ pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
+
+ pRoamInfo->staId = (tANI_U8)pDeauthInd->staId;
+
+ palCopyMemory(pMac->hHdd, pRoamInfo->peerMac, pDeauthInd->peerMacAddr, sizeof(tSirMacAddr));
+ palCopyMemory(pMac->hHdd, &pRoamInfo->bssid, pDeauthInd->bssId, sizeof(tCsrBssid));
+
+ status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_DEAUTH_IND);
+ }
+#endif
+ }
+ 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\n"));
+ 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 ) )
+ {
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+ pSession->connectedProfile.operationChannel = (tANI_U8)pSwitchChnInd->newChannelId;
+ if(pSession->pConnectBssDesc)
+ {
+ pSession->pConnectBssDesc->channelId = (tANI_U8)pSwitchChnInd->newChannelId;
+ }
+ }
+ break;
+
+ case eWNI_SME_DEAUTH_RSP:
+ smsLog( pMac, LOGW, FL("eWNI_SME_DEAUTH_RSP from SME\n"));
+#ifdef WLAN_SOFTAP_FEATURE
+ {
+ 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;
+ palCopyMemory(pMac->hHdd, 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);
+ }
+ }
+ }
+#endif
+ break;
+
+ case eWNI_SME_DISASSOC_RSP:
+ smsLog( pMac, LOGW, FL("eWNI_SME_DISASSOC_RSP from SME subState = %d\n"), pMac->roam.curSubState[sessionId]);
+#ifdef WLAN_SOFTAP_FEATURE
+ {
+ 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;
+ palCopyMemory(pMac->hHdd, 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);
+ }
+ }
+ }
+#endif
+ break;
+
+ case eWNI_SME_MIC_FAILURE_IND:
+ {
+ tpSirSmeMicFailureInd pMicInd = (tpSirSmeMicFailureInd)pSirMsg;
+ tCsrRoamInfo roamInfo, *pRoamInfo = NULL;
+ eCsrRoamResult result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ {
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+ WLAN_VOS_DIAG_EVENT_DEF(secEvent, vos_event_wlan_security_payload_type);
+ palZeroMemory(pMac->hHdd, &secEvent, sizeof(vos_event_wlan_security_payload_type));
+ 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);
+ palCopyMemory( pMac->hHdd, secEvent.bssid, pSession->connectedProfile.bssid, 6 );
+ WLAN_VOS_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY);
+ }
+#endif//FEATURE_WLAN_DIAG_SUPPORT_CSR
+
+ status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pMicInd->bssId, &sessionId );
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ 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);
+ }
+ }
+ break;
+
+#ifdef WLAN_SOFTAP_FEATURE
+ 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\n"));
+
+ status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pProbeReqInd->bssId, &sessionId );
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ 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;
+#endif
+
+
+ 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 );
+ pSession->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED;
+ if(pSession->pConnectBssDesc)
+ {
+ palCopyMemory(pMac->hHdd, &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\n");
+ }
+ 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 );
+ 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 );
+ // 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)
+ {
+ palCopyMemory(pMac->hHdd, pIbssLog->bssid, pNewBss->bssId, 6);
+ if(pNewBss->ssId.length)
+ {
+ palCopyMemory(pMac->hHdd, 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 );
+ 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;
+ palCopyMemory(pMac->hHdd, &roamInfo.bssid, &pNewBss->bssId, sizeof(tCsrBssid));
+ pRoamInfo = &roamInfo;
+ //This BSSID is th ereal BSSID, let's save it
+ if(pSession->pConnectBssDesc)
+ {
+ palCopyMemory(pMac->hHdd, pSession->pConnectBssDesc->bssId, &pNewBss->bssId, sizeof(tCsrBssid));
+ }
+ // Stop the join IBSS timer in case of join, for
+ // genuine merge do nothing
+ if(pSession->ibss_join_pending)
+ {
+ pSession->ibss_join_pending = FALSE;
+ csrRoamStopIbssJoinTimer(pMac, sessionId);
+ result = eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS;
+ }
+ }
+ smsLog(pMac, LOGW, "CSR: eSIR_SME_JOINED_NEW_BSS received from PE\n");
+ 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\n");
+ status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pApNewCaps->bssId, &sessionId );
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ csrScanForCapabilityChange( pMac, pApNewCaps );
+ result = eCSR_ROAM_RESULT_CAP_CHANGED;
+ roamStatus = eCSR_ROAM_GEN_INFO;
+ }
+ 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;
+ palCopyMemory(pMac->hHdd, 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 );
+ // Issue the set Context request to LIM to establish the Unicast STA context for the new peer...
+ if(pSession->pConnectBssDesc)
+ {
+ palCopyMemory(pMac->hHdd, &roamInfo.peerMac, pIbssPeerInd->peerAddr, sizeof(tCsrBssid));
+ palCopyMemory(pMac->hHdd, &roamInfo.bssid, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid));
+ if(pIbssPeerInd->mesgLen > sizeof(tSmeIbssPeerInd))
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&roamInfo.pbFrames,
+ (pIbssPeerInd->mesgLen - sizeof(tSmeIbssPeerInd)));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ roamInfo.nBeaconLength = (pIbssPeerInd->mesgLen - sizeof(tSmeIbssPeerInd));
+ palCopyMemory(pMac->hHdd, 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;
+ status = palAllocateMemory(pMac->hHdd, (void **)&roamInfo.pBssDesc,
+ pSession->pConnectBssDesc->length);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palCopyMemory(pMac->hHdd, roamInfo.pBssDesc, pSession->pConnectBssDesc,
+ pSession->pConnectBssDesc->length);
+ }
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ pRoamInfo = &roamInfo;
+ }
+ else
+ {
+ if(roamInfo.pbFrames)
+ {
+ palFreeMemory(pMac->hHdd, roamInfo.pbFrames);
+ }
+ if(roamInfo.pBssDesc)
+ {
+ palFreeMemory(pMac->hHdd, roamInfo.pBssDesc);
+ }
+ }
+ }
+ else
+ {
+ pRoamInfo = &roamInfo;
+ }
+ 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\n");
+ }
+ //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)
+ {
+ palFreeMemory(pMac->hHdd, roamInfo.pbFrames);
+ }
+ if(roamInfo.pBssDesc)
+ {
+ palFreeMemory(pMac->hHdd, 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)
+ {
+ palCopyMemory(pMac->hHdd, 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\n");
+ roamInfo.staId = (tANI_U8)pIbssPeerInd->staId;
+ roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig;
+ roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig;
+ palCopyMemory(pMac->hHdd, &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 );
+
+#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);
+ palZeroMemory(pMac->hHdd, &setKeyEvent, sizeof(vos_event_wlan_security_payload_type));
+ if( pRsp->peerMacAddr[0] & 0x01 )
+ {
+ setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_RSP;
+ }
+ else
+ {
+ setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_PTK_RSP;
+ }
+ setKeyEvent.encryptionModeMulticast =
+ (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType);
+ setKeyEvent.encryptionModeUnicast =
+ (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType);
+ palCopyMemory( pMac->hHdd, setKeyEvent.bssid, pSession->connectedProfile.bssid, 6 );
+ setKeyEvent.authMode =
+ (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType);
+ if( eSIR_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) )
+ {
+ //We are done with authentication, whethere succeed or not
+ csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId);
+
+ csrRoamStopWaitForKeyTimer( pMac );
+ //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_SUCCESS == pRsp->statusCode )
+ {
+ palCopyMemory( pMac, &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( palEqualMemory( pMac->hHdd, &Broadcastaddr, pRsp->peerMacAddr,
+ sizeof(tSirMacAddr) ) )
+ {
+ 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 %02X-%02X-%02X-%02X-%02X-%02X...\n",
+ pRsp->statusCode, pRsp->peerMacAddr[0], pRsp->peerMacAddr[1], pRsp->peerMacAddr[2],
+ pRsp->peerMacAddr[3], pRsp->peerMacAddr[4], pRsp->peerMacAddr[5] );
+ }
+ 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_CCX
+ //Send Adjacent AP repot to new AP.
+ if (result == eCSR_ROAM_RESULT_AUTHENTICATED &&
+ pSession->isPrevApInfoValid &&
+ pSession->connectedProfile.isCCXAssoc)
+ {
+#ifdef WLAN_FEATURE_VOWIFI
+ csrCcxSendAdjacentApRepMsg(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 ...\n" );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "CSR: SetKey Completion called but NO commands are ACTIVE ...\n" );
+ }
+
+ 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 );
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ {
+ WLAN_VOS_DIAG_EVENT_DEF(removeKeyEvent, vos_event_wlan_security_payload_type);
+ palZeroMemory(pMac->hHdd, &removeKeyEvent, sizeof(vos_event_wlan_security_payload_type));
+ 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);
+ palCopyMemory( pMac->hHdd, removeKeyEvent.bssid, pSession->connectedProfile.bssid, 6 );
+ removeKeyEvent.authMode =
+ (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType);
+ if( eSIR_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_SUCCESS == pRsp->statusCode )
+ {
+ palCopyMemory( pMac, &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 ...\n" );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: SetKey Completion called but NO commands are ACTIVE ...\n" );
+ }
+
+ smeProcessPendingQueue( pMac );
+ }
+ break;
+
+ case eWNI_SME_GET_STATISTICS_RSP:
+ smsLog( pMac, LOGW, FL("Stats rsp from PE\n"));
+ csrRoamStatsRspProcessor( pMac, pSirMsg );
+ break;
+
+ case eWNI_SME_GET_RSSI_REQ:
+ smsLog( pMac, LOGW, FL("GetRssiReq from self\n"));
+ csrUpdateRssi( pMac, pSirMsg );
+ break;
+
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eWNI_SME_FT_PRE_AUTH_RSP:
+ csrRoamFTPreAuthRspProcessor( 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\n"));
+ sessionId = pSmeMaxAssocInd->sessionId;
+ roamInfo.sessionId = sessionId;
+ palCopyMemory(pMac->hHdd, &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\n"));
+ btampEstablishLogLinkHdlr( pSirMsg );
+ break;
+
+ 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 );
+
+ //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\n"));
+ 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(CSR_IS_ROAMING(pSession))
+ {
+ smsLog(pMac, LOGW, " Cancelling roaming\n");
+ 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);
+ 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(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 );
+
+ smsLog(pMac, LOG1, " csrScanStartRoamingTimer \n ");
+ pSession->roamingTimerInfo.sessionId = (tANI_U8)sessionId;
+ status = palTimerStart(pMac->hHdd, pSession->hTimerRoaming, interval, eANI_BOOLEAN_FALSE);
+
+ return (status);
+}
+
+
+eHalStatus csrRoamStopRoamingTimer(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ return (palTimerStop(pMac->hHdd, pMac->roam.roamSession[sessionId].hTimerRoaming));
+}
+
+
+void csrRoamWaitForKeyTimeOutHandler(void *pv)
+{
+ tCsrTimerInfo *pInfo = (tCsrTimerInfo *)pv;
+ tpAniSirGlobal pMac = pInfo->pMac;
+
+ if( CSR_IS_WAIT_FOR_KEY( pMac, pInfo->sessionId ) )
+ {
+ smsLog(pMac, LOGW, " SME pre-auth state timeout. \n ");
+ //Change the substate so command queue is unblocked.
+ csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, pInfo->sessionId);
+ }
+
+}
+
+
+eHalStatus csrRoamStartWaitForKeyTimer(tpAniSirGlobal pMac, tANI_U32 interval)
+{
+ eHalStatus status;
+
+ smsLog(pMac, LOG1, " csrScanStartWaitForKeyTimer \n ");
+ status = palTimerStart(pMac->hHdd, pMac->roam.hTimerWaitForKey, interval, eANI_BOOLEAN_FALSE);
+
+ return (status);
+}
+
+
+eHalStatus csrRoamStopWaitForKeyTimer(tpAniSirGlobal pMac)
+{
+ return (palTimerStop(pMac->hHdd, pMac->roam.hTimerWaitForKey));
+}
+
+
+void csrRoamIbssJoinTimerHandler(void *pv)
+{
+ tCsrTimerInfo *pInfo = (tCsrTimerInfo *)pv;
+ tpAniSirGlobal pMac = pInfo->pMac;
+ eCsrRoamDisconnectReason reason = eCSR_DISCONNECT_REASON_IBSS_JOIN_FAILURE;
+ tANI_U32 sessionId = pInfo->sessionId;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ pSession->ibss_join_pending = FALSE;
+ // JEZ100225: As of main/latest "tip", we are no longer doing this. Check on this.
+ //csrRoamCallCallback(pMac, sessionId, NULL, 0, eCSR_ROAM_IBS_IND, eCSR_ROAM_RESULT_IBSS_JOIN_FAILED);
+ // Send an IBSS stop request to PE
+ csrRoamDisconnectInternal(pMac, sessionId, reason);
+
+}
+
+eHalStatus csrRoamStartIbssJoinTimer(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 interval)
+{
+ eHalStatus status;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOG1, " csrRoamStartIbssJoinTimer \n ");
+ pSession->ibssJoinTimerInfo.sessionId = (tANI_U8)sessionId;
+ status = palTimerStart(pMac->hHdd, pSession->hTimerIbssJoining, interval, eANI_BOOLEAN_FALSE);
+
+ return (status);
+}
+
+eHalStatus csrRoamStopIbssJoinTimer(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ return (palTimerStop(pMac->hHdd, pMac->roam.roamSession[sessionId].hTimerIbssJoining));
+}
+
+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;
+
+ if(pCommand)
+ {
+ roamId = pCommand->u.roamCmd.roamId;
+#if defined(VOSS_ENABLED)
+ VOS_ASSERT( sessionId == pCommand->sessionId );
+#endif
+ }
+
+ if(eCSR_ROAM_ROAMING_COMPLETION == roamStatus)
+ {
+ //if success, force roaming completion
+ csrRoamCompleteRoaming(pMac, sessionId, fSuccess, roamResult);
+ }
+ else
+ {
+ VOS_ASSERT((CSR_GET_SESSION( pMac, sessionId ))->bRefAssocStartCnt == 0);
+ smsLog(pMac, LOGW, FL(" indicates association completion. roamResult = %d\n"), 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 *pRoamInfo = NULL;
+ tCsrRoamInfo roamInfo;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+ //Only need to roam for infra station. In this case P2P client will roam as well
+ tANI_BOOLEAN fToRoam = CSR_IS_INFRASTRUCTURE(&pSession->connectedProfile);
+
+ pSession->fCancelRoaming = eANI_BOOLEAN_FALSE;
+ if ( eWNI_SME_DISASSOC_IND == type )
+ {
+ result = eCSR_ROAM_RESULT_DISASSOC_IND;
+ pDisassocIndMsg = (tSirSmeDisassocInd *)pSirMsg;
+ pSession->roamingStatusCode = pDisassocIndMsg->statusCode;
+ }
+ else if ( eWNI_SME_DEAUTH_IND == type )
+ {
+ result = eCSR_ROAM_RESULT_DEAUTH_IND;
+ pDeauthIndMsg = (tSirSmeDeauthInd *)pSirMsg;
+ pSession->roamingStatusCode = pDeauthIndMsg->statusCode;
+ }
+ else
+ {
+ smsLog(pMac, LOGW, FL("gets an unknown type (%d)\n"), type);
+ result = eCSR_ROAM_RESULT_NONE;
+ }
+
+ // call profile lost link routine here
+#ifdef WLAN_SOFTAP_FEATURE
+ if(!CSR_IS_INFRA_AP(&pSession->connectedProfile))
+#endif
+ {
+ 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(!HAL_STATUS_SUCCESS(status))
+ {
+ //If fail to send confirmation to PE, not to trigger roaming
+ fToRoam = eANI_BOOLEAN_FALSE;
+ }
+
+ //tell HDD to disconnect
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ roamInfo.statusCode = (tSirResultCodes)pSession->roamingStatusCode;
+ roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
+#ifdef WLAN_SOFTAP_FEATURE
+ if( eWNI_SME_DISASSOC_IND == type)
+ {
+ //staMacAddr
+ palCopyMemory(pMac->hHdd, roamInfo.peerMac, pDisassocIndMsg->peerMacAddr, sizeof(tSirMacAddr));
+ roamInfo.staId = (tANI_U8)pDisassocIndMsg->staId;
+ }
+ else if( eWNI_SME_DEAUTH_IND == type )
+ {
+ //staMacAddr
+ palCopyMemory(pMac->hHdd, roamInfo.peerMac, pDeauthIndMsg->peerMacAddr, sizeof(tSirMacAddr));
+ roamInfo.staId = (tANI_U8)pDeauthIndMsg->staId;
+ }
+#endif
+ smsLog(pMac, LOGW, FL("roamInfo.staId (%d)\n"), roamInfo.staId);
+ csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, eCSR_ROAM_LOSTLINK, result);
+ if(fToRoam)
+ {
+ //Only remove the connected BSS in infrastructure mode
+ csrRoamRemoveConnectedBssFromScanCache(pMac, &pSession->connectedProfile);
+ //Not to do anying for lostlink with WDS
+ if( pMac->roam.configParam.nRoamingTime )
+ {
+ if(HAL_STATUS_SUCCESS(status = csrRoamStartRoaming(pMac, sessionId,
+ ( eWNI_SME_DEAUTH_IND == type ) ?
+ eCsrLostlinkRoamingDeauth : eCsrLostlinkRoamingDisassoc)))
+ {
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ //For IBSS, we need to give some more info to HDD
+ if(csrIsBssTypeIBSS(pSession->connectedProfile.BSSType))
+ {
+ roamInfo.u.pConnectedProfile = &pSession->connectedProfile;
+ roamInfo.statusCode = (tSirResultCodes)pSession->roamingStatusCode;
+ roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
+ }
+ else
+ {
+ roamInfo.reasonCode = eCsrRoamReasonSmeIssuedForLostLink;
+ }
+ pRoamInfo = &roamInfo;
+ pSession->roamingReason = ( eWNI_SME_DEAUTH_IND == type ) ?
+ eCsrLostlinkRoamingDeauth : eCsrLostlinkRoamingDisassoc;
+ pSession->roamingStartTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd);
+ csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_LOSTLINK);
+ }
+ else
+ {
+ smsLog(pMac, LOGW, " %s Fail to start roaming, status = %d", __FUNCTION__, status);
+ fToRoam = eANI_BOOLEAN_FALSE;
+ }
+ }
+ else
+ {
+ //We are told not to roam, indicate lostlink
+ fToRoam = eANI_BOOLEAN_FALSE;
+ }
+ }
+
+ if(!fToRoam)
+ {
+ if( eWNI_SME_DISASSOC_IND == type)
+ {
+ //staMacAddr
+ palCopyMemory(pMac->hHdd, roamInfo.peerMac, pDisassocIndMsg->peerMacAddr, sizeof(tSirMacAddr));
+ roamInfo.staId = (tANI_U8)pDisassocIndMsg->staId;
+ }
+ else if( eWNI_SME_DEAUTH_IND == type )
+ {
+ //staMacAddr
+ palCopyMemory(pMac->hHdd, roamInfo.peerMac, pDeauthIndMsg->peerMacAddr, sizeof(tSirMacAddr));
+ roamInfo.staId = (tANI_U8)pDeauthIndMsg->staId;
+ }
+ csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, eCSR_ROAM_LOSTLINK, result);
+
+ /*No need to start idle scan in case of IBSS/SAP
+ Still enable idle scan for polling in case concurrent sessions are running */
+ if(CSR_IS_INFRASTRUCTURE(&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 );
+ 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 ...\n");
+ }
+ }
+ 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\n");
+ }
+
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: WmStatusChange Completion called but LOST LINK command is not ACTIVE ...\n" );
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: WmStatusChange Completion called but NO commands are ACTIVE ...\n" );
+ }
+
+ smeProcessPendingQueue( pMac );
+}
+
+
+void csrRoamProcessWmStatusChangeCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tSirSmeRsp *pSirSmeMsg;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pCommand->sessionId );
+
+ 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\n"), 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\n"));
+ }
+ }
+
+ // 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.
+#ifdef WLAN_SOFTAP_FEATURE
+static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile,
+ tANI_U8 operationChn, eCsrBand *pBand )
+#else
+static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, eCsrPhyMode phyModeIn,
+ tANI_U8 operationChn, eCsrBand *pBand )
+#endif
+{
+
+#ifdef WLAN_SOFTAP_FEATURE
+ eCsrPhyMode phyModeIn = (eCsrPhyMode)pProfile->phyMode;
+ eCsrCfgDot11Mode cfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(pProfile, phyModeIn,
+ pMac->roam.configParam.ProprietaryRatesEnabled);
+#else
+ eCsrCfgDot11Mode cfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(phyModeIn,
+ pMac->roam.configParam.ProprietaryRatesEnabled);
+#endif
+ eCsrBand eBand;
+
+ //If the global setting for dot11Mode is set to auto/abg, we overwrite the setting in the profile.
+#ifdef WLAN_SOFTAP_FEATURE
+ 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) )
+#else
+ if( (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) )
+
+#endif
+ {
+ 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 = eCSR_BAND_24;
+ break;
+ //case eCSR_CFG_DOT11_MODE_BEST:
+ // cfgDot11Mode = eCSR_CFG_DOT11_MODE_BEST;
+ // eBand = eCSR_BAND_24;
+ // 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) )
+ {
+ // channel is a 2.4GHz channel. Set mode to 11g.
+ //
+ // !!LAC - 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 \n"));
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
+ }
+
+ return( cfgDot11Mode );
+}
+
+
+eHalStatus csrRoamIssueStopBss( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamSubState NewSubstate )
+{
+ eHalStatus status;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, 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_STOP_REQ;
+ WLAN_VOS_DIAG_LOG_REPORT(pIbssLog);
+ }
+ }
+#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
+
+ pSession->ibss_join_pending = FALSE;
+ csrRoamStopIbssJoinTimer(pMac, sessionId );
+ // 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 );
+
+ 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));
+}
+
+
+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 tAniCBSecondaryMode csrGetCBModeFromIes(tpAniSirGlobal pMac, tANI_U8 primaryChn, tDot11fBeaconIEs *pIes)
+{
+ tAniCBSecondaryMode eRet = eANI_CB_SECONDARY_NONE;
+ 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))
+ {
+ if(pIes->HTInfo.present)
+ {
+ if(PHY_DOUBLE_CHANNEL_LOW_PRIMARY == pIes->HTInfo.secondaryChannelOffset)
+ {
+ eRet = eANI_CB_SECONDARY_UP;
+ centerChn = primaryChn + CSR_CB_CENTER_CHANNEL_OFFSET;
+ }
+ else if(PHY_DOUBLE_CHANNEL_HIGH_PRIMARY == pIes->HTInfo.secondaryChannelOffset)
+ {
+ eRet = eANI_CB_SECONDARY_DOWN;
+ centerChn = primaryChn - CSR_CB_CENTER_CHANNEL_OFFSET;
+ }
+ else
+ {
+ //PHY_SINGLE_CHANNEL_CENTERED
+ centerChn = primaryChn;
+ eRet = eANI_CB_SECONDARY_NONE;
+ }
+ if((eANI_CB_SECONDARY_NONE != eRet) && !csrRoamIsValid40MhzChannel(pMac, centerChn))
+ {
+ smsLog(pMac, LOGW, " Invalid center channel (%d), disable 40MHz mode\n", centerChn);
+ eRet = eANI_CB_SECONDARY_NONE;
+ }
+ }
+ }
+ }
+
+ 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)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ 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);
+ }
+ palFreeMemory(pMac->hHdd, 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(!palEqualMemory(pMac->hHdd, &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[ idx ]) ) // the max channel# in 11g is 14
+ {
+ channel = csrStartIbssChannels50[ idx ];
+ 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];
+ }
+
+#ifdef WLAN_SOFTAP_FEATURE
+ cfgDot11Mode = csrRoamGetPhyModeBandForBss( pMac, pProfile, operationChannel, &eBand );
+#else
+ cfgDot11Mode = csrRoamGetPhyModeBandForBss( pMac, (eCsrPhyMode)pProfile->phyMode, operationChannel, &eBand );
+#endif
+
+#ifdef WLAN_FEATURE_P2P
+ 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\n"),
+ pProfile->csrPersona);
+ VOS_ASSERT(0);
+ }
+#endif
+
+ 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)\n"), 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:
+#ifdef WLAN_FEATURE_P2P
+ /* 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
+#endif
+ {
+ 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 = eANI_CB_SECONDARY_NONE;
+ pParam->operationChn = pBssDesc->channelId;
+ palCopyMemory( pMac->hHdd, &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\n"),
+ pIes->SuppRates.num_rates);
+ pIes->SuppRates.num_rates = SIR_MAC_RATESET_EID_MAX;
+ }
+ palCopyMemory(pMac->hHdd, pParam->operationalRateSet.rate, pIes->SuppRates.rates,
+ sizeof(*pIes->SuppRates.rates) * pIes->SuppRates.num_rates);
+ }
+ if( pIes->SSID.present )
+ {
+ pParam->ssId.length = pIes->SSID.num_ssid;
+ palCopyMemory(pMac->hHdd, 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;
+}
+
+
+//this function finds a valid secondary channel for channel bonding with "channel".
+//Param: channel -- primary channel, caller must validate it
+// cbChoice -- CB directory
+//Return: if 0, no secondary channel is found. Otherwise a valid secondary channel.
+static tANI_U8 csrRoamGetSecondaryChannel(tpAniSirGlobal pMac, tANI_U8 channel, eCsrCBChoice cbChoice)
+{
+ tANI_U8 chnUp = 0, chnDown = 0, chnRet = 0;
+
+ switch (cbChoice)
+ {
+ case eCSR_CB_OFF:
+ chnUp = 0;
+ chnDown = 0;
+ break;
+ case eCSR_CB_DOWN:
+ chnUp = 0;
+ chnDown = channel - CSR_CB_CHANNEL_GAP;
+ break;
+ case eCSR_CB_UP:
+ chnUp = channel + CSR_CB_CHANNEL_GAP;
+ chnDown = 0;
+ break;
+ case eCSR_CB_AUTO:
+ //consider every other value means auto
+ default:
+ chnUp = channel + CSR_CB_CHANNEL_GAP;
+ chnDown = channel - CSR_CB_CHANNEL_GAP;
+ break;
+ }
+
+ //if CB_UP or auto, try channel up first
+ if(chnUp && CSR_IS_SAME_BAND_CHANNELS(chnUp, channel) && csrRoamIsChannelValid(pMac, chnUp))
+ {
+ //found a valid up channel for channel bonding
+ //check whether the center channel is valid
+ if(csrRoamIsValid40MhzChannel(pMac, channel + CSR_CB_CENTER_CHANNEL_OFFSET))
+ {
+ chnRet = chnUp;
+ }
+ }
+ if(chnRet == 0 && chnDown && CSR_IS_SAME_BAND_CHANNELS(chnDown, channel) && csrRoamIsChannelValid(pMac, chnDown))
+ {
+ //found a valid down channel for channel bonding
+ if(csrRoamIsValid40MhzChannel(pMac, channel - CSR_CB_CENTER_CHANNEL_OFFSET))
+ {
+ chnRet = chnDown;
+ }
+ }
+
+ return chnRet;
+}
+
+
+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;
+ palCopyMemory(pMac->hHdd, pIbssLog->bssid, pBssDesc->bssId, 6);
+ }
+ else
+ {
+ pIbssLog->eventId = WLAN_IBSS_EVENT_START_IBSS_REQ;
+ }
+ palCopyMemory(pMac->hHdd, 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;
+
+
+#ifdef WLAN_SOFTAP_FEATURE
+ 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;
+#endif
+
+
+#ifdef WLAN_SOFTAP_FEATURE
+ pParam->uCfgDot11Mode = csrRoamGetPhyModeBandForBss(pMac, pProfile, pParam->operationChn /* pProfile->operationChannel*/,
+ &eBand);
+#else
+ pParam->uCfgDot11Mode = csrRoamGetPhyModeBandForBss(pMac, (eCsrPhyMode)pProfile->phyMode, pProfile->operationChannel,
+ &eBand);
+#endif
+ pParam->bssPersona = pProfile->csrPersona;
+ // 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, tDot11fBeaconIEs *pIes)
+{
+ tANI_U8 Channel, SecondChn;
+ tAniCBSecondaryMode cbMode = eANI_CB_SECONDARY_NONE;
+ eCsrCBChoice cbChoice;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ 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 ) )
+ {
+ palCopyMemory(pMac->hHdd, &pSession->bssParams.bssid, &pSession->selfMacAddr, sizeof(tCsrBssid));
+ }
+ }
+ else
+ {
+ csrRoamGetBssStartParms(pMac, pProfile, &pSession->bssParams);
+
+ //Use the first SSID
+ if(pProfile->SSIDs.numOfSSIDs)
+ {
+ palCopyMemory(pMac->hHdd, &pSession->bssParams.ssId, pProfile->SSIDs.SSIDList, sizeof(tSirMacSSid));
+ }
+ //For WDS station, use selfMac as the self BSSID
+ if( CSR_IS_WDS_STA( pProfile ) )
+ {
+ palCopyMemory(pMac->hHdd, &pSession->bssParams.bssid, &pSession->selfMacAddr, sizeof(tCsrBssid));
+ }
+ //Use the first BSSID
+ else if( pProfile->BSSIDs.numOfBSSIDs )
+ {
+ palCopyMemory(pMac->hHdd, &pSession->bssParams.bssid, pProfile->BSSIDs.bssid, sizeof(tCsrBssid));
+ }
+ else
+ {
+ palZeroMemory( pMac->hHdd, &pSession->bssParams.bssid, sizeof(tCsrBssid) );
+ }
+ }
+ 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, LOGW, " CSR cannot find a channel to start IBSS\n");
+ }
+ else
+ {
+
+ csrRoamDetermineMaxRateForAdHoc( pMac, &pSession->bssParams.operationalRateSet );
+
+ if( CSR_IS_START_IBSS( pProfile ) )
+ {
+ //TBH: channel bonding is not supported for Libra
+ if( pProfile->ChannelInfo.ChannelList && eCSR_OPERATING_CHANNEL_AUTO != pProfile->ChannelInfo.ChannelList[0] )
+ {
+ Channel = pProfile->ChannelInfo.ChannelList[0];
+ cbChoice = pProfile->CBMode;
+ }
+ else {
+ cbChoice = pMac->roam.configParam.cbChoice;
+ }
+ pSession->bssParams.operationChn = Channel;
+ //make sure channel is valid
+ if(!csrRoamIsChannelValid(pMac, Channel))
+ {
+ //set Channel to 0 to let lim know this is invalid
+ //We still send this request down to lim even though we know the channel is wrong because
+ //lim will response with error and hdd's eWNI_SME_START_BSS_RSP handler will roam other profile (if any)
+ Channel = 0;
+ pSession->bssParams.operationChn = 0;
+ }
+ else {
+ tANI_U32 ChannelBondingMode;
+
+ if(CSR_IS_CHANNEL_24GHZ(Channel))
+ {
+ ChannelBondingMode = pMac->roam.configParam.channelBondingMode24GHz;
+ }
+ else
+ {
+ ChannelBondingMode = pMac->roam.configParam.channelBondingMode5GHz;
+ }
+
+ //now we have a valid channel
+ if(WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != ChannelBondingMode)
+ {
+ //let's pick a secondard channel
+ SecondChn = csrRoamGetSecondaryChannel(pMac, Channel, cbChoice);
+
+ if(SecondChn > Channel)
+ {
+ cbMode = eANI_CB_SECONDARY_UP;
+ }
+ else if(SecondChn && SecondChn < Channel)
+ {
+ cbMode =eANI_CB_SECONDARY_DOWN;
+ }
+ else
+ {
+ cbMode = eANI_CB_SECONDARY_NONE;
+ }
+ pSession->bssParams.cbMode = cbMode;
+ }
+ else
+ {
+ pSession->bssParams.cbMode = eANI_CB_SECONDARY_NONE;
+ }
+ }
+ }
+ }
+}
+
+
+
+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;
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pBssConfig, sizeof(tBssConfigParam));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pBssConfig, sizeof(tBssConfigParam));
+ // 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, NULL);
+ status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile, NULL, pBssConfig, NULL);
+ }
+
+ palFreeMemory(pMac->hHdd, 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( pNewBss )
+ {
+ // Set the operating channel.
+ pSession->connectedProfile.operationChannel = pNewBss->channelNumber;
+ // move the BSSId from the BSS description into the connected state information.
+ palCopyMemory( pMac->hHdd, &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;
+
+ if(!CSR_IS_SESSION_VALID( pMac, sessionId ))
+ {
+ smsLog(pMac, LOGE, FL(" Invalid session ID\n"));
+ return status;
+ }
+ smsLog(pMac, LOGW, "csrRoamSetBKIDCache called, numItems = %d\n", 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)
+ {
+ status = palCopyMemory( pMac->hHdd, pSession->BkidCacheInfo, pBKIDCache,
+ sizeof(tBkidCacheInfo) * numItems );
+ }
+ }
+
+ return (status);
+}
+
+eHalStatus csrRoamGetBKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pNum,
+ tBkidCacheInfo *pBkidCache)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tCsrRoamSession *pSession;
+
+ if(!CSR_IS_SESSION_VALID( pMac, sessionId ))
+ {
+ smsLog(pMac, LOGE, FL(" Invalid session ID\n"));
+ 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_PMKID_ALLOWED)
+ {
+ smsLog(pMac, LOGE, FL("NumPmkidCache :%d is more than CSR_MAX_PMKID_ALLOWED, resetting to CSR_MAX_PMKID_ALLOWED\n"),
+ pSession->NumBkidCache);
+ pSession->NumBkidCache = CSR_MAX_PMKID_ALLOWED;
+ }
+ palCopyMemory( pMac->hHdd, 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 )
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOGW, "csrRoamSetPMKIDCache called, numItems = %d\n", 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);
+ palZeroMemory(pMac->hHdd, &secEvent, sizeof(vos_event_wlan_security_payload_type));
+ 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);
+ palCopyMemory( pMac->hHdd, 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;
+ //numItems may be 0 to clear the cache
+ pSession->NumPmkidCache = (tANI_U16)numItems;
+ if(numItems && pPMKIDCache)
+ {
+ status = palCopyMemory( pMac->hHdd, pSession->PmkidCacheInfo, pPMKIDCache,
+ sizeof(tPmkidCacheInfo) * numItems );
+ }
+ }
+
+ return (status);
+}
+
+
+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 );
+
+ 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\n"),
+ pSession->NumPmkidCache);
+ pSession->NumPmkidCache = CSR_MAX_PMKID_ALLOWED;
+ }
+ palCopyMemory( pMac->hHdd, pPmkidCache, pSession->PmkidCacheInfo,
+ sizeof(tPmkidCacheInfo) * pSession->NumPmkidCache );
+ *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(pLen)
+ {
+ len = *pLen;
+ *pLen = pSession->nWpaRsnReqIeLength;
+ if(pBuf)
+ {
+ if(len >= pSession->nWpaRsnReqIeLength)
+ {
+ status = palCopyMemory(pMac->hHdd, pBuf, pSession->pWpaRsnReqIE, pSession->nWpaRsnReqIeLength);
+ }
+ }
+ }
+
+ 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(pLen)
+ {
+ len = *pLen;
+ *pLen = pSession->nWpaRsnRspIeLength;
+ if(pBuf)
+ {
+ if(len >= pSession->nWpaRsnRspIeLength)
+ {
+ status = palCopyMemory(pMac->hHdd, pBuf, pSession->pWpaRsnRspIE, pSession->nWpaRsnRspIeLength);
+ }
+ }
+ }
+
+ 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(pLen)
+ {
+ len = *pLen;
+ *pLen = pSession->nWapiReqIeLength;
+ if(pBuf)
+ {
+ if(len >= pSession->nWapiReqIeLength)
+ {
+ status = palCopyMemory(pMac->hHdd, pBuf, pSession->pWapiReqIE, pSession->nWapiReqIeLength);
+ }
+ }
+ }
+
+ 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(pLen)
+ {
+ len = *pLen;
+ *pLen = pSession->nWapiRspIeLength;
+ if(pBuf)
+ {
+ if(len >= pSession->nWapiRspIeLength)
+ {
+ status = palCopyMemory(pMac->hHdd, pBuf, pSession->pWapiRspIE, pSession->nWapiRspIeLength);
+ }
+ }
+ }
+
+ 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(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
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter->BSSIDs.bssid, sizeof(tCsrBssid));
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ palCopyMemory(pMac->hHdd, pScanFilter->BSSIDs.bssid, &pConnProfile->bssid, sizeof(tCsrBssid));
+ pScanFilter->BSSIDs.numOfBSSIDs = 1;
+ if(!csrIsNULLSSID(pConnProfile->SSID.ssId, pConnProfile->SSID.length))
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter->SSIDs.SSIDList, sizeof(tCsrSSIDInfo));
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ palCopyMemory(pMac->hHdd, &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->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
+ palFreeMemory(pMac->hHdd, 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);
+ palFreeMemory(pMac->hHdd, 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\n", 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)\n",
+ 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 ( 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
+ {
+#if defined(VOSS_ENABLED)
+ //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 ) );
+#endif
+ palZeroMemory(pMac->hHdd, &bssConfig, sizeof(tBssConfigParam));
+ /* Assume HDD provide bssid in profile */
+ palCopyMemory( pMac->hHdd, &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 );
+ if (HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd,
+ (void **)&pSession->pCurRoamProfile,
+ sizeof(tCsrRoamProfile))))
+ {
+ palZeroMemory(pMac->hHdd, pSession->pCurRoamProfile, sizeof(tCsrRoamProfile));
+ csrRoamCopyProfile(pMac, pSession->pCurRoamProfile, pProfile);
+ }
+
+ //Prepare some more parameters for this WDS
+ csrRoamPrepareBssParams(pMac, sessionId, pProfile, NULL, NULL);
+ status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile, NULL, &bssConfig, NULL);
+ }
+ }
+
+ 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_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;
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&fTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+ *pBuf++ = MIN_STA_PWR_CAP_DBM; // 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
+ *pBuf++ = MAX_STA_PWR_CAP_DBM;
+
+ size = sizeof(pMac->roam.validChannelList);
+ if(HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &size)))
+ {
+ *pBuf++ = (tANI_U8)size; //tSirSupChnl->numChnl
+ for ( i = 0; i < size; i++)
+ {
+ *pBuf++ = pMac->roam.validChannelList[ i ]; //tSirSupChnl->channelList[ i ]
+
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("can not find any valid channel\n"));
+ *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)\n"), uapsdMask);
+ *pBuf++ = 0;
+ }
+#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
+
+
+ // move the entire BssDescription into the join request.
+ palCopyMemory( pMac->hHdd, 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 )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirSmeJoinReq *pMsg;
+ tANI_U8 *pBuf;
+ 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
+
+ do {
+ pSession->joinFailStatusCode.statusCode = eSIR_SME_SUCCESS;
+ pSession->joinFailStatusCode.reasonCode = 0;
+ // 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.
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+ pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_JOIN_REQ);
+ 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++;
+ palCopyMemory( pMac->hHdd, pBuf, pIes->SSID.ssid, pIes->SSID.num_ssid );
+ pBuf += pIes->SSID.num_ssid;
+ }
+ else
+ {
+ *pBuf = 0;
+ pBuf++;
+ }
+
+ // selfMacAddr
+ palCopyMemory( pMac->hHdd, (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
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tSirBssType) );
+ pBuf += sizeof(tSirBssType);
+ // dot11mode
+ *pBuf = (tANI_U8)csrTranslateToWNICfgDot11Mode( pMac, pSession->bssParams.uCfgDot11Mode );
+ pBuf++;
+
+ //Persona
+ *pBuf = (tANI_U8)pProfile->csrPersona;
+ pBuf++;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("CSR PERSONA=%d"), pProfile->csrPersona);
+
+ // uapsdPerAcBitmask
+ *pBuf = pProfile->uapsd_mask;
+ pBuf++;
+
+
+
+#if (WNI_POLARIS_FW_PACKAGE == ADVANCED)
+#endif /*(WNI_POLARIS_FW_PACKAGE == ADVANCED)*/
+
+ status = csrGetRateSet(pMac, pProfile, (eCsrPhyMode)pProfile->phyMode, pBssDescription, pIes, &OpRateSet, &ExRateSet);
+ if (HAL_STATUS_SUCCESS(status) )
+ {
+ // OperationalRateSet
+ if (OpRateSet.numRates) {
+ *pBuf++ = OpRateSet.numRates;
+ palCopyMemory(pMac->hHdd, pBuf, OpRateSet.rate, OpRateSet.numRates);
+ pBuf += OpRateSet.numRates;
+ } else *pBuf++ = 0;
+ // ExtendedRateSet
+ if (ExRateSet.numRates) {
+ *pBuf++ = ExRateSet.numRates;
+ palCopyMemory(pMac->hHdd, pBuf, ExRateSet.rate, ExRateSet.numRates);
+ pBuf += ExRateSet.numRates;
+ } else *pBuf++ = 0;
+ }
+ else
+ {
+ *pBuf++ = 0;
+ *pBuf++ = 0;
+ }
+
+ // 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 ) );
+ }
+#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\n"), 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)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWapiReqIE);
+ }
+ status = palAllocateMemory(pMac->hHdd, (void **)&pSession->pWapiReqIE, ieLen);
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ }
+ pSession->nWapiReqIeLength = ieLen;
+ palCopyMemory(pMac->hHdd, pSession->pWapiReqIE, wpaRsnIE, ieLen);
+ wTmp = pal_cpu_to_be16( ieLen );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof(tANI_U16);
+ palCopyMemory( pMac->hHdd, 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)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWpaRsnReqIE);
+ }
+ status = palAllocateMemory(pMac->hHdd, (void **)&pSession->pWpaRsnReqIE, ieLen);
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ }
+ pSession->nWpaRsnReqIeLength = ieLen;
+ palCopyMemory(pMac->hHdd, pSession->pWpaRsnReqIE, wpaRsnIE, ieLen);
+ wTmp = pal_cpu_to_be16( ieLen );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof(tANI_U16);
+ palCopyMemory( pMac->hHdd, pBuf, wpaRsnIE, ieLen );
+ pBuf += ieLen;
+ }
+ }
+ else
+ {
+ //free whatever old info
+ pSession->nWpaRsnReqIeLength = 0;
+ if(pSession->pWpaRsnReqIE)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWpaRsnReqIE);
+ pSession->pWpaRsnReqIE = NULL;
+ }
+#ifdef FEATURE_WLAN_WAPI
+ pSession->nWapiReqIeLength = 0;
+ if(pSession->pWapiReqIE)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWapiReqIE);
+ pSession->pWapiReqIE = NULL;
+ }
+#endif /* FEATURE_WLAN_WAPI */
+ //length is two bytes
+ *pBuf = 0;
+ *(pBuf + 1) = 0;
+ pBuf += 2;
+ }
+
+#ifdef FEATURE_WLAN_CCX
+ // Never include the cckmIE in an Join Request
+ //length is two bytes
+ *pBuf = 0;
+ *(pBuf + 1) = 0;
+ pBuf += 2;
+#endif
+
+ // addIEScan
+ if(pProfile->nAddIEScanLength && pProfile->pAddIEScan)
+ {
+ ieLen = pProfile->nAddIEScanLength;
+
+ if(ieLen > pSession->nAddIEScanLength)
+ {
+ if(pSession->pAddIEScan && pSession->nAddIEScanLength)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pAddIEScan);
+ }
+ status = palAllocateMemory(pMac->hHdd,
+ (void **)&pSession->pAddIEScan, ieLen);
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ }
+ pSession->nAddIEScanLength = ieLen;
+ palCopyMemory(pMac->hHdd, pSession->pAddIEScan,
+ pProfile->pAddIEScan, ieLen);
+ wTmp = pal_cpu_to_be16( ieLen );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof(tANI_U16);
+ palCopyMemory( pMac->hHdd, pBuf, pProfile->pAddIEScan, ieLen );
+ pBuf += ieLen;
+ }
+ else
+ {
+ pSession->nAddIEScanLength = 0;
+ if(pSession->pAddIEScan)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pAddIEScan);
+ pSession->pAddIEScan = NULL;
+ }
+ *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)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pAddIEAssoc);
+ }
+ status = palAllocateMemory(pMac->hHdd,
+ (void **)&pSession->pAddIEAssoc, ieLen);
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ }
+ pSession->nAddIEAssocLength = ieLen;
+ palCopyMemory(pMac->hHdd, pSession->pAddIEAssoc,
+ pProfile->pAddIEAssoc, ieLen);
+ wTmp = pal_cpu_to_be16( ieLen );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof(tANI_U16);
+ palCopyMemory( pMac->hHdd, pBuf, pProfile->pAddIEAssoc, ieLen );
+ pBuf += ieLen;
+ }
+ else
+ {
+ pSession->nAddIEAssocLength = 0;
+ if(pSession->pAddIEAssoc)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pAddIEAssoc);
+ pSession->pAddIEAssoc = NULL;
+ }
+ *pBuf = 0;
+ *(pBuf + 1) = 0;
+ pBuf += 2;
+ }
+
+ dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedUCEncryptionType) );
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tANI_U32) );
+ pBuf += sizeof(tANI_U32);
+
+ dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedMCEncryptionType) );
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tANI_U32) );
+ pBuf += sizeof(tANI_U32);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (csrIsProfile11r( pProfile ) )
+ {
+ // is11Rconnection;
+ dwTmp = pal_cpu_to_be32(TRUE);
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+ }
+ else
+ {
+ // is11Rconnection;
+ dwTmp = pal_cpu_to_be32(FALSE);
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+ }
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+ /* A profile can not be both CCX and 11R. But an 802.11R AP
+ * may be advertising support for CCX as well. So if we are
+ * associating Open or explicitly CCX then we will get CCX.
+ * If we are associating explictly 11R only then we will get
+ * 11R.
+ */
+ if ((csrIsProfileCCX(pProfile) || ((pIes->CCXVersion.present) && ((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA)))) && (!(csrIsProfile11r( pProfile ))) && (pMac->roam.configParam.isCcxIniFeatureEnabled))
+ {
+ // isCCXconnection;
+ dwTmp = pal_cpu_to_be32(TRUE);
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+ }
+ else
+ {
+ //isCCXconnection;
+ dwTmp = pal_cpu_to_be32(FALSE);
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+ }
+ {
+ tCCXTspecInfo ccxTspec;
+ // CCX-Tspec IEs in the ASSOC request is presently not supported
+ // so nullify the TSPEC parameters
+ palZeroMemory(pMac->hHdd, &ccxTspec, sizeof(tCCXTspecInfo));
+ palCopyMemory( pMac->hHdd, pBuf, &ccxTspec, sizeof(tCCXTspecInfo));
+ pBuf += sizeof(tCCXTspecInfo);
+ }
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX
+ // Fill in isFastTransitionEnabled
+ if (pMac->roam.configParam.isFastTransitionEnabled)
+ {
+ dwTmp = pal_cpu_to_be32(TRUE);
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+ }
+ else
+ {
+ dwTmp = pal_cpu_to_be32(FALSE);
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+ }
+#endif
+
+ //BssDesc
+ csrPrepareJoinReassocReqBuffer( pMac, pBssDescription, pBuf,
+ (tANI_U8)pProfile->uapsd_mask);
+
+ status = palSendMBMessage(pMac->hHdd, pMsg );
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ //Tush-QoS: notify QoS module that join happening
+ else
+ {
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_JOIN_REQ, NULL);
+#endif
+ }
+ } while( 0 );
+ return( status );
+}
+
+
+eHalStatus csrSendSmeReassocReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDescription,
+ tDot11fBeaconIEs *pIes, tCsrRoamProfile *pProfile )
+{
+ eHalStatus status;
+ tSirSmeReassocReq *pMsg;
+ tANI_U8 *pBuf;
+ v_U8_t acm_mask = 0, uapsd_mask;
+ tANI_U16 msgLen, ieLen, wTmp;
+ tANI_U32 dwTmp;
+ tSirMacRateSet OpRateSet;
+ tSirMacRateSet ExRateSet;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+ tANI_U8 wpaRsnIE[DOT11F_IE_RSN_MAX_LEN]; //RSN MAX is bigger than WPA MAX
+
+ /* To satisfy klockworks */
+ if (pBssDescription == NULL)
+ {
+ smsLog(pMac, LOGE, FL(" pBssDescription is NULL\n"));
+ 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( tSirSmeReassocReq ) - 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.
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+ pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_REASSOC_REQ);
+ pMsg->length = pal_cpu_to_be16(msgLen);
+ pBuf = &pMsg->sessionId;
+ // sessionId
+ *pBuf++ = (tANI_U8)sessionId;
+ // 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;
+ palCopyMemory( pMac->hHdd, pBuf, pIes->SSID.ssid, pIes->SSID.num_ssid );
+ pBuf += pIes->SSID.num_ssid;
+ }
+ else
+ {
+ *pBuf++ = 0;
+ }
+ // selfMacAddr
+ palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, &pSession->selfMacAddr, sizeof(tSirMacAddr) );
+ pBuf += sizeof(tSirMacAddr);
+ // bsstype
+ dwTmp = pal_cpu_to_be32( csrTranslateBsstypeToMacType( pProfile->BSSType ) );
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tSirBssType) );
+ pBuf += sizeof(tSirBssType);
+ // dot11mode
+ *pBuf = (tANI_U8)csrTranslateToWNICfgDot11Mode( pMac, pSession->bssParams.uCfgDot11Mode );
+ pBuf++;
+
+ //Persona
+ *pBuf = (tANI_U8)pProfile->csrPersona;
+ pBuf++;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, FL("CSR PERSONA=%d\n"), pProfile->csrPersona);
+
+ // uapsdPerAcBitmask
+ *pBuf = pProfile->uapsd_mask;
+ pBuf++;
+
+
+
+ status = csrGetRateSet(pMac, pProfile, (eCsrPhyMode)pProfile->phyMode,
+ pBssDescription, pIes, &OpRateSet, &ExRateSet);
+ if (HAL_STATUS_SUCCESS(status) )
+ {
+ // OperationalRateSet
+ if (OpRateSet.numRates)
+ {
+ *pBuf++ = OpRateSet.numRates;
+ palCopyMemory(pMac->hHdd, pBuf, OpRateSet.rate, OpRateSet.numRates);
+ pBuf += OpRateSet.numRates;
+ }
+ else *pBuf++ = 0;
+ // ExtendedRateSet
+ if (ExRateSet.numRates)
+ {
+ *pBuf++ = ExRateSet.numRates;
+ palCopyMemory(pMac->hHdd, pBuf, ExRateSet.rate, ExRateSet.numRates);
+ pBuf += ExRateSet.numRates;
+ }
+ else *pBuf++ = 0;
+ }
+ else
+ {
+ *pBuf++ = 0;
+ *pBuf++ = 0;
+ }
+
+ // 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 ) );
+ }
+#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\n"), ieLen, DOT11F_IE_RSN_MAX_LEN);
+ ieLen = DOT11F_IE_RSN_MAX_LEN;
+ }
+
+ //Check whether we need to allocate more memory
+ if(ieLen > pSession->nWpaRsnReqIeLength)
+ {
+ if(pSession->pWpaRsnReqIE && pSession->nWpaRsnReqIeLength)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWpaRsnReqIE);
+ }
+ status = palAllocateMemory(pMac->hHdd, (void **)&pSession->pWpaRsnReqIE, ieLen);
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ }
+ pSession->nWpaRsnReqIeLength = ieLen;
+ palCopyMemory(pMac->hHdd, pSession->pWpaRsnReqIE, wpaRsnIE, ieLen);
+ wTmp = pal_cpu_to_be16( ieLen );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof(tANI_U16);
+ palCopyMemory( pMac->hHdd, pBuf, wpaRsnIE, ieLen );
+ pBuf += ieLen;
+ }
+ else
+ {
+ //free whatever old info
+ pSession->nWpaRsnReqIeLength = 0;
+ if(pSession->pWpaRsnReqIE)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWpaRsnReqIE);
+ pSession->pWpaRsnReqIE = NULL;
+ }
+ //length is two bytes
+ *pBuf = 0;
+ *(pBuf + 1) = 0;
+ pBuf += 2;
+ }
+
+#ifdef FEATURE_WLAN_CCX
+ // cckmIE
+ if( csrIsProfileCCX( pProfile ) )
+ {
+ // Insert the CCKM IE into the join request
+ ieLen = csrConstructCcxCckmIe( pMac,
+ pSession,
+ pProfile,
+ pBssDescription,
+ pSession->pWpaRsnReqIE,
+ pSession->nWpaRsnReqIeLength,
+ (void *)( wpaRsnIE ) );
+ }
+ 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 );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof(tANI_U16);
+ palCopyMemory( pMac->hHdd, 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_CCX */
+
+ // addIEScan
+ if(pProfile->nAddIEScanLength && pProfile->pAddIEScan)
+ {
+ ieLen = pProfile->nAddIEScanLength;
+
+ if(ieLen > pSession->nAddIEScanLength)
+ {
+ if(pSession->pAddIEScan && pSession->nAddIEScanLength)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pAddIEScan);
+ }
+ status = palAllocateMemory(pMac->hHdd,
+ (void **)&pSession->pAddIEScan, ieLen);
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ }
+ pSession->nAddIEScanLength = ieLen;
+ palCopyMemory(pMac->hHdd, pSession->pAddIEScan,
+ pProfile->pAddIEScan, ieLen);
+ wTmp = pal_cpu_to_be16( ieLen );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof(tANI_U16);
+ palCopyMemory( pMac->hHdd, pBuf, pProfile->pAddIEScan, ieLen );
+ pBuf += ieLen;
+ }
+ else
+ {
+ pSession->nAddIEScanLength = 0;
+ if(pSession->pAddIEScan)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pAddIEScan);
+ pSession->pAddIEScan = NULL;
+ }
+ *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)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pAddIEAssoc);
+ }
+ status = palAllocateMemory(pMac->hHdd,
+ (void **)&pSession->pAddIEAssoc, ieLen);
+ if(!HAL_STATUS_SUCCESS(status)) break;
+ }
+ pSession->nAddIEAssocLength = ieLen;
+ palCopyMemory(pMac->hHdd, pSession->pAddIEAssoc,
+ pProfile->pAddIEAssoc, ieLen);
+ wTmp = pal_cpu_to_be16( ieLen );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof(tANI_U16);
+ palCopyMemory( pMac->hHdd, pBuf, pProfile->pAddIEAssoc, ieLen );
+ pBuf += ieLen;
+ }
+ else
+ {
+ pSession->nAddIEAssocLength = 0;
+ if(pSession->pAddIEAssoc)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pAddIEAssoc);
+ pSession->pAddIEAssoc = NULL;
+ }
+ *pBuf = 0;
+ *(pBuf + 1) = 0;
+ pBuf += 2;
+ }
+
+ //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*/
+ uapsd_mask &= ~(acm_mask);
+ }
+ else
+ {
+ uapsd_mask = 0;
+ }
+ }
+
+ dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedUCEncryptionType) );
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tANI_U32) );
+ pBuf += sizeof(tANI_U32);
+
+ dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedMCEncryptionType) );
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tANI_U32) );
+ pBuf += sizeof(tANI_U32);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ // is11Rconnection;
+ dwTmp = csrIsProfile11r( pProfile )? pal_cpu_to_be32(TRUE) : 0;
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+
+#ifdef FEATURE_WLAN_CCX
+ //isCCXconnection;
+ //CCKM profile, ccxversion ie present, not 11r and ini file has CCX enabled
+ dwTmp = ((csrIsProfileCCX(pProfile) || ((pIes->CCXVersion.present) && ((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA)))) && (!(csrIsProfile11r( pProfile ))) && (pMac->roam.configParam.isCcxIniFeatureEnabled)) ? pal_cpu_to_be32(TRUE) : 0;
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+#endif // FEATURE_WLAN_CCX
+#endif // WLAN_FEATURE_VOWIFI_11R
+
+#ifdef FEATURE_WLAN_CCX
+ if ((csrIsProfileCCX(pProfile) || ((pIes->CCXVersion.present) && ((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA)))) && (!(csrIsProfile11r( pProfile ))) && (pMac->roam.configParam.isCcxIniFeatureEnabled))
+ {
+ tCCXTspecInfo ccxTspec;
+
+ // CCX Tspec information
+ palZeroMemory(pMac->hHdd, &ccxTspec, sizeof(tCCXTspecInfo));
+ ccxTspec.numTspecs = sme_QosCCxRetrieveTspecInfo(pMac, sessionId, (tTspecInfo *) &ccxTspec.tspec[0]);
+ *pBuf = ccxTspec.numTspecs;
+ pBuf += sizeof(tANI_U8);
+
+ // Copy the TSPEC information only if present
+ if (ccxTspec.numTspecs) {
+ palCopyMemory(pMac->hHdd, pBuf, (void*)&ccxTspec.tspec[0], (ccxTspec.numTspecs*sizeof(tTspecInfo)));
+ }
+ pBuf += sizeof(ccxTspec.tspec);
+ }
+ else
+ {
+ {
+ tCCXTspecInfo ccxTspec;
+ // CCX-Tspec IEs in the ASSOC request is presently not supported
+ // so nullify the TSPEC parameters
+ palZeroMemory(pMac->hHdd, &ccxTspec, sizeof(tCCXTspecInfo));
+ palCopyMemory( pMac->hHdd, pBuf, &ccxTspec, sizeof(tCCXTspecInfo));
+ pBuf += sizeof(tCCXTspecInfo);
+ }
+ }
+#endif // FEATURE_WLAN_CCX
+
+#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX
+ // Fill in isFastTransitionEnabled
+ if (pMac->roam.configParam.isFastTransitionEnabled)
+ {
+ dwTmp = pal_cpu_to_be32(TRUE);
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+ }
+ else
+ {
+ dwTmp = pal_cpu_to_be32(FALSE);
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) );
+ pBuf += sizeof(tAniBool);
+ }
+#endif
+
+ csrPrepareJoinReassocReqBuffer( pMac, pBssDescription, pBuf, uapsd_mask);
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ //Tush-QoS: notify QoS module that reassoc happening
+ sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_REASSOC_REQ, NULL);
+#endif
+ status = palSendMBMessage( pMac->hHdd, pMsg );
+ } while( 0 );
+
+ return( status );
+
+}
+
+
+//
+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;
+#ifdef WLAN_SOFTAP_FEATURE
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+ if (!CSR_IS_SESSION_VALID( pMac, sessionId ))
+ return eHAL_STATUS_FAILURE;
+#endif
+
+ do {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof( tSirSmeDisassocReq ));
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, sizeof( tSirSmeDisassocReq ));
+ 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);
+
+#ifdef WLAN_SOFTAP_FEATURE
+ if ( (pSession->pCurRoamProfile != NULL ) &&
+ ( reasonCode == eSIR_MAC_UNSPEC_FAILURE_REASON ) &&
+ ((CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) || (CSR_IS_WDS_AP(pSession->pCurRoamProfile))))
+ {
+ // Set the bssid address before sending the message to LIM
+ status = palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, pSession->selfMacAddr, sizeof( tSirMacAddr ) );
+ pBuf = pBuf + sizeof ( tSirMacAddr );
+
+ // Set the peer MAC address before sending the message to LIM
+ status = palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, bssId, sizeof( tSirMacAddr ) ); //perMacAddr is passed as bssId for softAP
+ pBuf = pBuf + sizeof ( tSirMacAddr );
+ }
+ else
+ {
+#endif
+ // Set the peer MAC address before sending the message to LIM
+ status = palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, bssId, sizeof( tSirMacAddr ) );
+ pBuf = pBuf + sizeof ( tSirMacAddr );
+
+ status = palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, bssId, sizeof( pMsg->bssId ) );
+ pBuf = pBuf + sizeof ( tSirMacAddr );
+#ifdef WLAN_SOFTAP_FEATURE
+ }
+#endif
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, pMsg);
+ break;
+ }
+
+ // reasonCode
+ wTmp = pal_cpu_to_be16(reasonCode);
+ status = palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, 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 );
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+eHalStatus csrSendMBTkipCounterMeasuresReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_BOOLEAN bEnable, tSirMacAddr bssId )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirSmeTkipCntrMeasReq *pMsg;
+ tANI_U8 *pBuf;
+
+ do
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof( tSirSmeTkipCntrMeasReq ));
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, sizeof( tSirSmeTkipCntrMeasReq ));
+ 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
+ status = palCopyMemory( pMac->hHdd, pMsg->bssId, bssId, sizeof( tSirMacAddr ) );
+ pBuf = pBuf + sizeof ( tSirMacAddr );
+ // bEnable
+ *pBuf = (tANI_BOOLEAN)bEnable;
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, 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
+ {
+ status = palAllocateMemory( pMac->hHdd, (void **)&pMsg, sizeof( tSirSmeGetAssocSTAsReq ) );
+ if (!HAL_STATUS_SUCCESS(status)) break;
+ palZeroMemory( pMac->hHdd, pMsg, sizeof( tSirSmeGetAssocSTAsReq ) );
+ pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_ASSOC_STAS_REQ);
+
+ pBuf = (tANI_U8 *)&pMsg->bssId;
+ wTmpBuf = pBuf;
+
+ // bssId
+ palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, bssId, sizeof(tSirMacAddr) );
+ pBuf += sizeof(tSirMacAddr);
+
+ // modId
+ dwTmp = pal_cpu_to_be16((tANI_U16)modId);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U16));
+ pBuf += sizeof(tANI_U16);
+
+ // pUsrContext
+ dwTmp = pal_cpu_to_be32((tANI_U32)pUsrContext);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U32));
+ pBuf += sizeof(tANI_U32);
+
+ // pfnSapEventCallback
+ dwTmp = pal_cpu_to_be32((tANI_U32)pfnSapEventCallback);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U32));
+ pBuf += sizeof(tANI_U32);
+
+ // pAssocStasBuf
+ dwTmp = pal_cpu_to_be32((tANI_U32)pAssocStasBuf);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U32));
+ pBuf += sizeof(tANI_U32);
+
+ 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;
+ tANI_U32 dwTmp;
+
+ do
+ {
+ status = palAllocateMemory( pMac->hHdd, (void **)&pMsg, sizeof(tSirSmeGetWPSPBCSessionsReq) );
+ if (!HAL_STATUS_SUCCESS(status)) break;
+ palZeroMemory( pMac->hHdd, pMsg, sizeof( tSirSmeGetWPSPBCSessionsReq ) );
+ pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_WPSPBC_SESSION_REQ);
+
+ pBuf = (tANI_U8 *)&pMsg->pUsrContext;
+ wTmpBuf = pBuf;
+
+ // pUsrContext
+ dwTmp = pal_cpu_to_be32((tANI_U32)pUsrContext);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U32));
+ pBuf += sizeof(tANI_U32);
+
+ // pSapEventCallback
+ dwTmp = pal_cpu_to_be32((tANI_U32)pfnSapEventCallback);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U32));
+ pBuf += sizeof(tANI_U32);
+
+ // bssId
+ palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, bssId, sizeof(tSirMacAddr) );
+ pBuf += sizeof(tSirMacAddr);
+
+ // MAC Address of STA in WPS session
+ palCopyMemory( pMac->hHdd, (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 );
+}
+#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 {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof( tSirSmeDeauthReq ));
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, sizeof( tSirSmeDeauthReq ));
+ 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) && (
+#ifdef WLAN_SOFTAP_FEATURE
+ (CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) ||
+#endif
+ (CSR_IS_WDS_AP(pSession->pCurRoamProfile)))){
+ // Set the BSSID before sending the message to LIM
+ status = palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, pSession->selfMacAddr, sizeof( pMsg->peerMacAddr ) );
+ pBuf = pBuf + sizeof(tSirMacAddr);
+ }
+ else
+ {
+ // Set the BSSID before sending the message to LIM
+ status = palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, bssId, sizeof( pMsg->peerMacAddr ) );
+ pBuf = pBuf + sizeof(tSirMacAddr);
+
+ }
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, pMsg);
+ break;
+ }
+ // Set the peer MAC address before sending the message to LIM
+ status = palCopyMemory( pMac->hHdd, (tSirMacAddr *) pBuf, bssId, sizeof( pMsg->peerMacAddr ) );
+ pBuf = pBuf + sizeof(tSirMacAddr);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, pMsg);
+ break;
+ }
+ wTmp = pal_cpu_to_be16(reasonCode);
+ status = palCopyMemory( pMac->hHdd, pBuf, &wTmp,sizeof( tANI_U16 ) );
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, 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 {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof( tSirSmeDisassocCnf ));
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, sizeof( tSirSmeDisassocCnf ));
+ 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 ));
+ status = palCopyMemory(pMac->hHdd, pMsg->peerMacAddr, pDisassocInd->peerMacAddr, sizeof(pMsg->peerMacAddr));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, pMsg);
+ break;
+ }
+//To test reconn
+ status = palCopyMemory(pMac->hHdd, pMsg->bssId, pDisassocInd->bssId, sizeof(pMsg->peerMacAddr));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, 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 {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof( tSirSmeDeauthCnf ));
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, sizeof( tSirSmeDeauthCnf ));
+ 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 ));
+ status = palCopyMemory(pMac->hHdd, pMsg->bssId, pDeauthInd->bssId, sizeof(pMsg->bssId));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, pMsg);
+ break;
+ }
+ status = palCopyMemory(pMac->hHdd, pMsg->peerMacAddr, pDeauthInd->peerMacAddr, sizeof(pMsg->peerMacAddr));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, 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;
+
+ do {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof( tSirSmeAssocCnf ));
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, sizeof( tSirSmeAssocCnf ));
+ 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);
+ palCopyMemory( pMac->hHdd, pBuf, &statusCode, sizeof(tSirResultCodes) );
+ pBuf += sizeof(tSirResultCodes);
+ // bssId
+ status = palCopyMemory(pMac->hHdd, (tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr));
+ pBuf += sizeof (tSirMacAddr);
+ // peerMacAddr
+ status = palCopyMemory(pMac->hHdd, (tSirMacAddr *)pBuf, pAssocInd->peerMacAddr, sizeof(tSirMacAddr));
+ pBuf += sizeof (tSirMacAddr);
+ // aid
+ wTmp = pal_cpu_to_be16(pAssocInd->aid);
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof (tANI_U16);
+ // alternateBssId
+ status = palCopyMemory(pMac->hHdd, (tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr));
+ pBuf += sizeof (tSirMacAddr);
+ // alternateChannelId
+ *pBuf = 11;
+
+ status = palSendMBMessage( pMac->hHdd, pMsg );
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ //pMsg is freed by palSendMBMessage
+ break;
+ }
+
+ } while( 0 );
+
+ return( status );
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+eHalStatus csrSendAssocIndToUpperLayerCnfMsg( tpAniSirGlobal pMac,
+ tpSirSmeAssocInd pAssocInd,
+ eHalStatus Halstatus,
+ tANI_U8 sessionId)
+{
+ tSirMsgQ msgQ;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirSmeAssocIndToUpperLayerCnf *pMsg;
+ tANI_U8 *pBuf;
+ tSirResultCodes statusCode;
+ tANI_U16 wTmp;
+
+ do {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof( tSirSmeAssocIndToUpperLayerCnf ));
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, sizeof( tSirSmeAssocIndToUpperLayerCnf ));
+ 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);
+ palCopyMemory( pMac->hHdd, pBuf, &statusCode, sizeof(tSirResultCodes) );
+ pBuf += sizeof(tSirResultCodes);
+ // bssId
+ status = palCopyMemory(pMac->hHdd, (tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr));
+ pBuf += sizeof (tSirMacAddr);
+ // peerMacAddr
+ status = palCopyMemory(pMac->hHdd, (tSirMacAddr *)pBuf, pAssocInd->peerMacAddr, sizeof(tSirMacAddr));
+ pBuf += sizeof (tSirMacAddr);
+ // StaId
+ wTmp = pal_cpu_to_be16(pAssocInd->staId);
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof (tANI_U16);
+ // alternateBssId
+ status = palCopyMemory(pMac->hHdd, (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
+ status = palCopyMemory(pMac->hHdd, (tSirRSNie *)pBuf, &pAssocInd->rsnIE, sizeof(tSirRSNie));
+ pBuf += sizeof (tSirRSNie);
+
+ //Additional IE
+ status = palCopyMemory(pMac->hHdd, (void *)pBuf, &pAssocInd->addIE, sizeof(tSirAddie));
+ pBuf += sizeof (tSirAddie);
+
+ //reassocReq
+ *pBuf = pAssocInd->reassocReq;
+ pBuf += sizeof (tANI_U8);
+
+ msgQ.type = eWNI_SME_UPPER_LAYER_ASSOC_CNF;
+ msgQ.bodyptr = pMsg;
+ msgQ.bodyval = 0;
+
+ SysProcessMmhMsg(pMac, &msgQ);
+
+ } while( 0 );
+
+ return( status );
+}
+#endif
+
+
+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;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tAniEdType tmpEdType;
+ tAniKeyDirection tmpDirection;
+ tANI_U8 *pBuf;
+ tANI_U8 *p;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ 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 ) );
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+ 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
+ palCopyMemory( pMac->hHdd, pBuf,
+ (tANI_U8 *)peerMacAddr, sizeof(tSirMacAddr) );
+
+ pBuf += sizeof(tSirMacAddr);
+
+ // bssId
+ palCopyMemory( pMac->hHdd, 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);
+ palCopyMemory( pMac->hHdd, 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);
+ palCopyMemory( pMac->hHdd, p, (tANI_U8 *)&tmpDirection, sizeof(tAniKeyDirection) );
+ p += sizeof(tAniKeyDirection);
+ // pSirKey->keyRsc = ;;
+ palCopyMemory( pMac->hHdd, 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 )
+ {
+ palCopyMemory( pMac->hHdd, p, pKey, keyLength );
+ if(keyLength == 16)
+ {
+ smsLog(pMac, LOGE, " SME Set keyIdx (%d) encType(%d) key = %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
+ keyId, edType, pKey[0], pKey[1], pKey[2], pKey[3], pKey[4],
+ pKey[5], pKey[6], pKey[7], pKey[8],
+ pKey[9], pKey[10], pKey[11], pKey[12], pKey[13], pKey[14], pKey[15]);
+ }
+ }
+
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+
+ } while( 0 );
+
+ return( status );
+}
+
+
+
+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;
+ tAniCBSecondaryMode cbMode;
+#ifdef WLAN_SOFTAP_FEATURE
+ tANI_U32 authType;
+#endif
+
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+ do {
+ pSession->joinFailStatusCode.statusCode = eSIR_SME_SUCCESS;
+ pSession->joinFailStatusCode.reasonCode = 0;
+ msgLen = sizeof(tSirSmeStartBssReq);
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+ 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
+ palCopyMemory( pMac->hHdd, pBuf, pParam->bssid, sizeof(tSirMacAddr) );
+ pBuf += sizeof(tSirMacAddr);
+ // selfMacAddr
+ palCopyMemory( pMac->hHdd, pBuf, pSession->selfMacAddr, sizeof(tSirMacAddr) );
+ pBuf += sizeof(tSirMacAddr);
+ // beaconInterval
+ if( pBssDesc && pBssDesc->beaconInterval )
+ {
+ wTmp = pal_cpu_to_be16( pBssDesc->beaconInterval );
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ else if(pParam->beaconInterval)
+ {
+ wTmp = pal_cpu_to_be16( pParam->beaconInterval );
+ }
+#endif
+ else
+ {
+ wTmp = pal_cpu_to_be16( WNI_CFG_BEACON_INTERVAL_STADEF );
+ }
+ palCopyMemory( pMac->hHdd, 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 ) );
+ palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tSirBssType) );
+ pBuf += sizeof(tSirBssType);
+ // ssId
+ if( pParam->ssId.length )
+ {
+ // ssId len
+ *pBuf = pParam->ssId.length;
+ pBuf++;
+ palCopyMemory( pMac->hHdd, 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 = (tAniCBSecondaryMode)pal_cpu_to_be32(pParam->cbMode);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&cbMode, sizeof(tAniCBSecondaryMode) );
+ pBuf += sizeof(tAniCBSecondaryMode);
+
+#ifdef WLAN_SOFTAP_FEATURE
+ // 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 );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof( tANI_U16 ) );
+ pBuf += sizeof(tANI_U16);
+
+ // Set Auth type
+ authType = pal_cpu_to_be32(pParam->authType);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&authType, sizeof(tANI_U32));
+ pBuf += sizeof(tANI_U32);
+
+ // Set DTIM
+ dwTmp = pal_cpu_to_be32(pParam->dtimPeriod);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U32));
+ pBuf += sizeof(tANI_U32);
+
+ // Set wps_state
+ *pBuf = pParam->wps_state;
+ pBuf++;
+
+#endif
+ //Persona
+ *pBuf = (tANI_U8)pParam->bssPersona;
+ pBuf++;
+
+
+
+ // set RSN IE
+ if( pParam->nRSNIELength > sizeof(pMsg->rsnIE.rsnIEdata) )
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ palFreeMemory( pMac->hHdd, pMsg );
+ break;
+ }
+ wTmp = pal_cpu_to_be16( pParam->nRSNIELength );
+ palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) );
+ pBuf += sizeof(tANI_U16);
+ if( wTmp )
+ {
+ wTmp = pParam->nRSNIELength;
+ palCopyMemory( pMac->hHdd, pBuf, pParam->pRSNIE, wTmp );
+ pBuf += wTmp;
+ }
+ nwType = (tSirNwType)pal_cpu_to_be32(pParam->sirNwType);
+ palCopyMemory( pMac->hHdd, pBuf, (tANI_U8 *)&nwType, sizeof(tSirNwType) );
+ pBuf += sizeof(tSirNwType);
+
+ *pBuf = pParam->operationalRateSet.numRates; //tSirMacRateSet->numRates
+ pBuf++;
+
+ palCopyMemory( pMac->hHdd, pBuf, pParam->operationalRateSet.rate, pParam->operationalRateSet.numRates );
+ pBuf += pParam->operationalRateSet.numRates ;
+ *pBuf++ = pParam->extendedRateSet.numRates;
+ if(0 != pParam->extendedRateSet.numRates)
+ {
+ palCopyMemory( pMac->hHdd, pBuf, pParam->extendedRateSet.rate, pParam->extendedRateSet.numRates );
+ pBuf += pParam->extendedRateSet.numRates;
+ }
+
+ 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;
+
+ do {
+ status = palAllocateMemory(pMac, (void **)&pMsg, sizeof(tSirSmeStopBssReq));
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, sizeof( tSirSmeStopBssReq ));
+ 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) )
+ {
+ palCopyMemory( pMac->hHdd, pBuf,(tANI_U8 *)&pSession->selfMacAddr, sizeof(tSirMacAddr) );
+ }
+ else
+ {
+ palCopyMemory( pMac->hHdd, 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 );
+#if 0
+ status = palAllocateMemory(pMac, (void **)&pMsg, sizeof(tSirSmeStopBssReq));
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+ palZeroMemory(pMac->hHdd, pMsg, sizeof( tSirSmeStopBssReq ));
+ pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_STOP_BSS_REQ);
+ pMsg->reasonCode = 0;
+ // bssid
+ // if BSSType is WDS sta, use selfmacAddr as bssid, else use bssid in connectedProfile
+ if( CSR_IS_CONN_WDS_STA(&pSession->connectedProfile) )
+ {
+ pbBssid = (tANI_U8 *)&pSession->selfMacAddr;
+ }
+ else
+ {
+ pbBssid = (tANI_U8 *)&pSession->connectedProfile.bssid;
+ }
+ palCopyMemory( pMac->hHdd, &pMsg->bssId, pbBssid, sizeof(tSirMacAddr) );
+ pMsg->transactionId = 0;
+ pMsg->sessionId = (tANI_U8)sessionId;
+ pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeStopBssReq ));
+ status = palSendMBMessage( pMac->hHdd, pMsg );
+#endif
+ } while( 0 );
+
+ 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 || (!palEqualMemory(pMac->hHdd, &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;
+
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ 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\n", __FUNCTION__);
+ 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\n", pRsp->status );
+ //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 ...\n",
+ __FUNCTION__);
+ status = eHAL_STATUS_FAILURE;
+ break;
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "in %s eWNI_SME_ADD_STA_SELF_RSP Received but NO commands are ACTIVE ...\n",
+ __FUNCTION__);
+ status = eHAL_STATUS_FAILURE;
+ break;
+ }
+ } while(0);
+
+ return status;
+
+}
+
+eHalStatus csrSendMBAddSelfStaReqMsg( tpAniSirGlobal pMac, tSirMacAddr macAddr )
+{
+ tSirSmeAddStaSelfReq *pMsg;
+ tANI_U16 msgLen;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+
+ do {
+
+ msgLen = sizeof( tANI_U16 ) + sizeof( tANI_U16 ) + sizeof( tSirMacAddr ) /*+
+ sizeof( tSirBssType )*/;
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+
+ pMsg->mesgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_ADD_STA_SELF_REQ);
+ pMsg->mesgLen = pal_cpu_to_be16(msgLen);
+
+ // self station address
+ palCopyMemory( pMac->hHdd, (tANI_U8 *)pMsg->selfMacAddr, (tANI_U8 *)macAddr, sizeof(tSirMacAddr) );
+
+ smsLog( pMac, LOGE, FL("selfMac=%02x, %02x, %02x, %02x, %02x, %02x\n"),
+ pMsg->selfMacAddr[0],
+ pMsg->selfMacAddr[1],
+ pMsg->selfMacAddr[2],
+ pMsg->selfMacAddr[3],
+ pMsg->selfMacAddr[4],
+ pMsg->selfMacAddr[5]);
+ 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;
+ palCopyMemory( pMac->hHdd, pCommand->u.addStaSessionCmd.selfMacAddr, sessionMacAddr, sizeof( tSirMacAddr ) );
+
+ status = csrQueueSmeCommand(pMac, pCommand, TRUE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ //Should be panic??
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ }
+ }
+
+ return (status);
+}
+
+eHalStatus csrProcessAddStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ return csrSendMBAddSelfStaReqMsg( pMac,
+ pCommand->u.addStaSessionCmd.selfMacAddr );
+}
+
+eHalStatus csrRoamOpenSession( tpAniSirGlobal pMac, csrRoamCompleteCallback callback, void *pContext,
+ tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_U32 i;
+ tCsrRoamSession *pSession;
+
+ *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;
+ palCopyMemory( pMac->hHdd, &pSession->selfMacAddr, pSelfMacAddr, sizeof(tCsrBssid) );
+ *pbSessionId = (tANI_U8)i;
+
+ status = palTimerAlloc(pMac->hHdd, &pSession->hTimerRoaming, csrRoamRoamingTimerHandler,
+ &pSession->roamingTimerInfo);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("cannot allocate memory for Roaming timer\n"));
+ break;
+ }
+#ifdef FEATURE_WLAN_BTAMP_UT_RF
+ status = palTimerAlloc(pMac->hHdd, &pSession->hTimerJoinRetry, csrRoamJoinRetryTimerHandler,
+ &pSession->joinRetryTimerInfo);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("cannot allocate memory for joinretry timer\n"));
+ break;
+ }
+#endif
+ pSession->ibssJoinTimerInfo.pMac = pMac;
+ pSession->ibssJoinTimerInfo.sessionId = CSR_SESSION_ID_INVALID;
+
+ status = palTimerAlloc(pMac->hHdd, &pSession->hTimerIbssJoining, csrRoamIbssJoinTimerHandler,
+ &pSession->ibssJoinTimerInfo);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("cannot allocate memory for IbssJoining timer\n"));
+ break;
+ }
+ 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\n", __FUNCTION__);
+ 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\n", 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\n", __FUNCTION__);
+ return status;
+ }
+ }
+ else {
+ smsLog(pMac, LOGE, "%s: Failed to Release Lock\n", __FUNCTION__);
+ }
+ }
+
+ //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 ...\n",
+ __FUNCTION__);
+ status = eHAL_STATUS_FAILURE;
+ break;
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "in %s eWNI_SME_DEL_STA_SELF_RSP Received but NO commands are ACTIVE ...\n",
+ __FUNCTION__);
+ 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 )*/;
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if ( !HAL_STATUS_SUCCESS(status) ) break;
+
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+
+ pMsg->mesgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DEL_STA_SELF_REQ);
+ pMsg->mesgLen = pal_cpu_to_be16(msgLen);
+
+ // self station address
+ palCopyMemory( pMac->hHdd, (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,
+ 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;
+ palCopyMemory( pMac->hHdd, pCommand->u.delStaSessionCmd.selfMacAddr, sessionMacAddr, sizeof( tSirMacAddr ) );
+
+ status = csrQueueSmeCommand(pMac, pCommand, TRUE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ //Should be panic??
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ }
+ }
+
+ return (status);
+}
+
+eHalStatus csrProcessDelStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ return csrSendMBDelSelfStaReqMsg( pMac,
+ pCommand->u.delStaSessionCmd.selfMacAddr );
+}
+
+static void purgeCsrSessionCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ 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(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);
+ palTimerFree(pMac->hHdd, pSession->hTimerRoaming);
+#ifdef FEATURE_WLAN_BTAMP_UT_RF
+ palTimerFree(pMac->hHdd, pSession->hTimerJoinRetry);
+#endif
+ palTimerFree(pMac->hHdd, pSession->hTimerIbssJoining);
+ purgeSmeSessionCmdList(pMac, sessionId);
+ purgeCsrSessionCmdList(pMac, sessionId);
+ csrInitSession(pMac, sessionId);
+ }
+}
+
+
+eHalStatus csrRoamCloseSession( tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tANI_BOOLEAN fSync,
+ 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
+ {
+ purgeSmeSessionCmdList(pMac, sessionId);
+ purgeCsrSessionCmdList(pMac, sessionId);
+ status = csrIssueDelStaForSessionReq( pMac, sessionId,
+ 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 );
+
+ pSession->sessionActive = eANI_BOOLEAN_FALSE;
+ pSession->sessionId = CSR_SESSION_ID_INVALID;
+ pSession->callback = NULL;
+ pSession->pContext = NULL;
+ pSession->ibss_join_pending = FALSE;
+ 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);
+ palZeroMemory( pMac->hHdd, &pSession->selfMacAddr, sizeof(tCsrBssid) );
+ if(pSession->pWpaRsnReqIE)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWpaRsnReqIE);
+ pSession->pWpaRsnReqIE = NULL;
+ }
+ pSession->nWpaRsnReqIeLength = 0;
+ if(pSession->pWpaRsnRspIE)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWpaRsnRspIE);
+ pSession->pWpaRsnRspIE = NULL;
+ }
+ pSession->nWpaRsnRspIeLength = 0;
+#ifdef FEATURE_WLAN_WAPI
+ if(pSession->pWapiReqIE)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWapiReqIE);
+ pSession->pWapiReqIE = NULL;
+ }
+ pSession->nWapiReqIeLength = 0;
+ if(pSession->pWapiRspIE)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pWapiRspIE);
+ pSession->pWapiRspIE = NULL;
+ }
+ pSession->nWapiRspIeLength = 0;
+#endif /* FEATURE_WLAN_WAPI */
+
+ if(pSession->pAddIEScan)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pAddIEScan);
+ pSession->pAddIEScan = NULL;
+ }
+ pSession->nAddIEScanLength = 0;
+
+ if(pSession->pAddIEAssoc)
+ {
+ palFreeMemory(pMac->hHdd, 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);
+}
+
+static void csrRoamLinkUp(tpAniSirGlobal pMac, tCsrBssid bssid)
+{
+ /* 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= %02x-%02x-%02x-%02x-%02x-%02x\n",
+ bssid[ 0 ], bssid[ 1 ], bssid[ 2 ],
+ bssid[ 3 ], bssid[ 4 ], bssid[ 5 ] );
+
+ /* 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;
+
+ /* Indicate the neighbor roal algorithm about the connect indication */
+ csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)bssid, &sessionId);
+ csrNeighborRoamIndicateConnect(pMac, sessionId, VOS_STATUS_SUCCESS);
+ }
+#endif
+
+}
+
+
+static void csrRoamLinkDown(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ //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
+
+}
+
+
+void csrRoamTlStatsTimerHandler(void *pv)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pv );
+ eHalStatus status;
+
+ pMac->roam.tlStatsReqInfo.timerRunning = FALSE;
+
+#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\n"));
+ }
+ else
+ {
+ //save in SME
+ csrRoamSaveStatsFromTl(pMac, tlStats);
+ }
+#endif
+ if(!pMac->roam.tlStatsReqInfo.timerRunning)
+ {
+ if(pMac->roam.tlStatsReqInfo.periodicity)
+ {
+ //start timer
+ status = palTimerStart(pMac->hHdd, pMac->roam.tlStatsReqInfo.hTlStatsTimer,
+ pMac->roam.tlStatsReqInfo.periodicity * PAL_TIMER_TO_MS_UNIT, eANI_BOOLEAN_FALSE);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("csrRoamTlStatsTimerHandler:cannot start TlStatsTimer timer\n"));
+ 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\n"));
+ }
+
+ // Free the entry
+ palFreeMemory(pMac->hHdd, 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\n"));
+ }
+ 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\n"));
+ 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\n"));
+
+ }
+#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;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof(tAniGetPEStatsReq));
+ if ( !HAL_STATUS_SUCCESS(status) )
+ {
+ smsLog(pMac, LOG1, " csrSendMBStatsReqMsg: failed to allocate mem for stats req \n");
+ return status;
+ }
+ // need to initiate a stats request to PE
+ pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_STATISTICS_REQ);
+ pMsg->msgLen = (tANI_U16)sizeof(tAniGetPEStatsReq);
+ pMsg->staId = staId;
+ pMsg->statsMask = statsMask;
+
+ status = palSendMBMessage(pMac->hHdd, pMsg );
+
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOG1, " csrSendMBStatsReqMsg: failed to send down the stats req \n");
+ }
+
+ 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;
+ tANI_U32 *pRssi = NULL;
+
+ pSmeStatsRsp = (tAniGetPEStatsRsp *)pSirMsg;
+ if(pSmeStatsRsp->rc)
+ {
+ smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:stats rsp from PE shows failure\n"));
+ 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, LOG1, FL("csrRoamStatsRspProcessor:summary stats\n"));
+ status = palCopyMemory(pMac->hHdd, (tANI_U8 *)&pMac->roam.summaryStatsInfo,
+ pStats, sizeof(tCsrSummaryStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:failed to copy summary stats\n"));
+ }
+ pStats += sizeof(tCsrSummaryStatsInfo);
+ length -= sizeof(tCsrSummaryStatsInfo);
+ break;
+
+ case eCsrGlobalClassAStats:
+ smsLog( pMac, LOG1, FL("csrRoamStatsRspProcessor:ClassA stats\n"));
+ status = palCopyMemory(pMac->hHdd, (tANI_U8 *)&pMac->roam.classAStatsInfo,
+ pStats, sizeof(tCsrGlobalClassAStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:failed to copy ClassA stats\n"));
+ }
+ pStats += sizeof(tCsrGlobalClassAStatsInfo);
+ length -= sizeof(tCsrGlobalClassAStatsInfo);
+ break;
+
+ case eCsrGlobalClassBStats:
+ smsLog( pMac, LOG1, FL("csrRoamStatsRspProcessor:ClassB stats\n"));
+ status = palCopyMemory(pMac->hHdd, (tANI_U8 *)&pMac->roam.classBStatsInfo,
+ pStats, sizeof(tCsrGlobalClassBStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:failed to copy ClassB stats\n"));
+ }
+ pStats += sizeof(tCsrGlobalClassBStatsInfo);
+ length -= sizeof(tCsrGlobalClassBStatsInfo);
+ break;
+
+ case eCsrGlobalClassCStats:
+ smsLog( pMac, LOG1, FL("csrRoamStatsRspProcessor:ClassC stats\n"));
+ status = palCopyMemory(pMac->hHdd, (tANI_U8 *)&pMac->roam.classCStatsInfo,
+ pStats, sizeof(tCsrGlobalClassCStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:failed to copy ClassC stats\n"));
+ }
+ pStats += sizeof(tCsrGlobalClassCStatsInfo);
+ length -= sizeof(tCsrGlobalClassCStatsInfo);
+ break;
+
+ case eCsrPerStaStats:
+ smsLog( pMac, LOG1, FL("csrRoamStatsRspProcessor:PerSta stats\n"));
+ if( CSR_MAX_STA > pSmeStatsRsp->staId )
+ {
+ status = palCopyMemory(pMac->hHdd, (tANI_U8 *)&pMac->roam.perStaStatsInfo[pSmeStatsRsp->staId],
+ pStats, sizeof(tCsrPerStaStatsInfo));
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ smsLog( pMac, LOGE, FL("csrRoamStatsRspProcessor:out bound staId:%d\n"), pSmeStatsRsp->staId);
+ VOS_ASSERT( 0 );
+ }
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:failed to copy PerSta stats\n"));
+ }
+ pStats += sizeof(tCsrPerStaStatsInfo);
+ length -= sizeof(tCsrPerStaStatsInfo);
+ break;
+
+ default:
+ smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:unknown stats type\n"));
+ 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;
+ }
+ else
+ {
+ /* If riva is not sending rssi, continue to use the hack */
+ rssi = RSSI_HACK_BMPS;
+ }
+ WDA_UpdateRssiBmps(pvosGCtx, pSmeStatsRsp->staId, rssi);
+
+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, LOGW, "csrRoamFindInPeStatsReqList: List empty, no request to PE\n");
+ return NULL;
+ }
+
+ while( pEntry )
+ {
+ pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrPeStatsReqInfo, link );
+
+ if(pTempStaEntry->statsMask == statsMask)
+ {
+ smsLog(pMac, LOGW, "csrRoamFindInPeStatsReqList: match found\n");
+ 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, LOGW, "csrRoamChecknUpdateClientReqList: List empty, no request from "
+ "upper layer client(s)\n");
+ return NULL;
+ }
+
+ while( pEntry )
+ {
+ pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link );
+
+ if((pTempStaEntry->requesterId == pStaEntry->requesterId) &&
+ (pTempStaEntry->statsMask == pStaEntry->statsMask))
+ {
+ smsLog(pMac, LOGW, "csrRoamChecknUpdateClientReqList: match found\n");
+ 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, LOGW, "csrRoamCheckClientReqList: List empty, no request from "
+ "upper layer client(s)\n");
+ return NULL;
+ }
+
+ while( pEntry )
+ {
+ pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link );
+
+ if((pTempStaEntry->statsMask & ~(1 << eCsrGlobalClassDStats)) == statsMask)
+ {
+ smsLog(pMac, LOGW, "csrRoamCheckClientReqList: match found\n");
+
+ 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\n",
+ ul_mac_loss_trigger_threshold );
+
+ if(ul_mac_loss_trigger_threshold < ul_mac_loss)
+ {
+ smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality is POOR \n");
+ newVccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND;
+ }
+ else
+ {
+ smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality is GOOD\n");
+ 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\n");
+ if(NULL != pMac->roam.linkQualityIndInfo.callback)
+ {
+ smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality indication %d\n",
+ 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\n",
+ pMac->roam.configParam.vccRssiThreshold);
+ if(!csrIsConnStateConnectedInfra(pMac, sessionId))
+ {
+ smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: ignoring the indication as we are not connected\n");
+ return VOS_STATUS_SUCCESS;
+ }
+
+ if(WLANTL_HO_THRESHOLD_DOWN == rssiNotification)
+ {
+ smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality is POOR\n");
+ newVccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND;
+ }
+ else if(WLANTL_HO_THRESHOLD_UP == rssiNotification)
+ {
+ smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality is GOOD \n");
+ newVccLinkQuality = eCSR_ROAM_LINK_QUAL_GOOD_IND;
+ }
+ else
+ {
+ smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: unknown rssi notification %d\n", 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\n");
+ if(NULL != pMac->roam.linkQualityIndInfo.callback)
+ {
+ smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality indication %d\n",
+ 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;
+
+ eHalStatus status;
+
+ //if same entity requested for same set of stats with different periodicity &
+ // callback update it
+ if(NULL == csrRoamChecknUpdateClientReqList(pMac, pStaEntry, TRUE))
+ {
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pNewStaEntry, sizeof(tCsrStatsClientReqInfo));
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGW, "csrRoamInsertEntryIntoList: couldn't allocate memory for the "
+ "entry\n");
+ 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;
+
+ eHalStatus status;
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pNewStaEntry, sizeof(tCsrPeStatsReqInfo));
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGW, "csrRoamInsertEntryIntoPeStatsReqList: couldn't allocate memory for the "
+ "entry\n");
+ 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"));
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof(tAniGetRssiReq));
+ if ( !HAL_STATUS_SUCCESS(status) )
+ {
+ smsLog(pMac, LOGE, " csrGetRssi: failed to allocate mem for req \n");
+ return status;
+ }
+
+ 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 \n");
+ palFreeMemory(pMac->hHdd, (void *)pMsg);
+ status = eHAL_STATUS_FAILURE;
+ }
+ smsLog(pMac, LOG2, FL("returned"));
+ return status;
+}
+
+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;
+
+ if( csrIsAllSessionDisconnected(pMac) )
+ {
+ //smsLog(pMac, LOGW, "csrGetStatistics: wrong state curState(%d) not connected\n", pMac->roam.curState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if((!statsMask) && (!callback))
+ {
+ //msg
+ smsLog(pMac, LOGW, "csrGetStatistics: statsMask & callback empty in the request\n");
+ 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\n");
+ return eHAL_STATUS_FAILURE;
+ }
+ else
+ {
+ //clean up & return
+ pStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link );
+ 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 = palTimerStop(pMac->hHdd, pMac->roam.tlStatsReqInfo.hTlStatsTimer);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("csrGetStatistics:cannot stop TlStatsTimer timer\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+ pMac->roam.tlStatsReqInfo.periodicity = 0;
+ pMac->roam.tlStatsReqInfo.timerRunning = FALSE;
+ }
+ 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("csrGetStatistics:failed to destroy Client req timer\n"));
+ }
+
+ 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\n"));
+ }
+ 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)
+ {
+#if 0
+ // TODO Session Specific info connectedInfo
+ //req TL for class D stats
+ if(WLANTL_GetStatistics(pMac->roam.gVosContext, &tlStats, pMac->roam.connectedInfo.staId))
+ {
+ smsLog(pMac, LOGE, FL("csrGetStatistics:couldn't get the stats from TL\n"));
+ }
+ else
+ {
+ //save in SME
+ csrRoamSaveStatsFromTl(pMac, tlStats);
+ }
+#endif
+ if(pMac->roam.tlStatsReqInfo.periodicity)
+ {
+ //start timer
+ status = palTimerStart(pMac->hHdd, pMac->roam.tlStatsReqInfo.hTlStatsTimer,
+ pMac->roam.tlStatsReqInfo.periodicity * PAL_TIMER_TO_MS_UNIT, eANI_BOOLEAN_FALSE);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("csrGetStatistics:cannot start TlStatsTimer timer\n"));
+ 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\n"));
+ }
+ //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))
+ {
+#if 0
+ // TODO : Per Session info connectedInfo
+ //req TL for class D stats
+ if(WLANTL_GetStatistics(pMac->roam.gVosContext, &tlStats, pMac->roam.connectedInfo.staId))
+ {
+ smsLog(pMac, LOGE, FL("csrGetStatistics:couldn't get the stats from TL\n"));
+ }
+ else
+ {
+ //save in SME
+ csrRoamSaveStatsFromTl(pMac, tlStats);
+ }
+#endif
+
+ }
+ //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\n");
+ return eHAL_STATUS_FAILURE;
+ }
+ //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\n"));
+ 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\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ }
+
+ }
+
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+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
+ {
+ palZeroMemory(pMac->hHdd, &staEntry, sizeof(tCsrPeStatsReqInfo));
+ 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\n");
+ 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\n"));
+ }
+ 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\n"));
+ return NULL;
+ }
+
+ }
+ //start timer
+ smsLog(pMac, LOG1, "csrRoamCheckPeStatsReqList:peStatsTimer period %d\n", 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\n"));
+ 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))
+ {
+ palFreeMemory(pMac->hHdd, 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, LOGW, "csrRoamRemoveEntryFromPeStatsReqList: List empty, no stats req for PE\n");
+ return;
+ }
+
+ while( pEntry )
+ {
+ pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrPeStatsReqInfo, link );
+
+ if( pTempStaEntry && pTempStaEntry->statsMask == pPeStaEntry->statsMask)
+ {
+ smsLog(pMac, LOGW, "csrRoamRemoveEntryFromPeStatsReqList: match found\n");
+ 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\n"));
+ }
+ }
+ 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)
+ {
+ palFreeMemory(pMac->hHdd, pTempStaEntry);
+ pTempStaEntry = NULL;
+ }
+ break;
+ }
+
+ pEntry = csrLLNext( &pMac->roam.peStatsReqList, pEntry, LL_ACCESS_NOLOCK );
+ }
+ }
+
+ return;
+}
+
+
+void csrRoamSaveStatsFromTl(tpAniSirGlobal pMac, WLANTL_TRANSFER_STA_TYPE tlStats)
+{
+
+ pMac->roam.classDStatsInfo.num_rx_bytes_crc_ok = tlStats.rxBcntCRCok;
+ pMac->roam.classDStatsInfo.rx_bc_byte_cnt = tlStats.rxBCBcnt;
+ pMac->roam.classDStatsInfo.rx_bc_frm_cnt = tlStats.rxBCFcnt;
+ pMac->roam.classDStatsInfo.rx_byte_cnt = tlStats.rxBcnt;
+ pMac->roam.classDStatsInfo.rx_mc_byte_cnt = tlStats.rxMCBcnt;
+ pMac->roam.classDStatsInfo.rx_mc_frm_cnt = tlStats.rxMCFcnt;
+ pMac->roam.classDStatsInfo.rx_rate = tlStats.rxRate;
+ //?? need per AC
+ pMac->roam.classDStatsInfo.rx_uc_byte_cnt[0] = tlStats.rxUCBcnt;
+ pMac->roam.classDStatsInfo.rx_uc_frm_cnt = tlStats.rxUCFcnt;
+ pMac->roam.classDStatsInfo.tx_bc_byte_cnt = tlStats.txBCBcnt;
+ pMac->roam.classDStatsInfo.tx_bc_frm_cnt = tlStats.txBCFcnt;
+ pMac->roam.classDStatsInfo.tx_mc_byte_cnt = tlStats.txMCBcnt;
+ pMac->roam.classDStatsInfo.tx_mc_frm_cnt = tlStats.txMCFcnt;
+ //?? need per AC
+ pMac->roam.classDStatsInfo.tx_uc_byte_cnt[0] = tlStats.txUCBcnt;
+ pMac->roam.classDStatsInfo.tx_uc_frm_cnt = tlStats.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;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+
+ if(!callback)
+ {
+ smsLog(pMac, LOGE, FL("csrRoamReportStatistics:cannot report callback NULL\n"));
+ return;
+ }
+ if(!statsMask)
+ {
+ smsLog(pMac, LOGE, FL("csrRoamReportStatistics:cannot report statsMask is 0\n"));
+ 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, LOG1, FL("csrRoamReportStatistics:summary stats\n"));
+ status = palCopyMemory(pMac->hHdd, pStats, (tANI_U8 *)&pMac->roam.summaryStatsInfo,
+ sizeof(tCsrSummaryStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:failed to copy summary stats\n"));
+ }
+ pStats += sizeof(tCsrSummaryStatsInfo);
+ break;
+
+ case eCsrGlobalClassAStats:
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:ClassA stats\n"));
+ status = palCopyMemory(pMac->hHdd, pStats, (tANI_U8 *)&pMac->roam.classAStatsInfo,
+ sizeof(tCsrGlobalClassAStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:failed to copy ClassA stats\n"));
+ }
+ pStats += sizeof(tCsrGlobalClassAStatsInfo);
+
+ break;
+
+ case eCsrGlobalClassBStats:
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:ClassB stats\n"));
+ status = palCopyMemory(pMac->hHdd, pStats, (tANI_U8 *)&pMac->roam.classBStatsInfo,
+ sizeof(tCsrGlobalClassBStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:failed to copy ClassB stats\n"));
+ }
+ pStats += sizeof(tCsrGlobalClassBStatsInfo);
+
+ break;
+
+ case eCsrGlobalClassCStats:
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:ClassC stats\n"));
+ status = palCopyMemory(pMac->hHdd, pStats, (tANI_U8 *)&pMac->roam.classCStatsInfo,
+ sizeof(tCsrGlobalClassCStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:failed to copy ClassC stats\n"));
+ }
+ pStats += sizeof(tCsrGlobalClassCStatsInfo);
+
+ break;
+
+ case eCsrGlobalClassDStats:
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:ClassD stats\n"));
+ status = palCopyMemory(pMac->hHdd, pStats, (tANI_U8 *)&pMac->roam.classDStatsInfo,
+ sizeof(tCsrGlobalClassDStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:failed to copy ClassD stats\n"));
+ }
+ pStats += sizeof(tCsrGlobalClassDStatsInfo);
+
+ break;
+
+ case eCsrPerStaStats:
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:PerSta stats\n"));
+ status = palCopyMemory(pMac->hHdd, pStats, (tANI_U8 *)&pMac->roam.perStaStatsInfo[staId],
+ sizeof(tCsrPerStaStatsInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:failed to copy PerSta stats\n"));
+ }
+ pStats += sizeof(tCsrPerStaStatsInfo);
+
+ break;
+
+ default:
+ smsLog( pMac, LOG1, FL("csrRoamReportStatistics:unknown stats type\n"));
+ 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)\n");
+ 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 = palTimerStop(pMac->hHdd, pMac->roam.tlStatsReqInfo.hTlStatsTimer);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("csrRoamDeregStatisticsReq:cannot stop TlStatsTimer timer\n"));
+ //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\n"));
+ }
+ }
+
+
+ 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 )
+ {
+ 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;
+
+ 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;
+ }
+ 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 %d\n" ), 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( (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;
+ }
+
+ //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\n" ), pCommand->command );
+ }
+
+ return ( status );
+
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+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
+ {
+ status = palAllocateMemory( pMac->hHdd, (void **)&pMsg, sizeof(tSirUpdateAPWPSIEsReq) );
+ if (!HAL_STATUS_SUCCESS(status)) break;
+ palZeroMemory( pMac->hHdd, pMsg, sizeof(tSirUpdateAPWPSIEsReq) );
+ pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_UPDATE_APWPSIE_REQ);
+
+ pBuf = (tANI_U8 *)&pMsg->transactionId;
+ wTmpBuf = pBuf;
+
+ // transactionId
+ *pBuf = 0;
+ *( pBuf + 1 ) = 0;
+ pBuf += sizeof(tANI_U16);
+
+ // bssId
+ palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, &pSession->selfMacAddr, sizeof(tSirMacAddr) );
+ pBuf += sizeof(tSirMacAddr);
+
+ //sessionId
+ *pBuf++ = (tANI_U8)sessionId;
+
+ // APWPSIEs
+ palCopyMemory( pMac->hHdd, (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
+ {
+ status = palAllocateMemory( pMac->hHdd, (void **)&pMsg, sizeof(tSirUpdateAPWPARSNIEsReq) );
+ if (!HAL_STATUS_SUCCESS(status)) break;
+ palZeroMemory( pMac->hHdd, pMsg, sizeof( tSirUpdateAPWPARSNIEsReq ) );
+ 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);
+
+ // bssId
+ palCopyMemory( pMac->hHdd, (tSirMacAddr *)pBuf, &pSession->selfMacAddr, sizeof(tSirMacAddr) );
+ pBuf += sizeof(tSirMacAddr);
+
+ // sessionId
+ *pBuf++ = (tANI_U8)sessionId;
+
+ // APWPARSNIEs
+ palCopyMemory( pMac->hHdd, (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 );
+}
+
+#endif //#ifdef WLAN_SOFTAP_FEATURE
+
+#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 (pftPreAuthReq == NULL)
+ {
+ 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;
+
+
+ palCopyMemory(pMac->hHdd, (void *)&pftPreAuthReq->currbssId, (void *)pSession->connectedProfile.bssid, sizeof(tSirMacAddr));
+
+ palCopyMemory(pMac->hHdd, (void *)&pftPreAuthReq->preAuthbssId, (void *)pBssDescription->bssId, sizeof(tSirMacAddr));
+
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (csrRoamIs11rAssoc(pMac))
+ {
+ pftPreAuthReq->ft_ies_length = (tANI_U16)pMac->ft.ftSmeContext.auth_ft_ies_length;
+ palCopyMemory(pMac->hHdd, 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, pBssDescription->length);
+
+ pftPreAuthReq->length = pal_cpu_to_be16(sizeof(tSirFTPreAuthReq) + sizeof(pBssDescription->length) +
+ pBssDescription->length);
+
+ 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 WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, FL("Preauth response status code %d"), pFTPreAuthRsp->status);
+#endif
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ csrNeighborRoamPreauthRspHandler(pMac, (VOS_STATUS)pFTPreAuthRsp->status);
+#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;
+ sme_QosCsrEventInd(pMac, pMac->ft.ftSmeContext.smeSessionId, SME_QOS_CSR_PREAUTH_SUCCESS_IND, NULL);
+
+ /* 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 = palTimerStart(pMac->hHdd, pMac->ft.ftSmeContext.preAuthReassocIntvlTimer,
+ 60 * PAL_TIMER_TO_MS_UNIT,
+ eANI_BOOLEAN_FALSE);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Preauth reassoc interval timer start failed to start with status %d\n"), status);
+ return;
+ }
+
+ // Save the received response
+ palCopyMemory(pMac->hHdd, (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);
+
+ // Currently we dont do anything special for CCX connection.
+
+
+ // 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\n" ), 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\n" ) );
+ }
+ }
+ }
+}
+
+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\n "), sessionId, pSession->maxRetryCount);
+ pSession->maxRetryCount--;
+ pSession->joinRetryTimerInfo.pMac = pMac;
+ pSession->joinRetryTimerInfo.sessionId = (tANI_U8)sessionId;
+ status = palTimerStart(pMac->hHdd, pSession->hTimerJoinRetry, interval, eANI_BOOLEAN_FALSE);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL(" fail to start timer status %s \n "), status);
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" not to start timer due to no profile or reach mac ret (%d)\n "),
+ pSession->maxRetryCount);
+ }
+
+ return (status);
+}
+
+eHalStatus csrRoamStopJoinRetryTimer(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ smsLog(pMac, LOGE, " csrRoamStopJoinRetryTimer \n ");
+ if( CSR_IS_SESSION_VALID(pMac, sessionId) )
+ {
+ return (palTimerStop(pMac->hHdd, 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);
+ }
+}
+
diff --git a/CORE/SME/src/csr/csrApiScan.c b/CORE/SME/src/csr/csrApiScan.c
new file mode 100644
index 0000000..3241cb4
--- /dev/null
+++ b/CORE/SME/src/csr/csrApiScan.c
@@ -0,0 +1,6477 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+
+
+ \file csrApiScan.c
+
+ Implementation for the Common Scan interfaces.
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+ ========================================================================== */
+
+#include "aniGlobal.h"
+
+#include "palApi.h"
+#include "csrInsideApi.h"
+#include "smeInside.h"
+#include "smsDebug.h"
+
+#include "csrSupport.h"
+#include "wlan_qct_tl.h"
+
+#include "vos_diag_core_log.h"
+#include "vos_diag_core_event.h"
+
+#include "vos_nvitem.h"
+#include "wlan_qct_wda.h"
+
+#define CSR_VALIDATE_LIST //This portion of code need to be removed once the issue is resolved.
+
+#ifdef CSR_VALIDATE_LIST
+tDblLinkList *g_pchannelPowerInfoList24 = NULL, * g_pchannelPowerInfoList5 = NULL;
+tpAniSirGlobal g_pMac = NULL;
+#endif
+
+/* Purpose of HIDDEN_TIMER
+** When we remove hidden ssid from the profile i.e., forget the SSID via GUI that SSID shouldn't see in the profile
+** For above requirement we used timer limit, logic is explained below
+** Timer value is initialsed to current time when it receives corresponding probe response of hidden SSID (The probe request is
+** received regularly till SSID in the profile. Once it is removed from profile probe request is not sent.) when we receive probe response
+** for broadcast probe request, during update SSID with saved SSID we will diff current time with saved SSID time if it is greater than 1 min
+** then we are not updating with old one
+*/
+
+#define HIDDEN_TIMER (1*60*1000)
+#define CSR_SCAN_RESULT_RSSI_WEIGHT 80 // must be less than 100, represent the persentage of new RSSI
+
+/*---------------------------------------------------------------------------
+ PER filter constant fraction: it is a %
+---------------------------------------------------------------------------*/
+#define CSR_SCAN_PER_FILTER_FRAC 100
+
+/*---------------------------------------------------------------------------
+ RSSI filter constant fraction: it is a %
+---------------------------------------------------------------------------*/
+#define CSR_SCAN_RSSI_FILTER_FRAC 100
+
+/*---------------------------------------------------------------------------
+Convert RSSI into overall score: Since RSSI is in -dBm values, and the
+overall needs to be weighted inversely (where greater value means better
+system), we convert.
+RSSI *cannot* be more than 0xFF or less than 0 for meaningful WLAN operation
+---------------------------------------------------------------------------*/
+#define CSR_SCAN_MAX_SCORE_VAL 0xFF
+#define CSR_SCAN_MIN_SCORE_VAL 0x0
+#define CSR_SCAN_HANDOFF_DELTA 10
+#define CSR_SCAN_OVERALL_SCORE( rssi ) \
+ ( rssi < CSR_SCAN_MAX_SCORE_VAL )\
+ ? (CSR_SCAN_MAX_SCORE_VAL-rssi) : CSR_SCAN_MIN_SCORE_VAL
+
+
+#define CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) \
+ ( (pMac)->scan.nBssLimit <= (csrLLCount(&(pMac)->scan.scanResultList)) )
+
+//*** This is temporary work around. It need to call CCM api to get to CFG later
+/// Get string parameter value
+extern tSirRetStatus wlan_cfgGetStr(tpAniSirGlobal, tANI_U16, tANI_U8*, tANI_U32*);
+
+void csrScanGetResultTimerHandler(void *);
+void csrScanResultAgingTimerHandler(void *pv);
+void csrScanIdleScanTimerHandler(void *);
+#ifdef WLAN_AP_STA_CONCURRENCY
+static void csrStaApConcTimerHandler(void *);
+#endif
+eHalStatus csrScanChannels( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+void csrSetCfgValidChannelList( tpAniSirGlobal pMac, tANI_U8 *pChannelList, tANI_U8 NumChannels );
+void csrSaveTxPowerToCfg( tpAniSirGlobal pMac, tDblLinkList *pList, tANI_U32 cfgId );
+void csrSetCfgCountryCode( tpAniSirGlobal pMac, tANI_U8 *countryCode );
+void csrPurgeChannelPower( tpAniSirGlobal pMac, tDblLinkList *pChannelList );
+//if bgPeriod is 0, background scan is disabled. It is in millisecond units
+eHalStatus csrSetCfgBackgroundScanPeriod(tpAniSirGlobal pMac, tANI_U32 bgPeriod);
+eHalStatus csrProcessSetBGScanParam(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+void csrReleaseScanCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus);
+static tANI_BOOLEAN csrScanValidateScanResult( tpAniSirGlobal pMac, tANI_U8 *pChannels,
+ tANI_U8 numChn, tSirBssDescription *pBssDesc,
+ tDot11fBeaconIEs **ppIes );
+eHalStatus csrSetBGScanChannelList( tpAniSirGlobal pMac, tANI_U8 *pAdjustChannels, tANI_U8 NumAdjustChannels);
+void csrReleaseCmdSingle(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+tANI_BOOLEAN csrRoamIsValidChannel( tpAniSirGlobal pMac, tANI_U8 channel );
+
+//pResult is invalid calling this function.
+void csrFreeScanResultEntry( tpAniSirGlobal pMac, tCsrScanResult *pResult )
+{
+ if( NULL != pResult->Result.pvIes )
+ {
+ palFreeMemory( pMac->hHdd, pResult->Result.pvIes );
+ }
+ palFreeMemory(pMac->hHdd, pResult);
+}
+
+
+static eHalStatus csrLLScanPurgeResult(tpAniSirGlobal pMac, tDblLinkList *pList)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tListElem *pEntry;
+ tCsrScanResult *pBssDesc;
+
+ csrLLLock(pList);
+
+ while((pEntry = csrLLRemoveHead(pList, LL_ACCESS_NOLOCK)) != NULL)
+ {
+ pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+ csrFreeScanResultEntry( pMac, pBssDesc );
+ }
+
+ csrLLUnlock(pList);
+
+ return (status);
+}
+
+
+int csrCheckValidateLists(void * dest, const void *src, v_SIZE_t num, int idx)
+{
+#ifdef CSR_VALIDATE_LIST
+
+ int ii = 1;
+
+ if( (NULL == g_pMac) || (!g_pMac->scan.fValidateList ) )
+ {
+ return ii;
+ }
+ if(g_pchannelPowerInfoList24)
+ {
+ //check 2.4 list
+ tListElem *pElem, *pHead;
+ int count;
+
+ count = (int)(g_pchannelPowerInfoList24->Count);
+ pHead = &g_pchannelPowerInfoList24->ListHead;
+ pElem = pHead->next;
+ if((tANI_U32)(pHead->next) > 0x00010000) //Assuming kernel address is not that low.
+ {
+ //this loop crashes if the pointer is not right
+ while(pElem->next != pHead)
+ {
+ if((tANI_U32)(pElem->next) > 0x00010000)
+ {
+ pElem = pElem->next;
+ VOS_ASSERT(count > 0);
+ count--;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ " %d Detect 1 list(0x%X) error Head(0x%X) next(0x%X) Count %d, dest(0x%X) src(0x%X) numBytes(%d)",
+ idx, (unsigned int)g_pchannelPowerInfoList24, (unsigned int)pHead,
+ (unsigned int)(pHead->next), (int)g_pchannelPowerInfoList24->Count,
+ (unsigned int)dest, (unsigned int)src, (int)num);
+ VOS_ASSERT(0);
+ ii = 0;
+ break;
+ }
+ }
+ }
+ else
+ {
+ //Bad list
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, " %d Detect list(0x%X) error Head(0x%X) next(0x%X) Count %d, dest(0x%X) src(0x%X) numBytes(%d)",
+ idx, (unsigned int)g_pchannelPowerInfoList24, (unsigned int)pHead,
+ (unsigned int)(pHead->next), (int)g_pchannelPowerInfoList24->Count,
+ (unsigned int)dest, (unsigned int)src, (int)num);
+ VOS_ASSERT(0);
+ ii = 0;
+ }
+ }
+ else
+ {
+ //list ok
+ ii = 1;
+ }
+
+
+ return ii;
+
+#else
+ return 1;
+#endif //#ifdef CSR_VALIDATE_LIST
+}
+
+
+eHalStatus csrScanOpen( tpAniSirGlobal pMac )
+{
+ eHalStatus status;
+
+ do
+ {
+ csrLLOpen(pMac->hHdd, &pMac->scan.scanResultList);
+ csrLLOpen(pMac->hHdd, &pMac->scan.tempScanResults);
+ csrLLOpen(pMac->hHdd, &pMac->scan.channelPowerInfoList24);
+ csrLLOpen(pMac->hHdd, &pMac->scan.channelPowerInfoList5G);
+#ifdef WLAN_AP_STA_CONCURRENCY
+ csrLLOpen(pMac->hHdd, &pMac->scan.scanCmdPendingList);
+#endif
+#ifdef CSR_VALIDATE_LIST
+ g_pchannelPowerInfoList5 = &pMac->scan.channelPowerInfoList5G;
+ g_pMac = pMac;
+ g_pchannelPowerInfoList24 = &pMac->scan.channelPowerInfoList24;
+#endif
+ pMac->scan.fFullScanIssued = eANI_BOOLEAN_FALSE;
+ pMac->scan.nBssLimit = CSR_MAX_BSS_SUPPORT;
+ status = palTimerAlloc(pMac->hHdd, &pMac->scan.hTimerGetResult, csrScanGetResultTimerHandler, pMac);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("cannot allocate memory for getResult timer\n"));
+ break;
+ }
+#ifdef WLAN_AP_STA_CONCURRENCY
+ status = palTimerAlloc(pMac->hHdd, &pMac->scan.hTimerStaApConcTimer, csrStaApConcTimerHandler, pMac);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("cannot allocate memory for hTimerStaApConcTimer timer\n"));
+ break;
+ }
+#endif
+ status = palTimerAlloc(pMac->hHdd, &pMac->scan.hTimerIdleScan, csrScanIdleScanTimerHandler, pMac);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("cannot allocate memory for idleScan timer\n"));
+ break;
+ }
+ status = palTimerAlloc(pMac->hHdd, &pMac->scan.hTimerResultAging, csrScanResultAgingTimerHandler, pMac);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("cannot allocate memory for ResultAging timer\n"));
+ break;
+ }
+ }while(0);
+
+ return (status);
+}
+
+
+eHalStatus csrScanClose( tpAniSirGlobal pMac )
+{
+#ifdef CSR_VALIDATE_LIST
+ g_pchannelPowerInfoList24 = NULL;
+ g_pchannelPowerInfoList5 = NULL;
+ g_pMac = NULL;
+#endif
+ csrLLScanPurgeResult(pMac, &pMac->scan.tempScanResults);
+ csrLLScanPurgeResult(pMac, &pMac->scan.scanResultList);
+#ifdef WLAN_AP_STA_CONCURRENCY
+ csrLLScanPurgeResult(pMac, &pMac->scan.scanCmdPendingList);
+#endif
+ csrLLClose(&pMac->scan.scanResultList);
+ csrLLClose(&pMac->scan.tempScanResults);
+#ifdef WLAN_AP_STA_CONCURRENCY
+ csrLLClose(&pMac->scan.scanCmdPendingList);
+#endif
+ csrPurgeChannelPower(pMac, &pMac->scan.channelPowerInfoList24);
+ csrPurgeChannelPower(pMac, &pMac->scan.channelPowerInfoList5G);
+ csrLLClose(&pMac->scan.channelPowerInfoList24);
+ csrLLClose(&pMac->scan.channelPowerInfoList5G);
+ csrScanDisable(pMac);
+ palTimerFree(pMac->hHdd, pMac->scan.hTimerResultAging);
+ palTimerFree(pMac->hHdd, pMac->scan.hTimerGetResult);
+#ifdef WLAN_AP_STA_CONCURRENCY
+ palTimerFree(pMac->hHdd, pMac->scan.hTimerStaApConcTimer);
+#endif
+ palTimerFree(pMac->hHdd, pMac->scan.hTimerIdleScan);
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+eHalStatus csrScanEnable( tpAniSirGlobal pMac )
+{
+
+ pMac->scan.fScanEnable = eANI_BOOLEAN_TRUE;
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+eHalStatus csrScanDisable( tpAniSirGlobal pMac )
+{
+
+ csrScanStopTimers(pMac);
+ pMac->scan.fScanEnable = eANI_BOOLEAN_FALSE;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+#ifdef WLAN_AP_STA_CONCURRENCY
+//Return SUCCESS is the command is queued, else returns eHAL_STATUS_FAILURE
+eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ tANI_BOOLEAN fNoCmdPending;
+ tSmeCmd *pQueueScanCmd=NULL;
+ tSmeCmd *pSendScanCmd=NULL;
+
+ if (vos_get_concurrency_mode() == VOS_STA_SAP) //TODO:- Also make sure AP BSS has started
+ {
+
+ tCsrScanRequest scanReq;
+ tANI_U8 numChn = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
+ tCsrChannelInfo *pChnInfo = &scanReq.ChannelInfo;
+ tANI_U8 channelToScan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ tANI_U8 i = 0;
+ tANI_BOOLEAN bMemAlloc = eANI_BOOLEAN_FALSE;
+
+ if (numChn == 0)
+ {
+
+ numChn = pMac->scan.baseChannels.numChannels;
+
+ status = palAllocateMemory( pMac->hHdd, (void **)&pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, numChn );
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" Failed to get memory for channel list \n") );
+ return eHAL_STATUS_FAILURE;
+ }
+ bMemAlloc = eANI_BOOLEAN_TRUE;
+ status = palCopyMemory( pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList,
+ pMac->scan.baseChannels.channelList, numChn );
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ palFreeMemory( pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList );
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = NULL;
+ smsLog( pMac, LOGE, FL(" Failed to copy memory to channel list \n") );
+ return eHAL_STATUS_FAILURE;
+ }
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = numChn;
+ }
+
+ //Whenever we get a scan request with multiple channels we break it up into 2 requests
+ //First request for first channel to scan and second request to scan remaining channels
+ for (i=0; i < 2; i++)
+ { //go through max 2 iterations.
+ //Once for using the existing command when number of channels is 1
+ //Second to go over the remaining channels after creating a new command
+
+ if (1 == numChn)
+ {
+ pSendScanCmd = pScanCmd;
+ pSendScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = 1;
+ pSendScanCmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ pSendScanCmd->u.scanCmd.u.scanRequest.maxChnTime =
+ CSR_MIN(pSendScanCmd->u.scanCmd.u.scanRequest.maxChnTime,CSR_ACTIVE_MAX_CHANNEL_TIME_CONC);
+ pSendScanCmd->u.scanCmd.u.scanRequest.minChnTime =
+ CSR_MIN(pSendScanCmd->u.scanCmd.u.scanRequest.minChnTime, CSR_ACTIVE_MIN_CHANNEL_TIME_CONC);
+ if (i != 0)
+ { //Callback should be NULL for all except last channel So hdd_callback will be called only after last command
+ //i!=0 then we came here in second iteration
+ pSendScanCmd->u.scanCmd.callback = NULL;
+ }
+ break; //break out of this loop in case there is only 1 channel then no need for 2nd iteration
+
+ } else { //if number of channels > 1 then
+
+ palZeroMemory(pMac->hHdd, &scanReq, sizeof(tCsrScanRequest));
+
+ pQueueScanCmd = csrGetCommandBuffer(pMac); //optimize this to use 2 command buffer only
+ if (!pQueueScanCmd)
+ {
+ if (bMemAlloc)
+ {
+ palFreeMemory( pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList );
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = NULL;
+
+ }
+ smsLog( pMac, LOGE, FL(" Failed to get Queue command buffer\n") );
+ return eHAL_STATUS_FAILURE;
+ }
+ pQueueScanCmd->command = pScanCmd->command;
+ pQueueScanCmd->sessionId = pScanCmd->sessionId;
+ pQueueScanCmd->u.scanCmd.callback = pScanCmd->u.scanCmd.callback;
+ pQueueScanCmd->u.scanCmd.pContext = pScanCmd->u.scanCmd.pContext;
+ pQueueScanCmd->u.scanCmd.reason = pScanCmd->u.scanCmd.reason;
+ pQueueScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around
+
+ pChnInfo->numOfChannels = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels - 1;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ FL(" &channelToScan %0x pScanCmd(0x%X) pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList(0x%X)numChn(%d)"),
+ &channelToScan[0], (unsigned int)pScanCmd,
+ (unsigned int)pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, numChn);
+
+ palCopyMemory(pMac->hHdd, &channelToScan[0], &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[1],
+ pChnInfo->numOfChannels * sizeof(tANI_U8));
+
+ pChnInfo->ChannelList = &channelToScan[0];
+
+
+ scanReq.BSSType = eCSR_BSS_TYPE_ANY;
+ //Modify callers parameters in case of concurrency
+ scanReq.scanType = eSIR_ACTIVE_SCAN;
+ scanReq.maxChnTime = CSR_ACTIVE_MAX_CHANNEL_TIME_CONC;
+ scanReq.minChnTime = CSR_ACTIVE_MIN_CHANNEL_TIME_CONC;
+
+ status = csrScanCopyRequest(pMac, &pQueueScanCmd->u.scanCmd.u.scanRequest, &scanReq);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ if (bMemAlloc)
+ {
+ palFreeMemory( pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList );
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = NULL;
+
+ }
+ smsLog( pMac, LOGE, FL(" Failed to get copy csrScanRequest = %d\n"), status );
+ return eHAL_STATUS_FAILURE;
+ }
+ numChn = 1; //make numChn to be 1 for second iteration to create a send command
+ }
+
+ }
+
+ fNoCmdPending = csrLLIsListEmpty( &pMac->scan.scanCmdPendingList, LL_ACCESS_LOCK );
+
+ //Logic Below is as follows
+ // If the scanCmdPendingList is empty then we directly send that command
+ // to smeCommandQueue else we buffer it in our scanCmdPendingList Queue
+ if( fNoCmdPending )
+ {
+
+ if (pQueueScanCmd != NULL)
+ {
+ csrLLInsertTail( &pMac->scan.scanCmdPendingList, &pQueueScanCmd->Link, LL_ACCESS_LOCK );
+ }
+
+ if (pSendScanCmd != NULL)
+ {
+ return csrQueueSmeCommand(pMac, pSendScanCmd, eANI_BOOLEAN_FALSE);
+ }
+ }
+ else
+ {
+ if (pSendScanCmd != NULL)
+ {
+ csrLLInsertTail( &pMac->scan.scanCmdPendingList, &pSendScanCmd->Link, LL_ACCESS_LOCK );
+ }
+ if (pQueueScanCmd != NULL)
+ {
+ csrLLInsertTail( &pMac->scan.scanCmdPendingList, &pQueueScanCmd->Link, LL_ACCESS_LOCK );
+ }
+ }
+
+ }
+ else
+ { //No concurrency case
+ return csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE);
+ }
+
+
+
+ return ( status );
+
+}
+#endif
+
+eHalStatus csrScanRequest(tpAniSirGlobal pMac, tANI_U16 sessionId,
+ tCsrScanRequest *pScanRequest, tANI_U32 *pScanRequestID,
+ csrScanCompleteCallback callback, void *pContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tSmeCmd *pScanCmd = NULL;
+
+ do
+ {
+ if(pMac->scan.fScanEnable)
+ {
+ pScanCmd = csrGetCommandBuffer(pMac);
+ if(pScanCmd)
+ {
+ palZeroMemory(pMac->hHdd, &pScanCmd->u.scanCmd, sizeof(tScanCmd));
+ pScanCmd->command = eSmeCommandScan;
+ pScanCmd->sessionId = sessionId;
+ pScanCmd->u.scanCmd.callback = callback;
+ pScanCmd->u.scanCmd.pContext = pContext;
+ if(eCSR_SCAN_REQUEST_11D_SCAN == pScanRequest->requestType)
+ {
+ pScanCmd->u.scanCmd.reason = eCsrScan11d1;
+ }
+ else if((eCSR_SCAN_REQUEST_FULL_SCAN == pScanRequest->requestType) ||
+ (eCSR_SCAN_P2P_DISCOVERY == pScanRequest->requestType)
+#ifdef SOFTAP_CHANNEL_RANGE
+ ||(eCSR_SCAN_SOFTAP_CHANNEL_RANGE == pScanRequest->requestType)
+#endif
+ )
+ {
+ pScanCmd->u.scanCmd.reason = eCsrScanUserRequest;
+ }
+ else if(eCSR_SCAN_HO_BG_SCAN == pScanRequest->requestType)
+ {
+ pScanCmd->u.scanCmd.reason = eCsrScanBgScan;
+ }
+ else if(eCSR_SCAN_HO_PROBE_SCAN == pScanRequest->requestType)
+ {
+ pScanCmd->u.scanCmd.reason = eCsrScanProbeBss;
+ }
+#if defined WLAN_FEATURE_P2P
+ else if(eCSR_SCAN_P2P_FIND_PEER == pScanRequest->requestType)
+ {
+ pScanCmd->u.scanCmd.reason = eCsrScanP2PFindPeer;
+ }
+#endif
+ else
+ {
+ pScanCmd->u.scanCmd.reason = eCsrScanIdleScan;
+ }
+ if(pScanRequest->minChnTime == 0 && pScanRequest->maxChnTime == 0)
+ {
+ //The caller doesn't set the time correctly. Set it here
+ if(pScanRequest->scanType == eSIR_ACTIVE_SCAN)
+ {
+ pScanRequest->maxChnTime = pMac->roam.configParam.nActiveMaxChnTime;
+ pScanRequest->minChnTime = pMac->roam.configParam.nActiveMinChnTime;
+ }
+ else
+ {
+ pScanRequest->maxChnTime = pMac->roam.configParam.nPassiveMaxChnTime;
+ pScanRequest->minChnTime = pMac->roam.configParam.nPassiveMinChnTime;
+ }
+ }
+ //Need to make the following atomic
+ pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around
+
+ if(pScanRequestID)
+ {
+ *pScanRequestID = pScanCmd->u.scanCmd.scanID;
+ }
+
+ //Tush : If it is the first scan request from HDD, CSR checks if it is for 11d.
+ // If it is not, CSR will save the scan request in the pending cmd queue
+ // & issue an 11d scan request to PE.
+ if(((0 == pScanCmd->u.scanCmd.scanID)
+ && (eCSR_SCAN_REQUEST_11D_SCAN != pScanRequest->requestType))
+#ifdef SOFTAP_CHANNEL_RANGE
+ && (eCSR_SCAN_SOFTAP_CHANNEL_RANGE != pScanRequest->requestType)
+#endif
+ && (eANI_BOOLEAN_FALSE == pMac->scan.fEnableBypass11d)
+ )
+ {
+ tSmeCmd *p11dScanCmd;
+ tCsrScanRequest scanReq;
+ tCsrChannelInfo *pChnInfo = &scanReq.ChannelInfo;
+
+ palZeroMemory(pMac->hHdd, &scanReq, sizeof(tCsrScanRequest));
+
+ p11dScanCmd = csrGetCommandBuffer(pMac);
+ if(p11dScanCmd)
+ {
+ tANI_U32 numChn = pMac->scan.baseChannels.numChannels;
+
+ palZeroMemory(pMac->hHdd, &p11dScanCmd->u.scanCmd, sizeof(tScanCmd));
+ status = palAllocateMemory( pMac->hHdd, (void **)&pChnInfo->ChannelList, numChn );
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ break;
+ }
+ status = palCopyMemory( pMac->hHdd, pChnInfo->ChannelList,
+ pMac->scan.baseChannels.channelList, numChn );
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ palFreeMemory( pMac->hHdd, pChnInfo->ChannelList );
+ pChnInfo->ChannelList = NULL;
+ break;
+ }
+ pChnInfo->numOfChannels = (tANI_U8)numChn;
+ p11dScanCmd->command = eSmeCommandScan;
+ p11dScanCmd->u.scanCmd.callback = NULL;
+ p11dScanCmd->u.scanCmd.pContext = NULL;
+ p11dScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++;
+ scanReq.BSSType = eCSR_BSS_TYPE_ANY;
+
+ if ( csrIs11dSupported(pMac) )
+ {
+ scanReq.scanType = eSIR_PASSIVE_SCAN;
+ scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
+ p11dScanCmd->u.scanCmd.reason = eCsrScan11d1;
+ scanReq.maxChnTime = pMac->roam.configParam.nPassiveMaxChnTime;
+ scanReq.minChnTime = pMac->roam.configParam.nPassiveMinChnTime;
+ }
+ else
+ {
+ scanReq.scanType = eSIR_ACTIVE_SCAN;
+ scanReq.requestType = eCSR_SCAN_IDLE_MODE_SCAN;
+ p11dScanCmd->u.scanCmd.reason = eCsrScanIdleScan;
+ scanReq.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime;
+ scanReq.minChnTime = pMac->roam.configParam.nActiveMinChnTime;
+ }
+ status = csrScanCopyRequest(pMac, &p11dScanCmd->u.scanCmd.u.scanRequest, &scanReq);
+ //Free the channel list
+ palFreeMemory( pMac->hHdd, pChnInfo->ChannelList );
+
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ //Start process the command
+#ifdef WLAN_AP_STA_CONCURRENCY
+ status = csrQueueScanRequest(pMac, p11dScanCmd);
+#else
+ status = csrQueueSmeCommand(pMac, p11dScanCmd, eANI_BOOLEAN_FALSE);
+#endif
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ //error
+ break;
+ }
+ }
+ status = csrScanCopyRequest(pMac, &pScanCmd->u.scanCmd.u.scanRequest, pScanRequest);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ //Start process the command
+#ifdef WLAN_AP_STA_CONCURRENCY
+ status = csrQueueScanRequest(pMac,pScanCmd);
+#else
+ status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE);
+#endif
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ break;
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" fail to copy request status = %d\n"), status );
+ break;
+ }
+ }
+ else
+ {
+ //log error
+ break;
+ }
+ }
+ } while(0);
+ if(!HAL_STATUS_SUCCESS(status) && pScanCmd)
+ {
+ if( eCsrScanIdleScan == pScanCmd->u.scanCmd.reason )
+ {
+ //Set the flag back for restarting idle scan
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE;
+ }
+ csrReleaseCommandScan(pMac, pScanCmd);
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanRequestResult(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSmeCmd *pScanCmd;
+
+ if(pMac->scan.fScanEnable)
+ {
+ pScanCmd = csrGetCommandBuffer(pMac);
+ if(pScanCmd)
+ {
+ pScanCmd->command = eSmeCommandScan;
+ palZeroMemory(pMac->hHdd, &pScanCmd->u.scanCmd, sizeof(tScanCmd));
+ pScanCmd->u.scanCmd.callback = NULL;
+ pScanCmd->u.scanCmd.pContext = NULL;
+ pScanCmd->u.scanCmd.reason = eCsrScanGetResult;
+ //Need to make the following atomic
+ pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around
+ status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ csrReleaseCommandScan(pMac, pScanCmd);
+ }
+ }
+ else
+ {
+ //log error
+ smsLog(pMac, LOGE, FL("can not obtain a common buffer\n"));
+ status = eHAL_STATUS_RESOURCES;
+ }
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanAllChannels(tpAniSirGlobal pMac, eCsrRequestType reqType)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_U32 scanId;
+ tCsrScanRequest scanReq;
+
+ palZeroMemory(pMac->hHdd, &scanReq, sizeof(tCsrScanRequest));
+ scanReq.BSSType = eCSR_BSS_TYPE_ANY;
+ scanReq.scanType = eSIR_ACTIVE_SCAN;
+ scanReq.requestType = reqType;
+ scanReq.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime;
+ scanReq.minChnTime = pMac->roam.configParam.nActiveMinChnTime;
+ //Scan with invalid sessionId.
+ //This results in SME using the first available session to scan.
+ status = csrScanRequest(pMac, CSR_SESSION_ID_INVALID, &scanReq,
+ &scanId, NULL, NULL);
+
+ return (status);
+}
+
+
+
+
+eHalStatus csrIssueRoamAfterLostlinkScan(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamReason reason)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tScanResultHandle hBSSList = NULL;
+ tCsrScanResultFilter *pScanFilter = NULL;
+ tANI_U32 roamId = 0;
+ tCsrRoamProfile *pProfile = NULL;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ do
+ {
+ smsLog(pMac, LOG1, " csrIssueRoamAfterLostlinkScan called\n");
+ if(pSession->fCancelRoaming)
+ {
+ smsLog(pMac, LOGW, " lostlink roaming is cancelled\n");
+ csrScanStartIdleScan(pMac);
+ status = eHAL_STATUS_SUCCESS;
+ break;
+ }
+ //Here is the profile we need to connect to
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ if(NULL == pSession->pCurRoamProfile)
+ {
+ pScanFilter->EncryptionType.numEntries = 1;
+ pScanFilter->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+ }
+ else
+ {
+ //We have to make a copy of pCurRoamProfile because it will be free inside csrRoamIssueConnect
+ status = palAllocateMemory(pMac->hHdd, (void **)&pProfile, sizeof(tCsrRoamProfile));
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ palZeroMemory(pMac->hHdd, pProfile, sizeof(tCsrRoamProfile));
+ status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile);
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter);
+ }//We have a profile
+ roamId = GET_NEXT_ROAM_ID(&pMac->roam);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ if(eCsrLostLink1 == reason)
+ {
+ //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, reason,
+ roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ csrScanResultPurge(pMac, hBSSList);
+ }
+ }//Have scan result
+ }
+ }while(0);
+ if(pScanFilter)
+ {
+ //we need to free memory for filter if profile exists
+ csrFreeScanFilter(pMac, pScanFilter);
+ palFreeMemory(pMac->hHdd, pScanFilter);
+ }
+ if(NULL != pProfile)
+ {
+ csrReleaseProfile(pMac, pProfile);
+ palFreeMemory(pMac->hHdd, (void *)pProfile);
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanGetScanChnInfo(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSmeCmd *pScanCmd;
+
+ if(pMac->scan.fScanEnable)
+ {
+ pScanCmd = csrGetCommandBuffer(pMac);
+ if(pScanCmd)
+ {
+ pScanCmd->command = eSmeCommandScan;
+ palZeroMemory(pMac->hHdd, &pScanCmd->u.scanCmd, sizeof(tScanCmd));
+ pScanCmd->u.scanCmd.callback = NULL;
+ pScanCmd->u.scanCmd.pContext = NULL;
+ pScanCmd->u.scanCmd.reason = eCsrScanGetScanChnInfo;
+ //Need to make the following atomic
+ pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around
+ status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ csrReleaseCommandScan(pMac, pScanCmd);
+ }
+ }
+ else
+ {
+ //log error
+ smsLog(pMac, LOGE, FL("can not obtain a common buffer\n"));
+ status = eHAL_STATUS_RESOURCES;
+ }
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanHandleFailedLostlink1(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOGW, " Lostlink scan 1 failed\n");
+ if(pSession->fCancelRoaming)
+ {
+ csrScanStartIdleScan(pMac);
+ }
+ else if(pSession->pCurRoamProfile)
+ {
+ //We fail lostlink1 but there may be other BSS in the cached result fit the profile. Give it a try first
+ if(pSession->pCurRoamProfile->SSIDs.numOfSSIDs == 0 ||
+ pSession->pCurRoamProfile->SSIDs.numOfSSIDs > 1)
+ {
+ //try lostlink scan2
+ status = csrScanRequestLostLink2(pMac, sessionId);
+ }
+ else if(!pSession->pCurRoamProfile->ChannelInfo.ChannelList ||
+ pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0)
+ {
+ //go straight to lostlink scan3
+ status = csrScanRequestLostLink3(pMac, sessionId);
+ }
+ else
+ {
+ //we are done with lostlink
+ if(csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE))
+ {
+ csrScanStartIdleScan(pMac);
+ }
+ status = eHAL_STATUS_SUCCESS;
+ }
+ }
+ else
+ {
+ status = csrScanRequestLostLink3(pMac, sessionId);
+ }
+
+ return (status);
+}
+
+
+
+eHalStatus csrScanHandleFailedLostlink2(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOGW, " Lostlink scan 2 failed\n");
+ if(pSession->fCancelRoaming)
+ {
+ csrScanStartIdleScan(pMac);
+ }
+ else if(!pSession->pCurRoamProfile || !pSession->pCurRoamProfile->ChannelInfo.ChannelList ||
+ pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0)
+ {
+ //try lostlink scan3
+ status = csrScanRequestLostLink3(pMac, sessionId);
+ }
+ else
+ {
+ //we are done with lostlink
+ if(csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE))
+ {
+ csrScanStartIdleScan(pMac);
+ }
+ }
+
+ return (status);
+}
+
+
+
+eHalStatus csrScanHandleFailedLostlink3(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ smsLog(pMac, LOGW, " Lostlink scan 3 failed\n");
+ if(eANI_BOOLEAN_TRUE == csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE))
+ {
+ //we are done with lostlink
+ csrScanStartIdleScan(pMac);
+ }
+
+ return (status);
+}
+
+
+
+
+//Lostlink1 scan is to actively scan the last connected profile's SSID on all matched BSS channels.
+//If no roam profile (it should not), it is like lostlinkscan3
+eHalStatus csrScanRequestLostLink1( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSmeCmd *pCommand = NULL;
+ tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ tCsrScanResultFilter *pScanFilter = NULL;
+ tScanResultHandle hBSSList = NULL;
+ tCsrScanResultInfo *pScanResult = NULL;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOGW, FL(" called\n"));
+ do
+ {
+ pCommand = csrGetCommandBuffer(pMac);
+ if(!pCommand)
+ {
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ palZeroMemory(pMac->hHdd, &pCommand->u.scanCmd, sizeof(tScanCmd));
+ pCommand->command = eSmeCommandScan;
+ pCommand->sessionId = (tANI_U8)sessionId;
+ pCommand->u.scanCmd.reason = eCsrScanLostLink1;
+ pCommand->u.scanCmd.callback = NULL;
+ pCommand->u.scanCmd.pContext = NULL;
+ pCommand->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime;
+ pCommand->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime;
+ pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ if(pSession->connectedProfile.SSID.length)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList, sizeof(tCsrSSIDInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = 1;
+ palCopyMemory(pMac->hHdd, &pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID,
+ &pSession->connectedProfile.SSID, sizeof(tSirMacSSid));
+ }
+ else
+ {
+ pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = 0;
+ }
+ if(pSession->pCurRoamProfile)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ //Don't change variable status here because whether we can get result or not, the command goes to PE.
+ //The status is also used to indicate whether the command is queued. Not success meaning not queue
+ if(HAL_STATUS_SUCCESS((csrScanGetResult(pMac, pScanFilter, &hBSSList))) && hBSSList)
+ {
+ tANI_U8 i, nChn = 0;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList,
+ WNI_CFG_VALID_CHANNEL_LIST_LEN);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) &&
+ nChn < WNI_CFG_VALID_CHANNEL_LIST_LEN)
+ {
+ for(i = 0; i < nChn; i++)
+ {
+ if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] ==
+ pScanResult->BssDescriptor.channelId)
+ {
+ break;
+ }
+ }
+ if(i == nChn)
+ {
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nChn++] = pScanResult->BssDescriptor.channelId;
+ }
+ }
+ //Include the last connected BSS' channel
+ if(csrRoamIsChannelValid(pMac, pSession->connectedProfile.operationChannel))
+ {
+ for(i = 0; i < nChn; i++)
+ {
+ if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] ==
+ pSession->connectedProfile.operationChannel)
+ {
+ break;
+ }
+ }
+ if(i == nChn)
+ {
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nChn++] = pSession->connectedProfile.operationChannel;
+ }
+ }
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = nChn;
+ }
+ else
+ {
+ if(csrRoamIsChannelValid(pMac, pSession->connectedProfile.operationChannel))
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList,
+ 1);
+ //just try the last connected channel
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[0] = pSession->connectedProfile.operationChannel;
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = 1;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+ palCopyMemory(pMac->hHdd, &pCommand->u.scanCmd.u.scanRequest.bssid, bAddr, sizeof(tCsrBssid));
+ status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ break;
+ }
+ } while( 0 );
+
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGW, " csrScanRequestLostLink1 failed with status %d\n", status);
+ if(pCommand)
+ {
+ csrReleaseCommandScan(pMac, pCommand);
+ }
+ status = csrScanHandleFailedLostlink1( pMac, sessionId );
+ }
+ if(pScanFilter)
+ {
+ csrFreeScanFilter(pMac, pScanFilter);
+ palFreeMemory(pMac->hHdd, pScanFilter);
+ }
+ if(hBSSList)
+ {
+ csrScanResultPurge(pMac, hBSSList);
+ }
+
+ return( status );
+}
+
+
+//Lostlink2 scan is to actively scan the all SSIDs of the last roaming profile's on all matched BSS channels.
+//Since MAC doesn't support multiple SSID, we scan all SSIDs and filter them afterwards
+eHalStatus csrScanRequestLostLink2( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ tCsrScanResultFilter *pScanFilter = NULL;
+ tScanResultHandle hBSSList = NULL;
+ tCsrScanResultInfo *pScanResult = NULL;
+ tSmeCmd *pCommand = NULL;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOGW, FL(" called\n"));
+ do
+ {
+ pCommand = csrGetCommandBuffer(pMac);
+ if(!pCommand)
+ {
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ palZeroMemory(pMac->hHdd, &pCommand->u.scanCmd, sizeof(tScanCmd));
+ pCommand->command = eSmeCommandScan;
+ pCommand->sessionId = (tANI_U8)sessionId;
+ pCommand->u.scanCmd.reason = eCsrScanLostLink2;
+ pCommand->u.scanCmd.callback = NULL;
+ pCommand->u.scanCmd.pContext = NULL;
+ pCommand->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime;
+ pCommand->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime;
+ pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ if(pSession->pCurRoamProfile)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ if(hBSSList)
+ {
+ tANI_U8 i, nChn = 0;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList,
+ WNI_CFG_VALID_CHANNEL_LIST_LEN);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) &&
+ nChn < WNI_CFG_VALID_CHANNEL_LIST_LEN)
+ {
+ for(i = 0; i < nChn; i++)
+ {
+ if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] ==
+ pScanResult->BssDescriptor.channelId)
+ {
+ break;
+ }
+ }
+ if(i == nChn)
+ {
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nChn++] = pScanResult->BssDescriptor.channelId;
+ }
+ }
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = nChn;
+ }
+ }
+ palCopyMemory(pMac->hHdd, &pCommand->u.scanCmd.u.scanRequest.bssid, bAddr, sizeof(tCsrBssid));
+ //Put to the head in pending queue
+ status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ break;
+ }
+ } while( 0 );
+
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGW, " csrScanRequestLostLink2 failed with status %d\n", status);
+ if(pCommand)
+ {
+ csrReleaseCommandScan(pMac, pCommand);
+ }
+ status = csrScanHandleFailedLostlink2( pMac, sessionId );
+ }
+ if(pScanFilter)
+ {
+ csrFreeScanFilter(pMac, pScanFilter);
+ palFreeMemory(pMac->hHdd, pScanFilter);
+ }
+ if(hBSSList)
+ {
+ csrScanResultPurge(pMac, hBSSList);
+ }
+
+ return( status );
+}
+
+
+//To actively scan all valid channels
+eHalStatus csrScanRequestLostLink3( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSmeCmd *pCommand;
+ tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ smsLog(pMac, LOGW, FL(" called\n"));
+ do
+ {
+ pCommand = csrGetCommandBuffer(pMac);
+ if(!pCommand)
+ {
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ palZeroMemory(pMac->hHdd, &pCommand->u.scanCmd, sizeof(tScanCmd));
+ pCommand->command = eSmeCommandScan;
+ pCommand->sessionId = (tANI_U8)sessionId;
+ pCommand->u.scanCmd.reason = eCsrScanLostLink3;
+ pCommand->u.scanCmd.callback = NULL;
+ pCommand->u.scanCmd.pContext = NULL;
+ pCommand->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime;
+ pCommand->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime;
+ pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ palCopyMemory(pMac->hHdd, &pCommand->u.scanCmd.u.scanRequest.bssid, bAddr, sizeof(tCsrBssid));
+ //Put to the head of pending queue
+ status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ break;
+ }
+ } while( 0 );
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGW, " csrScanRequestLostLink3 failed with status %d\n", status);
+ if(csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE))
+ {
+ csrScanStartIdleScan(pMac);
+ }
+ if(pCommand)
+ {
+ csrReleaseCommandScan(pMac, pCommand);
+ }
+ }
+
+ return( status );
+}
+
+
+eHalStatus csrScanHandleSearchForSSID(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tScanResultHandle hBSSList = CSR_INVALID_SCANRESULT_HANDLE;
+ tCsrScanResultFilter *pScanFilter = NULL;
+ tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile;
+ tANI_U32 sessionId = pCommand->sessionId;
+#ifdef FEATURE_WLAN_BTAMP_UT_RF
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+#endif
+ do
+ {
+ //If there is roam command waiting, ignore this roam because the newer roam command is the one to execute
+ if(csrIsRoamCommandWaitingForSession(pMac, sessionId))
+ {
+ smsLog(pMac, LOGW, FL(" aborts because roam command waiting\n"));
+ break;
+ }
+ if(pProfile == NULL)
+ break;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter);
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued,
+ pCommand->u.scanCmd.roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ }while(0);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ if(CSR_INVALID_SCANRESULT_HANDLE != hBSSList)
+ {
+ csrScanResultPurge(pMac, hBSSList);
+ }
+ //We haven't done anything to this profile
+ csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.scanCmd.roamId,
+ eCSR_ROAM_ASSOCIATION_FAILURE, eCSR_ROAM_RESULT_FAILURE);
+ //In case we have nothing else to do, restart idle scan
+ if(csrIsConnStateDisconnected(pMac, sessionId) && !csrIsRoamCommandWaiting(pMac))
+ {
+ status = csrScanStartIdleScan(pMac);
+ }
+#ifdef FEATURE_WLAN_BTAMP_UT_RF
+ //In case of WDS station, let it retry.
+ if( CSR_IS_WDS_STA(pProfile) )
+ {
+ //Save the roma profile so we can retry
+ csrFreeRoamProfile( pMac, sessionId );
+ if (HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd,
+ (void **)&pSession->pCurRoamProfile,
+ sizeof(tCsrRoamProfile))))
+ {
+ palZeroMemory(pMac->hHdd, pSession->pCurRoamProfile, sizeof(tCsrRoamProfile));
+ csrRoamCopyProfile(pMac, pSession->pCurRoamProfile, pProfile);
+ }
+ csrRoamStartJoinRetryTimer(pMac, sessionId, CSR_JOIN_RETRY_TIMEOUT_PERIOD);
+ }
+#endif
+ }
+ if(pScanFilter)
+ {
+ csrFreeScanFilter(pMac, pScanFilter);
+ palFreeMemory(pMac->hHdd, pScanFilter);
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanHandleSearchForSSIDFailure(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_U32 sessionId = pCommand->sessionId;
+ tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+#if defined(WLAN_DEBUG)
+ if(pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs == 1)
+ {
+ char str[36];
+ palCopyMemory(pMac->hHdd, str, pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID.ssId,
+ pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID.length);
+ str[pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID.length] = 0;
+ smsLog(pMac, LOGW, FL(" SSID = %s\n"), str);
+ }
+#endif
+ //Check whether it is for start ibss. No need to do anything if it is a JOIN request
+ if(pProfile && CSR_IS_START_IBSS(pProfile))
+ {
+ status = csrRoamIssueConnect(pMac, sessionId, pProfile, NULL, eCsrHddIssued,
+ pCommand->u.scanCmd.roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL("failed to issue startIBSS command with status = 0x%08X\n"), status);
+ csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.scanCmd.roamId, eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE);
+ }
+ }
+ else
+ {
+ eCsrRoamResult roamResult = eCSR_ROAM_RESULT_FAILURE;
+
+ if(csrIsConnStateDisconnected(pMac, sessionId) &&
+ !csrIsRoamCommandWaitingForSession(pMac, sessionId))
+ {
+ status = csrScanStartIdleScan(pMac);
+ }
+ if((NULL == pProfile) || !csrIsBssTypeIBSS(pProfile->BSSType))
+ {
+ //Only indicate assoc_completion if we indicate assoc_start.
+ if(pSession->bRefAssocStartCnt > 0)
+ {
+ tCsrRoamInfo *pRoamInfo = NULL, roamInfo;
+ palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo));
+ pRoamInfo = &roamInfo;
+ if(pCommand->u.roamCmd.pRoamBssEntry)
+ {
+ tCsrScanResult *pScanResult =
+ GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry,
+ tCsrScanResult, Link);
+ roamInfo.pBssDesc = &pScanResult->Result.BssDescriptor;
+ }
+ roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
+ roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
+ pSession->bRefAssocStartCnt--;
+ csrRoamCallCallback(pMac, sessionId, pRoamInfo,
+ pCommand->u.scanCmd.roamId,
+ eCSR_ROAM_ASSOCIATION_COMPLETION,
+ eCSR_ROAM_RESULT_FAILURE);
+ }
+#ifdef FEATURE_WLAN_BTAMP_UT_RF
+ //In case of WDS station, let it retry.
+ if( CSR_IS_WDS_STA(pProfile) )
+ {
+ //Save the roma profile so we can retry
+ csrFreeRoamProfile( pMac, sessionId );
+ if (HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd,
+ (void **)&pSession->pCurRoamProfile,
+ sizeof(tCsrRoamProfile))))
+ {
+ palZeroMemory(pMac->hHdd, pSession->pCurRoamProfile, sizeof(tCsrRoamProfile));
+ csrRoamCopyProfile(pMac, pSession->pCurRoamProfile, pProfile);
+ }
+ csrRoamStartJoinRetryTimer(pMac, sessionId, CSR_JOIN_RETRY_TIMEOUT_PERIOD);
+ }
+#endif
+ }
+ else
+ {
+ roamResult = eCSR_ROAM_RESULT_IBSS_START_FAILED;
+ }
+ csrRoamCompletion(pMac, sessionId, NULL, pCommand, roamResult, eANI_BOOLEAN_FALSE);
+ }
+
+ return (status);
+}
+
+
+//After scan for cap changes, issue a roaming command to either reconnect to the AP or pick another one to connect
+eHalStatus csrScanHandleCapChangeScanComplete(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tScanResultHandle hBSSList = NULL;
+ tCsrScanResultFilter *pScanFilter = NULL;
+ tANI_U32 roamId = 0;
+ tCsrRoamProfile *pProfile = NULL;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ do
+ {
+ //Here is the profile we need to connect to
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ if(NULL == pSession) break;
+ if(NULL == pSession->pCurRoamProfile)
+ {
+ pScanFilter->EncryptionType.numEntries = 1;
+ pScanFilter->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+ }
+ else
+ {
+ //We have to make a copy of pCurRoamProfile because it will be free inside csrRoamIssueConnect
+ status = palAllocateMemory(pMac->hHdd, (void **)&pProfile, sizeof(tCsrRoamProfile));
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile);
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter);
+ }//We have a profile
+ roamId = GET_NEXT_ROAM_ID(&pMac->roam);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ 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,
+ eCsrCapsChange, 0, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ csrScanResultPurge(pMac, hBSSList);
+ }
+ }//Have scan result
+ else
+ {
+ smsLog(pMac, LOGW, FL("cannot find matching BSS of %02X-%02X-%02X-%02X-%02X-%02X\n"),
+ pSession->connectedProfile.bssid[0],
+ pSession->connectedProfile.bssid[1],
+ pSession->connectedProfile.bssid[2],
+ pSession->connectedProfile.bssid[3],
+ pSession->connectedProfile.bssid[4],
+ pSession->connectedProfile.bssid[5]);
+ //Disconnect
+ csrRoamDisconnectInternal(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
+ }
+ }
+ }while(0);
+ if(pScanFilter)
+ {
+ csrFreeScanFilter(pMac, pScanFilter);
+ palFreeMemory(pMac->hHdd, pScanFilter);
+ }
+ if(NULL != pProfile)
+ {
+ csrReleaseProfile(pMac, pProfile);
+ palFreeMemory(pMac->hHdd, pProfile);
+ }
+
+ return (status);
+}
+
+
+
+eHalStatus csrScanResultPurge(tpAniSirGlobal pMac, tScanResultHandle hScanList)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tScanResultList *pScanList = (tScanResultList *)hScanList;
+
+ if(pScanList)
+ {
+ status = csrLLScanPurgeResult(pMac, &pScanList->List);
+ csrLLClose(&pScanList->List);
+ palFreeMemory(pMac->hHdd, pScanList);
+ }
+ return (status);
+}
+
+
+static tANI_U32 csrGetBssPreferValue(tpAniSirGlobal pMac, int rssi)
+{
+ tANI_U32 ret = 0;
+ int i = CSR_NUM_RSSI_CAT - 1;
+
+ while(i >= 0)
+ {
+ if(rssi >= pMac->roam.configParam.RSSICat[i])
+ {
+ ret = pMac->roam.configParam.BssPreferValue[i];
+ break;
+ }
+ i--;
+ };
+
+ return (ret);
+}
+
+
+//Return a CapValue base on the capabilities of a BSS
+static tANI_U32 csrGetBssCapValue(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes)
+{
+ tANI_U32 ret = CSR_BSS_CAP_VALUE_NONE;
+
+ if( pIes )
+ {
+ //We only care about 11N capability
+ if(pIes->HTCaps.present)
+ {
+ ret += CSR_BSS_CAP_VALUE_HT;
+ }
+ if(CSR_IS_QOS_BSS(pIes))
+ {
+ ret += CSR_BSS_CAP_VALUE_WMM;
+ //Give advantage to UAPSD
+ if(CSR_IS_UAPSD_BSS(pIes))
+ {
+ ret += CSR_BSS_CAP_VALUE_UAPSD;
+ }
+ }
+ }
+
+ return (ret);
+}
+
+
+//To check whther pBss1 is better than pBss2
+static tANI_BOOLEAN csrIsBetterBss(tCsrScanResult *pBss1, tCsrScanResult *pBss2)
+{
+ tANI_BOOLEAN ret;
+
+ if(CSR_IS_BETTER_PREFER_VALUE(pBss1->preferValue, pBss2->preferValue))
+ {
+ ret = eANI_BOOLEAN_TRUE;
+ }
+ else if(CSR_IS_EQUAL_PREFER_VALUE(pBss1->preferValue, pBss2->preferValue))
+ {
+ if(CSR_IS_BETTER_CAP_VALUE(pBss1->capValue, pBss2->capValue))
+ {
+ ret = eANI_BOOLEAN_TRUE;
+ }
+ else
+ {
+ ret = eANI_BOOLEAN_FALSE;
+ }
+ }
+ else
+ {
+ ret = eANI_BOOLEAN_FALSE;
+ }
+
+ return (ret);
+}
+
+
+//Put the BSS into the scan result list
+//pIes can not be NULL
+static void csrScanAddResult(tpAniSirGlobal pMac, tCsrScanResult *pResult, tDot11fBeaconIEs *pIes)
+{
+ pResult->preferValue = csrGetBssPreferValue(pMac, (int)pResult->Result.BssDescriptor.rssi);
+ pResult->capValue = csrGetBssCapValue(pMac, &pResult->Result.BssDescriptor, pIes);
+ csrLLInsertTail( &pMac->scan.scanResultList, &pResult->Link, LL_ACCESS_LOCK );
+}
+
+
+eHalStatus csrScanGetResult(tpAniSirGlobal pMac, tCsrScanResultFilter *pFilter, tScanResultHandle *phResult)
+{
+ eHalStatus status;
+ tScanResultList *pRetList;
+ tCsrScanResult *pResult, *pBssDesc;
+ tANI_U32 count = 0;
+ tListElem *pEntry;
+ tANI_U32 bssLen, allocLen;
+ eCsrEncryptionType uc = eCSR_ENCRYPT_TYPE_NONE, mc = eCSR_ENCRYPT_TYPE_NONE;
+ eCsrAuthType auth = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+ tDot11fBeaconIEs *pIes, *pNewIes;
+ tANI_BOOLEAN fMatch;
+
+ if(phResult)
+ {
+ *phResult = CSR_INVALID_SCANRESULT_HANDLE;
+ }
+ status = palAllocateMemory(pMac->hHdd, (void **)&pRetList, sizeof(tScanResultList));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pRetList, sizeof(tScanResultList));
+ csrLLOpen(pMac->hHdd, &pRetList->List);
+ pRetList->pCurEntry = NULL;
+
+ csrLLLock(&pMac->scan.scanResultList);
+ pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_NOLOCK );
+ while( pEntry )
+ {
+ pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+ pIes = (tDot11fBeaconIEs *)( pBssDesc->Result.pvIes );
+ //if pBssDesc->Result.pvIes is NULL, we need to free any memory allocated by csrMatchBSS
+ //for any error condition, otherwiase, it will be freed later.
+ //reset
+ fMatch = eANI_BOOLEAN_FALSE;
+ pNewIes = NULL;
+
+ if(pFilter)
+ {
+ fMatch = csrMatchBSS(pMac, &pBssDesc->Result.BssDescriptor, pFilter, &auth, &uc, &mc, &pIes);
+ if( NULL != pIes )
+ {
+ //Only save it when matching
+ if(fMatch)
+ {
+ if( !pBssDesc->Result.pvIes )
+ {
+ //csrMatchBSS allocates the memory. Simply pass it and it is freed later
+ pNewIes = pIes;
+ }
+ else
+ {
+ //The pIes is allocated by someone else. make a copy
+ //Only to save parsed IEs if caller provides a filter. Most likely the caller
+ //is using to for association, hence save the parsed IEs
+ status = palAllocateMemory(pMac->hHdd, (void **)&pNewIes, sizeof(tDot11fBeaconIEs));
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ palCopyMemory( pMac->hHdd, pNewIes, pIes, sizeof( tDot11fBeaconIEs ) );
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" fail to allocate memory for IEs\n"));
+ //Need to free memory allocated by csrMatchBSS
+ if( !pBssDesc->Result.pvIes )
+ {
+ palFreeMemory(pMac->hHdd, pIes);
+ }
+ break;
+ }
+ }
+ }//fMatch
+ else if( !pBssDesc->Result.pvIes )
+ {
+ palFreeMemory(pMac->hHdd, pIes);
+ }
+ }
+ }
+ if(NULL == pFilter || fMatch)
+ {
+ bssLen = pBssDesc->Result.BssDescriptor.length + sizeof(pBssDesc->Result.BssDescriptor.length);
+ allocLen = sizeof( tCsrScanResult ) + bssLen;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pResult, allocLen);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL(" fail to allocate memory for scan result, len=%d\n"), allocLen);
+ if(pNewIes)
+ {
+ palFreeMemory(pMac->hHdd, pNewIes);
+ }
+ break;
+ }
+ palZeroMemory(pMac->hHdd, pResult, allocLen);
+ pResult->capValue = pBssDesc->capValue;
+ pResult->preferValue = pBssDesc->preferValue;
+ pResult->ucEncryptionType = uc;
+ pResult->mcEncryptionType = mc;
+ pResult->authType = auth;
+ pResult->Result.ssId = pBssDesc->Result.ssId;
+ pResult->Result.timer = 0;
+ //save the pIes for later use
+ pResult->Result.pvIes = pNewIes;
+ //save bss description
+ status = palCopyMemory(pMac->hHdd, &pResult->Result.BssDescriptor, &pBssDesc->Result.BssDescriptor, bssLen);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL(" fail to copy memory for scan result\n"));
+ palFreeMemory(pMac->hHdd, pResult);
+ if(pNewIes)
+ {
+ palFreeMemory(pMac->hHdd, pNewIes);
+ }
+ break;
+ }
+ //No need to lock pRetList because it is locally allocated and no outside can access it at this time
+ if(csrLLIsListEmpty(&pRetList->List, LL_ACCESS_NOLOCK))
+ {
+ csrLLInsertTail(&pRetList->List, &pResult->Link, LL_ACCESS_NOLOCK);
+ }
+ else
+ {
+ //To sort the list
+ tListElem *pTmpEntry;
+ tCsrScanResult *pTmpResult;
+
+ pTmpEntry = csrLLPeekHead(&pRetList->List, LL_ACCESS_NOLOCK);
+ while(pTmpEntry)
+ {
+ pTmpResult = GET_BASE_ADDR( pTmpEntry, tCsrScanResult, Link );
+ if(csrIsBetterBss(pResult, pTmpResult))
+ {
+ csrLLInsertEntry(&pRetList->List, pTmpEntry, &pResult->Link, LL_ACCESS_NOLOCK);
+ //To indicate we are done
+ pResult = NULL;
+ break;
+ }
+ pTmpEntry = csrLLNext(&pRetList->List, pTmpEntry, LL_ACCESS_NOLOCK);
+ }
+ if(pResult != NULL)
+ {
+ //This one is not better than any one
+ csrLLInsertTail(&pRetList->List, &pResult->Link, LL_ACCESS_NOLOCK);
+ }
+ }
+ count++;
+ }
+ pEntry = csrLLNext( &pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK );
+ }//while
+ csrLLUnlock(&pMac->scan.scanResultList);
+
+ smsLog(pMac, LOG2, FL("return %d BSS\n"), csrLLCount(&pRetList->List));
+
+ if( !HAL_STATUS_SUCCESS(status) || (phResult == NULL) )
+ {
+ //Fail or No one wants the result.
+ csrScanResultPurge(pMac, (tScanResultHandle)pRetList);
+ }
+ else
+ {
+ if(0 == count)
+ {
+ //We are here meaning the there is no match
+ csrLLClose(&pRetList->List);
+ palFreeMemory(pMac->hHdd, pRetList);
+ status = eHAL_STATUS_E_NULL_VALUE;
+ }
+ else if(phResult)
+ {
+ *phResult = pRetList;
+ }
+ }
+ }//Allocated pRetList
+
+ return (status);
+}
+
+
+eHalStatus csrScanFlushResult(tpAniSirGlobal pMac)
+{
+ return ( csrLLScanPurgeResult(pMac, &pMac->scan.scanResultList) );
+}
+
+/**
+ * csrCheck11dChannel
+ *
+ *FUNCTION:
+ * This function is called from csrScanFilter11dResult function and
+ * compare channel number with given channel list.
+ *
+ *LOGIC:
+ * Check Scan result channel number with CFG channel list
+ *
+ *ASSUMPTIONS:
+ *
+ *
+ *NOTE:
+ *
+ * @param channelId channel number
+ * @param pChannelList Pointer to channel list
+ * @param numChannels Number of channel in channel list
+ *
+ * @return Status
+ */
+
+eHalStatus csrCheck11dChannel(tANI_U8 channelId, tANI_U8 *pChannelList, tANI_U32 numChannels)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tANI_U8 i = 0;
+
+ for (i = 0; i < numChannels; i++)
+ {
+ if(pChannelList[ i ] == channelId)
+ {
+ status = eHAL_STATUS_SUCCESS;
+ break;
+ }
+ }
+ return status;
+}
+
+/**
+ * csrScanFilter11dResult
+ *
+ *FUNCTION:
+ * This function is called from csrApplyCountryInformation function and
+ * filter scan result based on valid channel list number.
+ *
+ *LOGIC:
+ * Get scan result from scan list and Check Scan result channel number
+ * with 11d channel list if channel number is found in 11d channel list
+ * then do not remove scan result entry from scan list
+ *
+ *ASSUMPTIONS:
+ *
+ *
+ *NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ *
+ * @return Status
+ */
+
+eHalStatus csrScanFilter11dResult(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tListElem *pEntry,*pTempEntry;
+ tCsrScanResult *pBssDesc;
+ tANI_U32 len = sizeof(pMac->roam.validChannelList);
+
+ /* Get valid channels list from CFG */
+ if (!HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac,
+ pMac->roam.validChannelList, &len)))
+ {
+ smsLog( pMac, LOG1, "Failed to get Channel list from CFG");
+ }
+
+ pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_LOCK );
+ while( pEntry )
+ {
+ pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+ pTempEntry = csrLLNext( &pMac->scan.scanResultList, pEntry,
+ LL_ACCESS_LOCK );
+ if(csrCheck11dChannel(pBssDesc->Result.BssDescriptor.channelId,
+ pMac->roam.validChannelList, len))
+ {
+ /* Remove Scan result which does not have 11d channel */
+ if( csrLLRemoveEntry( &pMac->scan.scanResultList, pEntry,
+ LL_ACCESS_LOCK ))
+ {
+ csrFreeScanResultEntry( pMac, pBssDesc );
+ }
+ }
+ pEntry = pTempEntry;
+ }
+ return status;
+}
+
+
+eHalStatus csrScanCopyResultList(tpAniSirGlobal pMac, tScanResultHandle hIn, tScanResultHandle *phResult)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tScanResultList *pRetList, *pInList = (tScanResultList *)hIn;
+ tCsrScanResult *pResult, *pScanResult;
+ tANI_U32 count = 0;
+ tListElem *pEntry;
+ tANI_U32 bssLen, allocLen;
+
+ if(phResult)
+ {
+ *phResult = CSR_INVALID_SCANRESULT_HANDLE;
+ }
+ status = palAllocateMemory(pMac->hHdd, (void **)&pRetList, sizeof(tScanResultList));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pRetList, sizeof(tScanResultList));
+ csrLLOpen(pMac->hHdd, &pRetList->List);
+ pRetList->pCurEntry = NULL;
+ csrLLLock(&pMac->scan.scanResultList);
+ csrLLLock(&pInList->List);
+
+ pEntry = csrLLPeekHead( &pInList->List, LL_ACCESS_NOLOCK );
+ while( pEntry )
+ {
+ pScanResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+ bssLen = pScanResult->Result.BssDescriptor.length + sizeof(pScanResult->Result.BssDescriptor.length);
+ allocLen = sizeof( tCsrScanResult ) + bssLen;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pResult, allocLen);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ csrScanResultPurge(pMac, (tScanResultHandle *)pRetList);
+ count = 0;
+ break;
+ }
+ palZeroMemory(pMac->hHdd, pResult, allocLen);
+ status = palCopyMemory(pMac->hHdd, &pResult->Result.BssDescriptor, &pScanResult->Result.BssDescriptor, bssLen);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ csrScanResultPurge(pMac, (tScanResultHandle *)pRetList);
+ count = 0;
+ break;
+ }
+ if( pScanResult->Result.pvIes )
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pResult->Result.pvIes, sizeof( tDot11fBeaconIEs ));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ //Free the memory we allocate above first
+ palFreeMemory( pMac->hHdd, pResult );
+ csrScanResultPurge(pMac, (tScanResultHandle *)pRetList);
+ count = 0;
+ break;
+ }
+ status = palCopyMemory(pMac->hHdd, pResult->Result.pvIes,
+ pScanResult->Result.pvIes, sizeof( tDot11fBeaconIEs ));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ //Free the memory we allocate above first
+ palFreeMemory( pMac->hHdd, pResult );
+ csrScanResultPurge(pMac, (tScanResultHandle *)pRetList);
+ count = 0;
+ break;
+ }
+ }
+ csrLLInsertTail(&pRetList->List, &pResult->Link, LL_ACCESS_LOCK);
+ count++;
+ pEntry = csrLLNext( &pInList->List, pEntry, LL_ACCESS_NOLOCK );
+ }//while
+ csrLLUnlock(&pInList->List);
+ csrLLUnlock(&pMac->scan.scanResultList);
+
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ if(0 == count)
+ {
+ csrLLClose(&pRetList->List);
+ palFreeMemory(pMac->hHdd, pRetList);
+ status = eHAL_STATUS_E_NULL_VALUE;
+ }
+ else if(phResult)
+ {
+ *phResult = pRetList;
+ }
+ }
+ }//Allocated pRetList
+
+ return (status);
+}
+
+
+
+eHalStatus csrScanningStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirMbMsg *pMsg = (tSirMbMsg *)pMsgBuf;
+
+ if((eWNI_SME_SCAN_RSP == pMsg->type) || (eWNI_SME_GET_SCANNED_CHANNEL_RSP == pMsg->type))
+ {
+ status = csrScanSmeScanResponse( pMac, pMsgBuf );
+ }
+ else
+ {
+ if( csrIsAnySessionInConnectState( pMac ) )
+ {
+ //In case of we are connected, we need to check whether connect status changes
+ //because scan may also run while connected.
+ csrRoamCheckForLinkStatusChange( pMac, ( tSirSmeRsp * )pMsgBuf );
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "Message [0x%04x] received in state, when expecting Scan Response\n", pMsg->type );
+ }
+ }
+
+ return (status);
+}
+
+
+
+void csrCheckNSaveWscIe(tpAniSirGlobal pMac, tSirBssDescription *pNewBssDescr, tSirBssDescription *pOldBssDescr)
+{
+ int idx, len;
+ tANI_U8 *pbIe;
+
+ //If failed to remove, assuming someone else got it.
+ if((pNewBssDescr->fProbeRsp != pOldBssDescr->fProbeRsp) &&
+ (0 == pNewBssDescr->WscIeLen))
+ {
+ idx = 0;
+ len = pOldBssDescr->length - sizeof(tSirBssDescription) +
+ sizeof(tANI_U16) + sizeof(tANI_U32) - DOT11F_IE_WSCPROBERES_MIN_LEN - 2;
+ pbIe = (tANI_U8 *)pOldBssDescr->ieFields;
+ //Save WPS IE if it exists
+ pNewBssDescr->WscIeLen = 0;
+ while(idx < len)
+ {
+ if((DOT11F_EID_WSCPROBERES == pbIe[0]) &&
+ (0x00 == pbIe[2]) && (0x50 == pbIe[3]) && (0xf2 == pbIe[4]) && (0x04 == pbIe[5]))
+ {
+ //Founrd it
+ if((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >= pbIe[1])
+ {
+ palCopyMemory(pMac->hHdd, pNewBssDescr->WscIeProbeRsp,
+ pbIe, pbIe[1] + 2);
+ pNewBssDescr->WscIeLen = pbIe[1] + 2;
+ }
+ break;
+ }
+ idx += pbIe[1] + 2;
+ pbIe += pbIe[1] + 2;
+ }
+ }
+}
+
+
+
+//pIes may be NULL
+tANI_BOOLEAN csrRemoveDupBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDescr,
+ tDot11fBeaconIEs *pIes, tAniSSID *pSsid , v_TIME_t *timer )
+{
+ tListElem *pEntry;
+
+ tCsrScanResult *pBssDesc;
+ tANI_BOOLEAN fRC = FALSE;
+
+ // Walk through all the chained BssDescriptions. If we find a chained BssDescription that
+ // matches the BssID of the BssDescription passed in, then these must be duplicate scan
+ // results for this Bss. In that case, remove the 'old' Bss description from the linked list.
+ pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_LOCK );
+
+ while( pEntry )
+ {
+ pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+
+ // we have a duplicate scan results only when BSSID, SSID, Channel and NetworkType
+ // matches
+ if ( csrIsDuplicateBssDescription( pMac, &pBssDesc->Result.BssDescriptor,
+ pSirBssDescr, pIes ) )
+ {
+ pSirBssDescr->rssi = (tANI_S8)( (((tANI_S32)pSirBssDescr->rssi * CSR_SCAN_RESULT_RSSI_WEIGHT ) +
+ ((tANI_S32)pBssDesc->Result.BssDescriptor.rssi * (100 - CSR_SCAN_RESULT_RSSI_WEIGHT) )) / 100 );
+ // Remove the 'old' entry from the list....
+ if( csrLLRemoveEntry( &pMac->scan.scanResultList, pEntry, LL_ACCESS_LOCK ) )
+ {
+ // !we need to free the memory associated with this node
+ //If failed to remove, assuming someone else got it.
+ *pSsid = pBssDesc->Result.ssId;
+ *timer = pBssDesc->Result.timer;
+ csrCheckNSaveWscIe(pMac, pSirBssDescr, &pBssDesc->Result.BssDescriptor);
+
+ csrFreeScanResultEntry( pMac, pBssDesc );
+ }
+ else
+ {
+ smsLog( pMac, LOGW, FL( " fail to remove entry\n" ) );
+ }
+ fRC = TRUE;
+
+ // If we found a match, we can stop looking through the list.
+ break;
+ }
+
+ pEntry = csrLLNext( &pMac->scan.scanResultList, pEntry, LL_ACCESS_LOCK );
+ }
+
+ return fRC;
+}
+
+
+eHalStatus csrAddPMKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOGW, "csrAddPMKIDCandidateList called pMac->scan.NumPmkidCandidate = %d\n", pSession->NumPmkidCandidate);
+ if( pIes )
+ {
+ // check if this is a RSN BSS
+ if( pIes->RSN.present )
+ {
+ // Check if the BSS is capable of doing pre-authentication
+ if( pSession->NumPmkidCandidate < CSR_MAX_PMKID_ALLOWED )
+ {
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ {
+ WLAN_VOS_DIAG_EVENT_DEF(secEvent, vos_event_wlan_security_payload_type);
+ palZeroMemory(pMac->hHdd, &secEvent, sizeof(vos_event_wlan_security_payload_type));
+ secEvent.eventId = WLAN_SECURITY_EVENT_PMKID_CANDIDATE_FOUND;
+ secEvent.encryptionModeMulticast =
+ (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType);
+ secEvent.encryptionModeUnicast =
+ (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType);
+ palCopyMemory( pMac->hHdd, 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//#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+
+ // if yes, then add to PMKIDCandidateList
+ status = palCopyMemory(pMac->hHdd, pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate].BSSID,
+ pBssDesc->bssId, WNI_CFG_BSSID_LEN);
+
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ if ( pIes->RSN.preauth )
+ {
+ pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate].preAuthSupported = eANI_BOOLEAN_TRUE;
+ }
+ else
+ {
+ pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate].preAuthSupported = eANI_BOOLEAN_FALSE;
+ }
+ pSession->NumPmkidCandidate++;
+ }
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ }
+ }
+
+ return (status);
+}
+
+//This function checks whether new AP is found for the current connected profile
+//If it is found, it return the sessionId, else it return invalid sessionID
+tANI_U32 csrProcessBSSDescForPMKIDList(tpAniSirGlobal pMac,
+ tSirBssDescription *pBssDesc,
+ tDot11fBeaconIEs *pIes)
+{
+ tANI_U32 i, bRet = CSR_SESSION_ID_INVALID;
+ tCsrRoamSession *pSession;
+ tDot11fBeaconIEs *pIesLocal = pIes;
+
+ if( pIesLocal || HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal)) )
+ {
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) )
+ {
+ pSession = CSR_GET_SESSION( pMac, i );
+ if( csrIsConnStateConnectedInfra( pMac, i ) &&
+ ( eCSR_AUTH_TYPE_RSN == pSession->connectedProfile.AuthType ) )
+ {
+ if(csrMatchBSSToConnectProfile(pMac, &pSession->connectedProfile, pBssDesc, pIesLocal))
+ {
+ //this new BSS fits the current profile connected
+ if(HAL_STATUS_SUCCESS(csrAddPMKIDCandidateList(pMac, i, pBssDesc, pIesLocal)))
+ {
+ bRet = i;
+ }
+ break;
+ }
+ }
+ }
+ }
+ if( !pIes )
+ {
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+ }
+
+ return (tANI_U8)bRet;
+}
+
+#ifdef FEATURE_WLAN_WAPI
+eHalStatus csrAddBKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOGW, "csrAddBKIDCandidateList called pMac->scan.NumBkidCandidate = %d\n", pSession->NumBkidCandidate);
+ if( pIes )
+ {
+ // check if this is a WAPI BSS
+ if( pIes->WAPI.present )
+ {
+ // Check if the BSS is capable of doing pre-authentication
+ if( pSession->NumBkidCandidate < CSR_MAX_BKID_ALLOWED )
+ {
+
+ // if yes, then add to BKIDCandidateList
+ status = palCopyMemory(pMac->hHdd, pSession->BkidCandidateInfo[pSession->NumBkidCandidate].BSSID,
+ pBssDesc->bssId, WNI_CFG_BSSID_LEN);
+
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ if ( pIes->WAPI.preauth )
+ {
+ pSession->BkidCandidateInfo[pSession->NumBkidCandidate].preAuthSupported = eANI_BOOLEAN_TRUE;
+ }
+ else
+ {
+ pSession->BkidCandidateInfo[pSession->NumBkidCandidate].preAuthSupported = eANI_BOOLEAN_FALSE;
+ }
+ pSession->NumBkidCandidate++;
+ }
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ }
+ }
+
+ return (status);
+}
+
+//This function checks whether new AP is found for the current connected profile
+//if so add to BKIDCandidateList
+tANI_BOOLEAN csrProcessBSSDescForBKIDList(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc,
+ tDot11fBeaconIEs *pIes)
+{
+ tANI_BOOLEAN fRC = FALSE;
+ tDot11fBeaconIEs *pIesLocal = pIes;
+ tANI_U32 sessionId;
+ tCsrRoamSession *pSession;
+
+ if( pIesLocal || HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal)) )
+ {
+ for( sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId) )
+ {
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+ if( csrIsConnStateConnectedInfra( pMac, sessionId ) &&
+ eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == pSession->connectedProfile.AuthType)
+ {
+ if(csrMatchBSSToConnectProfile(pMac, &pSession->connectedProfile,pBssDesc, pIesLocal))
+ {
+ //this new BSS fits the current profile connected
+ if(HAL_STATUS_SUCCESS(csrAddBKIDCandidateList(pMac, sessionId, pBssDesc, pIesLocal)))
+ {
+ fRC = TRUE;
+ }
+ }
+ }
+ }
+ }
+ if(!pIes)
+ {
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+
+ }
+ return fRC;
+}
+
+#endif
+
+
+static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac )
+{
+ tListElem *pEntry;
+ tCsrScanResult *pBssDescription;
+ tANI_S8 cand_Bss_rssi;
+ tANI_BOOLEAN fDupBss;
+#ifdef FEATURE_WLAN_WAPI
+ tANI_BOOLEAN fNewWapiBSSForCurConnection = eANI_BOOLEAN_FALSE;
+#endif /* FEATURE_WLAN_WAPI */
+ tDot11fBeaconIEs *pIesLocal = NULL;
+ tANI_U32 sessionId = CSR_SESSION_ID_INVALID;
+ tAniSSID tmpSsid;
+ v_TIME_t timer=0;
+
+ tmpSsid.length = 0;
+ cand_Bss_rssi = -128; // RSSI coming from PE is -ve
+
+ // remove the BSS descriptions from temporary list
+ while( ( pEntry = csrLLRemoveTail( &pMac->scan.tempScanResults, LL_ACCESS_LOCK ) ) != NULL)
+ {
+ pBssDescription = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+
+ smsLog( pMac, LOGW, "...Bssid= %02x-%02x-%02x-%02x-%02x-%02x chan= %d, rssi = -%d\n",
+ pBssDescription->Result.BssDescriptor.bssId[ 0 ], pBssDescription->Result.BssDescriptor.bssId[ 1 ],
+ pBssDescription->Result.BssDescriptor.bssId[ 2 ], pBssDescription->Result.BssDescriptor.bssId[ 3 ],
+ pBssDescription->Result.BssDescriptor.bssId[ 4 ], pBssDescription->Result.BssDescriptor.bssId[ 5 ],
+ pBssDescription->Result.BssDescriptor.channelId,
+ pBssDescription->Result.BssDescriptor.rssi * (-1) );
+
+ //At this time, pBssDescription->Result.pvIes may be NULL
+ pIesLocal = (tDot11fBeaconIEs *)( pBssDescription->Result.pvIes );
+ if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, &pBssDescription->Result.BssDescriptor, &pIesLocal))) )
+ {
+ smsLog(pMac, LOGE, FL(" Cannot pared IEs\n"));
+ csrFreeScanResultEntry(pMac, pBssDescription);
+ continue;
+ }
+ fDupBss = csrRemoveDupBssDescription( pMac, &pBssDescription->Result.BssDescriptor, pIesLocal, &tmpSsid , &timer );
+ //Check whether we have reach out limit
+ if( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) )
+ {
+ //Limit reach
+ smsLog(pMac, LOGW, FL(" BSS limit reached\n"));
+ //Free the resources
+ if( (pBssDescription->Result.pvIes == NULL) && pIesLocal )
+ {
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+ csrFreeScanResultEntry(pMac, pBssDescription);
+ //Continue because there may be duplicated BSS
+ continue;
+ }
+ // check for duplicate scan results
+ if ( !fDupBss )
+ {
+ //Found a new BSS
+ sessionId = csrProcessBSSDescForPMKIDList(pMac,
+ &pBssDescription->Result.BssDescriptor, pIesLocal);
+ if( CSR_SESSION_ID_INVALID != sessionId)
+ {
+ csrRoamCallCallback(pMac, sessionId, NULL, 0,
+ eCSR_ROAM_SCAN_FOUND_NEW_BSS, eCSR_ROAM_RESULT_NONE);
+ }
+ }
+ else
+ {
+ //Check if the new one has SSID it it, if not, use the older SSID if it exists.
+ if( (0 == pBssDescription->Result.ssId.length) && tmpSsid.length )
+ {
+ //New BSS has a hidden SSID and old one has the SSID. Keep the SSID only
+ //if diff of saved SSID time and current time is less than 1 min to avoid
+ //side effect of saving SSID with old one is that if AP changes its SSID while remain
+ //hidden, we may never see it and also to address the requirement of
+ //When we remove hidden ssid from the profile i.e., forget the SSID via
+ // GUI that SSID shouldn't see in the profile
+ if( (vos_timer_get_system_time() - timer) <= HIDDEN_TIMER)
+ {
+ pBssDescription->Result.timer = timer;
+ pBssDescription->Result.ssId = tmpSsid;
+ }
+ }
+ }
+
+ //Tush: find a good AP for 11d info
+ if( csrIs11dSupported( pMac ) )
+ {
+ if(cand_Bss_rssi < pBssDescription->Result.BssDescriptor.rssi)
+ {
+ // check if country information element is present
+ if(pIesLocal->Country.present)
+ {
+ cand_Bss_rssi = pBssDescription->Result.BssDescriptor.rssi;
+ // learn country information
+ csrLearnCountryInformation( pMac, &pBssDescription->Result.BssDescriptor,
+ pIesLocal, eANI_BOOLEAN_FALSE );
+ }
+
+ }
+ }
+
+ // append to main list
+ csrScanAddResult(pMac, pBssDescription, pIesLocal);
+ if( (pBssDescription->Result.pvIes == NULL) && pIesLocal )
+ {
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+ }
+
+ //Tush: If we can find the current 11d info in any of the scan results, or
+ // a good enough AP with the 11d info from the scan results then no need to
+ // get into ambiguous state
+ if(pMac->scan.fAmbiguous11dInfoFound)
+ {
+ if((pMac->scan.fCurrent11dInfoMatch) || (cand_Bss_rssi != -128))
+ {
+ pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_FALSE;
+ }
+ }
+
+#ifdef FEATURE_WLAN_WAPI
+ if(fNewWapiBSSForCurConnection)
+ {
+ //remember it first
+ csrRoamCallCallback(pMac, sessionId, NULL, 0, eCSR_ROAM_SCAN_FOUND_NEW_BSS, eCSR_ROAM_RESULT_NEW_WAPI_BSS);
+ }
+#endif /* FEATURE_WLAN_WAPI */
+
+ return;
+}
+
+
+static tCsrScanResult *csrScanSaveBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pBSSDescription,
+ tDot11fBeaconIEs *pIes)
+{
+ tCsrScanResult *pCsrBssDescription = NULL;
+ tANI_U32 cbBSSDesc;
+ tANI_U32 cbAllocated;
+ eHalStatus halStatus;
+
+ // figure out how big the BSS description is (the BSSDesc->length does NOT
+ // include the size of the length field itself).
+ cbBSSDesc = pBSSDescription->length + sizeof( pBSSDescription->length );
+
+ cbAllocated = sizeof( tCsrScanResult ) + cbBSSDesc;
+
+ halStatus = palAllocateMemory( pMac->hHdd, (void **)&pCsrBssDescription, cbAllocated );
+ if ( HAL_STATUS_SUCCESS(halStatus) )
+ {
+ palZeroMemory( pMac->hHdd, pCsrBssDescription, cbAllocated );
+ pCsrBssDescription->AgingCount = (tANI_S32)pMac->roam.configParam.agingCount;
+ palCopyMemory(pMac->hHdd, &pCsrBssDescription->Result.BssDescriptor, pBSSDescription, cbBSSDesc );
+#if defined(VOSS_ENSBALED)
+ VOS_ASSERT( pCsrBssDescription->Result.pvIes == NULL );
+#endif
+ csrScanAddResult(pMac, pCsrBssDescription, pIes);
+ }
+
+ return( pCsrBssDescription );
+}
+
+// Append a Bss Description...
+tCsrScanResult *csrScanAppendBssDescription( tpAniSirGlobal pMac,
+ tSirBssDescription *pSirBssDescription,
+ tDot11fBeaconIEs *pIes )
+{
+ tCsrScanResult *pCsrBssDescription = NULL;
+ tAniSSID tmpSsid;
+ v_TIME_t timer = 0;
+ int result;
+
+ tmpSsid.length = 0;
+ result = csrRemoveDupBssDescription( pMac, pSirBssDescription, pIes, &tmpSsid, &timer );
+ pCsrBssDescription = csrScanSaveBssDescription( pMac, pSirBssDescription, pIes );
+ if (result && (pCsrBssDescription != NULL))
+ {
+ //Check if the new one has SSID it it, if not, use the older SSID if it exists.
+ if( (0 == pCsrBssDescription->Result.ssId.length) && tmpSsid.length )
+ {
+ //New BSS has a hidden SSID and old one has the SSID. Keep the SSID only
+ //if diff of saved SSID time and current time is less than 1 min to avoid
+ //side effect of saving SSID with old one is that if AP changes its SSID while remain
+ //hidden, we may never see it and also to address the requirement of
+ //When we remove hidden ssid from the profile i.e., forget the SSID via
+ // GUI that SSID shouldn't see in the profile
+ if((vos_timer_get_system_time()-timer) <= HIDDEN_TIMER)
+ {
+ pCsrBssDescription->Result.ssId = tmpSsid;
+ pCsrBssDescription->Result.timer = timer;
+ }
+ }
+ }
+
+
+ return( pCsrBssDescription );
+}
+
+
+
+void csrPurgeChannelPower( tpAniSirGlobal pMac, tDblLinkList *pChannelList )
+{
+ tCsrChannelPowerInfo *pChannelSet;
+ tListElem *pEntry;
+
+ csrLLLock(pChannelList);
+ // Remove the channel sets from the learned list and put them in the free list
+ while( ( pEntry = csrLLRemoveHead( pChannelList, LL_ACCESS_NOLOCK ) ) != NULL)
+ {
+ pChannelSet = GET_BASE_ADDR( pEntry, tCsrChannelPowerInfo, link );
+ if( pChannelSet )
+ {
+ palFreeMemory( pMac->hHdd, pChannelSet );
+ }
+ }
+ csrLLUnlock(pChannelList);
+ return;
+}
+
+
+/*
+ * Save the channelList into the ultimate storage as the final stage of channel
+ * Input: pCountryInfo -- the country code (e.g. "USI"), channel list, and power limit are all stored inside this data structure
+ */
+void csrSaveToChannelPower2G_5G( tpAniSirGlobal pMac, tANI_U32 tableSize, tSirMacChanInfo *channelTable )
+{
+ tANI_U32 i = tableSize / sizeof( tSirMacChanInfo );
+ tSirMacChanInfo *pChannelInfo;
+ tCsrChannelPowerInfo *pChannelSet;
+ tANI_BOOLEAN f2GHzInfoFound = FALSE;
+ tANI_BOOLEAN f2GListPurged = FALSE, f5GListPurged = FALSE;
+ eHalStatus halStatus;
+
+ pChannelInfo = channelTable;
+ // atleast 3 bytes have to be remaining -- from "countryString"
+ while ( i-- )
+ {
+ halStatus = palAllocateMemory( pMac->hHdd, (void **)&pChannelSet, sizeof(tCsrChannelPowerInfo) );
+ if ( eHAL_STATUS_SUCCESS == halStatus )
+ {
+ palZeroMemory(pMac->hHdd, pChannelSet, sizeof(tCsrChannelPowerInfo));
+ pChannelSet->firstChannel = pChannelInfo->firstChanNum;
+ pChannelSet->numChannels = pChannelInfo->numChannels;
+
+ // Now set the inter-channel offset based on the frequency band the channel set lies in
+ if( CSR_IS_CHANNEL_24GHZ(pChannelSet->firstChannel) )
+ {
+ pChannelSet->interChannelOffset = 1;
+ f2GHzInfoFound = TRUE;
+ }
+ else
+ {
+ pChannelSet->interChannelOffset = 4;
+ f2GHzInfoFound = FALSE;
+ }
+ pChannelSet->txPower = CSR_ROAM_MIN( pChannelInfo->maxTxPower, pMac->roam.configParam.nTxPowerCap );
+
+ if( f2GHzInfoFound )
+ {
+ if( !f2GListPurged )
+ {
+ // purge previous results if found new
+ csrPurgeChannelPower( pMac, &pMac->scan.channelPowerInfoList24 );
+ f2GListPurged = TRUE;
+ }
+
+ if(CSR_IS_OPERATING_BG_BAND(pMac))
+ {
+ // add to the list of 2.4 GHz channel sets
+ csrLLInsertTail( &pMac->scan.channelPowerInfoList24, &pChannelSet->link, LL_ACCESS_LOCK );
+ }
+ else {
+ smsLog( pMac, LOGW, FL("Adding 11B/G channels in 11A mode -- First Channel is %d"),
+ pChannelSet->firstChannel);
+ palFreeMemory(pMac->hHdd, pChannelSet);
+ }
+ }
+ else
+ {
+ // 5GHz info found
+ if( !f5GListPurged )
+ {
+ // purge previous results if found new
+ csrPurgeChannelPower( pMac, &pMac->scan.channelPowerInfoList5G );
+ f5GListPurged = TRUE;
+ }
+
+ if(CSR_IS_OPERATING_A_BAND(pMac))
+ {
+ // add to the list of 5GHz channel sets
+ csrLLInsertTail( &pMac->scan.channelPowerInfoList5G, &pChannelSet->link, LL_ACCESS_LOCK );
+ }
+ else {
+ smsLog( pMac, LOGW, FL("Adding 11A channels in B/G mode -- First Channel is %d"),
+ pChannelSet->firstChannel);
+ palFreeMemory(pMac->hHdd, pChannelSet);
+ }
+ }
+ }
+
+ pChannelInfo++; // move to next entry
+ }
+
+ return;
+}
+
+
+
+void csrApplyPower2Current( tpAniSirGlobal pMac )
+{
+ smsLog( pMac, LOG3, FL(" Updating Cfg with power settings\n"));
+ csrSaveTxPowerToCfg( pMac, &pMac->scan.channelPowerInfoList24, WNI_CFG_MAX_TX_POWER_2_4 );
+ csrSaveTxPowerToCfg( pMac, &pMac->scan.channelPowerInfoList5G, WNI_CFG_MAX_TX_POWER_5 );
+}
+
+
+void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannelList, tANI_U8 *countryCode)
+{
+ int i;
+ eNVChannelEnabledType channelEnabledType;
+ tANI_U8 numChannels = 0;
+ tANI_U8 tempNumChannels = 0;
+ tCsrChannel ChannelList;
+ if( pChannelList->numChannels )
+ {
+ tempNumChannels = CSR_MIN(pChannelList->numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
+ /* If user doesn't want to scan the DFS channels lets trim them from
+ the valid channel list*/
+ if(FALSE == pMac->scan.fEnableDFSChnlScan)
+ {
+ for(i = 0; i< tempNumChannels; i++)
+ {
+ channelEnabledType =
+ vos_nv_getChannelEnabledState(pChannelList->channelList[i]);
+ if( NV_CHANNEL_ENABLE == channelEnabledType)
+ {
+ ChannelList.channelList[numChannels] =
+ pChannelList->channelList[i];
+ numChannels++;
+ }
+ }
+ ChannelList.numChannels = numChannels;
+ }
+ else
+ {
+ ChannelList.numChannels = tempNumChannels;
+ vos_mem_copy(ChannelList.channelList,
+ pChannelList->channelList,
+ ChannelList.numChannels);
+ }
+
+ csrSetCfgValidChannelList(pMac, ChannelList.channelList, ChannelList.numChannels);
+ // extend scan capability
+ csrSetCfgScanControlList(pMac, countryCode, &ChannelList); // build a scan list based on the channel list : channel# + active/passive scan
+#ifdef FEATURE_WLAN_SCAN_PNO
+ // Send HAL UpdateScanParams message
+ //pmcUpdateScanParams(pMac, &(pMac->roam.configParam), pChannelList, TRUE);
+#endif // FEATURE_WLAN_SCAN_PNO
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" 11D channel list is empty\n"));
+ }
+ csrApplyPower2Current( pMac ); // Store the channel+power info in the global place: Cfg
+ csrSetCfgCountryCode(pMac, countryCode);
+}
+
+
+void csrResetCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce )
+{
+ if( fForce || (csrIs11dSupported( pMac ) && (!pMac->scan.f11dInfoReset)))
+ {
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ {
+ vos_log_802_11d_pkt_type *p11dLog;
+ int Index;
+
+ WLAN_VOS_DIAG_LOG_ALLOC(p11dLog, vos_log_802_11d_pkt_type, LOG_WLAN_80211D_C);
+ if(p11dLog)
+ {
+ p11dLog->eventId = WLAN_80211D_EVENT_RESET;
+ palCopyMemory(pMac->hHdd, p11dLog->countryCode, pMac->scan.countryCodeCurrent, 3);
+ p11dLog->numChannel = pMac->scan.base20MHzChannels.numChannels;
+ if(p11dLog->numChannel <= VOS_LOG_MAX_NUM_CHANNEL)
+ {
+ palCopyMemory(pMac->hHdd, p11dLog->Channels, pMac->scan.base20MHzChannels.channelList,
+ p11dLog->numChannel);
+ for (Index=0; Index < pMac->scan.base20MHzChannels.numChannels; Index++)
+ {
+ p11dLog->TxPwr[Index] = CSR_ROAM_MIN( pMac->scan.defaultPowerTable[Index].pwr, pMac->roam.configParam.nTxPowerCap );
+ }
+ }
+ if(!pMac->roam.configParam.Is11dSupportEnabled)
+ {
+ p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED;
+ }
+ else if(pMac->roam.configParam.fEnforceDefaultDomain)
+ {
+ p11dLog->supportMultipleDomain = WLAN_80211D_NOT_SUPPORT_MULTI_DOMAIN;
+ }
+ else
+ {
+ p11dLog->supportMultipleDomain = WLAN_80211D_SUPPORT_MULTI_DOMAIN;
+ }
+ WLAN_VOS_DIAG_LOG_REPORT(p11dLog);
+ }
+ }
+#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+
+ // switch to passive scans only when 11d is enabled
+ if( csrIs11dSupported( pMac ) )
+ {
+ pMac->scan.curScanType = eSIR_PASSIVE_SCAN;
+ }
+ csrSaveChannelPowerForBand(pMac, eANI_BOOLEAN_FALSE);
+ csrSaveChannelPowerForBand(pMac, eANI_BOOLEAN_TRUE);
+ // ... and apply the channel list, power settings, and the country code.
+ csrApplyChannelPowerCountryInfo( pMac, &pMac->scan.base20MHzChannels, pMac->scan.countryCodeCurrent );
+ // clear the 11d channel list
+ palZeroMemory( pMac->hHdd, &pMac->scan.channels11d, sizeof(pMac->scan.channels11d) );
+ pMac->scan.f11dInfoReset = eANI_BOOLEAN_TRUE;
+ pMac->scan.f11dInfoApplied = eANI_BOOLEAN_FALSE;
+ }
+
+ return;
+}
+
+
+eHalStatus csrResetCountryCodeInformation(tpAniSirGlobal pMac, tANI_BOOLEAN *pfRestartNeeded)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_BOOLEAN fRestart = eANI_BOOLEAN_FALSE;
+
+ //Use the Country code and domain from EEPROM
+ palCopyMemory(pMac->hHdd, pMac->scan.countryCodeCurrent, pMac->scan.countryCodeDefault, WNI_CFG_COUNTRY_CODE_LEN);
+ csrSetRegulatoryDomain(pMac, pMac->scan.domainIdCurrent, &fRestart);
+ if(eANI_BOOLEAN_FALSE == fRestart || (pfRestartNeeded == NULL))
+ {
+ //Only reset the country info if we don't need to restart
+ csrResetCountryInformation(pMac, eANI_BOOLEAN_TRUE);
+ }
+ if(pfRestartNeeded)
+ {
+ *pfRestartNeeded = fRestart;
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrSetCountryCode(tpAniSirGlobal pMac, tANI_U8 *pCountry, tANI_BOOLEAN *pfRestartNeeded)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ v_REGDOMAIN_t domainId;
+
+ if(pCountry)
+ {
+ status = csrGetRegulatoryDomainForCountry(pMac, pCountry, &domainId);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ status = csrSetRegulatoryDomain(pMac, domainId, pfRestartNeeded);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ //We don't need to check the pMac->roam.configParam.fEnforceDefaultDomain flag here,
+ //csrSetRegulatoryDomain will fail if the country doesn't fit our domain criteria.
+ palCopyMemory(pMac->hHdd, pMac->scan.countryCodeCurrent, pCountry, WNI_CFG_COUNTRY_CODE_LEN);
+ if((pfRestartNeeded == NULL) || !(*pfRestartNeeded))
+ {
+ //Simply set it to cfg. If we need to restart, restart will apply it to the CFG
+ csrSetCfgCountryCode(pMac, pCountry);
+ }
+ }
+ }
+ }
+
+ return (status);
+}
+
+
+
+//caller allocated memory for pNumChn and pChnPowerInfo
+//As input, *pNumChn has the size of the array of pChnPowerInfo
+//Upon return, *pNumChn has the number of channels assigned.
+void csrGetChannelPowerInfo( tpAniSirGlobal pMac, tDblLinkList *pList,
+ tANI_U32 *pNumChn, tChannelListWithPower *pChnPowerInfo)
+{
+ tListElem *pEntry;
+ tANI_U32 chnIdx = 0, idx;
+ tCsrChannelPowerInfo *pChannelSet;
+
+ //Get 2.4Ghz first
+ pEntry = csrLLPeekHead( pList, LL_ACCESS_LOCK );
+ while( pEntry && (chnIdx < *pNumChn) )
+ {
+ pChannelSet = GET_BASE_ADDR( pEntry, tCsrChannelPowerInfo, link );
+ if ( 1 != pChannelSet->interChannelOffset )
+ {
+ for( idx = 0; (idx < pChannelSet->numChannels) && (chnIdx < *pNumChn); idx++ )
+ {
+ pChnPowerInfo[chnIdx].chanId = (tANI_U8)(pChannelSet->firstChannel + ( idx * pChannelSet->interChannelOffset ));
+ pChnPowerInfo[chnIdx++].pwr = pChannelSet->txPower;
+ }
+ }
+ else
+ {
+ for( idx = 0; (idx < pChannelSet->numChannels) && (chnIdx < *pNumChn); idx++ )
+ {
+ pChnPowerInfo[chnIdx].chanId = (tANI_U8)(pChannelSet->firstChannel + idx);
+ pChnPowerInfo[chnIdx++].pwr = pChannelSet->txPower;
+ }
+ }
+
+ pEntry = csrLLNext( pList, pEntry, LL_ACCESS_LOCK );
+ }
+ *pNumChn = chnIdx;
+
+ return ;
+}
+
+
+
+void csrApplyCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce )
+{
+ v_REGDOMAIN_t domainId;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ do
+ {
+ if( !csrIs11dSupported( pMac ) || 0 == pMac->scan.channelOf11dInfo) break;
+ if( pMac->scan.fAmbiguous11dInfoFound )
+ {
+ // ambiguous info found
+ //Restore te default domain as well
+ if(HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry( pMac, pMac->scan.countryCodeCurrent, &domainId )))
+ {
+ pMac->scan.domainIdCurrent = domainId;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" failed to get domain from currentCountryCode %02X%02X\n"),
+ pMac->scan.countryCodeCurrent[0], pMac->scan.countryCodeCurrent[1]);
+ }
+ csrResetCountryInformation( pMac, eANI_BOOLEAN_FALSE );
+ break;
+ }
+ if ( pMac->scan.f11dInfoApplied && !fForce ) break;
+ if(HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry( pMac, pMac->scan.countryCode11d, &domainId )))
+ {
+ //Check whether we need to enforce default domain
+ if( ( !pMac->roam.configParam.fEnforceDefaultDomain ) ||
+ (pMac->scan.domainIdCurrent == domainId) )
+ {
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ {
+ vos_log_802_11d_pkt_type *p11dLog;
+ tChannelListWithPower chnPwrInfo[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ tANI_U32 nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN, nTmp;
+
+ WLAN_VOS_DIAG_LOG_ALLOC(p11dLog, vos_log_802_11d_pkt_type, LOG_WLAN_80211D_C);
+ if(p11dLog)
+ {
+ p11dLog->eventId = WLAN_80211D_EVENT_COUNTRY_SET;
+ palCopyMemory(pMac->hHdd, p11dLog->countryCode, pMac->scan.countryCode11d, 3);
+ p11dLog->numChannel = pMac->scan.channels11d.numChannels;
+ if(p11dLog->numChannel <= VOS_LOG_MAX_NUM_CHANNEL)
+ {
+ palCopyMemory(pMac->hHdd, p11dLog->Channels, pMac->scan.channels11d.channelList,
+ p11dLog->numChannel);
+ csrGetChannelPowerInfo(pMac, &pMac->scan.channelPowerInfoList24,
+ &nChnInfo, chnPwrInfo);
+ nTmp = nChnInfo;
+ nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN - nTmp;
+ csrGetChannelPowerInfo(pMac, &pMac->scan.channelPowerInfoList5G,
+ &nChnInfo, &chnPwrInfo[nTmp]);
+ for(nTmp = 0; nTmp < p11dLog->numChannel; nTmp++)
+ {
+ for(nChnInfo = 0; nChnInfo < WNI_CFG_VALID_CHANNEL_LIST_LEN; nChnInfo++)
+ {
+ if(p11dLog->Channels[nTmp] == chnPwrInfo[nChnInfo].chanId)
+ {
+ p11dLog->TxPwr[nTmp] = chnPwrInfo[nChnInfo].pwr;
+ break;
+ }
+ }
+ }
+ }
+ if(!pMac->roam.configParam.Is11dSupportEnabled)
+ {
+ p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED;
+ }
+ else if(pMac->roam.configParam.fEnforceDefaultDomain)
+ {
+ p11dLog->supportMultipleDomain = WLAN_80211D_NOT_SUPPORT_MULTI_DOMAIN;
+ }
+ else
+ {
+ p11dLog->supportMultipleDomain = WLAN_80211D_SUPPORT_MULTI_DOMAIN;
+ }
+ WLAN_VOS_DIAG_LOG_REPORT(p11dLog);
+ }
+ }
+#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ if(pMac->scan.domainIdCurrent != domainId)
+ {
+ /* Regulatory Domain Changed, Purge Only scan result
+ * which does not have channel number belong to 11d
+ * channel list
+ * */
+ smsLog(pMac, LOGW, FL("Domain Changed Old %d, new %d"),
+ pMac->scan.domainIdCurrent, domainId);
+ csrScanFilter11dResult(pMac);
+ }
+ status = WDA_SetRegDomain(pMac, domainId);
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog( pMac, LOGE, FL(" fail to set regId %d\n"), domainId );
+ }
+ pMac->scan.domainIdCurrent = domainId;
+ csrApplyChannelPowerCountryInfo( pMac, &pMac->scan.channels11d, pMac->scan.countryCode11d );
+ // switch to active scans using this new channel list
+ pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
+ pMac->scan.f11dInfoApplied = eANI_BOOLEAN_TRUE;
+ pMac->scan.f11dInfoReset = eANI_BOOLEAN_FALSE;
+ }
+ }
+
+ } while( 0 );
+
+ return;
+}
+
+
+
+tANI_BOOLEAN csrSave11dCountryString( tpAniSirGlobal pMac, tANI_U8 *pCountryCode,
+ tANI_BOOLEAN fForce)
+{
+ tANI_BOOLEAN fCountryStringChanged = FALSE, fUnknownCountryCode = FALSE;
+ tANI_U32 i;
+
+ // convert to UPPER here so we are assured the strings are always in upper case.
+ for( i = 0; i < 3; i++ )
+ {
+ pCountryCode[ i ] = (tANI_U8)csrToUpper( pCountryCode[ i ] );
+ }
+
+ // Some of the 'old' Cisco 350 series AP's advertise NA as the country code (for North America ??).
+ // NA is not a valid country code or domain so let's allow this by changing it to the proper
+ // country code (which is US). We've also seen some NETGEAR AP's that have "XX " as the country code
+ // with valid 2.4 GHz US channel information. If we cannot find the country code advertised in the
+ // 11d information element, let's default to US.
+ if ( !HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry( pMac, pCountryCode, NULL ) ) )
+ {
+ // Check the enforcement first
+ if( pMac->roam.configParam.fEnforceDefaultDomain || pMac->roam.configParam.fEnforceCountryCodeMatch )
+ {
+ fUnknownCountryCode = TRUE;
+ }
+ else
+ {
+ pCountryCode[ 0 ] = 'U';
+ pCountryCode[ 1 ] = 'S';
+ }
+ }
+
+ // We've seen some of the AP's improperly put a 0 for the third character of the country code.
+ // spec says valid charcters are 'O' (for outdoor), 'I' for Indoor, or ' ' (space; for either).
+ // if we see a 0 in this third character, let's change it to a ' '.
+ if ( 0 == pCountryCode[ 2 ] )
+ {
+ pCountryCode[ 2 ] = ' ';
+ }
+
+ if( !fUnknownCountryCode )
+ {
+ fCountryStringChanged = (!palEqualMemory( pMac->hHdd,
+ pMac->scan.countryCode11d, pCountryCode, 2));
+
+
+ if(( 0 == pMac->scan.countryCode11d[ 0 ] && 0 == pMac->scan.countryCode11d[ 1 ] )
+ || (fForce))
+ {
+ // this is the first .11d information
+ palCopyMemory( pMac->hHdd, pMac->scan.countryCode11d, pCountryCode, sizeof( pMac->scan.countryCode11d ) );
+ }
+ }
+
+ return( fCountryStringChanged );
+}
+
+
+void csrSaveChannelPowerForBand( tpAniSirGlobal pMac, tANI_BOOLEAN fPopulate5GBand )
+{
+ tANI_U32 Index, count=0;
+ tSirMacChanInfo *pChanInfo;
+ tSirMacChanInfo *pChanInfoStart;
+
+ if(HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd, (void **)&pChanInfo, sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN)))
+ {
+ palZeroMemory(pMac->hHdd, pChanInfo, sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN);
+ pChanInfoStart = pChanInfo;
+ for (Index=0; Index < pMac->scan.base20MHzChannels.numChannels; Index++)
+ {
+ if ((fPopulate5GBand && (CSR_IS_CHANNEL_5GHZ(pMac->scan.defaultPowerTable[Index].chanId))) ||
+ (!fPopulate5GBand && (CSR_IS_CHANNEL_24GHZ(pMac->scan.defaultPowerTable[Index].chanId))) )
+ {
+ pChanInfo->firstChanNum = pMac->scan.defaultPowerTable[Index].chanId;
+ pChanInfo->numChannels = 1;
+ pChanInfo->maxTxPower = CSR_ROAM_MIN( pMac->scan.defaultPowerTable[Index].pwr, pMac->roam.configParam.nTxPowerCap );
+ pChanInfo++;
+ count++;
+ }
+ }
+ if(count)
+ {
+ csrSaveToChannelPower2G_5G( pMac, count * sizeof(tSirMacChanInfo), pChanInfoStart );
+ }
+ palFreeMemory(pMac->hHdd, pChanInfoStart);
+ }
+}
+
+
+void csrSetOppositeBandChannelInfo( tpAniSirGlobal pMac )
+{
+ tANI_BOOLEAN fPopulate5GBand = FALSE;
+
+ do
+ {
+ // if this is not a dual band product, then we don't need to set the opposite
+ // band info. We only work in one band so no need to look in the other band.
+ if ( !CSR_IS_OPEARTING_DUAL_BAND( pMac ) ) break;
+ // if we found channel info on the 5.0 band and...
+ if ( CSR_IS_CHANNEL_5GHZ( pMac->scan.channelOf11dInfo ) )
+ {
+ // and the 2.4 band is empty, then populate the 2.4 channel info
+ if ( !csrLLIsListEmpty( &pMac->scan.channelPowerInfoList24, LL_ACCESS_LOCK ) ) break;
+ fPopulate5GBand = FALSE;
+ }
+ else
+ {
+ // else, we found channel info in the 2.4 GHz band. If the 5.0 band is empty
+ // set the 5.0 band info from the 2.4 country code.
+ if ( !csrLLIsListEmpty( &pMac->scan.channelPowerInfoList5G, LL_ACCESS_LOCK ) ) break;
+ fPopulate5GBand = TRUE;
+ }
+ csrSaveChannelPowerForBand( pMac, fPopulate5GBand );
+
+ } while( 0 );
+}
+
+
+tANI_BOOLEAN csrIsSupportedChannel(tpAniSirGlobal pMac, tANI_U8 channelId)
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
+ tANI_U32 i;
+
+ //Make sure it is a channel that is in our supported list.
+ for ( i = 0; i < pMac->scan.baseChannels.numChannels; i++ )
+ {
+ if ( channelId == pMac->scan.baseChannels.channelList[i] )
+ {
+ fRet = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+
+ //If it is configured to limit a set of the channels
+ if( fRet && pMac->roam.configParam.fEnforce11dChannels )
+ {
+ fRet = eANI_BOOLEAN_FALSE;
+ for ( i = 0; i < pMac->scan.base20MHzChannels.numChannels; i++ )
+ {
+ if ( channelId == pMac->scan.base20MHzChannels.channelList[i] )
+ {
+ fRet = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+ }
+
+ return (fRet);
+}
+
+
+
+//bSize specify the buffer size of pChannelList
+tANI_U8 csrGetChannelListFromChannelSet( tpAniSirGlobal pMac, tANI_U8 *pChannelList, tANI_U8 bSize, tCsrChannelPowerInfo *pChannelSet )
+{
+ tANI_U8 i, j = 0, chnId;
+
+ bSize = CSR_MIN(bSize, pChannelSet->numChannels);
+ for( i = 0; i < bSize; i++ )
+ {
+ chnId = (tANI_U8)(pChannelSet->firstChannel + ( i * pChannelSet->interChannelOffset ));
+ if ( csrIsSupportedChannel( pMac, chnId ) )
+ {
+ pChannelList[j++] = chnId;
+ }
+ }
+
+ return (j);
+}
+
+
+
+//bSize -- specify the buffer size of pChannelList
+void csrConstructCurrentValidChannelList( tpAniSirGlobal pMac, tDblLinkList *pChannelSetList,
+ tANI_U8 *pChannelList, tANI_U8 bSize, tANI_U8 *pNumChannels )
+{
+ tListElem *pEntry;
+ tCsrChannelPowerInfo *pChannelSet;
+ tANI_U8 numChannels;
+ tANI_U8 *pChannels;
+
+ if( pChannelSetList && pChannelList && pNumChannels )
+ {
+ pChannels = pChannelList;
+ *pNumChannels = 0;
+ pEntry = csrLLPeekHead( pChannelSetList, LL_ACCESS_LOCK );
+ while( pEntry )
+ {
+ pChannelSet = GET_BASE_ADDR( pEntry, tCsrChannelPowerInfo, link );
+ numChannels = csrGetChannelListFromChannelSet( pMac, pChannels, bSize, pChannelSet );
+ pChannels += numChannels;
+ *pNumChannels += numChannels;
+ pEntry = csrLLNext( pChannelSetList, pEntry, LL_ACCESS_LOCK );
+ }
+ }
+}
+
+
+/*
+ * 802.11D only: Gather 11d IE via beacon or Probe response and store them in pAdapter->channels11d
+*/
+tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes, tANI_BOOLEAN fForce)
+{
+ tANI_U8 Num2GChannels, bMaxNumChn;
+ eHalStatus status;
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
+ v_REGDOMAIN_t domainId;
+ tDot11fBeaconIEs *pIesLocal = pIes;
+
+#ifdef WLAN_SOFTAP_FEATURE
+ if (VOS_STA_SAP_MODE == vos_get_conparam ())
+ return eHAL_STATUS_SUCCESS;
+#endif
+
+ do
+ {
+ // check if .11d support is enabled
+ if( !csrIs11dSupported( pMac ) ) break;
+ if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) )
+ {
+ break;
+ }
+ // check if country information element is present
+ if(!pIesLocal->Country.present)
+ {
+ //No country info
+ break;
+ }
+
+ if( csrSave11dCountryString( pMac, pIesLocal->Country.country, fForce ) )
+ {
+ // country string changed, this should not happen
+ //Need to check whether we care about this BSS' domain info
+ //If it doesn't match of the connected profile or roaming profile, let's ignore it
+ tANI_U32 i;
+ 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)
+ {
+ tCsrScanResultFilter filter;
+
+ palZeroMemory(pMac->hHdd, &filter, sizeof(tCsrScanResultFilter));
+ status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, &filter);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ tANI_BOOLEAN fMatch = csrMatchBSS(pMac, pSirBssDesc, &filter, NULL, NULL, NULL, NULL);
+ //Free the resource first
+ csrFreeScanFilter( pMac, &filter );
+ if(fMatch)
+ {
+ smsLog(pMac, LOGW, " Matching roam profile BSSID %02X-%02X-%02X-%02X-%02X-%02X causing ambiguous domain info\n",
+ pSirBssDesc->bssId[0], pSirBssDesc->bssId[1], pSirBssDesc->bssId[2],
+ pSirBssDesc->bssId[3], pSirBssDesc->bssId[4], pSirBssDesc->bssId[5]);
+ pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+ }
+ else if( csrIsConnStateConnected(pMac, i))
+ {
+ //Reach here only when the currention is base on no profile.
+ //User doesn't give profile and just connect to anything.
+ if(csrMatchBSSToConnectProfile(pMac, &pSession->connectedProfile, pSirBssDesc, pIesLocal))
+ {
+ smsLog(pMac, LOGW, " Matching connect profile BSSID %02X-%02X-%02X-%02X-%02X-%02X causing ambiguous domain info\n",
+ pSirBssDesc->bssId[0], pSirBssDesc->bssId[1], pSirBssDesc->bssId[2],
+ pSirBssDesc->bssId[3], pSirBssDesc->bssId[4], pSirBssDesc->bssId[5]);
+ //Tush
+ pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_TRUE;
+ if(csrIsBssidMatch(pMac, (tCsrBssid *)&pSirBssDesc->bssId,
+ &pSession->connectedProfile.bssid))
+ {
+ //AP changed the 11d info on the fly, modify cfg
+ pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_FALSE;
+ fRet = eANI_BOOLEAN_TRUE;
+ }
+ break;
+ }
+ }
+ } //valid session
+ } //for
+ if ( i == CSR_ROAM_SESSION_MAX )
+ {
+ //Check whether we can use this country's 11d information
+ if( !pMac->roam.configParam.fEnforceDefaultDomain )
+ {
+ pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_TRUE;
+ }
+ else
+ {
+ VOS_ASSERT( pMac->scan.domainIdCurrent == pMac->scan.domainIdDefault );
+ if( HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry(
+ pMac, pIesLocal->Country.country, &domainId )) &&
+ ( domainId == pMac->scan.domainIdCurrent ) )
+ {
+ //Two countries in the same domain
+ }
+ }
+ }
+ }
+ else //Tush
+ {
+ pMac->scan.fCurrent11dInfoMatch = eANI_BOOLEAN_TRUE;
+ }
+
+ //In case that some channels in 5GHz have the same channel number as 2.4GHz (<= 14)
+ if(CSR_IS_CHANNEL_5GHZ(pSirBssDesc->channelId))
+ {
+ tANI_U8 iC;
+ tSirMacChanInfo* pMacChnSet = (tSirMacChanInfo *)(&pIesLocal->Country.triplets[0]);
+
+ for(iC = 0; iC < pIesLocal->Country.num_triplets; iC++)
+ {
+ if(CSR_IS_CHANNEL_24GHZ(pMacChnSet[iC].firstChanNum))
+ {
+ pMacChnSet[iC].firstChanNum += 200; //*** Where is this 200 defined?
+ }
+ }
+ }
+ smsLog(pMac, LOGE, FL(" %d sets each one is %d\n"), pIesLocal->Country.num_triplets, sizeof(tSirMacChanInfo));
+ // save the channel/power information from the Channel IE.
+ //sizeof(tSirMacChanInfo) has to be 3
+ csrSaveToChannelPower2G_5G( pMac, pIesLocal->Country.num_triplets * sizeof(tSirMacChanInfo),
+ (tSirMacChanInfo *)(&pIesLocal->Country.triplets[0]) );
+ // set the indicator of the channel where the country IE was found...
+ pMac->scan.channelOf11dInfo = pSirBssDesc->channelId;
+ // Populate both band channel lists based on what we found in the country information...
+ csrSetOppositeBandChannelInfo( pMac );
+ bMaxNumChn = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+ // construct 2GHz channel list first
+ csrConstructCurrentValidChannelList( pMac, &pMac->scan.channelPowerInfoList24, pMac->scan.channels11d.channelList,
+ bMaxNumChn, &Num2GChannels );
+ // construct 5GHz channel list now
+ if(bMaxNumChn > Num2GChannels)
+ {
+ csrConstructCurrentValidChannelList( pMac, &pMac->scan.channelPowerInfoList5G, pMac->scan.channels11d.channelList + Num2GChannels,
+ bMaxNumChn - Num2GChannels,
+ &pMac->scan.channels11d.numChannels );
+ }
+
+ pMac->scan.channels11d.numChannels += Num2GChannels;
+ fRet = eANI_BOOLEAN_TRUE;
+
+ } while( 0 );
+
+ if( !pIes && pIesLocal )
+ {
+ //locally allocated
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+
+ return( fRet );
+}
+
+
+static void csrSaveScanResults( tpAniSirGlobal pMac )
+{
+ // initialize this to FALSE. profMoveInterimScanResultsToMainList() routine
+ // will set this to the channel where an .11d beacon is seen
+ pMac->scan.channelOf11dInfo = 0;
+ // if we get any ambiguous .11d information then this will be set to TRUE
+ pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_FALSE;
+ //Tush
+ // if we get any ambiguous .11d information, then this will be set to TRUE
+ // only if the applied 11d info could be found in one of the scan results
+ pMac->scan.fCurrent11dInfoMatch = eANI_BOOLEAN_FALSE;
+ // move the scan results from interim list to the main scan list
+ csrMoveTempScanResultsToMainList( pMac );
+
+ // Now check if we gathered any domain/country specific information
+ // If so, we should update channel list and apply Tx power settings
+ csrApplyCountryInformation( pMac, FALSE );
+}
+
+
+void csrReinitScanCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ switch (pCommand->u.scanCmd.reason)
+ {
+ case eCsrScanSetBGScanParam:
+ case eCsrScanAbortBgScan:
+ if(pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList)
+ {
+ palFreeMemory(pMac->hHdd, pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList);
+ pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList = NULL;
+ }
+ break;
+ case eCsrScanBGScanAbort:
+ case eCsrScanBGScanEnable:
+ case eCsrScanGetScanChnInfo:
+ break;
+ case eCsrScanAbortNormalScan:
+ default:
+ csrScanFreeRequest(pMac, &pCommand->u.scanCmd.u.scanRequest);
+ break;
+ }
+ if(pCommand->u.scanCmd.pToRoamProfile)
+ {
+ csrReleaseProfile(pMac, pCommand->u.scanCmd.pToRoamProfile);
+ palFreeMemory(pMac->hHdd, pCommand->u.scanCmd.pToRoamProfile);
+ }
+ palZeroMemory(pMac->hHdd, &pCommand->u.scanCmd, sizeof(tScanCmd));
+}
+
+
+tANI_BOOLEAN csrGetRemainingChannelsFor11dScan( tpAniSirGlobal pMac, tANI_U8 *pChannels, tANI_U8 *pcChannels )
+{
+ tANI_U32 index11dChannels, index;
+ tANI_U32 indexCurrentChannels;
+ tANI_BOOLEAN fChannelAlreadyScanned;
+ tANI_U32 len = sizeof(pMac->roam.validChannelList);
+
+ *pcChannels = 0;
+ if ( CSR_IS_11D_INFO_FOUND(pMac) && csrRoamIsChannelValid(pMac, pMac->scan.channelOf11dInfo) )
+ {
+ if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len)))
+ {
+ //Find the channel index where we found the 11d info
+ for(index = 0; index < len; index++)
+ {
+ if(pMac->scan.channelOf11dInfo == pMac->roam.validChannelList[index])
+ break;
+ }
+ //check whether we found the channel index
+ if(index < len)
+ {
+ // Now, look through the 11d channel list and create a list of all channels in the 11d list that are
+ // NOT in the current channel list. This gives us a list of the new channels that have not been
+ // scanned. We'll scan this new list so we have a complete set of scan results on all of the domain channels
+ // initially.
+ for ( index11dChannels = 0; index11dChannels < pMac->scan.channels11d.numChannels; index11dChannels++ )
+ {
+ fChannelAlreadyScanned = eANI_BOOLEAN_FALSE;
+
+ for( indexCurrentChannels = 0; indexCurrentChannels < index; indexCurrentChannels++ )
+ {
+ if ( pMac->roam.validChannelList[ indexCurrentChannels ] == pMac->scan.channels11d.channelList[ index11dChannels ] )
+ {
+ fChannelAlreadyScanned = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+
+ if ( !fChannelAlreadyScanned )
+ {
+ pChannels[ *pcChannels ] = pMac->scan.channels11d.channelList[ index11dChannels ];
+ ( *pcChannels )++;
+ }
+ }
+ }
+ }//GetCFG
+ }
+ return( *pcChannels );
+}
+
+
+eCsrScanCompleteNextCommand csrScanGetNextCommandState( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fSuccess )
+{
+ eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing;
+
+ switch( pCommand->u.scanCmd.reason )
+ {
+ case eCsrScan11d1:
+ NextCommand = (fSuccess) ? eCsrNext11dScan1Success : eCsrNext11dScan1Failure;
+ break;
+ case eCsrScan11d2:
+ NextCommand = (fSuccess) ? eCsrNext11dScan2Success : eCsrNext11dScan2Failure;
+ break;
+ case eCsrScan11dDone:
+ NextCommand = eCsrNext11dScanComplete;
+ break;
+ case eCsrScanLostLink1:
+ NextCommand = (fSuccess) ? eCsrNextLostLinkScan1Success : eCsrNextLostLinkScan1Failed;
+ break;
+ case eCsrScanLostLink2:
+ NextCommand = (fSuccess) ? eCsrNextLostLinkScan2Success : eCsrNextLostLinkScan2Failed;
+ break;
+ case eCsrScanLostLink3:
+ NextCommand = (fSuccess) ? eCsrNextLostLinkScan3Success : eCsrNextLostLinkScan3Failed;
+ break;
+ case eCsrScanForSsid:
+ NextCommand = (fSuccess) ? eCsrNexteScanForSsidSuccess : eCsrNexteScanForSsidFailure;
+ break;
+ case eCsrScanForCapsChange:
+ NextCommand = eCsrNextCapChangeScanComplete; //don't care success or not
+ break;
+ case eCsrScanIdleScan:
+ NextCommand = eCsrNextIdleScanComplete;
+ break;
+ default:
+ NextCommand = eCsrNextScanNothing;
+ break;
+ }
+ return( NextCommand );
+}
+
+
+//Return whether the pCommand is finished.
+tANI_BOOLEAN csrHandleScan11d1Failure(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_TRUE;
+
+ //Apply back the default setting and passively scan one more time.
+ csrResetCountryInformation(pMac, eANI_BOOLEAN_FALSE);
+ pCommand->u.scanCmd.reason = eCsrScan11d2;
+ if(HAL_STATUS_SUCCESS(csrScanChannels(pMac, pCommand)))
+ {
+ fRet = eANI_BOOLEAN_FALSE;
+ }
+
+ return (fRet);
+}
+
+
+tANI_BOOLEAN csrHandleScan11dSuccess(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_TRUE;
+ tANI_U8 *pChannels;
+ tANI_U8 cChannels;
+
+ if(HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd, (void **)&pChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN)))
+ {
+ palZeroMemory(pMac->hHdd, pChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
+ if ( csrGetRemainingChannelsFor11dScan( pMac, pChannels, &cChannels ) )
+ {
+ pCommand->u.scanCmd.reason = eCsrScan11dDone;
+ if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList)
+ {
+ palFreeMemory(pMac->hHdd, pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList);
+ }
+ if(HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd, (void **)&pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, cChannels)))
+ {
+ palCopyMemory(pMac->hHdd, pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, pChannels, cChannels);
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = cChannels;
+ pCommand->u.scanCmd.u.scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
+ pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ if(HAL_STATUS_SUCCESS(csrScanChannels(pMac, pCommand)))
+ {
+ //Reuse the same command buffer
+ fRet = eANI_BOOLEAN_FALSE;
+ }
+ }
+ }
+ palFreeMemory(pMac->hHdd, pChannels);
+ }
+
+ return (fRet);
+}
+
+//Return whether the command should be removed
+tANI_BOOLEAN csrScanComplete( tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp )
+{
+ eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing;
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+ tANI_BOOLEAN fRemoveCommand = eANI_BOOLEAN_TRUE;
+ tANI_BOOLEAN fSuccess;
+
+ 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 SCAN command, remove
+ // and put this on the Free queue.
+ if ( eSmeCommandScan == pCommand->command )
+ {
+ tANI_U32 sessionId = pCommand->sessionId;
+
+ if(eSIR_SME_SUCCESS != pScanRsp->statusCode)
+ {
+ fSuccess = eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ //pMac->scan.tempScanResults is not empty meaning the scan found something
+ //This check only valid here because csrSaveScanresults is not yet called
+ fSuccess = (!csrLLIsListEmpty(&pMac->scan.tempScanResults, LL_ACCESS_LOCK));
+ }
+ csrSaveScanResults(pMac);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ {
+ vos_log_scan_pkt_type *pScanLog = NULL;
+ tScanResultHandle hScanResult;
+ tCsrScanResultInfo *pScanResult;
+ tDot11fBeaconIEs *pIes;
+ int n = 0, c = 0;
+
+ WLAN_VOS_DIAG_LOG_ALLOC(pScanLog, vos_log_scan_pkt_type, LOG_WLAN_SCAN_C);
+ if(pScanLog)
+ {
+ if(eCsrScanBgScan == pCommand->u.scanCmd.reason ||
+ eCsrScanProbeBss == pCommand->u.scanCmd.reason ||
+ eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason)
+ {
+ pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_RSP;
+ }
+ else
+ {
+ if( eSIR_PASSIVE_SCAN != pMac->scan.curScanType )
+ {
+ pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_RSP;
+ }
+ else
+ {
+ pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_RSP;
+ }
+ }
+ if(eSIR_SME_SUCCESS == pScanRsp->statusCode)
+ {
+ if(HAL_STATUS_SUCCESS(csrScanGetResult(pMac, NULL, &hScanResult)))
+ {
+ while(((pScanResult = csrScanResultGetNext(pMac, hScanResult)) != NULL))
+ {
+ if( n < VOS_LOG_MAX_NUM_BSSID )
+ {
+ if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, &pScanResult->BssDescriptor, &pIes)))
+ {
+ smsLog(pMac, LOGE, FL(" fail to parse IEs\n"));
+ break;
+ }
+ palCopyMemory(pMac->hHdd, pScanLog->bssid[n], pScanResult->BssDescriptor.bssId, 6);
+ if(pIes && pIes->SSID.present && VOS_LOG_MAX_SSID_SIZE >= pIes->SSID.num_ssid)
+ {
+ palCopyMemory(pMac->hHdd, pScanLog->ssid[n],
+ pIes->SSID.ssid, pIes->SSID.num_ssid);
+ }
+ palFreeMemory(pMac->hHdd, pIes);
+ n++;
+ }
+ c++;
+ }
+ pScanLog->numSsid = (v_U8_t)n;
+ pScanLog->totalSsid = (v_U8_t)c;
+ csrScanResultPurge(pMac, hScanResult);
+ }
+ }
+ else
+ {
+ pScanLog->status = WLAN_SCAN_STATUS_FAILURE;
+ }
+ WLAN_VOS_DIAG_LOG_REPORT(pScanLog);
+ }
+ }
+#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+
+ NextCommand = csrScanGetNextCommandState(pMac, pCommand, fSuccess);
+ //We reuse the command here instead reissue a new command
+ switch(NextCommand)
+ {
+ case eCsrNext11dScan1Success:
+ case eCsrNext11dScan2Success:
+ smsLog( pMac, LOG2, FL("11dScan1/3 produced results. Reissue Active scan...\n"));
+ // if we found country information, no need to continue scanning further, bail out
+ fRemoveCommand = eANI_BOOLEAN_TRUE;
+ NextCommand = eCsrNext11dScanComplete;
+ break;
+ case eCsrNext11dScan1Failure:
+ //We are not done yet. 11d scan fail once. We will try to reset anything and do it over again
+ //The only meaningful thing for this retry is that we cannot find 11d information after a reset so
+ //we clear the "old" 11d info and give it once more chance
+ fRemoveCommand = csrHandleScan11d1Failure(pMac, pCommand);
+ if(fRemoveCommand)
+ {
+ NextCommand = eCsrNext11dScanComplete;
+ }
+ break;
+ case eCsrNextLostLinkScan1Success:
+ if(!HAL_STATUS_SUCCESS(csrIssueRoamAfterLostlinkScan(pMac, sessionId, eCsrLostLink1)))
+ {
+ csrScanHandleFailedLostlink1(pMac, sessionId);
+ }
+ break;
+ case eCsrNextLostLinkScan2Success:
+ if(!HAL_STATUS_SUCCESS(csrIssueRoamAfterLostlinkScan(pMac, sessionId, eCsrLostLink2)))
+ {
+ csrScanHandleFailedLostlink2(pMac, sessionId);
+ }
+ break;
+ case eCsrNextLostLinkScan3Success:
+ if(!HAL_STATUS_SUCCESS(csrIssueRoamAfterLostlinkScan(pMac, sessionId, eCsrLostLink3)))
+ {
+ csrScanHandleFailedLostlink3(pMac, sessionId);
+ }
+ break;
+ case eCsrNextLostLinkScan1Failed:
+ csrScanHandleFailedLostlink1(pMac, sessionId);
+ break;
+ case eCsrNextLostLinkScan2Failed:
+ csrScanHandleFailedLostlink2(pMac, sessionId);
+ break;
+ case eCsrNextLostLinkScan3Failed:
+ csrScanHandleFailedLostlink3(pMac, sessionId);
+ break;
+ case eCsrNexteScanForSsidSuccess:
+ csrScanHandleSearchForSSID(pMac, pCommand);
+ break;
+ case eCsrNexteScanForSsidFailure:
+ csrScanHandleSearchForSSIDFailure(pMac, pCommand);
+ break;
+ case eCsrNextIdleScanComplete:
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE;
+ break;
+ case eCsrNextCapChangeScanComplete:
+ csrScanHandleCapChangeScanComplete(pMac, sessionId);
+ break;
+ default:
+
+ break;
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, FL("Scan Completion called but SCAN command is not ACTIVE ...\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, FL("Scan Completion called but NO commands are ACTIVE ...\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ }
+
+ return( fRemoveCommand );
+}
+
+
+
+static void csrScanRemoveDupBssDescriptionFromInterimList( tpAniSirGlobal pMac,
+ tSirBssDescription *pSirBssDescr,
+ tDot11fBeaconIEs *pIes)
+{
+ tListElem *pEntry;
+ tCsrScanResult *pCsrBssDescription;
+
+ // Walk through all the chained BssDescriptions. If we find a chained BssDescription that
+ // matches the BssID of the BssDescription passed in, then these must be duplicate scan
+ // results for this Bss. In that case, remove the 'old' Bss description from the linked list.
+ pEntry = csrLLPeekHead( &pMac->scan.tempScanResults, LL_ACCESS_LOCK );
+ while( pEntry )
+ {
+ pCsrBssDescription = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+
+ // we have a duplicate scan results only when BSSID, SSID, Channel and NetworkType
+ // matches
+
+ if ( csrIsDuplicateBssDescription( pMac, &pCsrBssDescription->Result.BssDescriptor,
+ pSirBssDescr, pIes ) )
+ {
+ pSirBssDescr->rssi = (tANI_S8)( (((tANI_S32)pSirBssDescr->rssi * CSR_SCAN_RESULT_RSSI_WEIGHT ) +
+ ((tANI_S32)pCsrBssDescription->Result.BssDescriptor.rssi * (100 - CSR_SCAN_RESULT_RSSI_WEIGHT) )) / 100 );
+
+ // Remove the 'old' entry from the list....
+ if( csrLLRemoveEntry( &pMac->scan.tempScanResults, pEntry, LL_ACCESS_LOCK ) )
+ {
+ csrCheckNSaveWscIe(pMac, pSirBssDescr, &pCsrBssDescription->Result.BssDescriptor);
+ // we need to free the memory associated with this node
+ csrFreeScanResultEntry( pMac, pCsrBssDescription );
+ }
+
+ // If we found a match, we can stop looking through the list.
+ break;
+ }
+
+ pEntry = csrLLNext( &pMac->scan.tempScanResults, pEntry, LL_ACCESS_LOCK );
+ }
+}
+
+
+
+//Caller allocated memory pfNewBssForConn to return whether new candidate for
+//current connection is found. Cannot be NULL
+tCsrScanResult *csrScanSaveBssDescriptionToInterimList( tpAniSirGlobal pMac,
+ tSirBssDescription *pBSSDescription,
+ tDot11fBeaconIEs *pIes)
+{
+ tCsrScanResult *pCsrBssDescription = NULL;
+ tANI_U32 cbBSSDesc;
+ tANI_U32 cbAllocated;
+ eHalStatus halStatus;
+
+ // figure out how big the BSS description is (the BSSDesc->length does NOT
+ // include the size of the length field itself).
+ cbBSSDesc = pBSSDescription->length + sizeof( pBSSDescription->length );
+
+ cbAllocated = sizeof( tCsrScanResult ) + cbBSSDesc;
+
+ halStatus = palAllocateMemory( pMac->hHdd, (void **)&pCsrBssDescription, cbAllocated );
+ if ( HAL_STATUS_SUCCESS(halStatus) )
+ {
+ palZeroMemory(pMac->hHdd, pCsrBssDescription, cbAllocated);
+ pCsrBssDescription->AgingCount = (tANI_S32)pMac->roam.configParam.agingCount;
+ palCopyMemory(pMac->hHdd, &pCsrBssDescription->Result.BssDescriptor, pBSSDescription, cbBSSDesc );
+ //Save SSID separately for later use
+ if( pIes->SSID.present && !csrIsNULLSSID(pIes->SSID.ssid, pIes->SSID.num_ssid) )
+ {
+ //SSID not hidden
+ tANI_U32 len = pIes->SSID.num_ssid;;
+ if (len > SIR_MAC_MAX_SSID_LENGTH)
+ {
+ // truncate to fit in our struct
+ len = SIR_MAC_MAX_SSID_LENGTH;
+ }
+ pCsrBssDescription->Result.ssId.length = len;
+ pCsrBssDescription->Result.timer = vos_timer_get_system_time();
+ palCopyMemory(pMac->hHdd, pCsrBssDescription->Result.ssId.ssId,
+ pIes->SSID.ssid, len );
+ }
+ csrLLInsertTail( &pMac->scan.tempScanResults, &pCsrBssDescription->Link, LL_ACCESS_LOCK );
+ }
+
+ return( pCsrBssDescription );
+}
+
+
+
+
+tANI_BOOLEAN csrIsDuplicateBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc1,
+ tSirBssDescription *pSirBssDesc2, tDot11fBeaconIEs *pIes2 )
+{
+ tANI_BOOLEAN fMatch = FALSE;
+ tSirMacCapabilityInfo *pCap1, *pCap2;
+ tDot11fBeaconIEs *pIes1 = NULL;
+
+ pCap1 = (tSirMacCapabilityInfo *)&pSirBssDesc1->capabilityInfo;
+ pCap2 = (tSirMacCapabilityInfo *)&pSirBssDesc2->capabilityInfo;
+ if(pCap1->ess == pCap2->ess)
+ {
+ if (pCap1->ess &&
+ csrIsMacAddressEqual( pMac, (tCsrBssid *)pSirBssDesc1->bssId, (tCsrBssid *)pSirBssDesc2->bssId))
+ {
+ fMatch = TRUE;
+ }
+ else if (pCap1->ibss && (pSirBssDesc1->channelId == pSirBssDesc2->channelId))
+ {
+ tDot11fBeaconIEs *pIesTemp = pIes2;
+
+ do
+ {
+ if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc1, &pIes1)))
+ {
+ break;
+ }
+ if( NULL == pIesTemp )
+ {
+ if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc2, &pIesTemp)))
+ {
+ break;
+ }
+ }
+ //Same channel cannot have same SSID for different IBSS
+ if(pIes1->SSID.present && pIesTemp->SSID.present)
+ {
+ fMatch = csrIsSsidMatch(pMac, pIes1->SSID.ssid, pIes1->SSID.num_ssid,
+ pIesTemp->SSID.ssid, pIesTemp->SSID.num_ssid, eANI_BOOLEAN_TRUE);
+ }
+ }while(0);
+ if( (NULL == pIes2) && pIesTemp )
+ {
+ //locally allocated
+ palFreeMemory(pMac->hHdd, pIesTemp);
+ }
+ }
+#if defined WLAN_FEATURE_P2P
+ /* In case of P2P devices, ess and ibss will be set to zero */
+ else if (!pCap1->ess &&
+ csrIsMacAddressEqual( pMac, (tCsrBssid *)pSirBssDesc1->bssId, (tCsrBssid *)pSirBssDesc2->bssId))
+ {
+ fMatch = TRUE;
+ }
+#endif
+ }
+
+ if(pIes1)
+ {
+ palFreeMemory(pMac->hHdd, pIes1);
+ }
+
+ return( fMatch );
+}
+
+
+tANI_BOOLEAN csrIsNetworkTypeEqual( tSirBssDescription *pSirBssDesc1, tSirBssDescription *pSirBssDesc2 )
+{
+ return( pSirBssDesc1->nwType == pSirBssDesc2->nwType );
+}
+
+
+//to check whether the BSS matches the dot11Mode
+static tANI_BOOLEAN csrScanIsBssAllowed(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc,
+ tDot11fBeaconIEs *pIes)
+{
+ tANI_BOOLEAN fAllowed = eANI_BOOLEAN_FALSE;
+ eCsrPhyMode phyMode;
+
+ if(HAL_STATUS_SUCCESS(csrGetPhyModeFromBss(pMac, pBssDesc, &phyMode, pIes)))
+ {
+ switch(pMac->roam.configParam.phyMode)
+ {
+ case eCSR_DOT11_MODE_11b:
+ fAllowed = (tANI_BOOLEAN)(eCSR_DOT11_MODE_11a != phyMode);
+ break;
+ case eCSR_DOT11_MODE_11g:
+ fAllowed = (tANI_BOOLEAN)(eCSR_DOT11_MODE_11a != phyMode);
+ break;
+ case eCSR_DOT11_MODE_11g_ONLY:
+ fAllowed = (tANI_BOOLEAN)(eCSR_DOT11_MODE_11g == phyMode);
+ break;
+ case eCSR_DOT11_MODE_11a:
+ fAllowed = (tANI_BOOLEAN)((eCSR_DOT11_MODE_11b != phyMode) && (eCSR_DOT11_MODE_11g != phyMode));
+ break;
+ case eCSR_DOT11_MODE_11n_ONLY:
+ fAllowed = (tANI_BOOLEAN)((eCSR_DOT11_MODE_11n == phyMode) || (eCSR_DOT11_MODE_TAURUS == phyMode));
+ break;
+ case eCSR_DOT11_MODE_11b_ONLY:
+ fAllowed = (tANI_BOOLEAN)(eCSR_DOT11_MODE_11b == phyMode);
+ break;
+ case eCSR_DOT11_MODE_11a_ONLY:
+ fAllowed = (tANI_BOOLEAN)(eCSR_DOT11_MODE_11a == phyMode);
+ break;
+ case eCSR_DOT11_MODE_11n:
+ case eCSR_DOT11_MODE_TAURUS:
+ default:
+ fAllowed = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+
+ return (fAllowed);
+}
+
+
+
+//Return pIes to caller for future use when returning TRUE.
+static tANI_BOOLEAN csrScanValidateScanResult( tpAniSirGlobal pMac, tANI_U8 *pChannels,
+ tANI_U8 numChn, tSirBssDescription *pBssDesc,
+ tDot11fBeaconIEs **ppIes )
+{
+ tANI_BOOLEAN fValidChannel = FALSE;
+ tDot11fBeaconIEs *pIes = NULL;
+ tANI_U8 index;
+
+ for( index = 0; index < numChn; index++ )
+ {
+ // This check relies on the fact that a single BSS description is returned in each
+ // ScanRsp call, which is the way LIM implemented the scan req/rsp funtions. We changed
+ // to this model when we ran with a large number of APs. If this were to change, then
+ // this check would have to mess with removing the bssDescription from somewhere in an
+ // arbitrary index in the bssDescription array.
+ if ( pChannels[ index ] == pBssDesc->channelId )
+ {
+ fValidChannel = TRUE;
+ break;
+ }
+ }
+ *ppIes = NULL;
+ if(fValidChannel)
+ {
+ if( HAL_STATUS_SUCCESS( csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes) ) )
+ {
+ fValidChannel = csrScanIsBssAllowed(pMac, pBssDesc, pIes);
+ if( fValidChannel )
+ {
+ *ppIes = pIes;
+ }
+ else
+ {
+ palFreeMemory( pMac->hHdd, pIes );
+ }
+ }
+ else
+ {
+ fValidChannel = FALSE;
+ }
+ }
+
+ return( fValidChannel );
+}
+
+
+//Return whether last scan result is received
+static tANI_BOOLEAN csrScanProcessScanResults( tpAniSirGlobal pMac, tSmeCmd *pCommand,
+ tSirSmeScanRsp *pScanRsp, tANI_BOOLEAN *pfRemoveCommand )
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE, fRemoveCommand = eANI_BOOLEAN_FALSE;
+ tDot11fBeaconIEs *pIes = NULL;
+ tANI_U32 cbParsed;
+ tSirBssDescription *pSirBssDescription;
+ tANI_U32 cbBssDesc;
+ tANI_U32 cbScanResult = GET_FIELD_OFFSET( tSirSmeScanRsp, bssDescription )
+ + sizeof(tSirBssDescription); //We need at least one CB
+
+ // don't consider the scan rsp to be valid if the status code is Scan Failure. Scan Failure
+ // is returned when the scan could not find anything. so if we get scan failure return that
+ // the scan response is invalid. Also check the lenght in the scan result for valid scan
+ // BssDescriptions....
+ do
+ {
+ if ( ( cbScanResult <= pScanRsp->length ) &&
+ (( eSIR_SME_SUCCESS == pScanRsp->statusCode ) ||
+ ( eSIR_SME_MORE_SCAN_RESULTS_FOLLOW == pScanRsp->statusCode ) ) )
+ {
+ tANI_U8 *pChannelList = NULL;
+ tANI_U8 cChannels = 0;
+
+ //Different scan type can reach this point, we need to distinguish it
+ if( eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason )
+ {
+ //eCsrScanSetBGScanParam uses different structure
+ tCsrBGScanRequest *pBgScanReq = &pCommand->u.scanCmd.u.bgScanRequest;
+
+ cChannels = pBgScanReq->ChannelInfo.numOfChannels;
+ pChannelList = pBgScanReq->ChannelInfo.ChannelList;
+ }
+ else
+ {
+ //the rest use generic scan request
+ cChannels = pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
+ pChannelList = pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList;
+ }
+
+ // if the scan result is not on one of the channels in the Valid channel list, then it
+ // must have come from an AP on an overlapping channel (in the 2.4GHz band). In this case,
+ // let's drop the scan result.
+ //
+ // The other situation is where the scan request is for a scan on a particular channel set
+ // and the scan result is from a
+
+ // if the NumChannels is 0, then we are supposed to be scanning all channels. Use the full channel
+ // list as the 'valid' channel list. Otherwise, use the specific channel list in the scan parms
+ // as the valid channels.
+ if ( 0 == cChannels )
+ {
+ tANI_U32 len = sizeof(pMac->roam.validChannelList);
+
+ if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len)))
+ {
+ pChannelList = pMac->roam.validChannelList;
+ cChannels = (tANI_U8)len;
+ }
+ else
+ {
+ //Cannot continue
+ smsLog( pMac, LOGE, "CSR: Processing internal SCAN results...csrGetCfgValidChannels failed\n" );
+ break;
+ }
+ }
+
+ smsLog( pMac, LOG2, "CSR: Processing internal SCAN results..." );
+ cbParsed = GET_FIELD_OFFSET( tSirSmeScanRsp, bssDescription );
+ pSirBssDescription = pScanRsp->bssDescription;
+ while( cbParsed < pScanRsp->length )
+ {
+ if ( csrScanValidateScanResult( pMac, pChannelList, cChannels, pSirBssDescription, &pIes ) )
+ {
+ csrScanRemoveDupBssDescriptionFromInterimList(pMac, pSirBssDescription, pIes);
+ csrScanSaveBssDescriptionToInterimList( pMac, pSirBssDescription, pIes );
+ if( eSIR_PASSIVE_SCAN == pMac->scan.curScanType )
+ {
+ if( csrIs11dSupported( pMac) )
+ {
+ //Check whether the BSS is acceptable base on 11d info and our configs.
+ if( csrMatchCountryCode( pMac, NULL, pIes ) )
+ {
+ //Double check whether the channel is acceptable by us.
+ if( csrIsSupportedChannel( pMac, pSirBssDescription->channelId ) )
+ {
+ pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
+ }
+ }
+ }
+ else
+ {
+ pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
+ }
+ }
+ //Free the resource
+ palFreeMemory( pMac->hHdd, pIes );
+ }
+ // skip over the BSS description to the next one...
+ cbBssDesc = pSirBssDescription->length + sizeof( pSirBssDescription->length );
+
+ cbParsed += cbBssDesc;
+ pSirBssDescription = (tSirBssDescription *)((tANI_U8 *)pSirBssDescription + cbBssDesc );
+
+ } //while
+ }
+ else
+ {
+ smsLog( pMac, LOGW, " Scanrsp fail (0x%08X), length = %d\n", pScanRsp->statusCode, pScanRsp->length );
+ //HO bg scan/probe failed no need to try autonomously
+ if(eCsrScanBgScan == pCommand->u.scanCmd.reason ||
+ eCsrScanProbeBss == pCommand->u.scanCmd.reason ||
+ eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason)
+ {
+ fRemoveCommand = eANI_BOOLEAN_TRUE;
+ }
+ }
+ }while(0);
+ if ( eSIR_SME_MORE_SCAN_RESULTS_FOLLOW != pScanRsp->statusCode )
+ {
+ smsLog(pMac, LOG1, " Scan received %d unique BSS scan reason is %d\n", csrLLCount(&pMac->scan.tempScanResults), pCommand->u.scanCmd.reason);
+ fRemoveCommand = csrScanComplete( pMac, pScanRsp );
+ fRet = eANI_BOOLEAN_TRUE;
+ }//if ( eSIR_SME_MORE_SCAN_RESULTS_FOLLOW != pScanRsp->statusCode )
+ if(pfRemoveCommand)
+ {
+ *pfRemoveCommand = fRemoveCommand;
+ }
+
+#ifdef WLAN_AP_STA_CONCURRENCY
+ if (!csrLLIsListEmpty( &pMac->scan.scanCmdPendingList, LL_ACCESS_LOCK ))
+ {
+ palTimerStart(pMac->hHdd, pMac->scan.hTimerStaApConcTimer,
+ CSR_SCAN_STAAP_CONC_INTERVAL, eANI_BOOLEAN_FALSE);
+ }
+#endif
+ return (fRet);
+}
+
+
+tANI_BOOLEAN csrScanIsWildCardScan( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ tANI_U8 bssid[WNI_CFG_BSSID_LEN] = {0, 0, 0, 0, 0, 0};
+ tANI_BOOLEAN f = palEqualMemory( pMac->hHdd, pCommand->u.scanCmd.u.scanRequest.bssid,
+ bssid, sizeof(tCsrBssid) );
+
+ //It is not a wild card scan if the bssid is not broadcast and the number of SSID is 1.
+ return ((tANI_BOOLEAN)( (f || (0xff == pCommand->u.scanCmd.u.scanRequest.bssid[0])) &&
+ (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs != 1) ));
+}
+
+
+eHalStatus csrScanSmeScanResponse( tpAniSirGlobal pMac, void *pMsgBuf )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+ eCsrScanStatus scanStatus;
+ tSirSmeScanRsp *pScanRsp = (tSirSmeScanRsp *)pMsgBuf;
+ tSmeGetScanChnRsp *pScanChnInfo;
+ tANI_BOOLEAN fRemoveCommand = eANI_BOOLEAN_TRUE;
+ eCsrScanReason reason = eCsrScanOther;
+
+ pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
+
+ if ( pEntry )
+ {
+ pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ if ( eSmeCommandScan == pCommand->command )
+ {
+ scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ? eCSR_SCAN_SUCCESS : eCSR_SCAN_FAILURE;
+ reason = pCommand->u.scanCmd.reason;
+ switch(pCommand->u.scanCmd.reason)
+ {
+ case eCsrScanAbortBgScan:
+ case eCsrScanAbortNormalScan:
+ case eCsrScanBGScanAbort:
+ case eCsrScanBGScanEnable:
+ break;
+ case eCsrScanGetScanChnInfo:
+ pScanChnInfo = (tSmeGetScanChnRsp *)pMsgBuf;
+ csrScanAgeResults(pMac, pScanChnInfo);
+ break;
+ case eCsrScanForCapsChange:
+ csrScanProcessScanResults( pMac, pCommand, pScanRsp, &fRemoveCommand );
+ break;
+#if WLAN_FEATURE_P2P
+ case eCsrScanP2PFindPeer:
+ scanStatus = ((eSIR_SME_SUCCESS == pScanRsp->statusCode) && (pScanRsp->length > 50)) ? eCSR_SCAN_FOUND_PEER : eCSR_SCAN_FAILURE;
+ csrScanProcessScanResults( pMac, pCommand, pScanRsp, NULL );
+ break;
+#endif
+ case eCsrScanSetBGScanParam:
+ default:
+ if(csrScanProcessScanResults( pMac, pCommand, pScanRsp, &fRemoveCommand ))
+ {
+ //Not to get channel info if the scan is not a wildcard scan because
+ //it may cause scan results got aged out incorrectly.
+ if( csrScanIsWildCardScan( pMac, pCommand ) && (!pCommand->u.scanCmd.u.scanRequest.p2pSearch) )
+ {
+ //Get the list of channels scanned
+ csrScanGetScanChnInfo(pMac);
+ }
+ }
+ break;
+ }//switch
+ if(fRemoveCommand)
+ {
+
+ csrReleaseScanCommand(pMac, pCommand, scanStatus);
+
+ }
+ smeProcessPendingQueue( pMac );
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: Scan Completion called but SCAN command is not ACTIVE ..." );
+ status = eHAL_STATUS_FAILURE;
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: Scan Completion called but NO commands are ACTIVE ..." );
+ status = eHAL_STATUS_FAILURE;
+ }
+
+ return (status);
+}
+
+
+
+
+tCsrScanResultInfo *csrScanResultGetFirst(tpAniSirGlobal pMac, tScanResultHandle hScanResult)
+{
+ tListElem *pEntry;
+ tCsrScanResult *pResult;
+ tCsrScanResultInfo *pRet = NULL;
+ tScanResultList *pResultList = (tScanResultList *)hScanResult;
+
+ if(pResultList)
+ {
+ csrLLLock(&pResultList->List);
+ pEntry = csrLLPeekHead(&pResultList->List, LL_ACCESS_NOLOCK);
+ if(pEntry)
+ {
+ pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+ pRet = &pResult->Result;
+ }
+ pResultList->pCurEntry = pEntry;
+ csrLLUnlock(&pResultList->List);
+ }
+
+ return pRet;
+}
+
+
+tCsrScanResultInfo *csrScanResultGetNext(tpAniSirGlobal pMac, tScanResultHandle hScanResult)
+{
+ tListElem *pEntry = NULL;
+ tCsrScanResult *pResult = NULL;
+ tCsrScanResultInfo *pRet = NULL;
+ tScanResultList *pResultList = (tScanResultList *)hScanResult;
+
+ if(pResultList)
+ {
+ csrLLLock(&pResultList->List);
+ if(NULL == pResultList->pCurEntry)
+ {
+ pEntry = csrLLPeekHead(&pResultList->List, LL_ACCESS_NOLOCK);
+ }
+ else
+ {
+ pEntry = csrLLNext(&pResultList->List, pResultList->pCurEntry, LL_ACCESS_NOLOCK);
+ }
+ if(pEntry)
+ {
+ pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+ pRet = &pResult->Result;
+ }
+ pResultList->pCurEntry = pEntry;
+ csrLLUnlock(&pResultList->List);
+ }
+
+ return pRet;
+}
+
+
+//This function moves the first BSS that matches the bssid to the head of the result
+eHalStatus csrMoveBssToHeadFromBSSID(tpAniSirGlobal pMac, tCsrBssid *bssid, tScanResultHandle hScanResult)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tScanResultList *pResultList = (tScanResultList *)hScanResult;
+ tCsrScanResult *pResult = NULL;
+ tListElem *pEntry = NULL;
+
+ if(pResultList && bssid)
+ {
+ csrLLLock(&pResultList->List);
+ pEntry = csrLLPeekHead(&pResultList->List, LL_ACCESS_NOLOCK);
+ while(pEntry)
+ {
+ pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+ if(palEqualMemory(pMac->hHdd, bssid, pResult->Result.BssDescriptor.bssId, sizeof(tCsrBssid)))
+ {
+ status = eHAL_STATUS_SUCCESS;
+ csrLLRemoveEntry(&pResultList->List, pEntry, LL_ACCESS_NOLOCK);
+ csrLLInsertHead(&pResultList->List, pEntry, LL_ACCESS_NOLOCK);
+ break;
+ }
+ pEntry = csrLLNext(&pResultList->List, pResultList->pCurEntry, LL_ACCESS_NOLOCK);
+ }
+ csrLLUnlock(&pResultList->List);
+ }
+
+ return (status);
+}
+
+
+//Remove the BSS if possible.
+//Return -- TRUE == the BSS is remove. False == Fail to remove it
+//This function is called when list lock is held. Be caution what functions it can call.
+tANI_BOOLEAN csrScanAgeOutBss(tpAniSirGlobal pMac, tCsrScanResult *pResult)
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
+ tANI_U32 i;
+ tCsrRoamSession *pSession;
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) )
+ {
+ pSession = CSR_GET_SESSION( pMac, i );
+ //Not to remove the BSS we are connected to.
+ if(csrIsConnStateDisconnected(pMac, i) || (NULL == pSession->pConnectBssDesc) ||
+ (!csrIsDuplicateBssDescription(pMac, &pResult->Result.BssDescriptor,
+ pSession->pConnectBssDesc, NULL))
+ )
+ {
+ smsLog(pMac, LOGW, "Aging out BSS %02X-%02X-%02X-%02X-%02X-%02X Channel %d\n",
+ pResult->Result.BssDescriptor.bssId[0],
+ pResult->Result.BssDescriptor.bssId[1],
+ pResult->Result.BssDescriptor.bssId[2],
+ pResult->Result.BssDescriptor.bssId[3],
+ pResult->Result.BssDescriptor.bssId[4],
+ pResult->Result.BssDescriptor.bssId[5],
+ pResult->Result.BssDescriptor.channelId);
+ //No need to hold the spin lock because caller should hold the lock for pMac->scan.scanResultList
+ if( csrLLRemoveEntry(&pMac->scan.scanResultList, &pResult->Link, LL_ACCESS_NOLOCK) )
+ {
+ csrFreeScanResultEntry(pMac, pResult);
+ }
+ fRet = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ } //valid session
+ } //for
+ if( CSR_ROAM_SESSION_MAX == i )
+ {
+ //reset the counter so this won't hapeen too soon
+ pResult->AgingCount = (tANI_S32)pMac->roam.configParam.agingCount;
+ pResult->Result.BssDescriptor.nReceivedTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd);
+ }
+
+ return (fRet);
+}
+
+
+eHalStatus csrScanAgeResults(tpAniSirGlobal pMac, tSmeGetScanChnRsp *pScanChnInfo)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tListElem *pEntry, *tmpEntry;
+ tCsrScanResult *pResult;
+ tLimScanChn *pChnInfo;
+ tANI_U8 i;
+
+ csrLLLock(&pMac->scan.scanResultList);
+ for(i = 0; i < pScanChnInfo->numChn; i++)
+ {
+ pChnInfo = &pScanChnInfo->scanChn[i];
+ pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_NOLOCK );
+ while( pEntry )
+ {
+ tmpEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK);
+ pResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+ if(pResult->Result.BssDescriptor.channelId == pChnInfo->channelId)
+ {
+ pResult->AgingCount--;
+ if(pResult->AgingCount <= 0)
+ {
+ smsLog(pMac, LOGW, " age out due to ref count");
+ csrScanAgeOutBss(pMac, pResult);
+ }
+ }
+ pEntry = tmpEntry;
+ }
+ }
+ csrLLUnlock(&pMac->scan.scanResultList);
+
+ return (status);
+}
+
+
+eHalStatus csrSendMBScanReq( tpAniSirGlobal pMac, tANI_U16 sessionId,
+ tCsrScanRequest *pScanReq, tScanReqParam *pScanReqParam )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirSmeScanReq *pMsg;
+ tANI_U16 msgLen;
+ tANI_U8 bssid[WNI_CFG_BSSID_LEN] = {0, 0, 0, 0, 0, 0};
+ tSirScanType scanType = pScanReq->scanType;
+ tANI_U32 minChnTime; //in units of milliseconds
+ tANI_U32 maxChnTime; //in units of milliseconds
+ tANI_U32 i;
+ tANI_U8 selfMacAddr[WNI_CFG_BSSID_LEN];
+ tANI_U8 *pSelfMac = NULL;
+
+ msgLen = (tANI_U16)(sizeof( tSirSmeScanReq ) - sizeof( pMsg->channelList.channelNumber ) +
+ ( sizeof( pMsg->channelList.channelNumber ) * pScanReq->ChannelInfo.numOfChannels )) +
+ ( pScanReq->uIEFieldLen ) ;
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ do
+ {
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+ pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_REQ);
+ pMsg->length = pal_cpu_to_be16(msgLen);
+ //ToDO: Fill in session info when we need to do scan base on session.
+ pMsg->sessionId = 0;
+ pMsg->transactionId = 0;
+ pMsg->dot11mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode ));
+ pMsg->bssType = pal_cpu_to_be32(csrTranslateBsstypeToMacType(pScanReq->BSSType));
+
+ if ( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ pSelfMac = (tANI_U8 *)&pMac->roam.roamSession[sessionId].selfMacAddr;
+ }
+ else
+ {
+ // Since we don't have session for the scanning, we find a valid session. In case we fail to
+ // do so, get the WNI_CFG_STA_ID
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) )
+ {
+ pSelfMac = (tANI_U8 *)&pMac->roam.roamSession[i].selfMacAddr;
+ break;
+ }
+ }
+ if( CSR_ROAM_SESSION_MAX == i )
+ {
+ tANI_U32 len = WNI_CFG_BSSID_LEN;
+ pSelfMac = selfMacAddr;
+ status = ccmCfgGetStr( pMac, WNI_CFG_STA_ID, pSelfMac, &len );
+ if( !HAL_STATUS_SUCCESS( status ) ||
+ ( len < WNI_CFG_BSSID_LEN ) )
+ {
+ smsLog( pMac, LOGE, FL(" Can not get self MAC address from CFG status = %d"), status );
+ //Force failed status
+ status = eHAL_STATUS_FAILURE;
+ break;
+ }
+ }
+ }
+ palCopyMemory( pMac->hHdd, (tANI_U8 *)pMsg->selfMacAddr, pSelfMac, sizeof(tSirMacAddr) );
+
+ //sirCopyMacAddr
+ palCopyMemory( pMac->hHdd, (tANI_U8 *)pMsg->bssId, (tANI_U8 *)&pScanReq->bssid, sizeof(tSirMacAddr) );
+ if( palEqualMemory( pMac->hHdd, pScanReq->bssid, bssid, sizeof(tCsrBssid) ) )
+ {
+ palFillMemory( pMac->hHdd, pMsg->bssId, sizeof(tSirMacAddr), 0xff );
+ }
+ else
+ {
+ palCopyMemory(pMac->hHdd, pMsg->bssId, pScanReq->bssid, WNI_CFG_BSSID_LEN);
+ }
+ minChnTime = pScanReq->minChnTime;
+ maxChnTime = pScanReq->maxChnTime;
+
+ //Verify the scan type first, if the scan is active scan, we need to make sure we
+ //are allowed to do so.
+ /* if 11d is enabled & we don't see any beacon around, scan type falls
+ back to passive. But in BT AMP STA mode we need to send out a
+ directed probe*/
+ if( (eSIR_PASSIVE_SCAN != scanType) && (eCSR_SCAN_P2P_DISCOVERY != pScanReq->requestType)
+ && (eCSR_BSS_TYPE_WDS_STA != pScanReq->BSSType)
+ && (eANI_BOOLEAN_FALSE == pMac->scan.fEnableBypass11d))
+ {
+ scanType = pMac->scan.curScanType;
+ if(eSIR_PASSIVE_SCAN == pMac->scan.curScanType)
+ {
+ if(minChnTime < pMac->roam.configParam.nPassiveMinChnTime)
+ {
+ minChnTime = pMac->roam.configParam.nPassiveMinChnTime;
+ }
+ if(maxChnTime < pMac->roam.configParam.nPassiveMaxChnTime)
+ {
+ maxChnTime = pMac->roam.configParam.nPassiveMaxChnTime;
+ }
+ }
+ }
+ pMsg->scanType = pal_cpu_to_be32(scanType);
+
+ pMsg->numSsid = (pScanReq->SSIDs.numOfSSIDs < SIR_SCAN_MAX_NUM_SSID) ? pScanReq->SSIDs.numOfSSIDs :
+ SIR_SCAN_MAX_NUM_SSID;
+ if((pScanReq->SSIDs.numOfSSIDs != 0) && ( eSIR_PASSIVE_SCAN != scanType ))
+ {
+ for (i = 0; i < pMsg->numSsid; i++)
+ {
+ palCopyMemory(pMac->hHdd, &pMsg->ssId[i], &pScanReq->SSIDs.SSIDList[i].SSID, sizeof(tSirMacSSid));
+ }
+ }
+ else
+ {
+ //Otherwise we scan all SSID and let the result filter later
+ for (i = 0; i < SIR_SCAN_MAX_NUM_SSID; i++)
+ {
+ pMsg->ssId[i].length = 0;
+ }
+ }
+
+//TODO: This preprocessor macro should be removed from CSR for production driver
+//This is a temperarory fix for scanning on FPGA.
+#if defined (ANI_CHIPSET_VIRGO) || defined (LIBRA_FPGA)|| defined (VOLANS_FPGA)
+ pMsg->minChannelTime = pal_cpu_to_be32(minChnTime * 8);
+ pMsg->maxChannelTime = pal_cpu_to_be32(maxChnTime * 8);
+#elif defined (ANI_CHIPSET_TAURUS) || defined(ANI_CHIPSET_LIBRA) || defined(ANI_CHIPSET_VOLANS)
+ pMsg->minChannelTime = pal_cpu_to_be32(minChnTime);
+ pMsg->maxChannelTime = pal_cpu_to_be32(maxChnTime);
+#else
+#error unknown chipset
+#endif
+ //hidden SSID option
+ pMsg->hiddenSsid = pScanReqParam->hiddenSsid;
+ //rest time
+ //pMsg->restTime = pScanReq->restTime;
+ pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch;
+ // All the scan results caching will be done by Roaming
+ // We do not want LIM to do any caching of scan results,
+ // so delete the LIM cache on all scan requests
+ pMsg->returnFreshResults = pScanReqParam->freshScan;
+ //Always ask for unique result
+ pMsg->returnUniqueResults = pScanReqParam->fUniqueResult;
+ pMsg->channelList.numChannels = (tANI_U8)pScanReq->ChannelInfo.numOfChannels;
+ if(pScanReq->ChannelInfo.numOfChannels)
+ {
+ //Assuming the channelNumber is tANI_U8 (1 byte)
+ status = palCopyMemory(pMac->hHdd, pMsg->channelList.channelNumber, pScanReq->ChannelInfo.ChannelList,
+ pScanReq->ChannelInfo.numOfChannels);
+ }
+
+ pMsg->uIEFieldLen = (tANI_U16) pScanReq->uIEFieldLen;
+ pMsg->uIEFieldOffset = (tANI_U16)(sizeof( tSirSmeScanReq ) - sizeof( pMsg->channelList.channelNumber ) +
+ ( sizeof( pMsg->channelList.channelNumber ) * pScanReq->ChannelInfo.numOfChannels )) ;
+ if(pScanReq->uIEFieldLen != 0)
+ {
+ palCopyMemory(pMac->hHdd, (tANI_U8 *)pMsg+pMsg->uIEFieldOffset,
+ pScanReq->pIEField, pScanReq->uIEFieldLen );
+ }
+#ifdef WLAN_FEATURE_P2P
+ pMsg->p2pSearch = pScanReq->p2pSearch;
+#endif
+
+ }while(0);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+ else {
+ palFreeMemory(pMac->hHdd, pMsg);
+ }
+ }//Success allocated memory
+
+
+ return( status );
+}
+
+eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tScanReqParam *pScanReqParam )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirSmeScanReq *pMsg;
+ tANI_U16 msgLen;
+
+ msgLen = (tANI_U16)(sizeof( tSirSmeScanReq ));
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+ pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_REQ);
+ pMsg->length = pal_cpu_to_be16(msgLen);
+ pMsg->sessionId = 0;
+ pMsg->returnFreshResults = pScanReqParam->freshScan;
+ //Always ask for unique result
+ pMsg->returnUniqueResults = pScanReqParam->fUniqueResult;
+ pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch;
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+
+ return( status );
+}
+
+
+
+eHalStatus csrScanChannels( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tScanReqParam scanReq;
+
+ do
+ {
+ scanReq.freshScan = CSR_SME_SCAN_FLAGS_DELETE_CACHE | TRUE;
+ scanReq.fUniqueResult = TRUE;
+ scanReq.hiddenSsid = SIR_SCAN_NO_HIDDEN_SSID;
+ if(eCsrScanForSsid == pCommand->u.scanCmd.reason)
+ {
+ scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_FIRST_MATCH;
+ }
+ else
+ {
+ // Basically do scan on all channels even for 11D 1st scan case.
+ scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS;
+ }
+ if((eCsrScanBgScan == pCommand->u.scanCmd.reason)||
+ (eCsrScanProbeBss == pCommand->u.scanCmd.reason))
+ {
+ scanReq.hiddenSsid = SIR_SCAN_HIDDEN_SSID_PE_DECISION;
+ }
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ {
+ vos_log_scan_pkt_type *pScanLog = NULL;
+
+ WLAN_VOS_DIAG_LOG_ALLOC(pScanLog, vos_log_scan_pkt_type, LOG_WLAN_SCAN_C);
+ if(pScanLog)
+ {
+ if(eCsrScanBgScan == pCommand->u.scanCmd.reason ||
+ eCsrScanProbeBss == pCommand->u.scanCmd.reason)
+ {
+ pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_REQ;
+ }
+ else
+ {
+ if( (eSIR_PASSIVE_SCAN != pCommand->u.scanCmd.u.scanRequest.scanType) &&
+ (eSIR_PASSIVE_SCAN != pMac->scan.curScanType) )
+ {
+ pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_REQ;
+ }
+ else
+ {
+ pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_REQ;
+ }
+ }
+ pScanLog->minChnTime = (v_U8_t)pCommand->u.scanCmd.u.scanRequest.minChnTime;
+ pScanLog->maxChnTime = (v_U8_t)pCommand->u.scanCmd.u.scanRequest.maxChnTime;
+ pScanLog->numChannel = (v_U8_t)pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
+ if(pScanLog->numChannel && (pScanLog->numChannel < VOS_LOG_MAX_NUM_CHANNEL))
+ {
+ palCopyMemory(pMac->hHdd, pScanLog->channels,
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList,
+ pScanLog->numChannel);
+ }
+ WLAN_VOS_DIAG_LOG_REPORT(pScanLog);
+ }
+ }
+#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+
+
+ status = csrSendMBScanReq(pMac, pCommand->sessionId,
+ &pCommand->u.scanCmd.u.scanRequest, &scanReq);
+ }while(0);
+
+ return( status );
+}
+
+
+eHalStatus csrScanRetrieveResult(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tScanReqParam scanReq;
+
+ do
+ {
+ //not a fresh scan
+ scanReq.freshScan = CSR_SME_SCAN_FLAGS_DELETE_CACHE;
+ scanReq.fUniqueResult = TRUE;
+ scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS;
+ status = csrSendMBScanResultReq(pMac, &scanReq);
+ }while(0);
+
+ return (status);
+}
+
+
+
+eHalStatus csrProcessScanCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tCsrChannelInfo newChannelInfo = {0, NULL};
+ int i, j;
+ tANI_U8 *pChannel = NULL;
+ tANI_U32 len = 0;
+
+ // Transition to Scanning state...
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if(CSR_IS_SESSION_VALID(pMac, i))
+ {
+ pCommand->u.scanCmd.lastRoamState[i] = csrRoamStateChange( pMac, eCSR_ROAMING_STATE_SCANNING, i);
+ smsLog( pMac, LOG3, "starting SCAN command from %d state.... reason is %d\n", pCommand->u.scanCmd.lastRoamState[i], pCommand->u.scanCmd.reason );
+ }
+ }
+
+ switch(pCommand->u.scanCmd.reason)
+ {
+ case eCsrScanGetResult:
+ case eCsrScanForCapsChange: //For cap change, LIM already save BSS description
+ status = csrScanRetrieveResult(pMac);
+ break;
+ case eCsrScanSetBGScanParam:
+ status = csrProcessSetBGScanParam(pMac, pCommand);
+ break;
+ case eCsrScanBGScanAbort:
+ status = csrSetCfgBackgroundScanPeriod(pMac, 0);
+ break;
+ case eCsrScanBGScanEnable:
+ status = csrSetCfgBackgroundScanPeriod(pMac, pMac->roam.configParam.bgScanInterval);
+ break;
+ case eCsrScanGetScanChnInfo:
+ status = csrScanGetScanChannelInfo(pMac);
+ break;
+ case eCsrScanUserRequest:
+ if(pMac->roam.configParam.fScanTwice)
+ {
+ //We scan 2.4 channel twice
+ if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels &&
+ (NULL != pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList))
+ {
+ len = pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
+ //allocate twice the channel
+ newChannelInfo.ChannelList = (tANI_U8 *)vos_mem_malloc(newChannelInfo.numOfChannels * 2);
+ pChannel = pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList;
+ }
+ else
+ {
+ //get the valid channel list to scan all.
+ len = sizeof(pMac->roam.validChannelList);
+
+ if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len)))
+ {
+ //allocate twice the channel
+ newChannelInfo.ChannelList = (tANI_U8 *)vos_mem_malloc(len * 2);
+ pChannel = pMac->roam.validChannelList;
+ }
+ }
+ if(NULL == newChannelInfo.ChannelList)
+ {
+ newChannelInfo.numOfChannels = 0;
+ }
+ else
+ {
+ j = 0;
+ for(i = 0; i < len; i++)
+ {
+ newChannelInfo.ChannelList[j++] = pChannel[i];
+ if(CSR_MAX_24GHz_CHANNEL_NUMBER >= pChannel[i])
+ {
+ newChannelInfo.ChannelList[j++] = pChannel[i];
+ }
+ }
+ if(NULL != pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList)
+ {
+ //pChannel points to the channellist from the command, free it.
+ vos_mem_free(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList);
+ }
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = j;
+ pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = newChannelInfo.ChannelList;
+ }
+ } //if(pMac->roam.configParam.fScanTwice)
+
+ status = csrScanChannels(pMac, pCommand);
+
+ break;
+ default:
+ status = csrScanChannels(pMac, pCommand);
+ break;
+ }
+
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ csrReleaseScanCommand(pMac, pCommand, eCSR_SCAN_FAILURE);
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanSetBGScanparams(tpAniSirGlobal pMac, tCsrBGScanRequest *pScanReq)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSmeCmd *pCommand = NULL;
+
+ if(pScanReq)
+ {
+ do
+ {
+ pCommand = csrGetCommandBuffer(pMac);
+ if(!pCommand)
+ {
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ palZeroMemory(pMac->hHdd, &pCommand->u.scanCmd, sizeof(tScanCmd));
+ pCommand->command = eSmeCommandScan;
+ pCommand->u.scanCmd.reason = eCsrScanSetBGScanParam;
+ pCommand->u.scanCmd.callback = NULL;
+ pCommand->u.scanCmd.pContext = NULL;
+ palCopyMemory(pMac->hHdd, &pCommand->u.scanCmd.u.bgScanRequest, pScanReq, sizeof(tCsrBGScanRequest));
+ //we have to do the follow
+ if(pScanReq->ChannelInfo.numOfChannels == 0)
+ {
+ pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList = NULL;
+ }
+ else
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList,
+ pScanReq->ChannelInfo.numOfChannels);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palCopyMemory(pMac->hHdd, pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList,
+ pScanReq->ChannelInfo.ChannelList, pScanReq->ChannelInfo.numOfChannels);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("ran out of memory\n"));
+ csrReleaseCommandScan(pMac, pCommand);
+ break;
+ }
+ }
+
+ //scan req for SSID
+ if(pScanReq->SSID.length)
+ {
+ palCopyMemory(pMac->hHdd,
+ pCommand->u.scanCmd.u.bgScanRequest.SSID.ssId,
+ pScanReq->SSID.ssId,
+ pScanReq->SSID.length);
+ pCommand->u.scanCmd.u.bgScanRequest.SSID.length = pScanReq->SSID.length;
+
+ }
+ pCommand->u.scanCmd.u.bgScanRequest.maxChnTime= pScanReq->maxChnTime;
+ pCommand->u.scanCmd.u.bgScanRequest.minChnTime = pScanReq->minChnTime;
+ pCommand->u.scanCmd.u.bgScanRequest.scanInterval = pScanReq->scanInterval;
+
+
+ status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ csrReleaseCommandScan( pMac, pCommand );
+ break;
+ }
+ }while(0);
+ }
+
+ return (status);
+}
+
+eHalStatus csrScanBGScanAbort( tpAniSirGlobal pMac )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSmeCmd *pCommand = NULL;
+
+ do
+ {
+ pCommand = csrGetCommandBuffer(pMac);
+ if(!pCommand)
+ {
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ palZeroMemory(pMac->hHdd, &pCommand->u.scanCmd, sizeof(tScanCmd));
+ pCommand->command = eSmeCommandScan;
+ pCommand->u.scanCmd.reason = eCsrScanBGScanAbort;
+ pCommand->u.scanCmd.callback = NULL;
+ pCommand->u.scanCmd.pContext = NULL;
+ status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ csrReleaseCommandScan( pMac, pCommand );
+ break;
+ }
+ }while(0);
+
+ return (status);
+}
+
+
+//This will enable the background scan with the non-zero interval
+eHalStatus csrScanBGScanEnable(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSmeCmd *pCommand = NULL;
+
+ if(pMac->roam.configParam.bgScanInterval)
+ {
+ do
+ {
+ pCommand = csrGetCommandBuffer(pMac);
+ if(!pCommand)
+ {
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ palZeroMemory(pMac->hHdd, &pCommand->u.scanCmd, sizeof(tScanCmd));
+ pCommand->command = eSmeCommandScan;
+ pCommand->u.scanCmd.reason = eCsrScanBGScanEnable;
+ pCommand->u.scanCmd.callback = NULL;
+ pCommand->u.scanCmd.pContext = NULL;
+ status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ csrReleaseCommandScan( pMac, pCommand );
+ break;
+ }
+ }while(0);
+ //BG scan results are reported automatically by PE to SME once the scan is done.
+ //No need to fetch the results explicitly.
+ //csrScanStartGetResultTimer(pMac);
+ csrScanStartResultAgingTimer(pMac);
+ }
+ else
+ {
+ //We don't have BG scan so stop the aging timer
+ csrScanStopResultAgingTimer(pMac);
+ smsLog(pMac, LOGE, FL("cannot continue because the bgscan interval is 0\n"));
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanCopyRequest(tpAniSirGlobal pMac, tCsrScanRequest *pDstReq, tCsrScanRequest *pSrcReq)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_U32 len = sizeof(pMac->roam.validChannelList);
+ tANI_U32 index = 0;
+ tANI_U32 new_index = 0;
+
+ do
+ {
+ status = csrScanFreeRequest(pMac, pDstReq);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ status = palCopyMemory(pMac->hHdd, pDstReq, pSrcReq, sizeof(tCsrScanRequest));
+ if(pSrcReq->uIEFieldLen == 0)
+ {
+ pDstReq->pIEField = NULL;
+ }
+ else
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstReq->pIEField, pSrcReq->uIEFieldLen);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palCopyMemory(pMac->hHdd, pDstReq->pIEField, pSrcReq->pIEField, pSrcReq->uIEFieldLen);
+ pDstReq->uIEFieldLen = pSrcReq->uIEFieldLen;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "No memory for scanning IE fields\n");
+ break;
+ }
+ }//Allocate memory for IE field
+ {
+ if(pSrcReq->ChannelInfo.numOfChannels == 0)
+ {
+ pDstReq->ChannelInfo.ChannelList = NULL;
+ pDstReq->ChannelInfo.numOfChannels = 0;
+ }
+ else
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstReq->ChannelInfo.ChannelList,
+ pSrcReq->ChannelInfo.numOfChannels * sizeof(*pDstReq->ChannelInfo.ChannelList));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ pDstReq->ChannelInfo.numOfChannels = 0;
+ smsLog(pMac, LOGE, "No memory for scanning Channel List\n");
+ break;
+ }
+
+ if((pSrcReq->scanType == eSIR_PASSIVE_SCAN) && (pSrcReq->requestType == eCSR_SCAN_REQUEST_11D_SCAN))
+ {
+ for ( index = 0; index < pSrcReq->ChannelInfo.numOfChannels ; index++ )
+ {
+ pDstReq->ChannelInfo.ChannelList[new_index] =
+ pSrcReq->ChannelInfo.ChannelList[index];
+ new_index++;
+ }
+ pDstReq->ChannelInfo.numOfChannels = new_index;
+ }
+ else if(HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, pMac->roam.validChannelList, &len)))
+ {
+ new_index = 0;
+ pMac->roam.numValidChannels = len;
+ for ( index = 0; index < pSrcReq->ChannelInfo.numOfChannels ; index++ )
+ {
+ if(csrRoamIsValidChannel(pMac, pSrcReq->ChannelInfo.ChannelList[index]))
+ {
+ pDstReq->ChannelInfo.ChannelList[new_index] =
+ pSrcReq->ChannelInfo.ChannelList[index];
+ new_index++;
+ }
+ }
+ pDstReq->ChannelInfo.numOfChannels = new_index;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "Couldn't get the valid Channel List, keeping requester's list\n");
+ palCopyMemory(pMac->hHdd, pDstReq->ChannelInfo.ChannelList, pSrcReq->ChannelInfo.ChannelList,
+ pSrcReq->ChannelInfo.numOfChannels * sizeof(*pDstReq->ChannelInfo.ChannelList));
+ pDstReq->ChannelInfo.numOfChannels = pSrcReq->ChannelInfo.numOfChannels;
+ }
+ }//Allocate memory for Channel List
+ }
+ if(pSrcReq->SSIDs.numOfSSIDs == 0)
+ {
+ pDstReq->SSIDs.numOfSSIDs = 0;
+ pDstReq->SSIDs.SSIDList = NULL;
+ }
+ else
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pDstReq->SSIDs.SSIDList,
+ pSrcReq->SSIDs.numOfSSIDs * sizeof(*pDstReq->SSIDs.SSIDList));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ pDstReq->SSIDs.numOfSSIDs = pSrcReq->SSIDs.numOfSSIDs;
+ palCopyMemory(pMac->hHdd, pDstReq->SSIDs.SSIDList, pSrcReq->SSIDs.SSIDList,
+ pSrcReq->SSIDs.numOfSSIDs * sizeof(*pDstReq->SSIDs.SSIDList));
+ }
+ else
+ {
+ pDstReq->SSIDs.numOfSSIDs = 0;
+ smsLog(pMac, LOGE, "No memory for scanning SSID List\n");
+ break;
+ }
+ }//Allocate memory for SSID List
+#ifdef WLAN_FEATURE_P2P
+ pDstReq->p2pSearch = pSrcReq->p2pSearch;
+#endif
+
+ }
+ }while(0);
+
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ csrScanFreeRequest(pMac, pDstReq);
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanFreeRequest(tpAniSirGlobal pMac, tCsrScanRequest *pReq)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ if(pReq->ChannelInfo.ChannelList)
+ {
+ status = palFreeMemory(pMac->hHdd, pReq->ChannelInfo.ChannelList);
+ pReq->ChannelInfo.ChannelList = NULL;
+ }
+ pReq->ChannelInfo.numOfChannels = 0;
+ if(pReq->pIEField)
+ {
+ status = palFreeMemory(pMac->hHdd, pReq->pIEField);
+ pReq->pIEField = NULL;
+ }
+ pReq->uIEFieldLen = 0;
+ if(pReq->SSIDs.SSIDList)
+ {
+ palFreeMemory(pMac->hHdd, pReq->SSIDs.SSIDList);
+ pReq->SSIDs.SSIDList = NULL;
+ }
+ pReq->SSIDs.numOfSSIDs = 0;
+
+ return (status);
+}
+
+
+void csrScanCallCallback(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus)
+{
+ if(pCommand->u.scanCmd.callback)
+ {
+// sme_ReleaseGlobalLock( &pMac->sme );
+ pCommand->u.scanCmd.callback(pMac, pCommand->u.scanCmd.pContext, pCommand->u.scanCmd.scanID, scanStatus);
+// sme_AcquireGlobalLock( &pMac->sme );
+ } else {
+ smsLog( pMac, LOGW, "%s:%d - Callback NULL!!!\n", __FUNCTION__, __LINE__);
+ }
+}
+
+
+void csrScanStopTimers(tpAniSirGlobal pMac)
+{
+ csrScanStopResultAgingTimer(pMac);
+ csrScanStopIdleScanTimer(pMac);
+ csrScanStopGetResultTimer(pMac);
+}
+
+
+eHalStatus csrScanStartGetResultTimer(tpAniSirGlobal pMac)
+{
+ eHalStatus status;
+
+ if(pMac->scan.fScanEnable)
+ {
+ status = palTimerStart(pMac->hHdd, pMac->scan.hTimerGetResult, CSR_SCAN_GET_RESULT_INTERVAL, eANI_BOOLEAN_TRUE);
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanStopGetResultTimer(tpAniSirGlobal pMac)
+{
+ return (palTimerStop(pMac->hHdd, pMac->scan.hTimerGetResult));
+}
+
+
+void csrScanGetResultTimerHandler(void *pv)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pv );
+
+ csrScanRequestResult(pMac);
+}
+
+#ifdef WLAN_AP_STA_CONCURRENCY
+static void csrStaApConcTimerHandler(void *pv)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pv );
+ tListElem *pEntry;
+ tSmeCmd *pScanCmd;
+
+ csrLLLock(&pMac->scan.scanCmdPendingList);
+
+ if ( NULL != ( pEntry = csrLLPeekHead( &pMac->scan.scanCmdPendingList, LL_ACCESS_NOLOCK) ) )
+ {
+ tCsrScanRequest scanReq;
+ tSmeCmd *pSendScanCmd = NULL;
+ tANI_U8 numChn = 0;
+ tANI_U8 i;
+ tCsrChannelInfo *pChnInfo = &scanReq.ChannelInfo;
+ tANI_U8 channelToScan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ eHalStatus status;
+
+
+ pScanCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ numChn = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
+ if (numChn > 1)
+ {
+ palZeroMemory(pMac->hHdd, &scanReq, sizeof(tCsrScanRequest));
+
+ pSendScanCmd = csrGetCommandBuffer(pMac); //optimize this to use 2 command buffer only
+ if (!pSendScanCmd)
+ {
+ smsLog( pMac, LOGE, FL(" Failed to get Queue command buffer\n") );
+ csrLLUnlock(&pMac->scan.scanCmdPendingList);
+ return;
+ }
+ pSendScanCmd->command = pScanCmd->command;
+ pSendScanCmd->sessionId = pScanCmd->sessionId;
+ pSendScanCmd->u.scanCmd.callback = NULL;
+ pSendScanCmd->u.scanCmd.pContext = pScanCmd->u.scanCmd.pContext;
+ pSendScanCmd->u.scanCmd.reason = pScanCmd->u.scanCmd.reason;
+ pSendScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around
+
+ pChnInfo->numOfChannels = 1;
+ palCopyMemory(pMac->hHdd, &channelToScan[0], &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[0],
+ 1 * sizeof(tANI_U8)); //just send one channel
+ pChnInfo->ChannelList = &channelToScan[0];
+
+ for (i = 0; i < (numChn-2); i++)
+ {
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] =
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i+1]; //Move all the channels one step
+ }
+
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = numChn -1; //reduce outstanding # of channels to be scanned
+
+ scanReq.BSSType = eCSR_BSS_TYPE_ANY;
+ //Modify callers parameters in case of concurrency
+ scanReq.scanType = eSIR_ACTIVE_SCAN;
+ scanReq.maxChnTime = CSR_MIN(pScanCmd->u.scanCmd.u.scanRequest.maxChnTime,CSR_ACTIVE_MAX_CHANNEL_TIME_CONC);
+ scanReq.minChnTime = CSR_MIN(pScanCmd->u.scanCmd.u.scanRequest.minChnTime,CSR_ACTIVE_MIN_CHANNEL_TIME_CONC);
+
+ status = csrScanCopyRequest(pMac, &pSendScanCmd->u.scanCmd.u.scanRequest, &scanReq);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog( pMac, LOGE, FL(" Failed to get copy csrScanRequest = %d\n"), status );
+ csrLLUnlock(&pMac->scan.scanCmdPendingList);
+ return;
+ }
+ }
+ else
+ { //numChn ==1 This is the last channel to be scanned
+ //last channel remaining to scan
+ pSendScanCmd = pScanCmd;
+ //remove this command from pending list
+ if (csrLLRemoveHead( &pMac->scan.scanCmdPendingList, LL_ACCESS_NOLOCK) == NULL)
+ { //In case between PeekHead and here, the entry got removed by another thread.
+ smsLog( pMac, LOGE, FL(" Failed to remove entry from scanCmdPendingList\n"));
+ }
+
+ }
+ csrQueueSmeCommand(pMac, pSendScanCmd, eANI_BOOLEAN_FALSE);
+
+ }
+
+ if (!csrLLIsListEmpty( &pMac->scan.scanCmdPendingList, LL_ACCESS_NOLOCK ))
+ {
+ palTimerStart(pMac->hHdd, pMac->scan.hTimerStaApConcTimer,
+ CSR_SCAN_STAAP_CONC_INTERVAL, eANI_BOOLEAN_FALSE);
+ }
+ csrLLUnlock(&pMac->scan.scanCmdPendingList);
+
+}
+#endif
+
+eHalStatus csrScanStartResultAgingTimer(tpAniSirGlobal pMac)
+{
+ eHalStatus status;
+
+ if(pMac->scan.fScanEnable)
+ {
+ status = palTimerStart(pMac->hHdd, pMac->scan.hTimerResultAging, CSR_SCAN_RESULT_AGING_INTERVAL, eANI_BOOLEAN_TRUE);
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanStopResultAgingTimer(tpAniSirGlobal pMac)
+{
+ return (palTimerStop(pMac->hHdd, pMac->scan.hTimerResultAging));
+}
+
+
+//This function returns the maximum time a BSS is allowed in the scan result.
+//The time varies base on connection and power saving factors.
+//Not connected, No PS
+//Not connected, with PS
+//Connected w/o traffic, No PS
+//Connected w/o traffic, with PS
+//Connected w/ traffic, no PS -- Not supported
+//Connected w/ traffic, with PS -- Not supported
+//the return unit is in seconds.
+tANI_U32 csrScanGetAgeOutTime(tpAniSirGlobal pMac)
+{
+ tANI_U32 nRet;
+
+ if(pMac->scan.nAgingCountDown)
+ {
+ //Calculate what should be the timeout value for this
+ nRet = pMac->scan.nLastAgeTimeOut * pMac->scan.nAgingCountDown;
+ pMac->scan.nAgingCountDown--;
+ }
+ else
+ {
+ if( csrIsAllSessionDisconnected( pMac ) )
+ {
+ if(pmcIsPowerSaveEnabled(pMac, ePMC_IDLE_MODE_POWER_SAVE))
+ {
+ nRet = pMac->roam.configParam.scanAgeTimeNCPS;
+ }
+ else
+ {
+ nRet = pMac->roam.configParam.scanAgeTimeNCNPS;
+ }
+ }
+ else
+ {
+ if(pmcIsPowerSaveEnabled(pMac, ePMC_BEACON_MODE_POWER_SAVE))
+ {
+ nRet = pMac->roam.configParam.scanAgeTimeCPS;
+ }
+ else
+ {
+ nRet = pMac->roam.configParam.scanAgeTimeCNPS;
+ }
+ }
+ //If state-change causing aging time out change, we want to delay it somewhat to avoid
+ //unnecessary removal of BSS. This is mostly due to transition from connect to disconnect.
+ if(pMac->scan.nLastAgeTimeOut > nRet)
+ {
+ if(nRet)
+ {
+ pMac->scan.nAgingCountDown = (pMac->scan.nLastAgeTimeOut / nRet);
+ }
+ pMac->scan.nLastAgeTimeOut = nRet;
+ nRet *= pMac->scan.nAgingCountDown;
+ }
+ else
+ {
+ pMac->scan.nLastAgeTimeOut = nRet;
+ }
+ }
+
+ return (nRet);
+}
+
+
+void csrScanResultAgingTimerHandler(void *pv)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pv );
+ tANI_BOOLEAN fDisconnected = csrIsAllSessionDisconnected(pMac);
+
+ //no scan, no aging
+ if(pMac->scan.fScanEnable &&
+ (((eANI_BOOLEAN_FALSE == fDisconnected) && pMac->roam.configParam.bgScanInterval)
+ || (fDisconnected && (pMac->scan.fCancelIdleScan == eANI_BOOLEAN_FALSE)))
+ )
+ {
+ tListElem *pEntry, *tmpEntry;
+ tCsrScanResult *pResult;
+ tANI_TIMESTAMP ageOutTime = (tANI_TIMESTAMP)(csrScanGetAgeOutTime(pMac) * PAL_TICKS_PER_SECOND); //turn it into 10ms units
+ tANI_TIMESTAMP curTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd);
+
+ csrLLLock(&pMac->scan.scanResultList);
+ pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_NOLOCK );
+ while( pEntry )
+ {
+ tmpEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK);
+ pResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+ if((curTime - pResult->Result.BssDescriptor.nReceivedTime) > ageOutTime)
+ {
+ smsLog(pMac, LOGW, " age out due to time out");
+ csrScanAgeOutBss(pMac, pResult);
+ }
+ pEntry = tmpEntry;
+ }
+ csrLLUnlock(&pMac->scan.scanResultList);
+ }
+}
+
+
+eHalStatus csrScanStartIdleScanTimer(tpAniSirGlobal pMac, tANI_U32 interval)
+{
+ eHalStatus status;
+
+ smsLog(pMac, LOG1, " csrScanStartIdleScanTimer \n ");
+ if((pMac->scan.fScanEnable) && (eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan) && interval)
+ {
+ pMac->scan.nIdleScanTimeGap += interval;
+ palTimerStop(pMac->hHdd, pMac->scan.hTimerIdleScan);
+ status = palTimerStart(pMac->hHdd, pMac->scan.hTimerIdleScan, interval, eANI_BOOLEAN_FALSE);
+ if( !HAL_STATUS_SUCCESS(status) )
+ {
+ smsLog(pMac, LOGE, " Fail to start Idle scan timer. status = %d interval = %d\n", status, interval);
+ //This should not happen but set the flag to restart when ready
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE;
+ }
+ }
+ else
+ {
+ if( pMac->scan.fScanEnable && (eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan) )
+ {
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE;
+ }
+ status = eHAL_STATUS_FAILURE;
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanStopIdleScanTimer(tpAniSirGlobal pMac)
+{
+ return (palTimerStop(pMac->hHdd, pMac->scan.hTimerIdleScan));
+}
+
+
+//Stop CSR from asking for IMPS, This function doesn't disable IMPS from CSR
+void csrScanSuspendIMPS( tpAniSirGlobal pMac )
+{
+ csrScanCancelIdleScan(pMac);
+}
+
+
+//Start CSR from asking for IMPS. This function doesn't trigger CSR to request entering IMPS
+//because IMPS maybe disabled.
+void csrScanResumeIMPS( tpAniSirGlobal pMac )
+{
+ csrScanStartIdleScan( pMac );
+}
+
+
+void csrScanIMPSCallback(void *callbackContext, eHalStatus status)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( callbackContext );
+
+ if(eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan)
+ {
+ if(pMac->roam.configParam.IsIdleScanEnabled)
+ {
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ if(csrIsAllSessionDisconnected(pMac) && !csrIsRoamCommandWaiting(pMac))
+ {
+ smsLog(pMac, LOGW, FL("starts idle mode full scan\n"));
+ csrScanAllChannels(pMac, eCSR_SCAN_IDLE_MODE_SCAN);
+ }
+ else
+ {
+ smsLog(pMac, LOGW, FL("cannot start idle mode full scan\n"));
+ //even though we are in timer handle, calling stop timer will make sure the timer
+ //doesn't get to restart.
+ csrScanStopIdleScanTimer(pMac);
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("sees not success status (%d)\n"), status);
+ }
+ }
+ else
+ {//we might need another flag to check if CSR needs to request imps at all
+
+ tANI_U32 nTime = 0;
+
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_FALSE;
+ if(!HAL_STATUS_SUCCESS(csrScanTriggerIdleScan(pMac, &nTime)))
+ {
+ csrScanStartIdleScanTimer(pMac, nTime);
+ }
+ }
+ }
+}
+
+
+//Param: pTimeInterval -- Caller allocated memory in return, if failed, to specify the nxt time interval for
+//idle scan timer interval
+//Return: Not success -- meaning it cannot start IMPS, caller needs to start a timer for idle scan
+eHalStatus csrScanTriggerIdleScan(tpAniSirGlobal pMac, tANI_U32 *pTimeInterval)
+{
+ eHalStatus status = eHAL_STATUS_CSR_WRONG_STATE;
+
+ //Do not trigger IMPS in case of concurrency
+ if (vos_concurrent_sessions_running())
+ return (status);
+
+ if(pTimeInterval)
+ {
+ *pTimeInterval = 0;
+ }
+
+ smsLog(pMac, LOGW, FL("called\n"));
+ if( smeCommandPending( pMac ) )
+ {
+ smsLog( pMac, LOGW, FL(" Cannot request IMPS because command pending\n") );
+ //Not to enter IMPS because more work to do
+ if(pTimeInterval)
+ {
+ *pTimeInterval = 0;
+ }
+ //restart when ready
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE;
+
+ return (status);
+ }
+
+ if((pMac->scan.fScanEnable) && (eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan)
+ /*&& pMac->roam.configParam.impsSleepTime*/)
+ {
+ //Stop get result timer because idle scan gets scan result out of PE
+ csrScanStopGetResultTimer(pMac);
+ if(pTimeInterval)
+ {
+ *pTimeInterval = pMac->roam.configParam.impsSleepTime;
+ }
+ //pmcRequestImps take a period in millisecond unit.
+ status = pmcRequestImps(pMac, pMac->roam.configParam.impsSleepTime / PAL_TIMER_TO_MS_UNIT, csrScanIMPSCallback, pMac);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ if(eHAL_STATUS_PMC_ALREADY_IN_IMPS != status)
+ {
+ //Do restart the timer if CSR thinks it cannot do IMPS
+ if( !csrCheckPSReady( pMac ) )
+ {
+ if(pTimeInterval)
+ {
+ *pTimeInterval = 0;
+ }
+ //Set the restart flag to true because that idle scan
+ //can be restarted even though the timer will not be running
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE;
+ }
+ else
+ {
+ //For not now, we do a quicker retry
+ if(pTimeInterval)
+ {
+ *pTimeInterval = CSR_IDLE_SCAN_WAIT_TIME;
+ }
+ }
+ smsLog(pMac, LOGW, FL("call pmcRequestImps and it returns status code (%d)\n"), status);
+ }
+ else
+ {
+ smsLog(pMac, LOGW, FL("already in IMPS\n"));
+ //Since CSR is the only module to request for IMPS. If it is already in IMPS, CSR assumes
+ //the callback will be called in the future. Should not happen though.
+ status = eHAL_STATUS_SUCCESS;
+ pMac->scan.nIdleScanTimeGap = 0;
+ }
+ }
+ else
+ {
+ //requested so let's reset the value
+ pMac->scan.nIdleScanTimeGap = 0;
+ }
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanStartIdleScan(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_CSR_WRONG_STATE;
+ tANI_U32 nTime = 0;
+
+ smsLog(pMac, LOGW, FL("called\n"));
+ if(pMac->roam.configParam.IsIdleScanEnabled)
+ {
+ //stop bg scan first
+ csrScanBGScanAbort(pMac);
+ //Stop get result timer because idle scan gets scan result out of PE
+ csrScanStopGetResultTimer(pMac);
+ //Enable aging timer since idle scan is going on
+ csrScanStartResultAgingTimer(pMac);
+ }
+ pMac->scan.fCancelIdleScan = eANI_BOOLEAN_FALSE;
+ status = csrScanTriggerIdleScan(pMac, &nTime);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ csrScanStartIdleScanTimer(pMac, nTime);
+ }
+
+ return (status);
+}
+
+
+void csrScanCancelIdleScan(tpAniSirGlobal pMac)
+{
+ if(eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan)
+ {
+#ifdef WLAN_SOFTAP_FEATURE
+ if (vos_concurrent_sessions_running()) {
+ return;
+ }
+#endif
+ smsLog(pMac, LOG1, " csrScanCancelIdleScan\n");
+ pMac->scan.fCancelIdleScan = eANI_BOOLEAN_TRUE;
+ //Set the restart flag in case later on it is uncancelled
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE;
+ csrScanStopIdleScanTimer(pMac);
+ csrScanRemoveNotRoamingScanCommand(pMac);
+ }
+}
+
+
+void csrScanIdleScanTimerHandler(void *pv)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pv );
+ eHalStatus status;
+ tANI_U32 nTime = 0;
+
+ smsLog(pMac, LOGW, " csrScanIdleScanTimerHandler called ");
+ status = csrScanTriggerIdleScan(pMac, &nTime);
+ if(!HAL_STATUS_SUCCESS(status) && (eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan))
+ {
+ //Check whether it is time to actually do an idle scan
+ if(pMac->scan.nIdleScanTimeGap >= pMac->roam.configParam.impsSleepTime)
+ {
+ pMac->scan.nIdleScanTimeGap = 0;
+ csrScanIMPSCallback(pMac, eHAL_STATUS_SUCCESS);
+ }
+ else
+ {
+ csrScanStartIdleScanTimer(pMac, nTime);
+ }
+ }
+}
+
+
+
+
+tANI_BOOLEAN csrScanRemoveNotRoamingScanCommand(tpAniSirGlobal pMac)
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
+ tListElem *pEntry, *pEntryTmp;
+ 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 fRet;
+ }
+
+ csrLLLock(&pMac->sme.smeCmdPendingList);
+ pEntry = csrLLPeekHead(&pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK);
+ while(pEntry)
+ {
+ pEntryTmp = csrLLNext(&pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK);
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ if( eSmeCommandScan == pCommand->command )
+ {
+ switch( pCommand->u.scanCmd.reason )
+ {
+ case eCsrScanIdleScan:
+ if( csrLLRemoveEntry(&pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK) )
+ {
+ csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK);
+ }
+ fRet = eANI_BOOLEAN_TRUE;
+ break;
+
+ default:
+ break;
+ } //switch
+ }
+ pEntry = pEntryTmp;
+ }
+
+ csrLLUnlock(&pMac->sme.smeCmdPendingList);
+
+ while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) )
+ {
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ csrReleaseCommandScan( pMac, pCommand );
+ }
+
+ csrLLClose(&localList);
+
+ return (fRet);
+}
+
+
+tANI_BOOLEAN csrScanRemoveFreshScanCommand(tpAniSirGlobal pMac, tANI_U8 sessionId)
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
+ tListElem *pEntry, *pEntryTmp;
+ 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 fRet;
+ }
+
+ csrLLLock(&pMac->sme.smeCmdPendingList);
+ pEntry = csrLLPeekHead(&pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK);
+ while(pEntry)
+ {
+ pEntryTmp = csrLLNext(&pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK);
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ if( (eSmeCommandScan == pCommand->command) && (sessionId == pCommand->sessionId) )
+ {
+ switch(pCommand->u.scanCmd.reason)
+ {
+ case eCsrScanGetResult:
+ case eCsrScanSetBGScanParam:
+ case eCsrScanBGScanAbort:
+ case eCsrScanBGScanEnable:
+ case eCsrScanGetScanChnInfo:
+ break;
+ default:
+ smsLog (pMac, LOGW, "%s: -------- abort scan command reason = %d\n",
+ __FUNCTION__, pCommand->u.scanCmd.reason);
+ //The rest are fresh scan requests
+ if( csrLLRemoveEntry(&pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK) )
+ {
+ csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK);
+ }
+ fRet = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+ pEntry = pEntryTmp;
+ }
+
+ csrLLUnlock(&pMac->sme.smeCmdPendingList);
+
+ while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) )
+ {
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ if (pCommand->u.scanCmd.callback)
+ {
+ /* User scan request is pending,
+ * send response with status eCSR_SCAN_ABORT*/
+ pCommand->u.scanCmd.callback(pMac,
+ pCommand->u.scanCmd.pContext,
+ pCommand->u.scanCmd.scanID,
+ eCSR_SCAN_ABORT);
+ }
+ csrReleaseCommandScan( pMac, pCommand );
+ }
+ csrLLClose(&localList);
+
+ return (fRet);
+}
+
+
+void csrReleaseScanCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus)
+{
+ eCsrScanReason reason = pCommand->u.scanCmd.reason;
+ tANI_U32 i;
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if(CSR_IS_SESSION_VALID(pMac, i))
+ csrRoamStateChange( pMac, pCommand->u.scanCmd.lastRoamState[i], i);
+ }
+
+ csrScanCallCallback(pMac, pCommand, scanStatus);
+
+ smsLog(pMac, LOG3, " Remove Scan command reason = %d\n", reason);
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, &pCommand->Link, LL_ACCESS_LOCK ) )
+ {
+ csrReleaseCommandScan( pMac, pCommand );
+ }
+ else
+ {
+ smsLog(pMac, LOGE, " ********csrReleaseScanCommand cannot release command reason %d\n", pCommand->u.scanCmd.reason );
+ }
+}
+
+
+eHalStatus csrScanGetPMKIDCandidateList(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tPmkidCandidateInfo *pPmkidList, tANI_U32 *pNumItems )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOGW, " pMac->scan.NumPmkidCandidate = %d\n ", pSession->NumPmkidCandidate);
+ csrResetPMKIDCandidateList(pMac, sessionId);
+ if(csrIsConnStateConnected(pMac, sessionId) && pSession->pCurRoamProfile)
+ {
+ tCsrScanResultFilter *pScanFilter;
+ tCsrScanResultInfo *pScanResult;
+ tScanResultHandle hBSSList;
+ tANI_U32 nItems = *pNumItems;
+
+ *pNumItems = 0;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ //Here is the profile we need to connect to
+ status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) && ( pSession->NumPmkidCandidate < nItems))
+ {
+ //NumPmkidCandidate adds up here
+ csrProcessBSSDescForPMKIDList(pMac, &pScanResult->BssDescriptor,
+ (tDot11fBeaconIEs *)( pScanResult->pvIes ));
+ }
+ if(pSession->NumPmkidCandidate)
+ {
+ *pNumItems = pSession->NumPmkidCandidate;
+ palCopyMemory(pMac->hHdd, pPmkidList, pSession->PmkidCandidateInfo,
+ pSession->NumPmkidCandidate * sizeof(tPmkidCandidateInfo));
+ }
+ csrScanResultPurge(pMac, hBSSList);
+ }//Have scan result
+ csrFreeScanFilter(pMac, pScanFilter);
+ }
+ palFreeMemory(pMac->hHdd, pScanFilter);
+ }
+ }
+
+ return (status);
+}
+
+
+
+#ifdef FEATURE_WLAN_WAPI
+eHalStatus csrScanGetBKIDCandidateList(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tBkidCandidateInfo *pBkidList, tANI_U32 *pNumItems )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ smsLog(pMac, LOGW, " pMac->scan.NumBkidCandidate = %d\n ", pSession->NumBkidCandidate);
+ csrResetBKIDCandidateList(pMac, sessionId);
+ if(csrIsConnStateConnected(pMac, sessionId) && pSession->pCurRoamProfile)
+ {
+ tCsrScanResultFilter *pScanFilter;
+ tCsrScanResultInfo *pScanResult;
+ tScanResultHandle hBSSList;
+ tANI_U32 nItems = *pNumItems;
+ *pNumItems = 0;
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanFilter, sizeof(tCsrScanResultFilter));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pScanFilter, sizeof(tCsrScanResultFilter));
+ //Here is the profile we need to connect to
+ status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) && ( pSession->NumBkidCandidate < nItems))
+ {
+ //pMac->scan.NumBkidCandidate adds up here
+ csrProcessBSSDescForBKIDList(pMac, &pScanResult->BssDescriptor,
+ (tDot11fBeaconIEs *)( pScanResult->pvIes ));
+
+ }
+ if(pSession->NumBkidCandidate)
+ {
+ *pNumItems = pSession->NumBkidCandidate;
+ palCopyMemory(pMac->hHdd, pBkidList, pSession->BkidCandidateInfo, pSession->NumBkidCandidate * sizeof(tBkidCandidateInfo));
+ }
+ csrScanResultPurge(pMac, hBSSList);
+ }//Have scan result
+ }
+ palFreeMemory(pMac->hHdd, pScanFilter);
+ }
+ }
+
+ return (status);
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+
+
+//This function is usually used for BSSs that suppresses SSID so the profile
+//shall have one and only one SSID
+eHalStatus csrScanForSSID(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tANI_U32 roamId)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tSmeCmd *pScanCmd = NULL;
+ tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ tANI_U8 index = 0;
+ tANI_U32 numSsid = pProfile->SSIDs.numOfSSIDs;
+
+ smsLog(pMac, LOG2, FL("called\n"));
+ //For WDS, we use the index 0. There must be at least one in there
+ if( CSR_IS_WDS_STA( pProfile ) && numSsid )
+ {
+ numSsid = 1;
+ }
+ if(pMac->scan.fScanEnable && ( numSsid == 1 ) )
+ {
+ do
+ {
+ pScanCmd = csrGetCommandBuffer(pMac);
+ if(!pScanCmd)
+ {
+ smsLog(pMac, LOGE, FL("failed to allocate command buffer\n"));
+ break;
+ }
+ palZeroMemory(pMac->hHdd, &pScanCmd->u.scanCmd, sizeof(tScanCmd));
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanCmd->u.scanCmd.pToRoamProfile, sizeof(tCsrRoamProfile));
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ status = csrRoamCopyProfile(pMac, pScanCmd->u.scanCmd.pToRoamProfile, pProfile);
+ if(!HAL_STATUS_SUCCESS(status))
+ break;
+ pScanCmd->u.scanCmd.roamId = roamId;
+ pScanCmd->command = eSmeCommandScan;
+ pScanCmd->sessionId = (tANI_U8)sessionId;
+ pScanCmd->u.scanCmd.callback = NULL;
+ pScanCmd->u.scanCmd.pContext = NULL;
+ pScanCmd->u.scanCmd.reason = eCsrScanForSsid;
+ pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around
+ palZeroMemory(pMac->hHdd, &pScanCmd->u.scanCmd.u.scanRequest, sizeof(tCsrScanRequest));
+ pScanCmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ pScanCmd->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime;
+ pScanCmd->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime;
+ pScanCmd->u.scanCmd.u.scanRequest.BSSType = pProfile->BSSType;
+ pScanCmd->u.scanCmd.u.scanRequest.uIEFieldLen = 0;
+ if(pProfile->BSSIDs.numOfBSSIDs == 1)
+ {
+ palCopyMemory(pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.bssid, pProfile->BSSIDs.bssid, sizeof(tCsrBssid));
+ }
+ else
+ {
+ palCopyMemory(pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.bssid, bAddr, 6);
+ }
+ if(pProfile->ChannelInfo.numOfChannels)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, sizeof(*pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList) * pProfile->ChannelInfo.numOfChannels);
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = 0;
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ csrRoamIsChannelValid(pMac, pProfile->ChannelInfo.ChannelList[0]);
+ for(index = 0; index < pProfile->ChannelInfo.numOfChannels; index++)
+ {
+ if(csrRoamIsValidChannel(pMac, pProfile->ChannelInfo.ChannelList[index]))
+ {
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels]
+ = pProfile->ChannelInfo.ChannelList[index];
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels++;
+ }
+ else
+ {
+ smsLog(pMac, LOGW, FL("process a channel (%d) that is invalid\n"), pProfile->ChannelInfo.ChannelList[index]);
+ }
+
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ else
+ {
+ pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = 0;
+ }
+ if(pProfile->SSIDs.numOfSSIDs)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pScanCmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList,
+ pProfile->SSIDs.numOfSSIDs * sizeof(tCsrSSIDInfo));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ break;
+ }
+ pScanCmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = 1;
+ palCopyMemory(pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList, pProfile->SSIDs.SSIDList,
+ sizeof(tCsrSSIDInfo));
+ }
+ //Start process the command
+ status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ break;
+ }
+ }while(0);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ if(pScanCmd)
+ {
+ csrReleaseCommandScan(pMac, pScanCmd);
+ //TODO:free the memory that is allocated in this function
+ }
+ csrRoamCallCallback(pMac, sessionId, NULL, roamId, eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE);
+ }
+ }//valid
+ else
+ {
+ smsLog(pMac, LOGE, FL("cannot scan because scanEnable (%d) or numSSID (%d) is invalid\n"),
+ pMac->scan.fScanEnable, pProfile->SSIDs.numOfSSIDs);
+ }
+
+ return (status);
+}
+
+
+//Issue a scan base on the new capability infomation
+//This should only happen when the associated AP changes its capability.
+//After this scan is done, CSR reroams base on the new scan results
+eHalStatus csrScanForCapabilityChange(tpAniSirGlobal pMac, tSirSmeApNewCaps *pNewCaps)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tSmeCmd *pScanCmd = NULL;
+
+ if(pNewCaps)
+ {
+ do
+ {
+ pScanCmd = csrGetCommandBuffer(pMac);
+ if(!pScanCmd)
+ {
+ smsLog(pMac, LOGE, FL("failed to allocate command buffer\n"));
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ palZeroMemory(pMac->hHdd, &pScanCmd->u.scanCmd, sizeof(tScanCmd));
+ status = eHAL_STATUS_SUCCESS;
+ pScanCmd->u.scanCmd.roamId = 0;
+ pScanCmd->command = eSmeCommandScan;
+ pScanCmd->u.scanCmd.callback = NULL;
+ pScanCmd->u.scanCmd.pContext = NULL;
+ pScanCmd->u.scanCmd.reason = eCsrScanForCapsChange;
+ pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around
+ status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE);
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+ break;
+ }
+ }while(0);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ if(pScanCmd)
+ {
+ csrReleaseCommandScan(pMac, pScanCmd);
+ }
+ }
+ }
+
+ return (status);
+}
+
+
+
+void csrInitBGScanChannelList(tpAniSirGlobal pMac)
+{
+ tANI_U32 len = CSR_MIN(sizeof(pMac->roam.validChannelList), sizeof(pMac->scan.bgScanChannelList));
+
+ palZeroMemory(pMac->hHdd, pMac->scan.bgScanChannelList, len);
+ pMac->scan.numBGScanChannel = 0;
+
+ if(HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, pMac->roam.validChannelList, &len)))
+ {
+ pMac->roam.numValidChannels = len;
+ pMac->scan.numBGScanChannel = (tANI_U8)CSR_MIN(len, WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN);
+ palCopyMemory(pMac->hHdd, pMac->scan.bgScanChannelList, pMac->roam.validChannelList, pMac->scan.numBGScanChannel);
+ csrSetBGScanChannelList(pMac, pMac->scan.bgScanChannelList, pMac->scan.numBGScanChannel);
+ }
+}
+
+
+//This function return TRUE if background scan channel list is adjusted.
+//this function will only shrink the background scan channel list
+tANI_BOOLEAN csrAdjustBGScanChannelList(tpAniSirGlobal pMac, tANI_U8 *pChannelList, tANI_U8 NumChannels,
+ tANI_U8 *pAdjustChannels, tANI_U8 *pNumAdjustChannels)
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
+ tANI_U8 i, j, count = *pNumAdjustChannels;
+
+ i = 0;
+ while(i < count)
+ {
+ for(j = 0; j < NumChannels; j++)
+ {
+ if(pChannelList[j] == pAdjustChannels[i])
+ break;
+ }
+ if(j == NumChannels)
+ {
+ //This channel is not in the list, remove it
+ fRet = eANI_BOOLEAN_TRUE;
+ count--;
+ if(count - i)
+ {
+ palCopyMemory(pMac->hHdd, &pAdjustChannels[i], &pAdjustChannels[i+1], count - i);
+ }
+ else
+ {
+ //already remove the last one. Done.
+ break;
+ }
+ }
+ else
+ {
+ i++;
+ }
+ }//while(i<count)
+ *pNumAdjustChannels = count;
+
+ return (fRet);
+}
+
+
+//Get the list of the base channels to scan for passively 11d info
+eHalStatus csrScanGetSupportedChannels( tpAniSirGlobal pMac )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ int n = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+
+ status = vos_nv_getSupportedChannels( pMac->scan.baseChannels.channelList, &n, NULL, NULL );
+ if( HAL_STATUS_SUCCESS(status) )
+ {
+ pMac->scan.baseChannels.numChannels = (tANI_U8)n;
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" failed\n") );
+ pMac->scan.baseChannels.numChannels = 0;
+ }
+
+ return ( status );
+}
+
+//This function use the input pChannelList to validate the current saved channel list
+eHalStatus csrSetBGScanChannelList( tpAniSirGlobal pMac, tANI_U8 *pAdjustChannels, tANI_U8 NumAdjustChannels)
+{
+ tANI_U32 dataLen = sizeof( tANI_U8 ) * NumAdjustChannels;
+
+ return (ccmCfgSetStr(pMac, WNI_CFG_BG_SCAN_CHANNEL_LIST, pAdjustChannels, dataLen, NULL, eANI_BOOLEAN_FALSE));
+}
+
+
+void csrSetCfgValidChannelList( tpAniSirGlobal pMac, tANI_U8 *pChannelList, tANI_U8 NumChannels )
+{
+ tANI_U32 dataLen = sizeof( tANI_U8 ) * NumChannels;
+
+
+ ccmCfgSetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, pChannelList, dataLen, NULL, eANI_BOOLEAN_FALSE);
+
+ return;
+}
+
+
+
+/*
+ * The Tx power limits are saved in the cfg for future usage.
+ */
+void csrSaveTxPowerToCfg( tpAniSirGlobal pMac, tDblLinkList *pList, tANI_U32 cfgId )
+{
+ tListElem *pEntry;
+ tANI_U32 cbLen = 0, dataLen;
+ tCsrChannelPowerInfo *pChannelSet;
+ tANI_U32 idx;
+ tSirMacChanInfo *pChannelPowerSet;
+ tANI_U8 *pBuf = NULL;
+
+ //allocate maximum space for all channels
+ dataLen = WNI_CFG_VALID_CHANNEL_LIST_LEN * sizeof(tSirMacChanInfo);
+ if(HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd, (void **)&pBuf, dataLen)))
+ {
+ palZeroMemory(pMac->hHdd, pBuf, dataLen);
+ pChannelPowerSet = (tSirMacChanInfo *)(pBuf);
+
+ pEntry = csrLLPeekHead( pList, LL_ACCESS_LOCK );
+ // write the tuples (startChan, numChan, txPower) for each channel found in the channel power list.
+ while( pEntry )
+ {
+ pChannelSet = GET_BASE_ADDR( pEntry, tCsrChannelPowerInfo, link );
+ if ( 1 != pChannelSet->interChannelOffset )
+ {
+ // we keep the 5G channel sets internally with an interchannel offset of 4. Expand these
+ // to the right format... (inter channel offset of 1 is the only option for the triplets
+ // that 11d advertises.
+ if ((cbLen + (pChannelSet->numChannels * sizeof(tSirMacChanInfo))) >= dataLen)
+ {
+ // expanding this entry will overflow our allocation
+ smsLog(pMac, LOGE,
+ "%s: Buffer overflow, start %d, num %d, offset %d",
+ __FUNCTION__,
+ pChannelSet->firstChannel,
+ pChannelSet->numChannels,
+ pChannelSet->interChannelOffset);
+ break;
+ }
+
+ for( idx = 0; idx < pChannelSet->numChannels; idx++ )
+ {
+ pChannelPowerSet->firstChanNum = (tSirMacChanNum)(pChannelSet->firstChannel + ( idx * pChannelSet->interChannelOffset ));
+ smsLog(pMac, LOG3, " Setting Channel Number %d\n", pChannelPowerSet->firstChanNum);
+ pChannelPowerSet->numChannels = 1;
+#ifdef WLAN_SOFTAP_FEATURE
+ pChannelPowerSet->maxTxPower = CSR_ROAM_MIN( pChannelSet->txPower, pMac->roam.configParam.nTxPowerCap );
+#else
+ pChannelPowerSet->maxTxPower = pChannelSet->txPower;
+#endif
+ smsLog(pMac, LOG3, " Setting Max Transmit Power %d\n", pChannelPowerSet->maxTxPower);
+ cbLen += sizeof( tSirMacChanInfo );
+ pChannelPowerSet++;
+ }
+ }
+ else
+ {
+ if (cbLen >= dataLen)
+ {
+ // this entry will overflow our allocation
+ smsLog(pMac, LOGE,
+ "%s: Buffer overflow, start %d, num %d, offset %d",
+ __FUNCTION__,
+ pChannelSet->firstChannel,
+ pChannelSet->numChannels,
+ pChannelSet->interChannelOffset);
+ break;
+ }
+ pChannelPowerSet->firstChanNum = pChannelSet->firstChannel;
+ smsLog(pMac, LOG3, " Setting Channel Number %d\n", pChannelPowerSet->firstChanNum);
+ pChannelPowerSet->numChannels = pChannelSet->numChannels;
+#ifdef WLAN_SOFTAP_FEATURE
+ pChannelPowerSet->maxTxPower = CSR_ROAM_MIN( pChannelSet->txPower, pMac->roam.configParam.nTxPowerCap );
+#else
+ pChannelPowerSet->maxTxPower = pChannelSet->txPower;
+#endif
+ smsLog(pMac, LOG3, " Setting Max Transmit Power %d, nTxPower %d\n", pChannelPowerSet->maxTxPower,pMac->roam.configParam.nTxPowerCap );
+
+
+ cbLen += sizeof( tSirMacChanInfo );
+ pChannelPowerSet++;
+ }
+
+ pEntry = csrLLNext( pList, pEntry, LL_ACCESS_LOCK );
+ }
+
+ if(cbLen)
+ {
+ ccmCfgSetStr(pMac, cfgId, (tANI_U8 *)pBuf, cbLen, NULL, eANI_BOOLEAN_FALSE);
+ }
+ palFreeMemory( pMac->hHdd, pBuf );
+ }//Allocate memory
+}
+
+
+void csrSetCfgCountryCode( tpAniSirGlobal pMac, tANI_U8 *countryCode )
+{
+ tANI_U8 cc[WNI_CFG_COUNTRY_CODE_LEN];
+ ///v_REGDOMAIN_t DomainId;
+
+ smsLog( pMac, LOG3, "Setting Country Code in Cfg from csrSetCfgCountryCode %s\n",countryCode );
+ palCopyMemory( pMac->hHdd, cc, countryCode, WNI_CFG_COUNTRY_CODE_LEN );
+
+ // don't program the bogus country codes that we created for Korea in the MAC. if we see
+ // the bogus country codes, program the MAC with the right country code.
+ if ( ( 'K' == countryCode[ 0 ] && '1' == countryCode[ 1 ] ) ||
+ ( 'K' == countryCode[ 0 ] && '2' == countryCode[ 1 ] ) ||
+ ( 'K' == countryCode[ 0 ] && '3' == countryCode[ 1 ] ) ||
+ ( 'K' == countryCode[ 0 ] && '4' == countryCode[ 1 ] ) )
+ {
+ // replace the alternate Korea country codes, 'K1', 'K2', .. with 'KR' for Korea
+ cc[ 1 ] = 'R';
+ }
+ ccmCfgSetStr(pMac, WNI_CFG_COUNTRY_CODE, cc, WNI_CFG_COUNTRY_CODE_LEN, NULL, eANI_BOOLEAN_FALSE);
+
+ //Need to let HALPHY know about the current domain so it can apply some
+ //domain-specific settings (TX filter...)
+ /*if(HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry(pMac, cc, &DomainId)))
+ {
+ halPhySetRegDomain(pMac, DomainId);
+ }*/
+}
+
+
+
+eHalStatus csrGetCountryCode(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U8 *pbLen)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tANI_U32 len;
+
+ if(pBuf && pbLen && (*pbLen >= WNI_CFG_COUNTRY_CODE_LEN))
+ {
+ len = *pbLen;
+ status = ccmCfgGetStr(pMac, WNI_CFG_COUNTRY_CODE, pBuf, &len);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ *pbLen = (tANI_U8)len;
+ }
+ }
+
+ return (status);
+}
+
+
+void csrSetCfgScanControlList( tpAniSirGlobal pMac, tANI_U8 *countryCode, tCsrChannel *pChannelList )
+{
+ tANI_U8 i, j;
+ tANI_BOOLEAN found=FALSE;
+ tANI_U8 *pControlList = NULL;
+ tANI_U32 len = WNI_CFG_SCAN_CONTROL_LIST_LEN;
+
+ if(HAL_STATUS_SUCCESS(palAllocateMemory(pMac->hHdd, (void **)&pControlList, WNI_CFG_SCAN_CONTROL_LIST_LEN)))
+ {
+ palZeroMemory(pMac->hHdd, (void *)pControlList, WNI_CFG_SCAN_CONTROL_LIST_LEN);
+ if(HAL_STATUS_SUCCESS(ccmCfgGetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, pControlList, &len)))
+ {
+ for (i = 0; i < pChannelList->numChannels; i++)
+ {
+ for (j = 0; j < len; j += 2)
+ {
+ if (pControlList[j] == pChannelList->channelList[i])
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found) // insert a pair(channel#, flag)
+ {
+ if (CSR_IS_CHANNEL_5GHZ(pControlList[j]))
+ {
+ pControlList[j+1] = csrGetScanType(pMac, pControlList[j]);
+ }
+ else
+ {
+ pControlList[j+1] = eSIR_ACTIVE_SCAN;
+ }
+
+ found = FALSE; // reset the flag
+ }
+
+ }
+
+ ccmCfgSetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, pControlList, len, NULL, eANI_BOOLEAN_FALSE);
+ }//Successfully getting scan control list
+ palFreeMemory(pMac->hHdd, pControlList);
+ }//AllocateMemory
+}
+
+
+//if bgPeriod is 0, background scan is disabled. It is in millisecond units
+eHalStatus csrSetCfgBackgroundScanPeriod(tpAniSirGlobal pMac, tANI_U32 bgPeriod)
+{
+ return (ccmCfgSetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, bgPeriod, (tCcmCfgSetCallback) csrScanCcmCfgSetCallback, eANI_BOOLEAN_FALSE));
+}
+
+
+void csrScanCcmCfgSetCallback(tHalHandle hHal, tANI_S32 result)
+{
+ tListElem *pEntry = NULL;
+ tSmeCmd *pCommand = NULL;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
+ if ( pEntry )
+ {
+ pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ if ( eSmeCommandScan == pCommand->command )
+ {
+ eCsrScanStatus scanStatus = (CCM_IS_RESULT_SUCCESS(result)) ? eCSR_SCAN_SUCCESS : eCSR_SCAN_FAILURE;
+ csrReleaseScanCommand(pMac, pCommand, scanStatus);
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "CSR: Scan Completion called but SCAN command is not ACTIVE ...\n" );
+ }
+ }
+ smeProcessPendingQueue( pMac );
+}
+
+eHalStatus csrProcessSetBGScanParam(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+ eHalStatus status;
+ tCsrBGScanRequest *pScanReq = &pCommand->u.scanCmd.u.bgScanRequest;
+ tANI_U32 dataLen = sizeof( tANI_U8 ) * pScanReq->ChannelInfo.numOfChannels;
+
+ //***setcfg for background scan channel list
+ status = ccmCfgSetInt(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, pScanReq->minChnTime, NULL, eANI_BOOLEAN_FALSE);
+ status = ccmCfgSetInt(pMac, WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME, pScanReq->maxChnTime, NULL, eANI_BOOLEAN_FALSE);
+ //Not set the background scan interval if not connected because bd scan should not be run if not connected
+ if(!csrIsAllSessionDisconnected(pMac))
+ {
+ //If disbaling BG scan here, we need to stop aging as well
+ if(pScanReq->scanInterval == 0)
+ {
+ //Stop aging because no new result is coming in
+ csrScanStopResultAgingTimer(pMac);
+ }
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+ {
+ vos_log_scan_pkt_type *pScanLog = NULL;
+
+ WLAN_VOS_DIAG_LOG_ALLOC(pScanLog, vos_log_scan_pkt_type, LOG_WLAN_SCAN_C);
+ if(pScanLog)
+ {
+ pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_REQ;
+ pScanLog->minChnTime = (v_U8_t)pScanReq->minChnTime;
+ pScanLog->maxChnTime = (v_U8_t)pScanReq->maxChnTime;
+ pScanLog->timeBetweenBgScan = (v_U8_t)pScanReq->scanInterval;
+ pScanLog->numChannel = pScanReq->ChannelInfo.numOfChannels;
+ if(pScanLog->numChannel && (pScanLog->numChannel < VOS_LOG_MAX_NUM_CHANNEL))
+ {
+ palCopyMemory(pMac->hHdd, pScanLog->channels, pScanReq->ChannelInfo.ChannelList,
+ pScanLog->numChannel);
+ }
+ WLAN_VOS_DIAG_LOG_REPORT(pScanLog);
+ }
+ }
+#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+
+ status = ccmCfgSetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, pScanReq->scanInterval, NULL, eANI_BOOLEAN_FALSE);
+ }
+ else
+ {
+ //No need to stop aging because IDLE scan is still running
+ status = ccmCfgSetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, 0, NULL, eANI_BOOLEAN_FALSE);
+ }
+
+ if(pScanReq->SSID.length > WNI_CFG_SSID_LEN)
+ {
+ pScanReq->SSID.length = WNI_CFG_SSID_LEN;
+ }
+
+ status = ccmCfgSetStr(pMac, WNI_CFG_BG_SCAN_CHANNEL_LIST, pScanReq->ChannelInfo.ChannelList, dataLen, NULL, eANI_BOOLEAN_FALSE);
+ status = ccmCfgSetStr(pMac, WNI_CFG_SSID, (tANI_U8 *)pScanReq->SSID.ssId, pScanReq->SSID.length, NULL, eANI_BOOLEAN_FALSE);
+
+
+
+ return (status);
+}
+
+
+eHalStatus csrScanAbortMacScan(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirMbMsg *pMsg;
+ tANI_U16 msgLen;
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+
+#ifdef WLAN_AP_STA_CONCURRENCY
+ csrLLLock(&pMac->scan.scanCmdPendingList);
+ while( NULL != ( pEntry = csrLLRemoveHead( &pMac->scan.scanCmdPendingList, LL_ACCESS_NOLOCK) ) )
+ {
+
+ pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ csrAbortCommand( pMac, pCommand, eANI_BOOLEAN_FALSE);
+ }
+ csrLLUnlock(&pMac->scan.scanCmdPendingList);
+#endif
+
+ pMac->scan.fDropScanCmd = eANI_BOOLEAN_TRUE;
+ csrRemoveCmdFromPendingList( pMac, &pMac->roam.roamCmdPendingList, eSmeCommandScan);
+ csrRemoveCmdFromPendingList( pMac, &pMac->sme.smeCmdPendingList, eSmeCommandScan);
+ pMac->scan.fDropScanCmd = eANI_BOOLEAN_FALSE;
+
+ //We need to abort scan only if we are scanning
+ if(NULL != (pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK)))
+ {
+ pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ if(eSmeCommandScan == pCommand->command)
+ {
+ msgLen = (tANI_U16)(sizeof( tSirMbMsg ));
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, (void *)pMsg, msgLen);
+ pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_ABORT_IND);
+ pMsg->msgLen = pal_cpu_to_be16(msgLen);
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+ }
+ }
+
+ return( status );
+}
+
+void csrRemoveCmdFromPendingList(tpAniSirGlobal pMac, tDblLinkList *pList,
+ eSmeCommandType commandType )
+{
+ tDblLinkList localList;
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+ tListElem *pEntryToRemove;
+
+ 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);
+ if( !csrLLIsListEmpty( pList, LL_ACCESS_NOLOCK ) )
+ {
+ pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK);
+
+ // Have to make sure we don't loop back to the head of the list, which will
+ // happen if the entry is NOT on the list...
+ while( pEntry )
+ {
+ pEntryToRemove = pEntry;
+ pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK);
+ pCommand = GET_BASE_ADDR( pEntryToRemove, tSmeCmd, Link );
+ if ( pCommand->command == commandType )
+ {
+ // Remove that entry only
+ if(csrLLRemoveEntry( pList, pEntryToRemove, LL_ACCESS_NOLOCK))
+ {
+ csrLLInsertTail(&localList, pEntryToRemove, LL_ACCESS_NOLOCK);
+ }
+ }
+ }
+
+
+ }
+ csrLLUnlock(pList);
+
+ while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) )
+ {
+ pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ csrAbortCommand( pMac, pCommand, eANI_BOOLEAN_FALSE);
+ }
+ csrLLClose(&localList);
+
+}
+
+
+eHalStatus csrScanAbortMacScanNotForConnect(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ if( !csrIsScanForRoamCommandActive( pMac ) )
+ {
+ //Only abort the scan if it is not used for other roam/connect purpose
+ status = csrScanAbortMacScan(pMac);
+ }
+
+ return (status);
+}
+
+
+eHalStatus csrScanGetScanChannelInfo(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirMbMsg *pMsg;
+ tANI_U16 msgLen;
+
+ msgLen = (tANI_U16)(sizeof( tSirMbMsg ));
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+ pMsg->type = eWNI_SME_GET_SCANNED_CHANNEL_REQ;
+ pMsg->msgLen = msgLen;
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+
+ return( status );
+}
+
+tANI_BOOLEAN csrRoamIsValidChannel( tpAniSirGlobal pMac, tANI_U8 channel )
+{
+ tANI_BOOLEAN fValid = FALSE;
+ tANI_U32 idxValidChannels;
+ tANI_U32 len = pMac->roam.numValidChannels;
+
+ for ( idxValidChannels = 0; ( idxValidChannels < len ); idxValidChannels++ )
+ {
+ if ( channel == pMac->roam.validChannelList[ idxValidChannels ] )
+ {
+ fValid = TRUE;
+ break;
+ }
+ }
+
+ return fValid;
+}
+
+
+
+
diff --git a/CORE/SME/src/csr/csrCmdProcess.c b/CORE/SME/src/csr/csrCmdProcess.c
new file mode 100644
index 0000000..cd99696
--- /dev/null
+++ b/CORE/SME/src/csr/csrCmdProcess.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+ \file csrCmdProcess.c
+
+ Implementation for processing various commands.
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+
+ ========================================================================== */
+
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include "halInternal.h" //Check if the below include of aniGobal.h is sufficient for Volans too.
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include "aniGlobal.h"
+#endif
+
+#include "palApi.h"
+#include "csrInsideApi.h"
+#include "smeInside.h"
+#include "smsDebug.h"
+
+
+
+
+eHalStatus csrMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirSmeRsp *pSmeRsp = (tSirSmeRsp *)pMsgBuf;
+
+ smsLog( pMac, LOG2, " Message %d[0x%04X] received in curState %d and substate %d\n",
+ pSmeRsp->messageType, pSmeRsp->messageType,
+ pMac->roam.curState[pSmeRsp->sessionId],
+ pMac->roam.curSubState[pSmeRsp->sessionId] );
+
+ // Process the message based on the state of the roaming states...
+
+#if defined( ANI_RTT_DEBUG )
+ if(!pAdapter->fRttModeEnabled)
+ {
+#endif//RTT
+ switch (pMac->roam.curState[pSmeRsp->sessionId])
+ {
+ case eCSR_ROAMING_STATE_SCANNING:
+ {
+ //Are we in scan state
+#if defined( ANI_EMUL_ASSOC )
+ emulScanningStateMsgProcessor( pAdapter, pMBBufHdr );
+#else
+ status = csrScanningStateMsgProcessor(pMac, pMsgBuf);
+#endif
+ break;
+ }
+
+ case eCSR_ROAMING_STATE_JOINED:
+ {
+ //are we in joined state
+ csrRoamJoinedStateMsgProcessor( pMac, pMsgBuf );
+ break;
+ }
+
+ case eCSR_ROAMING_STATE_JOINING:
+ {
+ //are we in roaming states
+#if defined( ANI_EMUL_ASSOC )
+ emulRoamingStateMsgProcessor( pAdapter, pMBBufHdr );
+#endif
+ csrRoamingStateMsgProcessor( pMac, pMsgBuf );
+ break;
+ }
+
+ //For all other messages, we ignore it
+ default:
+ {
+ /*To work-around an issue where checking for set/remove key base on connection state is no longer
+ * workable due to failure or finding the condition meets both SAP and infra/IBSS requirement.
+ */
+ if( (eWNI_SME_SETCONTEXT_RSP == pSmeRsp->messageType) ||
+ (eWNI_SME_REMOVEKEY_RSP == pSmeRsp->messageType) )
+ {
+ smsLog(pMac, LOGW, FL(" handling msg 0x%X CSR state is %d\n"), pSmeRsp->messageType, pMac->roam.curState[pSmeRsp->sessionId]);
+ csrRoamCheckForLinkStatusChange(pMac, pSmeRsp);
+ }
+ else
+ {
+ smsLog(pMac, LOGW, " Message 0x%04X is not handled by CSR. CSR state is %d \n", pSmeRsp->messageType, pMac->roam.curState[pSmeRsp->sessionId]);
+ }
+ break;
+ }
+
+ }//switch
+
+#if defined( ANI_RTT_DEBUG )
+ }
+#endif//RTT
+
+ return (status);
+}
+
+
+
+tANI_BOOLEAN csrCheckPSReady(void *pv)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pv );
+
+ VOS_ASSERT( pMac->roam.sPendingCommands >= 0 );
+ return (pMac->roam.sPendingCommands == 0);
+}
+
+
+void csrFullPowerCallback(void *pv, eHalStatus status)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pv );
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+
+ (void)status;
+
+ while( NULL != ( pEntry = csrLLRemoveHead( &pMac->roam.roamCmdPendingList, eANI_BOOLEAN_TRUE ) ) )
+ {
+ pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ smePushCommand( pMac, pCommand, eANI_BOOLEAN_FALSE );
+ }
+
+}
+
+
diff --git a/CORE/SME/src/csr/csrInsideApi.h b/CORE/SME/src/csr/csrInsideApi.h
new file mode 100644
index 0000000..526f680
--- /dev/null
+++ b/CORE/SME/src/csr/csrInsideApi.h
@@ -0,0 +1,918 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+
+
+ \file csrInsideApi.h
+
+ Define interface only used by CSR.
+
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+ ========================================================================== */
+#ifndef CSR_INSIDE_API_H__
+#define CSR_INSIDE_API_H__
+
+
+#include "csrSupport.h"
+#include "smeInside.h"
+#include "vos_nvitem.h"
+
+#define CSR_PASSIVE_MAX_CHANNEL_TIME 110
+#define CSR_PASSIVE_MIN_CHANNEL_TIME 60
+
+#define CSR_ACTIVE_MAX_CHANNEL_TIME 40
+#define CSR_ACTIVE_MIN_CHANNEL_TIME 20
+
+#ifdef WLAN_AP_STA_CONCURRENCY
+#define CSR_ACTIVE_MAX_CHANNEL_TIME_CONC 27
+#define CSR_ACTIVE_MIN_CHANNEL_TIME_CONC 20
+#endif
+
+#define CSR_MAX_NUM_SUPPORTED_CHANNELS 55
+
+#define CSR_MAX_BSS_SUPPORT 100
+
+//This number minus 1 means the number of times a channel is scanned before a BSS is remvoed from
+//cache scan result
+#define CSR_AGING_COUNT 3
+//The following defines are used by palTimer
+//This is used for palTimer when request to imps fails
+#define CSR_IDLE_SCAN_WAIT_TIME (1 * PAL_TIMER_TO_SEC_UNIT) //1 second
+//This is used for palTimer when imps ps is disabled
+//This number shall not be smaller than 5-6 seconds in general because a full scan may take 3-4 seconds
+#define CSR_IDLE_SCAN_NO_PS_INTERVAL (10 * PAL_TIMER_TO_SEC_UNIT) //10 second
+#define CSR_IDLE_SCAN_NO_PS_INTERVAL_MIN (5 * PAL_TIMER_TO_SEC_UNIT)
+#define CSR_SCAN_GET_RESULT_INTERVAL (5 * PAL_TIMER_TO_SEC_UNIT) //5 seconds
+#ifdef WLAN_AP_STA_CONCURRENCY
+#define CSR_SCAN_STAAP_CONC_INTERVAL (20 * PAL_TIMER_TO_MS_UNIT) //20 milliseconds
+#endif
+#define CSR_MIC_ERROR_TIMEOUT (60 * PAL_TIMER_TO_SEC_UNIT) //60 seconds
+#define CSR_TKIP_COUNTER_MEASURE_TIMEOUT (60 * PAL_TIMER_TO_SEC_UNIT) //60 seconds
+#define CSR_SCAN_RESULT_AGING_INTERVAL (5 * PAL_TIMER_TO_SEC_UNIT) //5 seconds
+//the following defines are NOT used by palTimer
+#define CSR_SCAN_AGING_TIME_NOT_CONNECT_NO_PS 50 //50 seconds
+#define CSR_SCAN_AGING_TIME_NOT_CONNECT_W_PS 300 //300 seconds
+#define CSR_SCAN_AGING_TIME_CONNECT_NO_PS 150 //150 seconds
+#define CSR_SCAN_AGING_TIME_CONNECT_W_PS 600 //600 seconds
+#define CSR_JOIN_FAILURE_TIMEOUT_DEFAULT ( 3000 )
+#define CSR_JOIN_FAILURE_TIMEOUT_MIN (300) //minimal value
+//These are going against the signed RSSI (tANI_S8) so it is between -+127
+#define CSR_BEST_RSSI_VALUE (-30) //RSSI >= this is in CAT4
+#define CSR_DEFAULT_RSSI_DB_GAP 30 //every 30 dbm for one category
+#define CSR_BSS_CAP_VALUE_NONE 0 //not much value
+#define CSR_BSS_CAP_VALUE_HT 2
+#define CSR_BSS_CAP_VALUE_WMM 1
+#define CSR_BSS_CAP_VALUE_UAPSD 1
+#define CSR_DEFAULT_ROAMING_TIME 10 //10 seconds
+#define CSR_ROAM_MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+#define CSR_ROAM_MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+
+#ifdef FEATURE_WLAN_BTAMP_UT_RF
+#define CSR_JOIN_MAX_RETRY_COUNT 10
+#define CSR_JOIN_RETRY_TIMEOUT_PERIOD ( 1 * PAL_TIMER_TO_SEC_UNIT ) // 1 second
+#endif
+
+typedef enum
+{
+ eCsrNextScanNothing,
+ eCsrNextLostLinkScan1Success,
+ eCsrNextLostLinkScan1Failed,
+ eCsrNextLostLinkScan2Success,
+ eCsrNextLostLinkScan2Failed,
+ eCsrNextLostLinkScan3Success,
+ eCsrNexteScanForSsidSuccess,
+ eCsrNextLostLinkScan3Failed,
+ eCsrNext11dScan1Failure,
+ eCsrNext11dScan1Success,
+ eCsrNext11dScan2Failure,
+ eCsrNext11dScan2Success,
+ eCsrNext11dScanComplete,
+ eCsrNexteScanForSsidFailure,
+ eCsrNextIdleScanComplete,
+ eCsrNextCapChangeScanComplete,
+
+}eCsrScanCompleteNextCommand;
+
+typedef enum
+{
+ eCsrJoinSuccess,
+ eCsrJoinFailure,
+ eCsrReassocSuccess,
+ eCsrReassocFailure,
+ eCsrNothingToJoin,
+ eCsrStartBssSuccess,
+ eCsrStartBssFailure,
+ eCsrSilentlyStopRoaming,
+ eCsrSilentlyStopRoamingSaveState,
+ eCsrJoinWdsFailure,
+
+}eCsrRoamCompleteResult;
+
+typedef struct tagScanReqParam
+{
+ tANI_U8 bReturnAfter1stMatch;
+ tANI_U8 fUniqueResult;
+ tANI_U8 freshScan;
+ tANI_U8 hiddenSsid;
+ tANI_U8 reserved;
+}tScanReqParam;
+
+typedef struct tagCsrScanResult
+{
+ tListElem Link;
+ tANI_S32 AgingCount; //This BSS is removed when it reaches 0 or less
+ tANI_U32 preferValue; //The bigger the number, the better the BSS. This value override capValue
+ tANI_U32 capValue; //The biggger the better. This value is in use only if we have equal preferValue
+ //This member must be the last in the structure because the end of tSirBssDescription (inside) is an
+ // array with nonknown size at this time
+
+ eCsrEncryptionType ucEncryptionType; //Preferred Encryption type that matched with profile.
+ eCsrEncryptionType mcEncryptionType;
+ eCsrAuthType authType; //Preferred auth type that matched with the profile.
+
+ tCsrScanResultInfo Result;
+}tCsrScanResult;
+
+typedef struct
+{
+ tDblLinkList List;
+ tListElem *pCurEntry;
+}tScanResultList;
+
+
+
+
+#define CSR_IS_ROAM_REASON( pCmd, reason ) ( (reason) == (pCmd)->roamCmd.roamReason )
+#define CSR_IS_BETTER_PREFER_VALUE(v1, v2) ((v1) > (v2))
+#define CSR_IS_EQUAL_PREFER_VALUE(v1, v2) ((v1) == (v2))
+#define CSR_IS_BETTER_CAP_VALUE(v1, v2) ((v1) > (v2))
+#define CSR_IS_ENC_TYPE_STATIC( encType ) ( ( eCSR_ENCRYPT_TYPE_NONE == (encType) ) || \
+ ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == (encType) ) || \
+ ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == (encType) ) )
+#define CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) ( CSR_IS_ROAM_JOINED( pMac, sessionId ) && CSR_IS_ROAM_SUBSTATE_WAITFORKEY( pMac, sessionId ) )
+//WIFI has a test case for not using HT rates with TKIP as encryption
+//We may need to add WEP but for now, TKIP only.
+
+#define CSR_IS_11n_ALLOWED( encType ) (( eCSR_ENCRYPT_TYPE_TKIP != (encType) ) && \
+ ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY != (encType) ) && \
+ ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY != (encType) ) && \
+ ( eCSR_ENCRYPT_TYPE_WEP40 != (encType) ) && \
+ ( eCSR_ENCRYPT_TYPE_WEP104 != (encType) ) )
+
+eCsrRoamState csrRoamStateChange( tpAniSirGlobal pMac, eCsrRoamState NewRoamState, tANI_U8 sessionId);
+eHalStatus csrScanningStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf );
+void csrRoamingStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf );
+void csrRoamJoinedStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf );
+tANI_BOOLEAN csrScanComplete( tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp );
+void csrReleaseCommandRoam(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+void csrReleaseCommandScan(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+void csrReleaseCommandWmStatusChange(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+//pIes2 can be NULL
+tANI_BOOLEAN csrIsDuplicateBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc1,
+ tSirBssDescription *pSirBssDesc2, tDot11fBeaconIEs *pIes2 );
+eHalStatus csrRoamSaveConnectedBssDesc( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDesc );
+tANI_BOOLEAN csrIsNetworkTypeEqual( tSirBssDescription *pSirBssDesc1, tSirBssDescription *pSirBssDesc2 );
+eHalStatus csrScanSmeScanResponse( tpAniSirGlobal pMac, void *pMsgBuf );
+/*
+ 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 csrRoamCopyProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pDstProfile, tCsrRoamProfile *pSrcProfile);
+eHalStatus csrRoamStart(tpAniSirGlobal pMac);
+void csrRoamStop(tpAniSirGlobal pMac, tANI_U32 sessionId);
+void csrRoamStartMICFailureTimer(tpAniSirGlobal pMac);
+void csrRoamStopMICFailureTimer(tpAniSirGlobal pMac);
+void csrRoamStartTKIPCounterMeasureTimer(tpAniSirGlobal pMac);
+void csrRoamStopTKIPCounterMeasureTimer(tpAniSirGlobal pMac);
+
+eHalStatus csrScanOpen(tpAniSirGlobal pMac);
+eHalStatus csrScanClose(tpAniSirGlobal pMac);
+eHalStatus csrScanRequestLostLink1( tpAniSirGlobal pMac, tANI_U32 sessionId );
+eHalStatus csrScanRequestLostLink2( tpAniSirGlobal pMac, tANI_U32 sessionId );
+eHalStatus csrScanRequestLostLink3( tpAniSirGlobal pMac, tANI_U32 sessionId );
+eHalStatus csrScanHandleFailedLostlink1(tpAniSirGlobal pMac, tANI_U32 sessionId);
+eHalStatus csrScanHandleFailedLostlink2(tpAniSirGlobal pMac, tANI_U32 sessionId);
+eHalStatus csrScanHandleFailedLostlink3(tpAniSirGlobal pMac, tANI_U32 sessionId);
+tCsrScanResult *csrScanAppendBssDescription( tpAniSirGlobal pMac,
+ tSirBssDescription *pSirBssDescription,
+ tDot11fBeaconIEs *pIes);
+void csrScanCallCallback(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus);
+eHalStatus csrScanCopyRequest(tpAniSirGlobal pMac, tCsrScanRequest *pDstReq, tCsrScanRequest *pSrcReq);
+eHalStatus csrScanFreeRequest(tpAniSirGlobal pMac, tCsrScanRequest *pReq);
+eHalStatus csrScanCopyResultList(tpAniSirGlobal pMac, tScanResultHandle hIn, tScanResultHandle *phResult);
+void csrInitBGScanChannelList(tpAniSirGlobal pMac);
+eHalStatus csrScanForSSID(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tANI_U32 roamId);
+eHalStatus csrScanForCapabilityChange(tpAniSirGlobal pMac, tSirSmeApNewCaps *pNewCaps);
+eHalStatus csrScanStartGetResultTimer(tpAniSirGlobal pMac);
+eHalStatus csrScanStopGetResultTimer(tpAniSirGlobal pMac);
+eHalStatus csrScanStartResultAgingTimer(tpAniSirGlobal pMac);
+eHalStatus csrScanStopResultAgingTimer(tpAniSirGlobal pMac);
+eHalStatus csrScanBGScanEnable(tpAniSirGlobal pMac);
+eHalStatus csrScanStartIdleScanTimer(tpAniSirGlobal pMac, tANI_U32 interval);
+eHalStatus csrScanStopIdleScanTimer(tpAniSirGlobal pMac);
+eHalStatus csrScanStartIdleScan(tpAniSirGlobal pMac);
+//Param: pTimeInterval -- Caller allocated memory in return, if failed, to specify the nxt time interval for
+//idle scan timer interval
+//Return: Not success -- meaning it cannot start IMPS, caller needs to start a timer for idle scan
+eHalStatus csrScanTriggerIdleScan(tpAniSirGlobal pMac, tANI_U32 *pTimeInterval);
+void csrScanCancelIdleScan(tpAniSirGlobal pMac);
+void csrScanStopTimers(tpAniSirGlobal pMac);
+//This function will remove scan commands that are not related to association or IBSS
+tANI_BOOLEAN csrScanRemoveNotRoamingScanCommand(tpAniSirGlobal pMac);
+//To remove fresh scan commands from the pending queue
+tANI_BOOLEAN csrScanRemoveFreshScanCommand(tpAniSirGlobal pMac, tANI_U8 sessionId);
+eHalStatus csrScanAbortMacScan(tpAniSirGlobal pMac);
+void csrRemoveCmdFromPendingList(tpAniSirGlobal pMac, tDblLinkList *pList,
+ eSmeCommandType commandType );
+eHalStatus csrScanAbortMacScanNotForConnect(tpAniSirGlobal pMac);
+eHalStatus csrScanGetScanChannelInfo(tpAniSirGlobal pMac);
+//To age out scan results base. tSmeGetScanChnRsp is a pointer returned by LIM that
+//has the information regarding scanned channels.
+//The logic is that whenever CSR add a BSS to scan result, it set the age count to
+//a value. This function deduct the age count if channelId matches the BSS' channelId
+//The BSS is remove if the count reaches 0.
+eHalStatus csrScanAgeResults(tpAniSirGlobal pMac, tSmeGetScanChnRsp *pScanChnInfo);
+
+//If fForce is TRUE we will save the new String that is learn't.
+//Typically it will be true in case of Join or user initiated ioctl
+tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes, tANI_BOOLEAN fForce );
+void csrApplyCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce );
+void csrSetCfgScanControlList( tpAniSirGlobal pMac, tANI_U8 *countryCode, tCsrChannel *pChannelList );
+void csrReinitScanCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+void csrFreeScanResultEntry( tpAniSirGlobal pMac, tCsrScanResult *pResult );
+
+eHalStatus csrRoamCallCallback(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamInfo *pRoamInfo,
+ tANI_U32 roamId, eRoamCmdStatus u1, eCsrRoamResult u2);
+eHalStatus csrRoamIssueConnect(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tScanResultHandle hBSSList,
+ eCsrRoamReason reason, tANI_U32 roamId,
+ tANI_BOOLEAN fImediate, tANI_BOOLEAN fClearScan);
+eHalStatus csrRoamIssueReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tCsrRoamModifyProfileFields *pModProfileFields,
+ eCsrRoamReason reason, tANI_U32 roamId, tANI_BOOLEAN fImediate);
+void csrRoamComplete( tpAniSirGlobal pMac, eCsrRoamCompleteResult Result, void *Context );
+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 csrRoamProcessDisassocDeauth( tpAniSirGlobal pMac, tSmeCmd *pCommand,
+ tANI_BOOLEAN fDisassoc, tANI_BOOLEAN fMICFailure );
+eHalStatus csrRoamSaveConnectedInfomation(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes);
+void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg );
+void csrRoamStatsRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg);
+eHalStatus csrRoamIssueStartBss( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamStartBssParams *pParam,
+ tCsrRoamProfile *pProfile, tSirBssDescription *pBssDesc, tANI_U32 roamId );
+eHalStatus csrRoamIssueStopBss( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamSubState NewSubstate );
+tANI_BOOLEAN csrIsSameProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile1, tCsrRoamProfile *pProfile2);
+tANI_BOOLEAN csrIsRoamCommandWaiting(tpAniSirGlobal pMac);
+tANI_BOOLEAN csrIsRoamCommandWaitingForSession(tpAniSirGlobal pMac, tANI_U32 sessionId);
+tANI_BOOLEAN csrIsScanForRoamCommandActive( tpAniSirGlobal pMac );
+eRoamCmdStatus csrGetRoamCompleteStatus(tpAniSirGlobal pMac, tANI_U32 sessionId);
+//pBand can be NULL if caller doesn't need to get it
+//eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, eCsrPhyMode phyModeIn, tANI_U8 operationChn, eCsrBand *pBand );
+eHalStatus csrRoamIssueDisassociateCmd( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason );
+eHalStatus csrRoamDisconnectInternal(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason);
+//pCommand may be NULL
+void csrRoamRemoveDuplicateCommand(tpAniSirGlobal pMac, tANI_U32 sessionId, tSmeCmd *pCommand, eCsrRoamReason eRoamReason);
+
+eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDescription,
+ tCsrRoamProfile *pProfile, tDot11fBeaconIEs *pIes );
+eHalStatus csrSendMBDisassocReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode );
+eHalStatus csrSendMBDeauthReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode );
+eHalStatus csrSendMBDisassocCnfMsg( tpAniSirGlobal pMac, tpSirSmeDisassocInd pDisassocInd );
+eHalStatus csrSendMBDeauthCnfMsg( tpAniSirGlobal pMac, tpSirSmeDeauthInd pDeauthInd );
+eHalStatus csrSendAssocCnfMsg( tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocInd, eHalStatus status );
+#ifdef WLAN_SOFTAP_FEATURE
+eHalStatus csrSendAssocIndToUpperLayerCnfMsg( tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocInd, eHalStatus Halstatus, tANI_U8 sessionId );
+#endif
+eHalStatus csrSendMBStartBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamBssType bssType,
+ tCsrRoamStartBssParams *pParam, tSirBssDescription *pBssDesc );
+eHalStatus csrSendMBStopBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId );
+eHalStatus csrSendSmeReassocReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDescription,
+ tDot11fBeaconIEs *pIes, tCsrRoamProfile *pProfile );
+
+tANI_BOOLEAN csrIsMacAddressEqual( tpAniSirGlobal pMac, tCsrBssid *pMacAddr1, tCsrBssid *pMacAddr2 );
+//Caller should put the BSS' ssid to fiedl bssSsid when comparing SSID for a BSS.
+tANI_BOOLEAN csrIsSsidMatch( tpAniSirGlobal pMac, tANI_U8 *ssid1, tANI_U8 ssid1Len, tANI_U8 *bssSsid,
+ tANI_U8 bssSsidLen, tANI_BOOLEAN fSsidRequired );
+tANI_BOOLEAN csrIsPhyModeMatch( tpAniSirGlobal pMac, tANI_U32 phyMode,
+ tSirBssDescription *pSirBssDesc, tCsrRoamProfile *pProfile,
+ eCsrCfgDot11Mode *pReturnCfgDot11Mode,
+ tDot11fBeaconIEs *pIes);
+tANI_BOOLEAN csrRoamIsChannelValid( tpAniSirGlobal pMac, tANI_U8 channel );
+
+//pNumChan is a caller allocated space with the sizeof pChannels
+eHalStatus csrGetCfgValidChannels(tpAniSirGlobal pMac, tANI_U8 *pChannels, tANI_U32 *pNumChan);
+void csrRoamCcmCfgSetCallback(tHalHandle hHal, tANI_S32 result);
+void csrScanCcmCfgSetCallback(tHalHandle hHal, tANI_S32 result);
+
+//To free the last roaming profile
+void csrFreeRoamProfile(tpAniSirGlobal pMac, tANI_U32 sessionId);
+void csrFreeConnectBssDesc(tpAniSirGlobal pMac, tANI_U32 sessionId);
+eHalStatus csrMoveBssToHeadFromBSSID(tpAniSirGlobal pMac, tCsrBssid *bssid, tScanResultHandle hScanResult);
+tANI_BOOLEAN csrCheckPSReady(void *pv);
+void csrFullPowerCallback(void *pv, eHalStatus status);
+//to free memory allocated inside the profile structure
+void csrReleaseProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile);
+//To free memory allocated inside scanFilter
+void csrFreeScanFilter(tpAniSirGlobal pMac, tCsrScanResultFilter *pScanFilter);
+#ifdef WLAN_SOFTAP_FEATURE
+eCsrCfgDot11Mode csrGetCfgDot11ModeFromCsrPhyMode(tCsrRoamProfile *pProfile, eCsrPhyMode phyMode, tANI_BOOLEAN fProprietary);
+#else
+eCsrCfgDot11Mode csrGetCfgDot11ModeFromCsrPhyMode(eCsrPhyMode phyMode, tANI_BOOLEAN fProprietary);
+#endif
+tANI_U32 csrTranslateToWNICfgDot11Mode(tpAniSirGlobal pMac, eCsrCfgDot11Mode csrDot11Mode);
+void csrSaveChannelPowerForBand( tpAniSirGlobal pMac, tANI_BOOLEAN fPopulate5GBand );
+void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannelList, tANI_U8 *countryCode);
+void csrAssignRssiForCategory(tpAniSirGlobal pMac, tANI_U8 catOffset);
+tANI_BOOLEAN csrIsMacAddressZero( tpAniSirGlobal pMac, tCsrBssid *pMacAddr );
+tANI_BOOLEAN csrIsMacAddressBroadcast( tpAniSirGlobal pMac, tCsrBssid *pMacAddr );
+eHalStatus csrRoamRemoveConnectedBssFromScanCache(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pConnProfile);
+eHalStatus csrRoamStartRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamingReason roamingReason);
+//return a boolean to indicate whether roaming completed or continue.
+tANI_BOOLEAN csrRoamCompleteRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tANI_BOOLEAN fForce, eCsrRoamResult roamResult);
+void csrRoamCompletion(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamInfo *pRoamInfo, tSmeCmd *pCommand, eCsrRoamResult roamResult, tANI_BOOLEAN fSuccess);
+void csrRoamCancelRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId);
+void csrResetCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce );
+void csrResetPMKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId );
+#ifdef FEATURE_WLAN_WAPI
+void csrResetBKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId );
+#endif /* FEATURE_WLAN_WAPI */
+void csrSaveToChannelPower2G_5G( tpAniSirGlobal pMac, tANI_U32 tableSize, tSirMacChanInfo *channelTable );
+//Get the list of the base channels to scan for passively 11d info
+eHalStatus csrScanGetSupportedChannels( tpAniSirGlobal pMac );
+//To check whether a country code matches the one in the IE
+//Only check the first two characters, ignoring in/outdoor
+//pCountry -- caller allocated buffer contain the country code that is checking against
+//the one in pIes. It can be NULL.
+//caller must provide pIes, it cannot be NULL
+//This function always return TRUE if 11d support is not turned on.
+//pIes cannot be NULL
+tANI_BOOLEAN csrMatchCountryCode( tpAniSirGlobal pMac, tANI_U8 *pCountry, tDot11fBeaconIEs *pIes );
+eHalStatus csrRoamSetKey( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 roamId );
+eHalStatus csrRoamOpenSession( tpAniSirGlobal pMac, csrRoamCompleteCallback callback, void *pContext,
+ tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId );
+//fSync: TRUE means cleanupneeds to handle synchronously.
+eHalStatus csrRoamCloseSession( tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tANI_BOOLEAN fSync,
+ csrRoamSessionCloseCallback callback,
+ void *pContext );
+void csrCleanupSession(tpAniSirGlobal pMac, tANI_U32 sessionId);
+eHalStatus csrRoamGetSessionIdFromBSSID( tpAniSirGlobal pMac, tCsrBssid *bssid, tANI_U32 *pSessionId );
+eCsrCfgDot11Mode csrFindBestPhyMode( tpAniSirGlobal pMac, tANI_U32 phyMode );
+
+/* ---------------------------------------------------------------------------
+ \fn csrScanEnable
+ \brief Enable the scanning feature of CSR. It must be called before any scan request can be performed.
+ \param tHalHandle - HAL context handle
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrScanEnable(tpAniSirGlobal);
+
+/* ---------------------------------------------------------------------------
+ \fn csrScanDisable
+ \brief Disableing the scanning feature of CSR. After this function return success, no scan is performed until
+a successfull to csrScanEnable
+ \param tHalHandle - HAL context handle
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrScanDisable(tpAniSirGlobal);
+/* ---------------------------------------------------------------------------
+ \fn csrScanRequest
+ \brief Request a 11d or full scan.
+ \param pScanRequestID - pointer to an object to get back the request ID
+ \param callback - a callback function that scan calls upon finish, will not be called if csrScanRequest returns error
+ \param pContext - a pointer passed in for the callback
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrScanRequest(tpAniSirGlobal, tANI_U16, tCsrScanRequest *,
+ tANI_U32 *pScanRequestID, csrScanCompleteCallback callback,
+ void *pContext);
+
+/* ---------------------------------------------------------------------------
+ \fn csrScanAbort
+ \brief If a scan request is abort, the scan complete callback will be called first before csrScanAbort returns.
+ \param pScanRequestID - The request ID returned from csrScanRequest
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrScanAbort(tpAniSirGlobal, tANI_U32 scanRequestID);
+
+eHalStatus csrScanSetBGScanparams(tpAniSirGlobal, tCsrBGScanRequest *);
+eHalStatus csrScanBGScanAbort(tpAniSirGlobal);
+
+/* ---------------------------------------------------------------------------
+ \fn csrScanGetResult
+ \brief Return scan results.
+ \param pFilter - If pFilter is NULL, all cached results are returned
+ \param phResult - an object for the result.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrScanGetResult(tpAniSirGlobal, tCsrScanResultFilter *pFilter, tScanResultHandle *phResult);
+
+/* ---------------------------------------------------------------------------
+ \fn csrScanFlushResult
+ \brief Clear scan results.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrScanFlushResult(tpAniSirGlobal);
+
+/* ---------------------------------------------------------------------------
+ \fn csrScanBGScanGetParam
+ \brief Returns the current background scan settings.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrScanBGScanGetParam(tpAniSirGlobal, tCsrBGScanRequest *);
+
+/* ---------------------------------------------------------------------------
+ \fn csrScanResultGetFirst
+ \brief Returns the first element of scan result.
+ \param hScanResult - returned from csrScanGetResult
+ \return tCsrScanResultInfo * - NULL if no result
+ -------------------------------------------------------------------------------*/
+tCsrScanResultInfo *csrScanResultGetFirst(tpAniSirGlobal, tScanResultHandle hScanResult);
+/* ---------------------------------------------------------------------------
+ \fn csrScanResultGetNext
+ \brief Returns the next element of scan result. It can be called without calling csrScanResultGetFirst first
+ \param hScanResult - returned from csrScanGetResult
+ \return Null if no result or reach the end
+ -------------------------------------------------------------------------------*/
+tCsrScanResultInfo *csrScanResultGetNext(tpAniSirGlobal, tScanResultHandle hScanResult);
+
+/* ---------------------------------------------------------------------------
+ \fn csrGetCountryCode
+ \brief this function is to get the country code current being used
+ \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return, this has the country code
+ \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return,
+ this contains the length of the data in pBuf
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrGetCountryCode(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U8 *pbLen);
+
+/* ---------------------------------------------------------------------------
+ \fn csrSetCountryCode
+ \brief this function is to set the country code so channel/power setting matches the countrycode and
+ the domain it belongs to.
+ \param pCountry - Caller allocated buffer with at least 3 bytes specifying the country code
+ \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether
+ a restart is needed to apply the change
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrSetCountryCode(tpAniSirGlobal pMac, tANI_U8 *pCountry, tANI_BOOLEAN *pfRestartNeeded);
+
+/* ---------------------------------------------------------------------------
+ \fn csrResetCountryCodeInformation
+ \brief this function is to reset the country code current being used back to EEPROM default
+ this includes channel list and power setting.
+ \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether
+ a restart is needed to apply the change
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrResetCountryCodeInformation(tpAniSirGlobal pMac, tANI_BOOLEAN *pfRestartNeeded);
+
+/* ---------------------------------------------------------------------------
+ \fn csrGetSupportedCountryCode
+ \brief this function is to get a list of the country code current being supported
+ \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return,
+ this has the country code list. 3 bytes for each country code. This may be NULL if
+ caller wants to know the needed bytes.
+ \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return,
+ this contains the length of the data in pBuf
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrGetSupportedCountryCode(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U32 *pbLen);
+
+/* ---------------------------------------------------------------------------
+ \fn csrSetRegulatoryDomain
+ \brief this function is to set the current regulatory domain.
+ This function must be called after CFG is downloaded and all the band/mode setting already passed into
+ CSR.
+ \param domainId - indicate the domain (defined in the driver) needs to set to.
+ See eRegDomainId for definition
+ \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether
+ a restart is needed to apply the change
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrSetRegulatoryDomain(tpAniSirGlobal pMac, v_REGDOMAIN_t domainId, tANI_BOOLEAN *pfRestartNeeded);
+
+/* ---------------------------------------------------------------------------
+ \fn csrGetCurrentRegulatoryDomain
+ \brief this function is to get the current regulatory domain.
+ This function must be called after CFG is downloaded and all the band/mode setting already passed into
+ CSR.
+ \return eRegDomainId
+ -------------------------------------------------------------------------------*/
+v_REGDOMAIN_t csrGetCurrentRegulatoryDomain(tpAniSirGlobal pMac);
+
+/* ---------------------------------------------------------------------------
+ \fn csrGetRegulatoryDomainForCountry
+ \brief this function is to get the regulatory domain for a country.
+ This function must be called after CFG is downloaded and all the band/mode setting already passed into
+ CSR.
+ \param pCountry - Caller allocated buffer with at least 3 bytes specifying the country code
+ \param pDomainId - Caller allocated buffer to get the return domain ID upon success return. Can be NULL.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrGetRegulatoryDomainForCountry(tpAniSirGlobal pMac, tANI_U8 *pCountry, v_REGDOMAIN_t *pDomainId);
+
+
+tANI_BOOLEAN csrSave11dCountryString( tpAniSirGlobal pMac, tANI_U8 *pCountryCode, tANI_BOOLEAN fForce );
+
+//some support functions
+tANI_BOOLEAN csrIs11dSupported(tpAniSirGlobal pMac);
+tANI_BOOLEAN csrIs11hSupported(tpAniSirGlobal pMac);
+tANI_BOOLEAN csrIs11eSupported(tpAniSirGlobal pMac);
+tANI_BOOLEAN csrIsWmmSupported(tpAniSirGlobal pMac);
+tANI_BOOLEAN csrIsMCCSupported(tpAniSirGlobal pMac);
+
+//Upper layer to get the list of the base channels to scan for passively 11d info from csr
+eHalStatus csrScanGetBaseChannels( tpAniSirGlobal pMac, tCsrChannelInfo * pChannelInfo );
+//Return SUCCESS is the command is queued, failed
+eHalStatus csrQueueSmeCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fHighPriority );
+tSmeCmd *csrGetCommandBuffer( tpAniSirGlobal pMac );
+void csrReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+#ifdef FEATURE_WLAN_WAPI
+tANI_BOOLEAN csrIsProfileWapi( tCsrRoamProfile *pProfile );
+#endif /* FEATURE_WLAN_WAPI */
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+
+//Security
+#define WLAN_SECURITY_EVENT_SET_PTK_REQ 1
+#define WLAN_SECURITY_EVENT_SET_PTK_RSP 2
+#define WLAN_SECURITY_EVENT_SET_GTK_REQ 3
+#define WLAN_SECURITY_EVENT_SET_GTK_RSP 4
+#define WLAN_SECURITY_EVENT_REMOVE_KEY_REQ 5
+#define WLAN_SECURITY_EVENT_REMOVE_KEY_RSP 6
+#define WLAN_SECURITY_EVENT_PMKID_CANDIDATE_FOUND 7
+#define WLAN_SECURITY_EVENT_PMKID_UPDATE 8
+#define WLAN_SECURITY_EVENT_MIC_ERROR 9
+
+#define AUTH_OPEN 0
+#define AUTH_SHARED 1
+#define AUTH_WPA_EAP 2
+#define AUTH_WPA_PSK 3
+#define AUTH_WPA2_EAP 4
+#define AUTH_WPA2_PSK 5
+#ifdef FEATURE_WLAN_WAPI
+#define AUTH_WAPI_CERT 6
+#define AUTH_WAPI_PSK 7
+#endif /* FEATURE_WLAN_WAPI */
+
+#define ENC_MODE_OPEN 0
+#define ENC_MODE_WEP40 1
+#define ENC_MODE_WEP104 2
+#define ENC_MODE_TKIP 3
+#define ENC_MODE_AES 4
+#ifdef FEATURE_WLAN_WAPI
+#define ENC_MODE_SMS4 5 //WAPI
+#endif /* FEATURE_WLAN_WAPI */
+
+#define NO_MATCH 0
+#define MATCH 1
+
+#define WLAN_SECURITY_STATUS_SUCCESS 0
+#define WLAN_SECURITY_STATUS_FAILURE 1
+
+//Scan
+#define WLAN_SCAN_EVENT_ACTIVE_SCAN_REQ 1
+#define WLAN_SCAN_EVENT_ACTIVE_SCAN_RSP 2
+#define WLAN_SCAN_EVENT_PASSIVE_SCAN_REQ 3
+#define WLAN_SCAN_EVENT_PASSIVE_SCAN_RSP 4
+#define WLAN_SCAN_EVENT_HO_SCAN_REQ 5
+#define WLAN_SCAN_EVENT_HO_SCAN_RSP 6
+
+#define WLAN_SCAN_STATUS_SUCCESS 0
+#define WLAN_SCAN_STATUS_FAILURE 1
+#define WLAN_SCAN_STATUS_ABORT 2
+
+//Ibss
+#define WLAN_IBSS_EVENT_START_IBSS_REQ 0
+#define WLAN_IBSS_EVENT_START_IBSS_RSP 1
+#define WLAN_IBSS_EVENT_JOIN_IBSS_REQ 2
+#define WLAN_IBSS_EVENT_JOIN_IBSS_RSP 3
+#define WLAN_IBSS_EVENT_COALESCING 4
+#define WLAN_IBSS_EVENT_PEER_JOIN 5
+#define WLAN_IBSS_EVENT_PEER_LEAVE 6
+#define WLAN_IBSS_EVENT_STOP_REQ 7
+#define WLAN_IBSS_EVENT_STOP_RSP 8
+
+#define AUTO_PICK 0
+#define SPECIFIED 1
+
+#define WLAN_IBSS_STATUS_SUCCESS 0
+#define WLAN_IBSS_STATUS_FAILURE 1
+
+//11d
+#define WLAN_80211D_EVENT_COUNTRY_SET 0
+#define WLAN_80211D_EVENT_RESET 1
+
+#define WLAN_80211D_DISABLED 0
+#define WLAN_80211D_SUPPORT_MULTI_DOMAIN 1
+#define WLAN_80211D_NOT_SUPPORT_MULTI_DOMAIN 2
+
+int diagAuthTypeFromCSRType(eCsrAuthType authType);
+int diagEncTypeFromCSRType(eCsrEncryptionType encType);
+#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+/* ---------------------------------------------------------------------------
+ \fn csrScanResultPurge
+ \brief remove all items(tCsrScanResult) in the list and free memory for each item
+ \param hScanResult - returned from csrScanGetResult. hScanResult is considered gone by
+ calling this function and even before this function reutrns.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrScanResultPurge(tpAniSirGlobal pMac, tScanResultHandle hScanResult);
+
+
+///////////////////////////////////////////Common Scan ends
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamConnect
+ \brief To inititiate an association
+ \param pProfile - can be NULL to join to any open ones
+ \param hBssListIn - a list of BSS descriptor to roam to. It is returned from csrScanGetResult
+ \param pRoamId - to get back the request ID
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamConnect(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tScanResultHandle hBssListIn, tANI_U32 *pRoamId);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamReassoc
+ \brief To inititiate a re-association
+ \param pProfile - can be NULL to join the currently connected AP. In that
+ case modProfileFields should carry the modified field(s) which could trigger
+ reassoc
+ \param modProfileFields - fields which are part of tCsrRoamConnectedProfile
+ that might need modification dynamically once STA is up & running and this
+ could trigger a reassoc
+ \param pRoamId - to get back the request ID
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tCsrRoamModifyProfileFields modProfileFields,
+ tANI_U32 *pRoamId);
+
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamReconnect
+ \brief To disconnect and reconnect with the same profile
+ \return eHalStatus. It returns fail if currently not connected
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamReconnect(tpAniSirGlobal pMac, tANI_U32 sessionId);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamSetPMKIDCache
+ \brief return the PMKID candidate list
+ \param pPMKIDCache - caller allocated buffer point to an array of tPmkidCacheInfo
+ \param numItems - a variable that has the number of tPmkidCacheInfo allocated
+ when retruning, this is either the number needed or number of items put into pPMKIDCache
+ \return eHalStatus - when fail, it usually means the buffer allocated is not big enough and pNumItems
+ has the number of tPmkidCacheInfo.
+ \Note: pNumItems is a number of tPmkidCacheInfo, not sizeof(tPmkidCacheInfo) * something
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamSetPMKIDCache( tpAniSirGlobal pMac, tANI_U32 sessionId, tPmkidCacheInfo *pPMKIDCache, tANI_U32 numItems );
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetWpaRsnReqIE
+ \brief return the WPA or RSN IE CSR passes to PE to JOIN request or START_BSS request
+ \param pLen - caller allocated memory that has the length of pBuf as input. Upon returned, *pLen has the
+ needed or IE length in pBuf.
+ \param pBuf - Caller allocated memory that contain the IE field, if any, upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not big enough
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamGetWpaRsnReqIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetWpaRsnRspIE
+ \brief return the WPA or RSN IE from the beacon or probe rsp if connected
+ \param pLen - caller allocated memory that has the length of pBuf as input. Upon returned, *pLen has the
+ needed or IE length in pBuf.
+ \param pBuf - Caller allocated memory that contain the IE field, if any, upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not big enough
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamGetWpaRsnRspIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf);
+
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetNumPMKIDCache
+ \brief return number of PMKID cache entries
+ \return tANI_U32 - the number of PMKID cache entries
+ -------------------------------------------------------------------------------*/
+tANI_U32 csrRoamGetNumPMKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetPMKIDCache
+ \brief return PMKID cache from CSR
+ \param pNum - caller allocated memory that has the space of the number of pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the
+ needed or actually number in tPmkidCacheInfo.
+ \param pPmkidCache - Caller allocated memory that contains PMKID cache, if any, upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not big enough
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamGetPMKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tANI_U32 *pNum, tPmkidCacheInfo *pPmkidCache);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetConnectProfile
+ \brief To return the current connect profile. Caller must call csrRoamFreeConnectProfile
+ after it is done and before reuse for another csrRoamGetConnectProfile call.
+ \param pProfile - pointer to a caller allocated structure tCsrRoamConnectedProfile
+ \return eHalStatus. Failure if not connected
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamGetConnectProfile(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tCsrRoamConnectedProfile *pProfile);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetConnectState
+ \brief To return the current connect state of Roaming
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamGetConnectState(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrConnectState *pState);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamFreeConnectProfile
+ \brief To free and reinitialize the profile return previous by csrRoamGetConnectProfile.
+ \param pProfile - pointer to a caller allocated structure tCsrRoamConnectedProfile
+ \return eHalStatus.
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamFreeConnectProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile);
+
+/* ---------------------------------------------------------------------------
+ \fn csrInitChannelList
+ \brief HDD calls this function to set the WNI_CFG_VALID_CHANNEL_LIST base on the band/mode settings.
+ This function must be called after CFG is downloaded and all the band/mode setting already passed into
+ CSR.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrInitChannelList( tHalHandle hHal );
+
+/* ---------------------------------------------------------------------------
+ \fn csrChangeConfigParams
+ \brief The CSR API exposed for HDD to provide config params to CSR during
+ SMEs stop -> start sequence.
+ If HDD changed the domain that will cause a reset. This function will
+ provide the new set of 11d information for the new domain. Currrently this
+ API provides info regarding 11d only at reset but we can extend this for
+ other params (PMC, QoS) which needs to be initialized again at reset.
+ \param
+ hHal - Handle to the HAL. The HAL handle is returned by the HAL after it is
+ opened (by calling halOpen).
+ pUpdateConfigParam - a pointer to a structure (tCsrUpdateConfigParam) that
+ currently provides 11d related information like Country code,
+ Regulatory domain, valid channel list, Tx power per channel, a
+ list with active/passive scan allowed per valid channel.
+
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus csrChangeConfigParams(tpAniSirGlobal pMac,
+ tCsrUpdateConfigParam *pUpdateConfigParam);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamConnectToLastProfile
+ \brief To disconnect and reconnect with the same profile
+ \return eHalStatus. It returns fail if currently connected
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamConnectToLastProfile(tpAniSirGlobal pMac, tANI_U32 sessionId);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamDisconnect
+ \brief To disconnect from a network
+ \param reason -- To indicate the reason for disconnecting. Currently, only eCSR_DISCONNECT_REASON_MIC_ERROR is meanful.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrRoamDisconnect(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason);
+
+/* ---------------------------------------------------------------------------
+ \fn csrScanGetPMKIDCandidateList
+ \brief return the PMKID candidate list
+ \param pPmkidList - caller allocated buffer point to an array of tPmkidCandidateInfo
+ \param pNumItems - pointer to a variable that has the number of tPmkidCandidateInfo allocated
+ when retruning, this is either the number needed or number of items put into pPmkidList
+ \return eHalStatus - when fail, it usually means the buffer allocated is not big enough and pNumItems
+ has the number of tPmkidCandidateInfo.
+ \Note: pNumItems is a number of tPmkidCandidateInfo, not sizeof(tPmkidCandidateInfo) * something
+ -------------------------------------------------------------------------------*/
+eHalStatus csrScanGetPMKIDCandidateList(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tPmkidCandidateInfo *pPmkidList, tANI_U32 *pNumItems );
+
+//This function is used to stop a BSS. It is similar of csrRoamIssueDisconnect but this function
+//doesn't have any logic other than blindly trying to stop BSS
+eHalStatus csrRoamIssueStopBssCmd( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_BOOLEAN fHighPriority );
+
+void csrCallRoamingCompletionCallback(tpAniSirGlobal pMac, tCsrRoamSession *pSession,
+ tCsrRoamInfo *pRoamInfo, tANI_U32 roamId, eCsrRoamResult roamResult);
+
+#ifdef WLAN_SOFTAP_FEATURE
+/* ---------------------------------------------------------------------------
+ \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,
+ tANI_U8 *pPeerMacAddr,
+ tANI_U32 reason);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamIssueDeauthSta
+ \brief csr function that HDD calls to delete 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 csrRoamIssueDeauthStaCmd( tpAniSirGlobal pMac,
+ tANI_U32 sessionId,
+ tANI_U8 *pPeerMacAddr,
+ tANI_U32 reason);
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamIssueTkipCounterMeasures
+ \brief csr function that HDD calls to start and stop tkip countermeasures
+ \param sessionId - session Id for Soft AP
+ \param bEnable - Flag to start/stop countermeasures
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus csrRoamIssueTkipCounterMeasures( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_BOOLEAN bEnable);
+
+eHalStatus csrSendMBTkipCounterMeasuresReqMsg( tpAniSirGlobal pMac, tANI_U32 sessinId, tANI_BOOLEAN bEnable, tSirMacAddr bssId );
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetAssociatedStas
+ \brief csr function that HDD calls to get list of associated stations based on module ID
+ \param sessionId - session Id for Soft AP
+ \param modId - module ID - PE/HAL/TL
+ \param pUsrContext - Opaque HDD context
+ \param pfnSapEventCallback - Sap event callback in HDD
+ \param pAssocStasBuf - Caller allocated memory to be filled with associatd stations info
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus csrRoamGetAssociatedStas( tpAniSirGlobal pMac, tANI_U32 sessionId, VOS_MODULE_ID modId,
+ void *pUsrContext, void *pfnSapEventCallback, tANI_U8 *pAssocStasBuf );
+
+eHalStatus csrSendMBGetAssociatedStasReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, VOS_MODULE_ID modId, tSirMacAddr bssId,
+ void *pUsrContext, void *pfnSapEventCallback, tANI_U8 *pAssocStasBuf );
+
+/* ---------------------------------------------------------------------------
+ \fn csrRoamGetWpsSessionOverlap
+ \brief csr function that HDD calls to get WPS PBC session overlap information
+ \param sessionId - session Id for Soft AP
+ \param pUsrContext - Opaque HDD context
+ \param pfnSapEventCallback - Sap event callback in HDD
+ \param pRemoveMac - pointer to MAC address of session to be removed
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus csrRoamGetWpsSessionOverlap( tpAniSirGlobal pMac, tANI_U32 sessionId,
+ void *pUsrContext, void *pfnSapEventCallback,v_MACADDR_t pRemoveMac );
+
+eHalStatus csrSendMBGetWPSPBCSessions( tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tSirMacAddr bssId, void *pUsrContext, void *pfnSapEventCallback,v_MACADDR_t pRemoveMac);
+
+#endif
+#ifdef FEATURE_WLAN_BTAMP_UT_RF
+eHalStatus csrRoamStartJoinRetryTimer(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 interval);
+eHalStatus csrRoamStopJoinRetryTimer(tpAniSirGlobal pMac, tANI_U32 sessionId);
+#endif
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/* ---------------------------------------------------------------------------
+ \fn csrRoamFTPreAuthRspProcessor
+ \brief csr function that handles pre auth response from LIM
+ ---------------------------------------------------------------------------*/
+void csrRoamFTPreAuthRspProcessor( tHalHandle hHal, tpSirFTPreAuthRsp pFTPreAuthRsp );
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+void csrCcxSendAdjacentApRepMsg(tpAniSirGlobal pMac, tCsrRoamSession *pSession);
+#endif
+#endif
+
diff --git a/CORE/SME/src/csr/csrLinkList.c b/CORE/SME/src/csr/csrLinkList.c
new file mode 100644
index 0000000..a2b08e8
--- /dev/null
+++ b/CORE/SME/src/csr/csrLinkList.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+ \file csrLinkList.c
+
+ Implementation for the Common link list interfaces.
+
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+ ========================================================================== */
+
+#include "palApi.h"
+#include "csrLinkList.h"
+#include "vos_lock.h"
+#include "vos_memory.h"
+#include "vos_trace.h"
+
+ANI_INLINE_FUNCTION void csrListInit(tListElem *pList)
+{
+ pList->last = pList->next = pList;
+}
+
+
+ANI_INLINE_FUNCTION void csrListRemoveEntry(tListElem *pEntry)
+{
+ tListElem *pLast;
+ tListElem *pNext;
+
+ pLast = pEntry->last;
+ pNext = pEntry->next;
+ pLast->next = pNext;
+ pNext->last = pLast;
+}
+
+
+ANI_INLINE_FUNCTION tListElem * csrListRemoveHead(tListElem *pHead)
+{
+ tListElem *pEntry;
+ tListElem *pNext;
+
+ pEntry = pHead->next;
+ pNext = pEntry->next;
+ pHead->next = pNext;
+ pNext->last = pHead;
+
+ return (pEntry);
+}
+
+
+
+ANI_INLINE_FUNCTION tListElem * csrListRemoveTail(tListElem *pHead)
+{
+ tListElem *pEntry;
+ tListElem *pLast;
+
+ pEntry = pHead->last;
+ pLast = pEntry->last;
+ pHead->last = pLast;
+ pLast->next = pHead;
+
+ return (pEntry);
+}
+
+
+ANI_INLINE_FUNCTION void csrListInsertTail(tListElem *pHead, tListElem *pEntry)
+{
+ tListElem *pLast;
+
+ pLast = pHead->last;
+ pEntry->last = pLast;
+ pEntry->next = pHead;
+ pLast->next = pEntry;
+ pHead->last = pEntry;
+}
+
+
+ANI_INLINE_FUNCTION void csrListInsertHead(tListElem *pHead, tListElem *pEntry)
+{
+ tListElem *pNext;
+
+ pNext = pHead->next;
+ pEntry->next = pNext;
+ pEntry->last = pHead;
+ pNext->last = pEntry;
+ pHead->next = pEntry;
+}
+
+
+//Insert pNewEntry before pEntry
+void csrListInsertEntry(tListElem *pEntry, tListElem *pNewEntry)
+{
+ tListElem *pLast;
+ if( !pEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pEntry is Null", __FUNCTION__);
+ return;
+ }
+
+ pLast = pEntry->last;
+ pLast->next = pNewEntry;
+ pEntry->last = pNewEntry;
+ pNewEntry->next = pEntry;
+ pNewEntry->last = pLast;
+}
+
+tANI_U32 csrLLCount( tDblLinkList *pList )
+{
+ tANI_U32 c = 0;
+
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return c;
+ }
+
+ if ( pList && ( LIST_FLAG_OPEN == pList->Flag ) )
+ {
+ c = pList->Count;
+ }
+
+ return( c );
+}
+
+
+void csrLLLock( tDblLinkList *pList )
+{
+
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ vos_lock_acquire(&pList->Lock);
+ }
+}
+
+
+void csrLLUnlock( tDblLinkList *pList )
+{
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ vos_lock_release(&pList->Lock);
+ }
+}
+
+
+tANI_BOOLEAN csrLLIsListEmpty( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
+{
+ tANI_BOOLEAN fEmpty = eANI_BOOLEAN_TRUE;
+
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return fEmpty ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if(fInterlocked)
+ {
+ csrLLLock(pList);
+ }
+
+ fEmpty = csrIsListEmpty( &pList->ListHead );
+
+ if(fInterlocked)
+ {
+ csrLLUnlock(pList);
+ }
+ }
+ return( fEmpty );
+}
+
+
+
+tANI_BOOLEAN csrLLFindEntry( tDblLinkList *pList, tListElem *pEntryToFind )
+{
+ tANI_BOOLEAN fFound = eANI_BOOLEAN_FALSE;
+ tListElem *pEntry;
+
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return fFound ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK);
+
+ // Have to make sure we don't loop back to the head of the list, which will
+ // happen if the entry is NOT on the list...
+
+ while( pEntry && ( pEntry != &pList->ListHead ) )
+ {
+ if ( pEntry == pEntryToFind )
+ {
+ fFound = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ pEntry = pEntry->next;
+ }
+
+ }
+ return( fFound );
+}
+
+
+eHalStatus csrLLOpen( tHddHandle hHdd, tDblLinkList *pList )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vosStatus;
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return eHAL_STATUS_FAILURE ;
+ }
+
+ if ( LIST_FLAG_OPEN != pList->Flag )
+ {
+ pList->Count = 0;
+
+ vosStatus = vos_lock_init(&pList->Lock);
+
+ if(VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ csrListInit( &pList->ListHead );
+ pList->Flag = LIST_FLAG_OPEN;
+ pList->hHdd = hHdd;
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ }
+ return (status);
+}
+
+void csrLLClose( tDblLinkList *pList )
+{
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ // Make sure the list is empty...
+ csrLLPurge( pList, LL_ACCESS_LOCK );
+ vos_lock_destroy( &pList->Lock );
+ pList->Flag = LIST_FLAG_CLOSE;
+ }
+}
+
+void csrLLInsertTail( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked )
+{
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if(fInterlocked)
+ {
+ csrLLLock(pList);
+ }
+ csrListInsertTail( &pList->ListHead, pEntry );
+ pList->Count++;
+ if(fInterlocked)
+ {
+ csrLLUnlock(pList);
+ }
+ }
+}
+
+
+
+void csrLLInsertHead( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked )
+{
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if(fInterlocked)
+ {
+ csrLLLock(pList);
+ }
+ csrListInsertHead( &pList->ListHead, pEntry );
+ pList->Count++;
+ if(fInterlocked)
+ {
+ csrLLUnlock(pList);
+ }
+ }
+}
+
+
+void csrLLInsertEntry( tDblLinkList *pList, tListElem *pEntry, tListElem *pNewEntry, tANI_BOOLEAN fInterlocked )
+{
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if(fInterlocked)
+ {
+ csrLLLock(pList);
+ }
+ csrListInsertEntry( pEntry, pNewEntry );
+ pList->Count++;
+ if(fInterlocked)
+ {
+ csrLLUnlock(pList);
+ }
+ }
+}
+
+
+
+tListElem *csrLLRemoveTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
+{
+ tListElem *pEntry = NULL;
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return pEntry ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if ( fInterlocked )
+ {
+ csrLLLock( pList );
+ }
+
+ if ( !csrIsListEmpty(&pList->ListHead) )
+ {
+
+ pEntry = csrListRemoveTail( &pList->ListHead );
+ pList->Count--;
+ }
+ if ( fInterlocked )
+ {
+ csrLLUnlock( pList );
+ }
+ }
+
+ return( pEntry );
+}
+
+
+tListElem *csrLLPeekTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
+{
+ tListElem *pEntry = NULL;
+
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return pEntry ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if ( fInterlocked )
+ {
+ csrLLLock( pList );
+ }
+
+ if ( !csrIsListEmpty(&pList->ListHead) )
+ {
+ pEntry = pList->ListHead.last;
+ }
+ if ( fInterlocked )
+ {
+ csrLLUnlock( pList );
+ }
+ }
+
+ return( pEntry );
+}
+
+
+
+tListElem *csrLLRemoveHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
+{
+ tListElem *pEntry = NULL;
+
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return pEntry ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if ( fInterlocked )
+ {
+ csrLLLock( pList );
+ }
+
+ if ( !csrIsListEmpty(&pList->ListHead) )
+ {
+ pEntry = csrListRemoveHead( &pList->ListHead );
+ pList->Count--;
+ }
+
+ if ( fInterlocked )
+ {
+ csrLLUnlock( pList );
+ }
+ }
+
+ return( pEntry );
+}
+
+
+tListElem *csrLLPeekHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
+{
+ tListElem *pEntry = NULL;
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return pEntry ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if ( fInterlocked )
+ {
+ csrLLLock( pList );
+ }
+
+ if ( !csrIsListEmpty(&pList->ListHead) )
+ {
+ pEntry = pList->ListHead.next;
+ }
+ if ( fInterlocked )
+ {
+ csrLLUnlock( pList );
+ }
+ }
+
+ return( pEntry );
+}
+
+
+
+void csrLLPurge( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
+{
+ tListElem *pEntry;
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if ( fInterlocked )
+ {
+ csrLLLock( pList );
+ }
+ while( (pEntry = csrLLRemoveHead( pList, LL_ACCESS_NOLOCK )) )
+ {
+ // just remove everything from the list until
+ // nothing left on the list.
+ }
+ if ( fInterlocked )
+ {
+ csrLLUnlock( pList );
+ }
+ }
+}
+
+
+tANI_BOOLEAN csrLLRemoveEntry( tDblLinkList *pList, tListElem *pEntryToRemove, tANI_BOOLEAN fInterlocked )
+{
+ tANI_BOOLEAN fFound = eANI_BOOLEAN_FALSE;
+ tListElem *pEntry;
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return fFound;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if ( fInterlocked )
+ {
+ csrLLLock( pList );
+ }
+
+ pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK );
+
+ // Have to make sure we don't loop back to the head of the list, which will
+ // happen if the entry is NOT on the list...
+ while( pEntry && ( pEntry != &pList->ListHead ) )
+ {
+ if ( pEntry == pEntryToRemove )
+ {
+ csrListRemoveEntry( pEntry );
+ pList->Count--;
+
+ fFound = eANI_BOOLEAN_TRUE;
+ break;
+ }
+
+ pEntry = pEntry->next;
+ }
+ if ( fInterlocked )
+ {
+ csrLLUnlock( pList );
+ }
+ }
+
+ return( fFound );
+}
+
+
+
+tListElem *csrLLNext( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked )
+{
+ tListElem *pNextEntry = NULL;
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return pNextEntry ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if ( fInterlocked )
+ {
+ csrLLLock( pList );
+ }
+
+ if ( !csrIsListEmpty(&pList->ListHead) && csrLLFindEntry( pList, pEntry ) )
+ {
+ pNextEntry = pEntry->next;
+ //Make sure we don't walk past the head
+ if ( pNextEntry == &pList->ListHead )
+ {
+ pNextEntry = NULL;
+ }
+ }
+
+ if ( fInterlocked )
+ {
+ csrLLUnlock( pList );
+ }
+ }
+
+ return( pNextEntry );
+}
+
+
+tListElem *csrLLPrevious( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked )
+{
+ tListElem *pNextEntry = NULL;
+
+ if( !pList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __FUNCTION__);
+ return pNextEntry ;
+ }
+
+ if ( LIST_FLAG_OPEN == pList->Flag )
+ {
+ if ( fInterlocked )
+ {
+ csrLLLock( pList );
+ }
+
+ if ( !csrIsListEmpty(&pList->ListHead) && csrLLFindEntry( pList, pEntry ) )
+ {
+ pNextEntry = pEntry->last;
+ //Make sure we don't walk past the head
+ if ( pNextEntry == &pList->ListHead )
+ {
+ pNextEntry = NULL;
+ }
+ }
+
+ if ( fInterlocked )
+ {
+ csrLLUnlock( pList );
+ }
+ }
+
+ return( pNextEntry );
+}
+
+
+
+
diff --git a/CORE/SME/src/csr/csrLogDump.c b/CORE/SME/src/csr/csrLogDump.c
new file mode 100644
index 0000000..26fb3eb
--- /dev/null
+++ b/CORE/SME/src/csr/csrLogDump.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/*============================================================================
+Copyright (c) 2007 QUALCOMM Incorporated.
+All Rights Reserved.
+Qualcomm Confidential and Proprietary
+csrLogDump.c
+Implements the dump commands specific to the csr module.
+============================================================================*/
+#include "aniGlobal.h"
+#include "csrApi.h"
+#include "btcApi.h"
+#include "logDump.h"
+#include "smsDebug.h"
+#include "smeInside.h"
+#include "csrInsideApi.h"
+#if defined(ANI_LOGDUMP)
+static char *
+dump_csr( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p )
+{
+ static tCsrRoamProfile x;
+ static tSirMacSSid ssid; //To be allocated for array of SSIDs
+ static tANI_U8 sessionId = 0; // Defined for fixed session ID
+ palZeroMemory(pMac->hHdd, (void*)&x, sizeof(x));
+ x.SSIDs.numOfSSIDs=1 ;
+ x.SSIDs.SSIDList[0].SSID = ssid ;
+ ssid.length=6 ;
+ palCopyMemory(pMac->hHdd, ssid.ssId, "AniNet", 6);
+ if(HAL_STATUS_SUCCESS(sme_AcquireGlobalLock( &pMac->sme )))
+ {
+ (void)csrRoamConnect(pMac, sessionId, &x, NULL, NULL);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return p;
+}
+static char *dump_btcSetEvent( tpAniSirGlobal pMac, tANI_U32 arg1,
+ tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p )
+{
+ tSmeBtEvent btEvent;
+ if( arg1 < BT_EVENT_TYPE_MAX )
+ {
+ smsLog(pMac, LOGE, FL(" signal BT event (%d) handle (%d) 3rd param(%d)\n"), arg1, arg2, arg3);
+ vos_mem_zero(&btEvent, sizeof(tSmeBtEvent));
+ btEvent.btEventType = arg1;
+ switch( arg1 )
+ {
+ case BT_EVENT_SYNC_CONNECTION_COMPLETE:
+ case BT_EVENT_SYNC_CONNECTION_UPDATED:
+ btEvent.uEventParam.btSyncConnection.connectionHandle = (v_U16_t)arg2;
+ btEvent.uEventParam.btSyncConnection.status = (v_U8_t)arg3;
+ break;
+ case BT_EVENT_DISCONNECTION_COMPLETE:
+ btEvent.uEventParam.btDisconnect.connectionHandle = (v_U16_t)arg2;
+ break;
+ case BT_EVENT_CREATE_ACL_CONNECTION:
+ case BT_EVENT_ACL_CONNECTION_COMPLETE:
+ btEvent.uEventParam.btAclConnection.connectionHandle = (v_U16_t)arg2;
+ btEvent.uEventParam.btAclConnection.status = (v_U8_t)arg3;
+ break;
+ case BT_EVENT_MODE_CHANGED:
+ btEvent.uEventParam.btAclModeChange.connectionHandle = (v_U16_t)arg2;
+ break;
+ default:
+ break;
+ }
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ if(HAL_STATUS_SUCCESS(sme_AcquireGlobalLock( &pMac->sme )))
+ {
+ btcSignalBTEvent(pMac, &btEvent);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+#endif
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL(" invalid event (%d)\n"), arg1);
+ }
+ return p;
+}
+
+static tDumpFuncEntry csrMenuDumpTable[] = {
+ {0, "CSR (850-860)", NULL},
+ {851, "CSR: CSR testing connection to AniNet", dump_csr},
+ {852, "BTC: Fake BT events (event, handle)", dump_btcSetEvent},
+};
+
+void csrDumpInit(tHalHandle hHal)
+{
+ logDumpRegisterTable( (tpAniSirGlobal)hHal, &csrMenuDumpTable[0],
+ sizeof(csrMenuDumpTable)/sizeof(csrMenuDumpTable[0]) );
+}
+
+#endif //#if defined(ANI_LOGDUMP)
diff --git a/CORE/SME/src/csr/csrNeighborRoam.c b/CORE/SME/src/csr/csrNeighborRoam.c
new file mode 100644
index 0000000..9ae1066
--- /dev/null
+++ b/CORE/SME/src/csr/csrNeighborRoam.c
@@ -0,0 +1,2842 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/*
+ * */
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+
+
+ \file csrNeighborRoam.c
+
+ Implementation for the simple roaming algorithm for 802.11r Fast transitions and Legacy roaming for Android platform.
+
+ Copyright (C) 2010 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
+---------- --- --------------------------------------------------------
+08/01/10 Murali Created
+
+===========================================================================*/
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+#include "wlan_qct_wda.h"
+#include "palApi.h"
+#include "csrInsideApi.h"
+#include "smsDebug.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 "wlan_qct_tl.h"
+#include "sme_Api.h"
+#include "csrNeighborRoam.h"
+#ifdef FEATURE_WLAN_CCX
+#include "csrCcx.h"
+#endif
+
+#define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG
+#define NEIGHBOR_ROAM_DEBUG smsLog
+#else
+#define NEIGHBOR_ROAM_DEBUG(x...)
+#endif
+
+VOS_STATUS csrNeighborRoamNeighborLookupUPCallback (v_PVOID_t pAdapter, v_U8_t rssiNotification,
+ v_PVOID_t pUserCtxt);
+VOS_STATUS csrNeighborRoamNeighborLookupDOWNCallback (v_PVOID_t pAdapter, v_U8_t rssiNotification,
+ v_PVOID_t pUserCtxt);
+void csrNeighborRoamRRMNeighborReportResult(void *context, VOS_STATUS vosStatus);
+eHalStatus csrRoamCopyConnectedProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pDstProfile );
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+static eHalStatus csrNeighborRoamIssuePreauthReq(tpAniSirGlobal pMac);
+VOS_STATUS csrNeighborRoamIssueNeighborRptRequest(tpAniSirGlobal pMac);
+#endif
+
+/* State Transition macro */
+#define CSR_NEIGHBOR_ROAM_STATE_TRANSITION(newState)\
+{\
+ pMac->roam.neighborRoamInfo.prevNeighborRoamState = pMac->roam.neighborRoamInfo.neighborRoamState;\
+ pMac->roam.neighborRoamInfo.neighborRoamState = newState;\
+ smsLog(pMac, LOGE, FL("Neighbor Roam Transition from state %d ==> %d"), pMac->roam.neighborRoamInfo.prevNeighborRoamState, newState);\
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamFreeNeighborRoamBSSNode
+
+ \brief This function frees all the internal pointers CSR NeighborRoam BSS Info
+ and also frees the node itself
+
+ \param pMac - The handle returned by macOpen.
+ neighborRoamBSSNode - Neighbor Roam BSS Node to be freed
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamFreeNeighborRoamBSSNode(tpAniSirGlobal pMac, tpCsrNeighborRoamBSSInfo neighborRoamBSSNode)
+{
+ if (neighborRoamBSSNode)
+ {
+ if (neighborRoamBSSNode->pBssDescription)
+ {
+ vos_mem_free(neighborRoamBSSNode->pBssDescription);
+ neighborRoamBSSNode->pBssDescription = NULL;
+ }
+ vos_mem_free(neighborRoamBSSNode);
+ neighborRoamBSSNode = NULL;
+ }
+
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamRemoveRoamableAPListEntry
+
+ \brief This function removes a given entry from the given list
+
+ \param pMac - The handle returned by macOpen.
+ pList - The list from which the entry should be removed
+ pNeighborEntry - Neighbor Roam BSS Node to be removed
+
+ \return TRUE if successfully removed, else FALSE
+
+---------------------------------------------------------------------------*/
+tANI_BOOLEAN csrNeighborRoamRemoveRoamableAPListEntry(tpAniSirGlobal pMac,
+ tDblLinkList *pList, tpCsrNeighborRoamBSSInfo pNeighborEntry)
+{
+ if(pList)
+ {
+ return csrLLRemoveEntry(pList, &pNeighborEntry->List, LL_ACCESS_LOCK);
+ }
+
+ smsLog(pMac, LOGE, FL("Removing neighbor BSS node from list failed. Current count = %d\n"), csrLLCount(pList));
+
+ return eANI_BOOLEAN_FALSE;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamGetRoamableAPListNextEntry
+
+ \brief Gets the entry next to passed entry. If NULL is passed, return the entry in the head of the list
+
+ \param pMac - The handle returned by macOpen.
+ pList - The list from which the entry should be returned
+ pNeighborEntry - Neighbor Roam BSS Node whose next entry should be returned
+
+ \return Neighbor Roam BSS Node to be returned
+
+---------------------------------------------------------------------------*/
+tpCsrNeighborRoamBSSInfo csrNeighborRoamGetRoamableAPListNextEntry(tpAniSirGlobal pMac,
+ tDblLinkList *pList, tpCsrNeighborRoamBSSInfo pNeighborEntry)
+{
+ tListElem *pEntry = NULL;
+ tpCsrNeighborRoamBSSInfo pResult = NULL;
+
+ if(pList)
+ {
+ if(NULL == pNeighborEntry)
+ {
+ pEntry = csrLLPeekHead(pList, LL_ACCESS_LOCK);
+ }
+ else
+ {
+ pEntry = csrLLNext(pList, &pNeighborEntry->List, LL_ACCESS_LOCK);
+ }
+ if(pEntry)
+ {
+ pResult = GET_BASE_ADDR(pEntry, tCsrNeighborRoamBSSInfo, List);
+ }
+ }
+
+ return pResult;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamFreeRoamableBSSList
+
+ \brief Empties and frees all the nodes in the roamable AP list
+
+ \param pMac - The handle returned by macOpen.
+ pList - Neighbor Roam BSS List to be emptied
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamFreeRoamableBSSList(tpAniSirGlobal pMac, tDblLinkList *pList)
+{
+ tpCsrNeighborRoamBSSInfo pResult = NULL;
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Emptying the BSS list. Current count = %d\n"), csrLLCount(pList));
+
+ /* Pick up the head, remove and free the node till the list becomes empty */
+ while ((pResult = csrNeighborRoamGetRoamableAPListNextEntry(pMac, pList, NULL)) != NULL)
+ {
+ csrNeighborRoamRemoveRoamableAPListEntry(pMac, pList, pResult);
+ csrNeighborRoamFreeNeighborRoamBSSNode(pMac, pResult);
+ }
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamReassocIndCallback
+
+ \brief Reassoc callback invoked by TL on crossing the registered re-assoc threshold.
+ Directly triggere HO in case of non-11r association
+ In case of 11R association, triggers a pre-auth eventually followed by actual HO
+
+ \param pAdapter - VOS Context
+ trafficStatus - UP/DOWN indication from TL
+ pUserCtxt - Parameter for callback registered during callback registration. Should be pMac
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+VOS_STATUS csrNeighborRoamReassocIndCallback(v_PVOID_t pAdapter,
+ v_U8_t trafficStatus,
+ v_PVOID_t pUserCtxt)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pUserCtxt );
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+
+ smsLog(pMac, LOG1, FL("Reassoc indication callback called"));
+
+
+ //smsLog(pMac, LOGE, FL("Reassoc indication callback called at state %d"), pNeighborRoamInfo->neighborRoamState);
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering DOWN event reassoc callback with TL. RSSI = %d"), pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1));
+
+
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamReassocIndCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamReassocIndCallback with TL: Status = %d\n"), vosStatus);
+ }
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering UP event neighbor lookup callback with TL. RSSI = %d"), pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1));
+ /* Deregister reassoc callback. Ignore return status */
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamNeighborLookupUPCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamReassocIndCallback with TL: Status = %d\n"), vosStatus);
+ }
+
+ /* We dont need to run this timer any more. */
+ palTimerStop(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (pNeighborRoamInfo->is11rAssoc)
+ {
+ if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState)
+ {
+ csrNeighborRoamIssuePreauthReq(pMac);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("11R Reassoc indication received in unexpected state %d"), pNeighborRoamInfo->neighborRoamState);
+ VOS_ASSERT(0);
+ }
+ }
+ else
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+ if (pNeighborRoamInfo->isCCXAssoc)
+ {
+ if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState)
+ {
+ csrNeighborRoamIssuePreauthReq(pMac);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("CCX Reassoc indication received in unexpected state %d"), pNeighborRoamInfo->neighborRoamState);
+ VOS_ASSERT(0);
+ }
+ }
+ else
+#endif
+ {
+ if (eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN == pNeighborRoamInfo->neighborRoamState)
+ {
+ csrNeighborRoamRequestHandoff(pMac);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("Non-11R Reassoc indication received in unexpected state %d"), pNeighborRoamInfo->neighborRoamState);
+ VOS_ASSERT(0);
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamResetConnectedStateControlInfo
+
+ \brief This function will reset the neighbor roam control info data structures.
+ This function should be invoked whenever we move to CONNECTED state from
+ any state other than INIT state
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamResetConnectedStateControlInfo(tpAniSirGlobal pMac)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ /* Do not reset the currentNeighborLookup Threshold here. The threshold and multiplier will be set before calling this API */
+ if ((pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived == FALSE) &&
+ (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels))
+ {
+ pNeighborRoamInfo->roamChannelInfo.currentChanIndex = CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX;
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0;
+
+ if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList)
+ vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList);
+
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0;
+ pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_TRUE;
+ }
+
+ csrNeighborRoamFreeRoamableBSSList(pMac, &pNeighborRoamInfo->roamableAPList);
+
+ palTimerStop(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer);
+
+ /* Abort any ongoing BG scans */
+ if (eANI_BOOLEAN_TRUE == pNeighborRoamInfo->scanRspPending)
+ csrScanAbortMacScan(pMac);
+
+ pNeighborRoamInfo->scanRspPending = eANI_BOOLEAN_FALSE;
+
+ /* We dont need to run this timer any more. */
+ palTimerStop(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ /* Do not free up the preauth done list here */
+ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0;
+ pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_FALSE;
+ pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0;
+ pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0;
+ pNeighborRoamInfo->FTRoamInfo.preauthRspPending = 0;
+ vos_mem_zero(pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo, sizeof(tCsrNeighborReportBssInfo) * MAX_BSS_IN_NEIGHBOR_RPT);
+ palTimerStop(pMac->hHdd, pNeighborRoamInfo->FTRoamInfo.preAuthRspWaitTimer);
+#endif
+
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamResetInitStateControlInfo
+
+ \brief This function will reset the neighbor roam control info data structures.
+ This function should be invoked whenever we move to CONNECTED state from
+ INIT state
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamResetInitStateControlInfo(tpAniSirGlobal pMac)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+
+ csrNeighborRoamResetConnectedStateControlInfo(pMac);
+
+ /* In addition to the above resets, we should clear off the curAPBssId/Session ID in the timers */
+ pNeighborRoamInfo->csrSessionId = CSR_SESSION_ID_INVALID;
+ vos_mem_set(pNeighborRoamInfo->currAPbssid, sizeof(tCsrBssid), 0);
+ pNeighborRoamInfo->neighborScanTimerInfo.pMac = pMac;
+ pNeighborRoamInfo->neighborScanTimerInfo.sessionId = CSR_SESSION_ID_INVALID;
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ pNeighborRoamInfo->is11rAssoc = eANI_BOOLEAN_FALSE;
+ pNeighborRoamInfo->FTRoamInfo.preAuthRspWaitTimerInfo.pMac = pMac;
+ pNeighborRoamInfo->FTRoamInfo.preAuthRspWaitTimerInfo.sessionId = CSR_SESSION_ID_INVALID;
+ csrNeighborRoamPurgePreauthFailedList(pMac);
+#endif
+#ifdef FEATURE_WLAN_CCX
+ pNeighborRoamInfo->isCCXAssoc = eANI_BOOLEAN_FALSE;
+ pNeighborRoamInfo->isVOAdmitted = eANI_BOOLEAN_FALSE;
+ pNeighborRoamInfo->MinQBssLoadRequired = 0;
+#endif
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering DOWN event reassoc callback with TL. RSSI = %d"), pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1));
+ /* Deregister reassoc callback. Ignore return status */
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamReassocIndCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamReassocIndCallback with TL: Status = %d\n"), vosStatus);
+ }
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering DOWN event neighborLookup callback with TL. RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold * (-1));
+ /* Deregister neighbor lookup callback. Ignore return status */
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamNeighborLookupDOWNCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d\n"), vosStatus);
+ }
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering UP event neighbor lookup callback with TL. RSSI = %d"), pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1));
+ /* Deregister reassoc callback. Ignore return status */
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_UP,
+ csrNeighborRoamNeighborLookupUPCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamReassocIndCallback with TL: Status = %d\n"), vosStatus);
+ }
+
+ /* Reset currentNeighborLookupThreshold only after deregistering DOWN event from TL */
+ pNeighborRoamInfo->currentLookupIncrementMultiplier = 0;
+ pNeighborRoamInfo->currentNeighborLookupThreshold = pNeighborRoamInfo->cfgParams.neighborLookupThreshold;
+
+ return;
+}
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamBssIdScanFilter
+
+ \brief This API is used to prepare a filter to obtain scan results when
+ we complete the scan in the REPORT_SCAN state after receiving a
+ valid neighbor report from AP. This filter includes BSSIDs received from
+ the neighbor report from the AP in addition to the other filter parameters
+ created from connected profile
+
+ \param pMac - The handle returned by macOpen.
+ pScanFilter - Scan filter to be filled and returned
+
+ \return eHAL_STATUS_SUCCESS on succesful filter creation, corresponding error
+ code otherwise
+
+---------------------------------------------------------------------------*/
+static eHalStatus csrNeighborRoamBssIdScanFilter(tpAniSirGlobal pMac, tCsrScanResultFilter *pScanFilter)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ tANI_U8 i = 0;
+
+ VOS_ASSERT(pScanFilter != NULL);
+ vos_mem_zero(pScanFilter, sizeof(tCsrScanResultFilter));
+
+ pScanFilter->BSSIDs.numOfBSSIDs = pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport;
+ pScanFilter->BSSIDs.bssid = vos_mem_malloc(sizeof(tSirMacAddr) * pScanFilter->BSSIDs.numOfBSSIDs);
+ if (NULL == pScanFilter->BSSIDs.bssid)
+ {
+ smsLog(pMac, LOGE, FL("Scan Filter BSSID mem alloc failed"));
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+
+ vos_mem_zero(pScanFilter->BSSIDs.bssid, sizeof(tSirMacAddr) * pScanFilter->BSSIDs.numOfBSSIDs);
+
+ /* Populate the BSSID from Neighbor BSS info received from neighbor report */
+ for (i = 0; i < pScanFilter->BSSIDs.numOfBSSIDs; i++)
+ {
+ vos_mem_copy(&pScanFilter->BSSIDs.bssid[i],
+ pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo[i].neighborBssId, sizeof(tSirMacAddr));
+ }
+
+ /* Fill other general scan filter params */
+ return csrNeighborRoamPrepareScanProfileFilter(pMac, pScanFilter);
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamPurgePreauthFailList
+
+ \brief This function empties the preauth fail list
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamPurgePreauthFailList(tpAniSirGlobal pMac)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Purging the preauth fail list"));
+ while (pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress)
+ {
+ vos_mem_zero(pNeighborRoamInfo->FTRoamInfo.preAuthFailList.macAddress[pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress-1],
+ sizeof(tSirMacAddr));
+ pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress--;
+ }
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamAddBssIdToPreauthFailList
+
+ \brief This function adds the given BSSID to the Preauth fail list
+
+ \param pMac - The handle returned by macOpen.
+ bssId - BSSID to be added to the preauth fail list
+
+ \return eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise
+
+---------------------------------------------------------------------------*/
+eHalStatus csrNeighborRoamAddBssIdToPreauthFailList(tpAniSirGlobal pMac, tSirMacAddr bssId)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL(" Added BSSID %02x:%02x:%02x:%02x:%02x:%02x to Preauth failed list\n"),
+ bssId[0], bssId[1], bssId[2], bssId[3], bssId[4], bssId[5]);
+
+
+ if ((pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress + 1) >
+ MAX_NUM_PREAUTH_FAIL_LIST_ADDRESS)
+ {
+ smsLog(pMac, LOGE, FL("Preauth fail list already full.. Cannot add new one"));
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_copy(pNeighborRoamInfo->FTRoamInfo.preAuthFailList.macAddress[pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress],
+ bssId, sizeof(tSirMacAddr));
+ pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress++;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamIsPreauthCandidate
+
+ \brief This function checks whether the given MAC address is already
+ present in the preauth fail list and returns TRUE/FALSE accordingly
+
+ \param pMac - The handle returned by macOpen.
+
+ \return eANI_BOOLEAN_TRUE if preauth candidate, eANI_BOOLEAN_FALSE otherwise
+
+---------------------------------------------------------------------------*/
+tANI_BOOLEAN csrNeighborRoamIsPreauthCandidate(tpAniSirGlobal pMac, tSirMacAddr bssId)
+{
+ tANI_U8 i = 0;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ if (0 == pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress)
+ return eANI_BOOLEAN_TRUE;
+
+ for (i = 0; i < pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress; i++)
+ {
+ if (VOS_TRUE == vos_mem_compare(pNeighborRoamInfo->FTRoamInfo.preAuthFailList.macAddress[i],
+ bssId, sizeof(tSirMacAddr)))
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("BSSID %02x:%02x:%02x:%02x:%02x:%02x already present in preauth fail list"),
+ bssId[0], bssId[1], bssId[2], bssId[3], bssId[4], bssId[5]);
+ return eANI_BOOLEAN_FALSE;
+ }
+ }
+
+ return eANI_BOOLEAN_TRUE;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamIssuePreauthReq
+
+ \brief This function issues preauth request to PE with the 1st AP entry in the
+ roamable AP list
+
+ \param pMac - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise
+
+---------------------------------------------------------------------------*/
+static eHalStatus csrNeighborRoamIssuePreauthReq(tpAniSirGlobal pMac)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpCsrNeighborRoamBSSInfo pNeighborBssNode;
+
+ /* This must not be true here */
+ VOS_ASSERT(pNeighborRoamInfo->FTRoamInfo.preauthRspPending == eANI_BOOLEAN_FALSE);
+
+ /* Issue Preauth request to PE here */
+ /* Need to issue the preauth request with the BSSID that is there in the head of the roamable AP list */
+ /* Parameters that should be passed are BSSID, Channel number and the neighborScanPeriod(probably) */
+ /* If roamableAPList gets empty, should transition to REPORT_SCAN state */
+ pNeighborBssNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, &pNeighborRoamInfo->roamableAPList, NULL);
+
+ if (NULL == pNeighborBssNode)
+ {
+ smsLog(pMac, LOG1, FL("Roamable AP list is empty.. "));
+ return eHAL_STATUS_FAILURE;
+ }
+ else
+ {
+ status = csrRoamIssueFTPreauthReq(pMac, pNeighborRoamInfo->csrSessionId, pNeighborBssNode->pBssDescription);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Send Preauth request to PE failed with status %d\n"), status);
+ return status;
+ }
+ }
+
+ pNeighborRoamInfo->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_TRUE;
+
+ /* Increment the preauth retry count */
+ pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries++;
+
+ /* Transition the state to preauthenticating */
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING)
+
+ /* Start the preauth rsp timer */
+ status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->FTRoamInfo.preAuthRspWaitTimer,
+ CSR_NEIGHBOR_ROAM_PREAUTH_RSP_WAIT_MULTIPLIER * pNeighborRoamInfo->cfgParams.neighborScanPeriod * PAL_TIMER_TO_MS_UNIT,
+ eANI_BOOLEAN_FALSE);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Preauth response wait timer start failed with status %d\n"), status);
+ return status;
+ }
+
+
+ return status;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamPreauthRspHandler
+
+ \brief This function handle the Preauth response from PE
+ Every preauth is allowed max 3 tries if it fails. If a bssid failed
+ for more than MAX_TRIES, we will remove it from the list and try
+ with the next node in the roamable AP list and add the BSSID to pre-auth failed
+ list. If no more entries present in
+ roamable AP list, transition to REPORT_SCAN state
+
+ \param pMac - The handle returned by macOpen.
+ vosStatus - VOS_STATUS_SUCCESS/FAILURE/TIMEOUT status from PE
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamPreauthRspHandler(tpAniSirGlobal pMac, VOS_STATUS vosStatus)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpCsrNeighborRoamBSSInfo pPreauthRspNode = NULL;
+
+ // We can receive it in these 2 states.
+ VOS_ASSERT((pNeighborRoamInfo->neighborRoamState == eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING) ||
+ (pNeighborRoamInfo->neighborRoamState == eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN));
+
+ if ((pNeighborRoamInfo->neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING) &&
+ (pNeighborRoamInfo->neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN))
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Preauth response received in state %\n"),
+ pNeighborRoamInfo->neighborRoamState);
+ }
+
+ if (VOS_STATUS_E_TIMEOUT != vosStatus)
+ {
+ /* This means we got the response from PE. Hence stop the timer */
+ status = palTimerStop(pMac->hHdd, pNeighborRoamInfo->FTRoamInfo.preAuthRspWaitTimer);
+ pNeighborRoamInfo->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_FALSE;
+ }
+
+ if (VOS_STATUS_SUCCESS == vosStatus)
+ {
+ pPreauthRspNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, &pNeighborRoamInfo->roamableAPList, NULL);
+ }
+ if ((VOS_STATUS_SUCCESS == vosStatus) && (NULL != pPreauthRspNode))
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Preauth completed successfully after %d tries\n"), pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries);
+
+ /* Preauth competer successfully. Insert the preauthenticated node to tail of preAuthDoneList */
+ csrNeighborRoamRemoveRoamableAPListEntry(pMac, &pNeighborRoamInfo->roamableAPList, pPreauthRspNode);
+ csrLLInsertTail(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList, &pPreauthRspNode->List, LL_ACCESS_LOCK);
+
+ /* Pre-auth completed successfully. Transition to PREAUTH Done state */
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE)
+ pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0;
+
+ /* The caller of this function would start a timer and by the time it expires, supplicant should
+ have provided the updated FTIEs to SME. So, when it expires, handoff will be triggered then */
+ }
+ else
+ {
+ tpCsrNeighborRoamBSSInfo pNeighborBssNode = NULL;
+ tListElem *pEntry;
+
+ smsLog(pMac, LOGE, FL("Preauth failed retry number %d, status = %d\n"), pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries, vosStatus);
+
+ /* Preauth failed. Add the bssId to the preAuth failed list MAC Address. Also remove the AP from roamable AP list */
+ if (pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries >= CSR_NEIGHBOR_ROAM_MAX_NUM_PREAUTH_RETRIES)
+ {
+ /* We are going to remove the node as it fails for more than MAX tries. Reset this count to 0 */
+ pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0;
+
+ /* The one in the head of the list should be one with which we issued pre-auth and failed */
+ pEntry = csrLLRemoveHead(&pNeighborRoamInfo->roamableAPList, LL_ACCESS_LOCK);
+ if(pEntry)
+ {
+ pNeighborBssNode = GET_BASE_ADDR(pEntry, tCsrNeighborRoamBSSInfo, List);
+ /* Add the BSSID to pre-auth fail list */
+ status = csrNeighborRoamAddBssIdToPreauthFailList(pMac, pNeighborBssNode->pBssDescription->bssId);
+ /* Now we can free this node */
+ csrNeighborRoamFreeNeighborRoamBSSNode(pMac, pNeighborBssNode);
+ }
+ }
+
+ /* Issue preauth request for the same/next entry */
+ if (eHAL_STATUS_SUCCESS == csrNeighborRoamIssuePreauthReq(pMac))
+ return;
+
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN)
+
+ /* Start the neighbor results refresh timer and transition to REPORT_SCAN state to perform scan again */
+ status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer,
+ pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod * PAL_TIMER_TO_MS_UNIT,
+ eANI_BOOLEAN_FALSE);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Neighbor results refresh timer start failed with status %d\n"), status);
+ return;
+ }
+ }
+}
+#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamPrepareScanProfileFilter
+
+ \brief This function creates a scan filter based on the currently connected profile.
+ Based on this filter, scan results are obtained
+
+ \param pMac - The handle returned by macOpen.
+ pScanFilter - Populated scan filter based on the connected profile
+
+ \return eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise
+
+---------------------------------------------------------------------------*/
+eHalStatus csrNeighborRoamPrepareScanProfileFilter(tpAniSirGlobal pMac, tCsrScanResultFilter *pScanFilter)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ tANI_U8 sessionId = (tANI_U8)pNeighborRoamInfo->csrSessionId;
+ tCsrRoamConnectedProfile *pCurProfile = &pMac->roam.roamSession[sessionId].connectedProfile;
+ tANI_U8 i = 0;
+
+ VOS_ASSERT(pScanFilter != NULL);
+
+ vos_mem_zero(pScanFilter, sizeof(tCsrScanResultFilter));
+
+ /* We dont want to set BSSID based Filter */
+ pScanFilter->BSSIDs.numOfBSSIDs = 0;
+
+ /* Populate all the information from the connected profile */
+ pScanFilter->SSIDs.numOfSSIDs = 1;
+ pScanFilter->SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo));
+ if (NULL == pScanFilter->SSIDs.SSIDList)
+ {
+ smsLog(pMac, LOGE, FL("Scan Filter SSID mem alloc failed"));
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ pScanFilter->SSIDs.SSIDList->handoffPermitted = 1;
+ pScanFilter->SSIDs.SSIDList->ssidHidden = 0;
+ pScanFilter->SSIDs.SSIDList->SSID.length = pCurProfile->SSID.length;
+ vos_mem_copy((void *)pScanFilter->SSIDs.SSIDList->SSID.ssId, (void *)pCurProfile->SSID.ssId, pCurProfile->SSID.length);
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Filtering for SSID %s from scan results.. SSID Length = %d\n"),
+ pScanFilter->SSIDs.SSIDList->SSID.ssId, pScanFilter->SSIDs.SSIDList->SSID.length);
+ pScanFilter->authType.numEntries = 1;
+ pScanFilter->authType.authType[0] = pCurProfile->AuthType;
+
+ pScanFilter->EncryptionType.numEntries = 1; //This must be 1
+ pScanFilter->EncryptionType.encryptionType[0] = pCurProfile->EncryptionType;
+
+ pScanFilter->mcEncryptionType.numEntries = 1;
+ pScanFilter->mcEncryptionType.encryptionType[0] = pCurProfile->mcEncryptionType;
+
+ pScanFilter->BSSType = pCurProfile->BSSType;
+
+ /* We are intrested only in the scan results on channels that we scanned */
+ pScanFilter->ChannelInfo.numOfChannels = pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels;
+ pScanFilter->ChannelInfo.ChannelList = vos_mem_malloc(pScanFilter->ChannelInfo.numOfChannels * sizeof(tANI_U8));
+ if (NULL == pScanFilter->ChannelInfo.ChannelList)
+ {
+ smsLog(pMac, LOGE, FL("Scan Filter Channel list mem alloc failed"));
+ vos_mem_free(pScanFilter->SSIDs.SSIDList);
+ pScanFilter->SSIDs.SSIDList = NULL;
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ for (i = 0; i < pScanFilter->ChannelInfo.numOfChannels; i++)
+ {
+ pScanFilter->ChannelInfo.ChannelList[i] = pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i];
+ }
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (pNeighborRoamInfo->is11rAssoc)
+ {
+ /* MDIE should be added as a part of profile. This should be added as a part of filter as well */
+ pScanFilter->MDID.mdiePresent = pCurProfile->MDID.mdiePresent;
+ pScanFilter->MDID.mobilityDomain = pCurProfile->MDID.mobilityDomain;
+ }
+#endif
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamProcessScanResults
+
+ \brief This function extracts scan results, sorts on the basis of neighbor score(todo).
+ Assumed that the results are already sorted by RSSI by csrScanGetResult
+
+ \param pMac - The handle returned by macOpen.
+ pScanResultList - Scan result result obtained from csrScanGetResult()
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+
+static void csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, tScanResultHandle *pScanResultList)
+{
+ tCsrScanResultInfo *pScanResult;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ tpCsrNeighborRoamBSSInfo pBssInfo;
+
+ /* Expecting the scan result already to be in the sorted order based on the RSSI */
+ /* Based on the previous state we need to check whether the list should be sorted again taking neighbor score into consideration */
+ /* If previous state is CFG_CHAN_LIST_SCAN, there should not be any neighbor score associated with any of the BSS.
+ If the previous state is REPORT_QUERY, then there will be neighbor score for each of the APs */
+ /* For now, let us take the top of the list provided as it is by the CSR Scan result API. This means it is assumed that neighbor score
+ and rssi score are in the same order. This will be taken care later */
+
+ while (NULL != (pScanResult = csrScanResultGetNext(pMac, *pScanResultList)))
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Scan result: BSSID : %02x:%02x:%02x:%02x:%02x:%02x"),
+ pScanResult->BssDescriptor.bssId[0],
+ pScanResult->BssDescriptor.bssId[1],
+ pScanResult->BssDescriptor.bssId[2],
+ pScanResult->BssDescriptor.bssId[3],
+ pScanResult->BssDescriptor.bssId[4],
+ pScanResult->BssDescriptor.bssId[5]);
+
+ if (VOS_TRUE == vos_mem_compare(pScanResult->BssDescriptor.bssId,
+ pNeighborRoamInfo->currAPbssid, sizeof(tSirMacAddr)))
+ {
+ //currently associated AP. Do not have this in the roamable AP list
+ continue;
+ }
+
+ if (abs(pNeighborRoamInfo->cfgParams.neighborReassocThreshold) < abs(pScanResult->BssDescriptor.rssi))
+ {
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "%s: [INFOLOG]Current reassoc threshold %d new ap rssi worse=%d\n", __func__,
+ (int)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1),
+ (int)pScanResult->BssDescriptor.rssi * (-1) );
+ continue;
+ }
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (pNeighborRoamInfo->is11rAssoc)
+ {
+ if (!csrNeighborRoamIsPreauthCandidate(pMac, pScanResult->BssDescriptor.bssId))
+ {
+ smsLog(pMac, LOGE, FL("BSSID present in pre-auth fail list.. Ignoring"));
+ continue;
+ }
+ }
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+#ifdef FEATURE_WLAN_CCX
+ if (pNeighborRoamInfo->isCCXAssoc)
+ {
+ if (!csrNeighborRoamIsPreauthCandidate(pMac, pScanResult->BssDescriptor.bssId))
+ {
+ smsLog(pMac, LOGE, FL("BSSID present in pre-auth fail list.. Ignoring"));
+ continue;
+ }
+ }
+ if ((pScanResult->BssDescriptor.QBSSLoad_present) &&
+ (pScanResult->BssDescriptor.QBSSLoad_avail))
+ {
+ if (pNeighborRoamInfo->isVOAdmitted)
+ {
+ smsLog(pMac, LOG1, FL("New AP has %x BW available\n"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail);
+ smsLog(pMac, LOG1, FL("We need %x BW available\n"),(unsigned int)pNeighborRoamInfo->MinQBssLoadRequired);
+ if (pScanResult->BssDescriptor.QBSSLoad_avail < pNeighborRoamInfo->MinQBssLoadRequired)
+ {
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no bandwidth ignoring..not adding to roam list\n",
+ pScanResult->BssDescriptor.bssId[0],
+ pScanResult->BssDescriptor.bssId[1],
+ pScanResult->BssDescriptor.bssId[2],
+ pScanResult->BssDescriptor.bssId[3],
+ pScanResult->BssDescriptor.bssId[4],
+ pScanResult->BssDescriptor.bssId[5]);
+ continue;
+ }
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("No QBss %x %x\n"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail, (unsigned int)pScanResult->BssDescriptor.QBSSLoad_present);
+ if (pNeighborRoamInfo->isVOAdmitted)
+ {
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no QBSSLoad IE, ignoring..not adding to roam list\n",
+ pScanResult->BssDescriptor.bssId[0],
+ pScanResult->BssDescriptor.bssId[1],
+ pScanResult->BssDescriptor.bssId[2],
+ pScanResult->BssDescriptor.bssId[3],
+ pScanResult->BssDescriptor.bssId[4],
+ pScanResult->BssDescriptor.bssId[5]);
+ continue;
+ }
+ }
+#endif /* FEATURE_WLAN_CCX */
+
+ /* If the received timestamp in BSS description is earlier than the scan request timestamp, skip
+ * this result */
+ if (pNeighborRoamInfo->scanRequestTimeStamp >= pScanResult->BssDescriptor.nReceivedTime)
+ {
+ smsLog(pMac, LOGE, FL("Ignoring BSS as it is older than the scan request timestamp"));
+ continue;
+ }
+
+ pBssInfo = vos_mem_malloc(sizeof(tCsrNeighborRoamBSSInfo));
+ if (NULL == pBssInfo)
+ {
+ smsLog(pMac, LOGE, FL("Memory allocation for Neighbor Roam BSS Info failed.. Just ignoring"));
+ continue;
+ }
+
+ pBssInfo->pBssDescription = vos_mem_malloc(pScanResult->BssDescriptor.length + sizeof(pScanResult->BssDescriptor.length));
+ if (pBssInfo->pBssDescription != NULL)
+ {
+ vos_mem_copy(pBssInfo->pBssDescription, &pScanResult->BssDescriptor,
+ pScanResult->BssDescriptor.length + sizeof(pScanResult->BssDescriptor.length));
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("Memory allocation for Neighbor Roam BSS Descriptor failed.. Just ignoring"));
+ vos_mem_free(pBssInfo);
+ continue;
+
+ }
+ pBssInfo->apPreferenceVal = 10; //some value for now. Need to calculate the actual score based on RSSI and neighbor AP score
+
+ /* Just add to the end of the list as it is already sorted by RSSI */
+ csrLLInsertTail(&pNeighborRoamInfo->roamableAPList, &pBssInfo->List, LL_ACCESS_LOCK);
+ }
+
+ /* Now we have all the scan results in our local list. Good time to free up the the list we got as a part of csrGetScanResult */
+ csrScanResultPurge(pMac, *pScanResultList);
+
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamHandleEmptyScanResult
+
+ \brief This function will be invoked in CFG_CHAN_LIST_SCAN state when
+ there are no valid APs in the scan result for roaming. This means
+ out AP is the best and no other AP is around. No point in scanning
+ again and again. Performing the following here.
+ 1. Deregister the pre-auth callback from TL
+ 2. Stop the neighbor scan timer
+ 3. Re-register the neighbor lookup callback with increased pre-auth threshold
+ 4. Transition the state to CONNECTED state
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+static VOS_STATUS csrNeighborRoamHandleEmptyScanResult(tpAniSirGlobal pMac)
+{
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ /* Stop the neighbor scan timer now */
+ status = palTimerStop(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGW, FL(" palTimerStop failed with status %d\n"), status);
+ }
+
+ /* Increase the neighbor lookup threshold by a constant factor or 1 */
+ if ((pNeighborRoamInfo->currentNeighborLookupThreshold+3) < pNeighborRoamInfo->cfgParams.neighborReassocThreshold)
+ {
+ pNeighborRoamInfo->currentNeighborLookupThreshold += 3;
+ }
+
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ /* Clear off the old neighbor report details */
+ vos_mem_zero(&pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo, sizeof(tCsrNeighborReportBssInfo) * MAX_BSS_IN_NEIGHBOR_RPT);
+#endif
+
+ /* Reset all the necessary variables before transitioning to the CONNECTED state */
+ csrNeighborRoamResetConnectedStateControlInfo(pMac);
+
+ /* Transition to CONNECTED state */
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)
+ /* Re-register Neighbor Lookup threshold callback with TL */
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering DOWN event neighbor lookup callback with TL for RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold * (-1));
+ vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamNeighborLookupDOWNCallback,
+ VOS_MODULE_ID_SME, pMac);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't re-register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d\n"), status);
+ }
+ return vosStatus;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamScanRequestCallback
+
+ \brief This function is the callback function registered in csrScanRequest() to
+ indicate the completion of scan. If scan is completed for all the channels in
+ the channel list, this function gets the scan result and starts the refresh results
+ timer to avoid having stale results. If scan is not completed on all the channels,
+ it restarts the neighbor scan timer which on expiry issues scan on the next
+ channel
+
+ \param halHandle - The handle returned by macOpen.
+ pContext - not used
+ scanId - not used
+ status - not used
+
+ \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, void *pContext,
+ tANI_U32 scanId, eCsrScanStatus status)
+{
+ tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ tANI_U8 currentChanIndex;
+ tCsrScanResultFilter scanFilter;
+ tScanResultHandle scanResult;
+ tANI_U32 tempVal = 0;
+
+ pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_FALSE;
+
+ /* This can happen when we receive a UP event from TL in any of the scan states. Silently ignore it */
+ if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == pNeighborRoamInfo->neighborRoamState)
+ {
+ smsLog(pMac, LOGE, FL("Received in CONNECTED state. Must be because a UP event from TL after issuing scan request. Ignore it"));
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ /* -1 is done because the chanIndex would have got incremented after issuing a successful scan request */
+ currentChanIndex = (pMac->roam.neighborRoamInfo.roamChannelInfo.currentChanIndex) ? (pMac->roam.neighborRoamInfo.roamChannelInfo.currentChanIndex - 1) : 0;
+
+ /* Validate inputs */
+ if (pMac->roam.neighborRoamInfo.roamChannelInfo.currentChannelListInfo.ChannelList) {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("csrNeighborRoamScanRequestCallback received for Channel = %d, ChanIndex = %d"),
+ pMac->roam.neighborRoamInfo.roamChannelInfo.currentChannelListInfo.ChannelList[currentChanIndex], currentChanIndex);
+ }
+ else
+ {
+ smsLog(pMac, LOG1, FL("Received during clean-up. Silently ignore scan completion event."));
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ if (eANI_BOOLEAN_FALSE == pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress)
+ {
+ /* Scan is completed in the CFG_CHAN_SCAN state. We can transition to REPORT_SCAN state
+ just to get the results and perform PREAUTH */
+ /* Now we have completed scanning the channel list. We have get the result by applying appropriate filter
+ sort the results based on neighborScore and RSSI and select the best candidate out of the list */
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Channel list scan completed. Current chan index = %d"), currentChanIndex);
+ VOS_ASSERT(pNeighborRoamInfo->roamChannelInfo.currentChanIndex == 0);
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ /* If the state is REPORT_SCAN, then this must be the scan after the REPORT_QUERY state. So, we
+ should use the BSSID filter made out of neighbor reports */
+ if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState)
+ {
+ status = csrNeighborRoamBssIdScanFilter(pMac, &scanFilter);
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("11R or CCX Association: Prepare scan filter status with neighbor AP = %d"), status);
+ tempVal = 1;
+ }
+ else
+#endif
+ {
+ status = csrNeighborRoamPrepareScanProfileFilter(pMac, &scanFilter);
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("11R/CCX/Other Association: Prepare scan to find neighbor AP filter status = %d"), status);
+ }
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Scan Filter preparation failed for Assoc type %d.. Bailing out.."), tempVal);
+ return eHAL_STATUS_FAILURE;
+ }
+ status = csrScanGetResult(pMac, &scanFilter, &scanResult);
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Get Scan Result status code %d"), status);
+ /* Process the scan results and update roamable AP list */
+ csrNeighborRoamProcessScanResults(pMac, &scanResult);
+
+ /* Free the scan filter */
+ csrFreeScanFilter(pMac, &scanFilter);
+
+ tempVal = csrLLCount(&pNeighborRoamInfo->roamableAPList);
+
+ switch(pNeighborRoamInfo->neighborRoamState)
+ {
+ case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN:
+ if (tempVal)
+ {
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ /* If this is a non-11r association, then we can register the reassoc callback here as we have some
+ APs in the roamable AP list */
+ if (pNeighborRoamInfo->is11rAssoc)
+ {
+ /* Valid APs are found after scan. Now we can initiate pre-authentication */
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN)
+ }
+ else
+#endif
+#ifdef FEATURE_WLAN_CCX
+ /* If this is a non-11r association, then we can register the reassoc callback here as we have some
+ APs in the roamable AP list */
+ if (pNeighborRoamInfo->isCCXAssoc)
+ {
+ /* Valid APs are found after scan. Now we can initiate pre-authentication */
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN)
+ }
+ else
+#endif
+ {
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Completed scanning of CFG CHAN LIST in non-11r association. Registering reassoc callback"));
+ /* Nothing much to do now. Will continue to remain in this state in case of non-11r association */
+ /* Stop the timer. But how long the roamable AP list will be valid in here. At some point of time, we
+ need to restart the CFG CHAN list scan procedure if reassoc callback is not invoked from TL
+ within certain duration */
+
+// palTimerStop(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer);
+ }
+ }
+ else
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("No candidate found after scanning in state %d.. "), pNeighborRoamInfo->neighborRoamState);
+ /* Handle it appropriately */
+ csrNeighborRoamHandleEmptyScanResult(pMac);
+ }
+ break;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN:
+ if (!tempVal)
+ {
+ smsLog(pMac, LOGE, FL("No candidate found after scanning in state %d.. "), pNeighborRoamInfo->neighborRoamState);
+ /* Stop the timer here as the same timer will be started again in CFG_CHAN_SCAN_STATE */
+ csrNeighborRoamTransitToCFGChanScan(pMac);
+ }
+ break;
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+ default:
+ // Can come only in INIT state. Where in we are associated, we sent scan and user
+ // in the meantime decides to disassoc, we will be in init state and still received call
+ // back issued. Should not come here in any other state, printing just in case
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "%s: [INFOLOG] State %d\n", __func__, (pNeighborRoamInfo->neighborRoamState));
+
+ // Lets just exit out silently.
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ if (tempVal)
+ {
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+
+ /* This timer should be started before registering the Reassoc callback with TL. This is because, it is very likely
+ * that the callback getting called immediately and the timer would never be stopped when pre-auth is in progress */
+ if (eHAL_STATUS_SUCCESS != palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer,
+ pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod * PAL_TIMER_TO_MS_UNIT,
+ eANI_BOOLEAN_FALSE))
+ {
+ smsLog(pMac, LOGE, FL("Neighbor results refresh timer failed to start, status = %d"), status);
+ vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList);
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering DOWN event Reassoc callback with TL. RSSI = %d"), pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1));
+ /* Register a reassoc Indication callback */
+ vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamReassocIndCallback,
+ VOS_MODULE_ID_SME, pMac);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamReassocIndCallback with TL: Status = %d\n"), vosStatus);
+ }
+
+ }
+ }
+ else
+ {
+
+ /* Restart the timer for the next scan sequence as scanning is not over */
+ status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer,
+ pNeighborRoamInfo->cfgParams.neighborScanPeriod * PAL_TIMER_TO_MS_UNIT,
+ eANI_BOOLEAN_FALSE);
+
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ /* Timer start failed.. Should we ASSERT here??? */
+ smsLog(pMac, LOGE, FL("Neighbor scan PAL Timer start failed, status = %d, Ignoring state transition"), status);
+ vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList);
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamIssueBgScanRequest
+
+ \brief This function issues CSR scan request after populating all the BG scan params
+ passed
+
+ \param pMac - The handle returned by macOpen.
+ pBgScanParams - Params that need to be populated into csr Scan request
+
+ \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+eHalStatus csrNeighborRoamIssueBgScanRequest(tpAniSirGlobal pMac, tCsrBGScanRequest *pBgScanParams)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_U32 scanId;
+ tCsrScanRequest scanReq;
+ tANI_U8 channel;
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("csrNeighborRoamIssueBgScanRequest for Channel = %d, ChanIndex = %d"),
+ pBgScanParams->ChannelInfo.ChannelList[0], pMac->roam.neighborRoamInfo.roamChannelInfo.currentChanIndex);
+
+
+ //send down the scan req for 1 channel on the associated SSID
+ palZeroMemory(pMac->hHdd, &scanReq, sizeof(tCsrScanRequest));
+ /* Fill in the SSID Info */
+ scanReq.SSIDs.numOfSSIDs = 1;
+ scanReq.SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo) * scanReq.SSIDs.numOfSSIDs);
+ if(NULL == scanReq.SSIDs.SSIDList)
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL("Couldn't allocate memory for the SSID..Freeing memory allocated for Channel List\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_zero(scanReq.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) * scanReq.SSIDs.numOfSSIDs);
+
+ scanReq.SSIDs.SSIDList[0].handoffPermitted = eANI_BOOLEAN_TRUE;
+ scanReq.SSIDs.SSIDList[0].ssidHidden = eANI_BOOLEAN_TRUE;
+ vos_mem_copy((void *)&scanReq.SSIDs.SSIDList[0].SSID, (void *)&pBgScanParams->SSID, sizeof(pBgScanParams->SSID));
+
+ scanReq.ChannelInfo.numOfChannels = pBgScanParams->ChannelInfo.numOfChannels;
+
+ channel = pBgScanParams->ChannelInfo.ChannelList[0];
+ scanReq.ChannelInfo.ChannelList = &channel;
+
+ scanReq.BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
+ scanReq.scanType = eSIR_ACTIVE_SCAN;
+ scanReq.requestType = eCSR_SCAN_HO_BG_SCAN;
+ scanReq.maxChnTime = pBgScanParams->maxChnTime;
+ scanReq.minChnTime = pBgScanParams->minChnTime;
+ status = csrScanRequest(pMac, CSR_SESSION_ID_INVALID, &scanReq,
+ &scanId, csrNeighborRoamScanRequestCallback, NULL);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("CSR Scan Request failed with status %d"), status);
+ vos_mem_free(scanReq.SSIDs.SSIDList);
+ return status;
+ }
+ pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_TRUE;
+
+ vos_mem_free(scanReq.SSIDs.SSIDList);
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Channel List Address = %08x, Actual index = %d"),
+ &pMac->roam.neighborRoamInfo.roamChannelInfo.currentChannelListInfo.ChannelList[0],
+ pMac->roam.neighborRoamInfo.roamChannelInfo.currentChanIndex);
+ return status;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamPerformBgScan
+
+ \brief This function is invoked on every expiry of neighborScanTimer till all
+ the channels in the channel list are scanned. It populates necessary
+ parameters for BG scan and calls appropriate AP to invoke the CSR scan
+ request
+
+ \param pMac - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ tCsrBGScanRequest bgScanParams;
+ tANI_U8 broadcastBssid[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ tANI_U8 channel = 0;
+
+ if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList)
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Channel List Address = %08x"), &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[0]);
+ }
+ else
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Channel List Empty"));
+ // Go back and restart. Mostly timer start failure has occured.
+ // When timer start is declared a failure, then we delete the list.
+ // Should not happen now as we stop and then only start the scan timer.
+ // still handle the unlikely case.
+ csrNeighborRoamHandleEmptyScanResult(pMac);
+ return status;
+ }
+ /* Need to perform scan here before getting the list */
+ vos_mem_copy(bgScanParams.bssid, broadcastBssid, sizeof(tCsrBssid));
+ bgScanParams.SSID.length = pMac->roam.roamSession[pNeighborRoamInfo->csrSessionId].connectedProfile.SSID.length;
+ vos_mem_copy(bgScanParams.SSID.ssId, pMac->roam.roamSession[pNeighborRoamInfo->csrSessionId].connectedProfile.SSID.ssId,
+ pMac->roam.roamSession[pNeighborRoamInfo->csrSessionId].connectedProfile.SSID.length);
+
+ channel = pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[pNeighborRoamInfo->roamChannelInfo.currentChanIndex];
+ bgScanParams.ChannelInfo.numOfChannels = 1;
+ bgScanParams.ChannelInfo.ChannelList = &channel;
+
+ bgScanParams.minChnTime = pNeighborRoamInfo->cfgParams.minChannelScanTime;
+ bgScanParams.maxChnTime = pNeighborRoamInfo->cfgParams.maxChannelScanTime;
+
+ status = csrNeighborRoamIssueBgScanRequest(pMac, &bgScanParams);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Issue of BG Scan request failed: Status = %d"), status);
+ return status;
+ }
+
+ pNeighborRoamInfo->roamChannelInfo.currentChanIndex++;
+ if (pNeighborRoamInfo->roamChannelInfo.currentChanIndex >=
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels)
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Completed scanning channels in Channel List: CurrChanIndex = %d, Num Channels = %d"),
+ pNeighborRoamInfo->roamChannelInfo.currentChanIndex,
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels);
+ /* We have completed scanning all the channels */
+ pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0;
+ /* We are no longer scanning the channel list. Next timer firing should be used to get the scan results
+ and select the best AP in the list */
+ if (eANI_BOOLEAN_TRUE == pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress)
+ {
+ pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_FALSE;
+ }
+ }
+
+ return status;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamNeighborScanTimerCallback
+
+ \brief This function is the neighbor scan timer callback function. It invokes
+ the BG scan request based on the current and previous states
+
+ \param pv - CSR timer context info which includes pMac and session ID
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamNeighborScanTimerCallback(void *pv)
+{
+ tCsrTimerInfo *pInfo = (tCsrTimerInfo *)pv;
+ tpAniSirGlobal pMac = pInfo->pMac;
+ tANI_U32 sessionId = pInfo->sessionId;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ // check if bg scan is on going, no need to send down the new params if true
+ if(eANI_BOOLEAN_TRUE == pNeighborRoamInfo->scanRspPending)
+ {
+ //msg
+ smsLog(pMac, LOGW, FL("Already BgScanRsp is Pending\n"));
+ return;
+ }
+
+ VOS_ASSERT(sessionId == pNeighborRoamInfo->csrSessionId);
+
+ switch (pNeighborRoamInfo->neighborRoamState)
+ {
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN:
+ switch(pNeighborRoamInfo->prevNeighborRoamState)
+ {
+ case eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY:
+ csrNeighborRoamPerformBgScan(pMac);
+ break;
+ default:
+ smsLog(pMac, LOGE, FL("Neighbor scan callback received in state %d, prev state = %d"),
+ pNeighborRoamInfo->neighborRoamState, pNeighborRoamInfo->prevNeighborRoamState);
+ break;
+ }
+ break;
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+ case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN:
+ csrNeighborRoamPerformBgScan(pMac);
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamResultsRefreshTimerCallback
+
+ \brief This function is the timer callback function for results refresh timer.
+ When this is invoked, it is as good as down event received from TL. So,
+ clear off the roamable AP list and start the scan procedure based on 11R
+ or non-11R association
+
+ \param context - CSR timer context info which includes pMac and session ID
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamResultsRefreshTimerCallback(void *context)
+{
+ tCsrTimerInfo *pInfo = (tCsrTimerInfo *)context;
+ tpAniSirGlobal pMac = pInfo->pMac;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering DOWN event reassoc callback with TL. RSSI = %d"), pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1));
+
+ /* Deregister reassoc callback. Ignore return status */
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamReassocIndCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamReassocIndCallback with TL: Status = %d\n"), vosStatus);
+ }
+
+ /* Reset all the variables just as no scan had happened before */
+ csrNeighborRoamResetConnectedStateControlInfo(pMac);
+
+#if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI
+ if ((pNeighborRoamInfo->is11rAssoc) && (pMac->rrm.rrmSmeContext.rrmConfig.rrmEnabled))
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("11R Association:Neighbor Lookup Down event received in CONNECTED state"));
+ vosStatus = csrNeighborRoamIssueNeighborRptRequest(pMac);
+ if (VOS_STATUS_SUCCESS != vosStatus)
+ {
+ smsLog(pMac, LOGE, FL("Neighbor report request failed. status = %d\n"), vosStatus);
+ return;
+ }
+ /* Increment the neighbor report retry count after sending the neighbor request successfully */
+ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum++;
+ pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_TRUE;
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY)
+ }
+ else
+#endif
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Non 11R or CCX Association:Neighbor Lookup Down event received in CONNECTED state"));
+ vosStatus = csrNeighborRoamTransitToCFGChanScan(pMac);
+ if (VOS_STATUS_SUCCESS != vosStatus)
+ {
+ return;
+ }
+ }
+ return;
+}
+
+#if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamIssueNeighborRptRequest
+
+ \brief This function is invoked when TL issues a down event and the current assoc
+ is a 11R association. It invokes SME RRM API to issue the neighbor request to
+ the currently associated AP with the current SSID
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+VOS_STATUS csrNeighborRoamIssueNeighborRptRequest(tpAniSirGlobal pMac)
+{
+ tRrmNeighborRspCallbackInfo callbackInfo;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ tRrmNeighborReq neighborReq;
+
+
+ neighborReq.no_ssid = 0;
+
+ /* Fill in the SSID */
+ neighborReq.ssid.length = pMac->roam.roamSession[pNeighborRoamInfo->csrSessionId].connectedProfile.SSID.length;
+ vos_mem_copy(neighborReq.ssid.ssId, pMac->roam.roamSession[pNeighborRoamInfo->csrSessionId].connectedProfile.SSID.ssId,
+ pMac->roam.roamSession[pNeighborRoamInfo->csrSessionId].connectedProfile.SSID.length);
+
+ callbackInfo.neighborRspCallback = csrNeighborRoamRRMNeighborReportResult;
+ callbackInfo.neighborRspCallbackContext = pMac;
+ callbackInfo.timeout = pNeighborRoamInfo->FTRoamInfo.neighborReportTimeout;
+
+ return sme_NeighborReportRequest(pMac,(tANI_U8) pNeighborRoamInfo->csrSessionId, &neighborReq, &callbackInfo);
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamCreateChanListFromNeighborReport
+
+ \brief This function is invoked when neighbor report is received for the
+ neighbor request. Based on the channels present in the neighbor report,
+ it generates channel list which will be used in REPORT_SCAN state to
+ scan for these neighbor APs
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+VOS_STATUS csrNeighborRoamCreateChanListFromNeighborReport(tpAniSirGlobal pMac)
+{
+ tpRrmNeighborReportDesc pNeighborBssDesc;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ tANI_U8 numChannels = 0, i = 0, j=0;
+ tANI_U8 channelList[MAX_BSS_IN_NEIGHBOR_RPT];
+
+ /* This should always start from 0 whenever we create a channel list out of neighbor AP list */
+ pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0;
+
+ pNeighborBssDesc = smeRrmGetFirstBssEntryFromNeighborCache(pMac);
+
+ while (pNeighborBssDesc)
+ {
+ if (pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport >= MAX_BSS_IN_NEIGHBOR_RPT) break;
+
+ /* Update the neighbor BSS Info in the 11r FT Roam Info */
+ pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo[pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport].channelNum =
+ pNeighborBssDesc->pNeighborBssDescription->channel;
+ pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo[pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport].neighborScore =
+ (tANI_U8)pNeighborBssDesc->roamScore;
+ vos_mem_copy(pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo[pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport].neighborBssId,
+ pNeighborBssDesc->pNeighborBssDescription->bssId, sizeof(tSirMacAddr));
+ pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport++;
+
+ /* Saving the channel list non-redundantly */
+ if (numChannels > 0)
+ {
+ for (i = 0; i < numChannels; i++)
+ {
+ if (pNeighborBssDesc->pNeighborBssDescription->channel == channelList[i])
+ break;
+ }
+
+ }
+ if (i == numChannels)
+ {
+ if (pNeighborBssDesc->pNeighborBssDescription->channel)
+ {
+ // Make sure to add only if its the same band
+ if ((pNeighborRoamInfo->currAPoperationChannel <= (RF_CHAN_14+1)) &&
+ (pNeighborBssDesc->pNeighborBssDescription->channel <= (RF_CHAN_14+1)))
+ {
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "%s: [INFOLOG] Adding %d to Neighbor channel list\n", __func__,
+ pNeighborBssDesc->pNeighborBssDescription->channel);
+ channelList[numChannels] = pNeighborBssDesc->pNeighborBssDescription->channel;
+ numChannels++;
+ }
+ else if ((pNeighborRoamInfo->currAPoperationChannel >= RF_CHAN_128) &&
+ (pNeighborBssDesc->pNeighborBssDescription->channel >= RF_CHAN_128))
+ {
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "%s: [INFOLOG] Adding %d to Neighbor channel list\n", __func__,
+ pNeighborBssDesc->pNeighborBssDescription->channel);
+ channelList[numChannels] = pNeighborBssDesc->pNeighborBssDescription->channel;
+ numChannels++;
+ }
+ }
+ }
+
+ pNeighborBssDesc = smeRrmGetNextBssEntryFromNeighborCache(pMac, pNeighborBssDesc);
+ }
+
+ if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList)
+ {
+ // Before we free the existing channel list for a safety net make sure
+ // we have a union of the IAPP and the already existing list.
+ for (i = 0; i < pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels; i++)
+ {
+ for (j = 0; j < numChannels; j++)
+ {
+ if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i] == channelList[j])
+ break;
+ }
+ if (j == numChannels)
+ {
+ if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i])
+ {
+ // Make sure to add only if its the same band
+ if ((pNeighborRoamInfo->currAPoperationChannel <= (RF_CHAN_14+1)) &&
+ (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i] <= (RF_CHAN_14+1)))
+ {
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "%s: [INFOLOG] Adding extra %d to Neighbor channel list\n", __func__,
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i]);
+ channelList[numChannels] =
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i];
+ numChannels++;
+ }
+ if ((pNeighborRoamInfo->currAPoperationChannel >= RF_CHAN_128) &&
+ (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i] >= RF_CHAN_128))
+ {
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "%s: [INFOLOG] Adding extra %d to Neighbor channel list\n", __func__,
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i]);
+ channelList[numChannels] =
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i];
+ numChannels++;
+ }
+ }
+ }
+ }
+ vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList);
+ }
+
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ /* Store the obtained channel list to the Neighbor Control data structure */
+ if (numChannels)
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = vos_mem_malloc((numChannels) * sizeof(tANI_U8));
+ if (NULL == pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList)
+ {
+ smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed.. TL event ignored"));
+ return VOS_STATUS_E_RESOURCES;
+ }
+
+ vos_mem_copy(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList,
+ channelList, (numChannels) * sizeof(tANI_U8));
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = numChannels;
+ if (numChannels)
+ {
+ smsLog(pMac, LOG1, FL("IAPP Neighbor list callback received as expected in state %d."),
+ pNeighborRoamInfo->neighborRoamState);
+ pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_TRUE;
+ }
+ pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0;
+ pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_TRUE;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamRRMNeighborReportResult
+
+ \brief This function is the neighbor report callback that will be invoked by
+ SME RRM on receiving a neighbor report or of neighbor report is not
+ received after timeout. On receiving a valid report, it generates a
+ channel list from the neighbor report and starts the
+ neighbor scan timer
+
+ \param context - The handle returned by macOpen.
+ vosStatus - Status of the callback(SUCCESS/FAILURE)
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamRRMNeighborReportResult(void *context, VOS_STATUS vosStatus)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(context);
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ smsLog(pMac, LOG1, FL("Neighbor report result callback with status = %d\n"), vosStatus);
+ switch (pNeighborRoamInfo->neighborRoamState)
+ {
+ case eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY:
+ /* Reset the report pending variable */
+ pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_FALSE;
+ if (VOS_STATUS_SUCCESS == vosStatus)
+ {
+ /* Need to create channel list based on the neighbor AP list and transition to REPORT_SCAN state */
+ vosStatus = csrNeighborRoamCreateChanListFromNeighborReport(pMac);
+ if (VOS_STATUS_SUCCESS == vosStatus)
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Channel List created from Neighbor report, Transitioning to NEIGHBOR_SCAN state\n"));
+ }
+
+ /* We are gonna scan now. Remember the time stamp to filter out results only after this timestamp */
+ pNeighborRoamInfo->scanRequestTimeStamp = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd);
+
+ /* Now ready for neighbor scan based on the channel list created */
+ /* Start Neighbor scan timer now. Multiplication by PAL_TIMER_TO_MS_UNIT is to convert ms to us which is
+ what palTimerStart expects */
+ status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer,
+ pNeighborRoamInfo->cfgParams.neighborScanPeriod * PAL_TIMER_TO_MS_UNIT,
+ eANI_BOOLEAN_FALSE);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ /* Timer start failed.. Should we ASSERT here??? */
+ smsLog(pMac, LOGE, FL("PAL Timer start for neighbor scan timer failed, status = %d, Ignoring state transition"), status);
+ vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList);
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ return;
+ }
+ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0;
+ /* Neighbor scan timer started. Transition to REPORT_SCAN state */
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN)
+ }
+ else
+ {
+ /* Neighbor report timeout happened in SME RRM. We can try sending more neighbor requests until we
+ reach the maxNeighborRetries or receiving a successful neighbor response */
+ smsLog(pMac, LOGE, FL("Neighbor report result failed after %d retries, MAX RETRIES = %d\n"),
+ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum, pNeighborRoamInfo->cfgParams.maxNeighborRetries);
+ if (pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum >=
+ pNeighborRoamInfo->cfgParams.maxNeighborRetries)
+ {
+ smsLog(pMac, LOGE, FL("Bailing out to CFG Channel list scan.. \n"));
+ vosStatus = csrNeighborRoamTransitToCFGChanScan(pMac);
+ if (VOS_STATUS_SUCCESS != vosStatus)
+ {
+ smsLog(pMac, LOGE, FL("Transit to CFG Channel list scan state failed with status %d \n"), vosStatus);
+ return;
+ }
+ /* We transitioned to different state now. Reset the Neighbor report retry count */
+ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0;
+ }
+ else
+ {
+ vosStatus = csrNeighborRoamIssueNeighborRptRequest(pMac);
+ if (VOS_STATUS_SUCCESS != vosStatus)
+ {
+ smsLog(pMac, LOGE, FL("Neighbor report request failed. status = %d\n"), vosStatus);
+ return;
+ }
+ pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_TRUE;
+ /* Increment the neighbor report retry count after sending the neighbor request successfully */
+ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum++;
+ }
+ }
+ break;
+ default:
+ smsLog(pMac, LOGE, FL("Neighbor result callback not expected in state %d, Ignoring.."), pNeighborRoamInfo->neighborRoamState);
+ break;
+ }
+ return;
+}
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamTransitToCFGChanScan
+
+ \brief This function is called whenever there is a transition to CFG chan scan
+ state from any state. It frees up the current channel list and allocates
+ a new memory for the channels received from CFG item. It then starts the
+ neighbor scan timer to perform the scan on each channel one by one
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ int i = 0;
+ int numOfChannels = 0;
+ tANI_U8 channelList[MAX_BSS_IN_NEIGHBOR_RPT];
+
+ if (
+#ifdef FEATURE_WLAN_CCX
+ ((pNeighborRoamInfo->isCCXAssoc) &&
+ (pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived == eANI_BOOLEAN_FALSE)) ||
+ (pNeighborRoamInfo->isCCXAssoc == eANI_BOOLEAN_FALSE) ||
+#endif // CCX
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels == 0)
+
+ {
+ smsLog(pMac, LOGW, FL("Falling back to CFG channel list"));
+
+
+ /* Free up the channel list and allocate a new memory. This is because we dont know how much
+ was allocated last time. If we directly copy more number of bytes than allocated earlier, this might
+ result in memory corruption */
+ if (NULL != pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList)
+ {
+ vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList);
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ }
+ // Find the right subset of the cfg list based on the current band we are on.
+ for (i = 0; i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++)
+ {
+ if (pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i])
+ {
+ // Make sure to add only if its the same band
+ if ((pNeighborRoamInfo->currAPoperationChannel <= (RF_CHAN_14+1)) &&
+ (pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i] <= (RF_CHAN_14+1)))
+ {
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: [INFOLOG] Adding %d to Neighbor channel list\n", __func__,
+ pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]);
+ channelList[numOfChannels] = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i];
+ numOfChannels++;
+ }
+ if ((pNeighborRoamInfo->currAPoperationChannel >= RF_CHAN_128) &&
+ (pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i] >= RF_CHAN_128))
+ {
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: [INFOLOG] Adding %d to Neighbor channel list\n", __func__,
+ pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]);
+ channelList[numOfChannels] = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i];
+ numOfChannels++;
+ }
+ }
+ }
+
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = numOfChannels;
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ if (numOfChannels)
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = vos_mem_malloc(numOfChannels);
+
+ if (NULL == pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList)
+ {
+ smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed.. TL event ignored"));
+ return VOS_STATUS_E_RESOURCES;
+ }
+
+ /* Since this is a legacy case, copy the channel list from CFG here */
+ vos_mem_copy(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList,
+ channelList, numOfChannels * sizeof(tANI_U8));
+
+ for (i = 0; i < pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels; i++)
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, "Channel List from CFG = %d\n",
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i]);
+ }
+ }
+
+ /* We are gonna scan now. Remember the time stamp to filter out results only after this timestamp */
+ pNeighborRoamInfo->scanRequestTimeStamp = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd);
+
+ palTimerStop(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer);
+ /* Start Neighbor scan timer now. Multiplication by PAL_TIMER_TO_MS_UNIT is to convert ms to us which is
+ what palTimerStart expects */
+ status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer,
+ pNeighborRoamInfo->cfgParams.neighborScanPeriod * PAL_TIMER_TO_MS_UNIT,
+ eANI_BOOLEAN_FALSE);
+
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ /* Timer start failed.. */
+ smsLog(pMac, LOGE, FL("Neighbor scan PAL Timer start failed, status = %d, Ignoring state transition"), status);
+ vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList);
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0;
+ pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_TRUE;
+
+ /* Transition to CFG_CHAN_LIST_SCAN_STATE */
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN)
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamNeighborLookupUpEvent
+
+ \brief This function is called as soon as TL indicates that the current AP's
+ RSSI is better than the neighbor lookup threshold. Here, we transition to
+ CONNECTED state and reset all the scan parameters
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+VOS_STATUS csrNeighborRoamNeighborLookupUpEvent(tpAniSirGlobal pMac)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ VOS_STATUS vosStatus;
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering UP event neighbor lookup callback with TL. RSSI = %d,"), pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1));
+ /* Deregister the UP event now */
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_UP,
+ csrNeighborRoamNeighborLookupUPCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't Deregister csrNeighborRoamNeighborLookupCallback UP event from TL: Status = %d\n"), vosStatus);
+ }
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering DOWN event neighbor lookup callback with TL. RSSI = %d,"), pNeighborRoamInfo->currentNeighborLookupThreshold * (-1));
+ /* Deregister the UP event now */
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamNeighborLookupDOWNCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't Deregister csrNeighborRoamNeighborLookupCallback UP event from TL: Status = %d\n"), vosStatus);
+ }
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering DOWN event reassoc callback with TL. RSSI = %d"), pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1));
+ /* Deregister reassoc callback. */
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamReassocIndCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamReassocIndCallback with TL: Status = %d\n"), vosStatus);
+ }
+
+
+ /* RSSI got better than the CFG neighbor lookup threshold. Reset the threshold to older value and set the increment multiplier to 0 */
+ pNeighborRoamInfo->currentLookupIncrementMultiplier = 0;
+
+ pNeighborRoamInfo->currentNeighborLookupThreshold = pNeighborRoamInfo->cfgParams.neighborLookupThreshold;
+
+ /* Reset all the neighbor roam info control variables. Free all the allocated memory. It is like we are just associated now */
+ csrNeighborRoamResetConnectedStateControlInfo(pMac);
+
+ /* Recheck whether the below check is needed. */
+ if (pNeighborRoamInfo->neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering DOWN event neighbor lookup callback with TL. RSSI = %d,"), pNeighborRoamInfo->currentNeighborLookupThreshold * (-1));
+ /* Register Neighbor Lookup threshold callback with TL for DOWN event now */
+ vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamNeighborLookupDOWNCallback,
+ VOS_MODULE_ID_SME, pMac);
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback DOWN event with TL: Status = %d\n"), vosStatus);
+ }
+
+
+ return vosStatus;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamNeighborLookupDownEvent
+
+ \brief This function is called as soon as TL indicates that the current AP's
+ RSSI falls below the current eighbor lookup threshold. Here, we transition to
+ REPORT_QUERY for 11r association and CFG_CHAN_LIST_SCAN state if the assoc is
+ a non-11R association.
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+VOS_STATUS csrNeighborRoamNeighborLookupDownEvent(tpAniSirGlobal pMac)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ switch (pNeighborRoamInfo->neighborRoamState)
+ {
+ case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED:
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering DOWN event neighbor lookup callback with TL. RSSI = %d,"),
+ pNeighborRoamInfo->currentNeighborLookupThreshold * (-1));
+ /* De-register Neighbor Lookup threshold callback with TL */
+ vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamNeighborLookupDOWNCallback,
+ VOS_MODULE_ID_SME);
+
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't Deregister csrNeighborRoamNeighborLookupCallback DOWN event from TL: Status = %d\n"), status);
+ }
+
+
+#if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI
+ if ((pNeighborRoamInfo->is11rAssoc) && (pMac->rrm.rrmSmeContext.rrmConfig.rrmEnabled))
+ {
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("11R Association:Neighbor Lookup Down event received in CONNECTED state"));
+ vosStatus = csrNeighborRoamIssueNeighborRptRequest(pMac);
+ if (VOS_STATUS_SUCCESS != vosStatus)
+ {
+ smsLog(pMac, LOGE, FL("Neighbor report request failed. status = %d\n"), vosStatus);
+ return vosStatus;
+ }
+ /* Increment the neighbor report retry count after sending the neighbor request successfully */
+ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum++;
+ pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_TRUE;
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY)
+ }
+ else
+#endif
+ {
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Non 11R or CCX Association:Neighbor Lookup Down event received in CONNECTED state"));
+
+ vosStatus = csrNeighborRoamTransitToCFGChanScan(pMac);
+ if (VOS_STATUS_SUCCESS != vosStatus)
+ {
+ return vosStatus;
+ }
+ }
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering UP event neighbor lookup callback with TL. RSSI = %d,"), pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1));
+ /* Register Neighbor Lookup threshold callback with TL for UP event now */
+ vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_UP,
+ csrNeighborRoamNeighborLookupUPCallback,
+ VOS_MODULE_ID_SME, pMac);
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback UP event with TL: Status = %d\n"), status);
+ }
+ break;
+ default:
+ smsLog(pMac, LOGE, FL("DOWN event received in invalid state %d..Ignoring..."), pNeighborRoamInfo->neighborRoamState);
+ break;
+
+ }
+ return vosStatus;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamNeighborLookupUPCallback
+
+ \brief This function is registered with TL to indicate whenever the RSSI
+ gets better than the neighborLookup RSSI Threshold
+
+ \param pAdapter - VOS Context
+ trafficStatus - UP/DOWN indication from TL
+ pUserCtxt - Parameter for callback registered during callback registration. Should be pMac
+
+ \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+VOS_STATUS csrNeighborRoamNeighborLookupUPCallback (v_PVOID_t pAdapter, v_U8_t rssiNotification,
+ v_PVOID_t pUserCtxt)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pUserCtxt );
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Neighbor Lookup UP indication callback called with notification %d"), rssiNotification);
+
+ if(!csrIsConnStateConnectedInfra(pMac, pNeighborRoamInfo->csrSessionId))
+ {
+ smsLog(pMac, LOGW, "Ignoring the indication as we are not connected\n");
+ return VOS_STATUS_SUCCESS;
+ }
+
+ VOS_ASSERT(WLANTL_HO_THRESHOLD_UP == rssiNotification);
+ vosStatus = csrNeighborRoamNeighborLookupUpEvent(pMac);
+ return vosStatus;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamNeighborLookupDOWNCallback
+
+ \brief This function is registered with TL to indicate whenever the RSSI
+ falls below the current neighborLookup RSSI Threshold
+
+ \param pAdapter - VOS Context
+ trafficStatus - UP/DOWN indication from TL
+ pUserCtxt - Parameter for callback registered during callback registration. Should be pMac
+
+ \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+VOS_STATUS csrNeighborRoamNeighborLookupDOWNCallback (v_PVOID_t pAdapter, v_U8_t rssiNotification,
+ v_PVOID_t pUserCtxt)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( pUserCtxt );
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Neighbor Lookup DOWN indication callback called with notification %d"), rssiNotification);
+
+ if(!csrIsConnStateConnectedInfra(pMac, pNeighborRoamInfo->csrSessionId))
+ {
+ smsLog(pMac, LOGW, "Ignoring the indication as we are not connected\n");
+ return VOS_STATUS_SUCCESS;
+ }
+
+ VOS_ASSERT(WLANTL_HO_THRESHOLD_DOWN == rssiNotification);
+ vosStatus = csrNeighborRoamNeighborLookupDownEvent(pMac);
+
+ return vosStatus;
+}
+
+#ifdef RSSI_HACK
+extern int dumpCmdRSSI;
+#endif
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamIndicateDisconnect
+
+ \brief This function is called by CSR as soon as the station disconnects from
+ the AP. This function does the necessary cleanup of neighbor roam data
+ structures. Neighbor roam state transitions to INIT state whenever this
+ function is called except if the current state is REASSOCIATING
+
+ \param pMac - The handle returned by macOpen.
+ sessionId - CSR session id that got disconnected
+
+ \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessionId)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ smsLog(pMac, LOGE, FL("Disconnect indication received with session id %d in state %d"), sessionId, pNeighborRoamInfo->neighborRoamState);
+
+#ifdef FEATURE_WLAN_CCX
+ {
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId);
+ if (pSession->connectedProfile.isCCXAssoc)
+ {
+ vos_mem_copy(&pSession->prevApSSID, &pSession->connectedProfile.SSID, sizeof(tSirMacSSid));
+ vos_mem_copy(pSession->prevApBssid, pSession->connectedProfile.bssid, sizeof(tSirMacAddr));
+ pSession->prevOpChannel = pSession->connectedProfile.operationChannel;
+ pSession->isPrevApInfoValid = TRUE;
+ pSession->roamTS1 = vos_timer_get_system_time();
+
+ }
+ }
+#endif
+
+#ifdef RSSI_HACK
+ dumpCmdRSSI = -40;
+#endif
+ switch (pNeighborRoamInfo->neighborRoamState)
+ {
+ case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING:
+ // Stop scan and neighbor refresh timers.
+ // These are indeed not required when we are in reassociating
+ // state.
+ palTimerStop(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer);
+ palTimerStop(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer);
+ break;
+
+ case eCSR_NEIGHBOR_ROAM_STATE_INIT:
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Ignoring disconnect event in INIT state"));
+ csrNeighborRoamResetInitStateControlInfo(pMac);
+ break;
+
+ default:
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Received disconnect event in state %d"), pNeighborRoamInfo->neighborRoamState);
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Transitioning to INIT state"));
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT)
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamIndicateConnect
+
+ \brief This function is called by CSR as soon as the station connects to an AP.
+ This initializes all the necessary data structures related to the
+ associated AP and transitions the state to CONNECTED state
+
+ \param pMac - The handle returned by macOpen.
+ sessionId - CSR session id that got connected
+ vosStatus - connect status SUCCESS/FAILURE
+
+ \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, tANI_U8 sessionId, VOS_STATUS vosStatus)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ int init_ft_flag = FALSE;
+#endif
+
+ smsLog(pMac, LOGE, FL("Connect indication received with session id %d in state %d"), sessionId, pNeighborRoamInfo->neighborRoamState);
+
+ switch (pNeighborRoamInfo->neighborRoamState)
+ {
+ case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING:
+ if (VOS_STATUS_SUCCESS != vosStatus)
+ {
+ /* Just transition the state to INIT state. Rest of the clean up happens when we get next connect indication */
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT)
+ break;
+ }
+ /* Fall through if the status is SUCCESS */
+ case eCSR_NEIGHBOR_ROAM_STATE_INIT:
+ /* Reset all the data structures here */
+ csrNeighborRoamResetInitStateControlInfo(pMac);
+
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)
+
+ pNeighborRoamInfo->csrSessionId = sessionId;
+ vos_mem_copy(pNeighborRoamInfo->currAPbssid,
+ pMac->roam.roamSession[sessionId].connectedProfile.bssid, sizeof(tCsrBssid));
+ pNeighborRoamInfo->currAPoperationChannel = pMac->roam.roamSession[sessionId].connectedProfile.operationChannel;
+ pNeighborRoamInfo->neighborScanTimerInfo.pMac = pMac;
+ pNeighborRoamInfo->neighborScanTimerInfo.sessionId = sessionId;
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ /* Now we can clear the preauthDone that was saved as we are connected afresh */
+ csrNeighborRoamFreeRoamableBSSList(pMac, &pMac->roam.neighborRoamInfo.FTRoamInfo.preAuthDoneList);
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ // Based on the auth scheme tell if we are 11r
+ if ( csrIsAuthType11r( pMac->roam.roamSession[sessionId].connectedProfile.AuthType ) )
+ {
+ if (pMac->roam.configParam.isFastTransitionEnabled)
+ init_ft_flag = TRUE;
+ pNeighborRoamInfo->is11rAssoc = eANI_BOOLEAN_TRUE;
+ }
+ else
+ pNeighborRoamInfo->is11rAssoc = eANI_BOOLEAN_FALSE;
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("11rAssoc is = %d"), pNeighborRoamInfo->is11rAssoc);
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+ // Based on the auth scheme tell if we are 11r
+ if (pMac->roam.roamSession[sessionId].connectedProfile.isCCXAssoc)
+ {
+ if (pMac->roam.configParam.isFastTransitionEnabled)
+ init_ft_flag = TRUE;
+ pNeighborRoamInfo->isCCXAssoc = eANI_BOOLEAN_TRUE;
+ }
+ else
+ pNeighborRoamInfo->isCCXAssoc = eANI_BOOLEAN_FALSE;
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("isCCXAssoc is = %d"), pNeighborRoamInfo->isCCXAssoc);
+ VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "ccx=%d ft=%d\n", pNeighborRoamInfo->isCCXAssoc, init_ft_flag);
+
+#endif
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ if ( init_ft_flag == TRUE )
+ {
+ /* Initialize all the data structures needed for the 11r FT Preauth */
+ pNeighborRoamInfo->FTRoamInfo.preAuthRspWaitTimerInfo.pMac = pMac;
+ pNeighborRoamInfo->FTRoamInfo.preAuthRspWaitTimerInfo.sessionId = sessionId;
+ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0;
+ csrNeighborRoamPurgePreauthFailedList(pMac);
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold);
+ /* Register Neighbor Lookup threshold callback with TL for DOWN event only */
+ status = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1),
+ WLANTL_HO_THRESHOLD_DOWN,
+ csrNeighborRoamNeighborLookupDOWNCallback,
+ VOS_MODULE_ID_SME, pMac);
+
+ if(!VOS_IS_STATUS_SUCCESS( status))
+ {
+ //err msg
+ smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d\n"), status);
+ }
+ }
+#endif
+
+
+ break;
+ default:
+ smsLog(pMac, LOGE, FL("Connect event received in invalid state %d..Ignoring..."), pNeighborRoamInfo->neighborRoamState);
+ break;
+ }
+ return status;
+}
+
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamPreAuthResponseWaitTimerHandler
+
+ \brief If this function is invoked, that means the preauthentication response
+ is timed out from the PE. Preauth rsp handler is called with status as
+ TIMEOUT
+
+ \param context - CSR Timer info which holds pMac and session ID
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamPreAuthResponseWaitTimerHandler(void *context)
+{
+ tCsrTimerInfo *pTimerInfo = (tCsrTimerInfo *)context;
+ tpAniSirGlobal pMac = (tpAniSirGlobal)pTimerInfo->pMac;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ pNeighborRoamInfo->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_FALSE;
+
+ csrNeighborRoamPreauthRspHandler(pMac, VOS_STATUS_E_TIMEOUT);
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamPurgePreauthFailedList
+
+ \brief This function purges all the MAC addresses in the pre-auth fail list
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamPurgePreauthFailedList(tpAniSirGlobal pMac)
+{
+ tANI_U8 i;
+
+ for (i = 0; i < pMac->roam.neighborRoamInfo.FTRoamInfo.preAuthFailList.numMACAddress; i++)
+ {
+ vos_mem_zero(pMac->roam.neighborRoamInfo.FTRoamInfo.preAuthFailList.macAddress[i], sizeof(tSirMacAddr));
+ }
+ pMac->roam.neighborRoamInfo.FTRoamInfo.preAuthFailList.numMACAddress = 0;
+
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamInit11rAssocInfo
+
+ \brief This function initializes 11r related neighbor roam data structures
+
+ \param pMac - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+eHalStatus csrNeighborRoamInit11rAssocInfo(tpAniSirGlobal pMac)
+{
+ eHalStatus status;
+ tpCsr11rAssocNeighborInfo pFTRoamInfo = &pMac->roam.neighborRoamInfo.FTRoamInfo;
+
+ pMac->roam.neighborRoamInfo.is11rAssoc = eANI_BOOLEAN_FALSE;
+ pMac->roam.neighborRoamInfo.cfgParams.maxNeighborRetries = pMac->roam.configParam.neighborRoamConfig.nMaxNeighborRetries;
+ pFTRoamInfo->neighborReportTimeout = CSR_NEIGHBOR_ROAM_REPORT_QUERY_TIMEOUT;
+ pFTRoamInfo->PEPreauthRespTimeout = CSR_NEIGHBOR_ROAM_PREAUTH_RSP_WAIT_MULTIPLIER * pMac->roam.neighborRoamInfo.cfgParams.neighborScanPeriod;
+ pFTRoamInfo->neighborRptPending = eANI_BOOLEAN_FALSE;
+ pFTRoamInfo->preauthRspPending = eANI_BOOLEAN_FALSE;
+
+ pFTRoamInfo->preAuthRspWaitTimerInfo.pMac = pMac;
+ pFTRoamInfo->preAuthRspWaitTimerInfo.sessionId = CSR_SESSION_ID_INVALID;
+ status = palTimerAlloc(pMac->hHdd, &pFTRoamInfo->preAuthRspWaitTimer,
+ csrNeighborRoamPreAuthResponseWaitTimerHandler, (void *)&pFTRoamInfo->preAuthRspWaitTimerInfo);
+
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Response wait Timer allocation failed"));
+ return eHAL_STATUS_RESOURCES;
+ }
+
+ pMac->roam.neighborRoamInfo.FTRoamInfo.currentNeighborRptRetryNum = 0;
+ pMac->roam.neighborRoamInfo.FTRoamInfo.numBssFromNeighborReport = 0;
+ vos_mem_zero(pMac->roam.neighborRoamInfo.FTRoamInfo.neighboReportBssInfo,
+ sizeof(tCsrNeighborReportBssInfo) * MAX_BSS_IN_NEIGHBOR_RPT);
+
+
+ status = csrLLOpen(pMac->hHdd, &pFTRoamInfo->preAuthDoneList);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("LL Open of preauth done AP List failed"));
+ palTimerFree(pMac->hHdd, pFTRoamInfo->preAuthRspWaitTimer);
+ return eHAL_STATUS_RESOURCES;
+ }
+ return status;
+}
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamInit
+
+ \brief This function initializes neighbor roam data structures
+
+ \param pMac - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+eHalStatus csrNeighborRoamInit(tpAniSirGlobal pMac)
+{
+ eHalStatus status;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ pNeighborRoamInfo->neighborRoamState = eCSR_NEIGHBOR_ROAM_STATE_CLOSED;
+ pNeighborRoamInfo->prevNeighborRoamState = eCSR_NEIGHBOR_ROAM_STATE_CLOSED;
+ pNeighborRoamInfo->csrSessionId = CSR_SESSION_ID_INVALID;
+ pNeighborRoamInfo->cfgParams.maxChannelScanTime = pMac->roam.configParam.neighborRoamConfig.nNeighborScanMaxChanTime;
+ pNeighborRoamInfo->cfgParams.minChannelScanTime = pMac->roam.configParam.neighborRoamConfig.nNeighborScanMinChanTime;
+ pNeighborRoamInfo->cfgParams.maxNeighborRetries = 0;
+ pNeighborRoamInfo->cfgParams.neighborLookupThreshold = pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold;
+ pNeighborRoamInfo->cfgParams.neighborReassocThreshold = pMac->roam.configParam.neighborRoamConfig.nNeighborReassocRssiThreshold;
+ pNeighborRoamInfo->cfgParams.neighborScanPeriod = pMac->roam.configParam.neighborRoamConfig.nNeighborScanTimerPeriod;
+ pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod = pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod;
+
+ pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels =
+ pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels;
+
+ pNeighborRoamInfo->cfgParams.channelInfo.ChannelList =
+ vos_mem_malloc(pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels);
+
+ if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList)
+ {
+ smsLog(pMac, LOGE, FL("Memory Allocation for CFG Channel List failed"));
+ return eHAL_STATUS_RESOURCES;
+ }
+
+ /* Update the roam global structure from CFG */
+ palCopyMemory(pMac->hHdd, pNeighborRoamInfo->cfgParams.channelInfo.ChannelList,
+ pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList,
+ pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels);
+
+ vos_mem_set(pNeighborRoamInfo->currAPbssid, sizeof(tCsrBssid), 0);
+ pNeighborRoamInfo->currentNeighborLookupThreshold = pMac->roam.neighborRoamInfo.cfgParams.neighborLookupThreshold;
+ pNeighborRoamInfo->currentLookupIncrementMultiplier = 0;
+ pNeighborRoamInfo->scanRspPending = eANI_BOOLEAN_FALSE;
+
+ pNeighborRoamInfo->neighborScanTimerInfo.pMac = pMac;
+ pNeighborRoamInfo->neighborScanTimerInfo.sessionId = CSR_SESSION_ID_INVALID;
+ status = palTimerAlloc(pMac->hHdd, &pNeighborRoamInfo->neighborScanTimer,
+ csrNeighborRoamNeighborScanTimerCallback, (void *)&pNeighborRoamInfo->neighborScanTimerInfo);
+
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Response wait Timer allocation failed"));
+ vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList);
+ pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL;
+ return eHAL_STATUS_RESOURCES;
+ }
+
+ status = palTimerAlloc(pMac->hHdd, &pNeighborRoamInfo->neighborResultsRefreshTimer,
+ csrNeighborRoamResultsRefreshTimerCallback, (void *)&pNeighborRoamInfo->neighborScanTimerInfo);
+
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Response wait Timer allocation failed"));
+ smsLog(pMac, LOGE, FL("LL Open of roamable AP List failed"));
+ vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList);
+ pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL;
+ palTimerFree(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer);
+ return eHAL_STATUS_RESOURCES;
+ }
+
+ status = csrLLOpen(pMac->hHdd, &pNeighborRoamInfo->roamableAPList);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("LL Open of roamable AP List failed"));
+ vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList);
+ pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL;
+ palTimerFree(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer);
+ palTimerFree(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer);
+ return eHAL_STATUS_RESOURCES;
+ }
+
+ pNeighborRoamInfo->roamChannelInfo.currentChanIndex = CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX;
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0;
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_FALSE;
+ pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ status = csrNeighborRoamInit11rAssocInfo(pMac);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("LL Open of roamable AP List failed"));
+ vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList);
+ pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL;
+ palTimerFree(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer);
+ palTimerFree(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer);
+ csrLLClose(&pNeighborRoamInfo->roamableAPList);
+ return eHAL_STATUS_RESOURCES;
+ }
+#endif
+ /* Initialize this with the current tick count */
+ pNeighborRoamInfo->scanRequestTimeStamp = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd);
+
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT)
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamClose
+
+ \brief This function closes/frees all the neighbor roam data structures
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamClose(tpAniSirGlobal pMac)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+
+ if (eCSR_NEIGHBOR_ROAM_STATE_CLOSED == pNeighborRoamInfo->neighborRoamState)
+ {
+ smsLog(pMac, LOGE, FL("Neighbor Roam Algorithm Already Closed\n"));
+ return;
+ }
+
+ if (pNeighborRoamInfo->cfgParams.channelInfo.ChannelList)
+ vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList);
+
+ pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL;
+
+ pNeighborRoamInfo->neighborScanTimerInfo.pMac = NULL;
+ pNeighborRoamInfo->neighborScanTimerInfo.sessionId = CSR_SESSION_ID_INVALID;
+ palTimerFree(pMac->hHdd, pNeighborRoamInfo->neighborScanTimer);
+ palTimerFree(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer);
+
+ /* Should free up the nodes in the list before closing the double Linked list */
+ csrNeighborRoamFreeRoamableBSSList(pMac, &pNeighborRoamInfo->roamableAPList);
+ csrLLClose(&pNeighborRoamInfo->roamableAPList);
+
+ if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList)
+ {
+ vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList);
+ }
+
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ pNeighborRoamInfo->roamChannelInfo.currentChanIndex = CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX;
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0;
+ pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
+ pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_FALSE;
+ pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE;
+
+ /* Free the profile.. */
+ csrReleaseProfile(pMac, &pNeighborRoamInfo->csrNeighborRoamProfile);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ pMac->roam.neighborRoamInfo.FTRoamInfo.currentNeighborRptRetryNum = 0;
+ palTimerFree(pMac->hHdd, pMac->roam.neighborRoamInfo.FTRoamInfo.preAuthRspWaitTimer);
+ pMac->roam.neighborRoamInfo.FTRoamInfo.preAuthRspWaitTimerInfo.pMac = NULL;
+ pMac->roam.neighborRoamInfo.FTRoamInfo.preAuthRspWaitTimerInfo.sessionId = CSR_SESSION_ID_INVALID;
+ pMac->roam.neighborRoamInfo.FTRoamInfo.numBssFromNeighborReport = 0;
+ vos_mem_zero(pMac->roam.neighborRoamInfo.FTRoamInfo.neighboReportBssInfo,
+ sizeof(tCsrNeighborReportBssInfo) * MAX_BSS_IN_NEIGHBOR_RPT);
+ csrNeighborRoamFreeRoamableBSSList(pMac, &pMac->roam.neighborRoamInfo.FTRoamInfo.preAuthDoneList);
+ csrLLClose(&pMac->roam.neighborRoamInfo.FTRoamInfo.preAuthDoneList);
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CLOSED)
+
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamRequestHandoff
+
+ \brief This function triggers actual switching from one AP to the new AP.
+ It issues disassociate with reason code as Handoff and CSR as a part of
+ handling disassoc rsp, issues reassociate to the new AP
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamRequestHandoff(tpAniSirGlobal pMac)
+{
+
+ tCsrRoamInfo roamInfo;
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ tANI_U32 sessionId = pNeighborRoamInfo->csrSessionId;
+ tCsrNeighborRoamBSSInfo handoffNode;
+ extern void csrRoamRoamingStateDisassocRspProcessor( tpAniSirGlobal pMac, tSirSmeDisassocRsp *pSmeDisassocRsp );
+ tANI_U32 roamId = 0;
+
+ if (pMac->roam.neighborRoamInfo.neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE)
+ {
+ smsLog(pMac, LOGE, FL("Roam requested when Neighbor roam is in %d state"),
+ pMac->roam.neighborRoamInfo.neighborRoamState);
+ return;
+ }
+
+ vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo));
+ csrRoamCallCallback(pMac, pNeighborRoamInfo->csrSessionId, &roamInfo, roamId, eCSR_ROAM_FT_START,
+ eSIR_SME_SUCCESS);
+
+ vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo));
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING)
+
+ csrNeighborRoamGetHandoffAPInfo(pMac, &handoffNode);
+ smsLog(pMac, LOGE, FL("HANDOFF CANDIDATE BSSID %02x:%02x:%02x:%02x:%02x:%02x"),
+ handoffNode.pBssDescription->bssId[0],
+ handoffNode.pBssDescription->bssId[1],
+ handoffNode.pBssDescription->bssId[2],
+ handoffNode.pBssDescription->bssId[3],
+ handoffNode.pBssDescription->bssId[4],
+ handoffNode.pBssDescription->bssId[5]);
+
+ /* Free the profile.. Just to make sure we dont leak memory here */
+ csrReleaseProfile(pMac, &pNeighborRoamInfo->csrNeighborRoamProfile);
+ /* Create the Handoff AP profile. Copy the currently connected profile and update only the BSSID and channel number
+ This should happen before issuing disconnect */
+ csrRoamCopyConnectedProfile(pMac, pNeighborRoamInfo->csrSessionId, &pNeighborRoamInfo->csrNeighborRoamProfile);
+ vos_mem_copy(pNeighborRoamInfo->csrNeighborRoamProfile.BSSIDs.bssid, handoffNode.pBssDescription->bssId, sizeof(tSirMacAddr));
+ pNeighborRoamInfo->csrNeighborRoamProfile.ChannelInfo.ChannelList[0] = handoffNode.pBssDescription->channelId;
+
+ NEIGHBOR_ROAM_DEBUG(pMac, LOGW, " csrRoamHandoffRequested: disassociating with current AP\n");
+
+ if(!HAL_STATUS_SUCCESS(csrRoamIssueDisassociateCmd(pMac, sessionId, eCSR_DISCONNECT_REASON_HANDOFF)))
+ {
+ smsLog(pMac, LOGW, "csrRoamHandoffRequested: fail to issue disassociate\n");
+ return;
+ }
+
+ //notify HDD for handoff, providing the BSSID too
+ roamInfo.reasonCode = eCsrRoamReasonBetterAP;
+
+ vos_mem_copy(roamInfo.bssid,
+ handoffNode.pBssDescription->bssId,
+ sizeof( tCsrBssid ));
+
+ csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE);
+
+
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamIsHandoffInProgress
+
+ \brief This function returns whether handoff is in progress or not based on
+ the current neighbor roam state
+
+ \param pMac - The handle returned by macOpen.
+ is11rReassoc - Return whether reassoc is of type 802.11r reassoc
+
+ \return eANI_BOOLEAN_TRUE if reassoc in progress, eANI_BOOLEAN_FALSE otherwise
+
+---------------------------------------------------------------------------*/
+tANI_BOOLEAN csrNeighborRoamIsHandoffInProgress(tpAniSirGlobal pMac)
+{
+ if (eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING == pMac->roam.neighborRoamInfo.neighborRoamState)
+ return eANI_BOOLEAN_TRUE;
+
+ return eANI_BOOLEAN_FALSE;
+}
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamIs11rAssoc
+
+ \brief This function returns whether the current association is a 11r assoc or not
+
+ \param pMac - The handle returned by macOpen.
+
+ \return eANI_BOOLEAN_TRUE if current assoc is 11r, eANI_BOOLEAN_FALSE otherwise
+
+---------------------------------------------------------------------------*/
+tANI_BOOLEAN csrNeighborRoamIs11rAssoc(tpAniSirGlobal pMac)
+{
+ return pMac->roam.neighborRoamInfo.is11rAssoc;
+}
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn csrNeighborRoamGetHandoffAPInfo
+
+ \brief This function returns the best possible AP for handoff. For 11R case, it
+ returns the 1st entry from pre-auth done list. For non-11r case, it returns
+ the 1st entry from roamable AP list
+
+ \param pMac - The handle returned by macOpen.
+ pHandoffNode - AP node that is the handoff candidate returned
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+void csrNeighborRoamGetHandoffAPInfo(tpAniSirGlobal pMac, tpCsrNeighborRoamBSSInfo pHandoffNode)
+{
+ tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+ tpCsrNeighborRoamBSSInfo pBssNode;
+
+ VOS_ASSERT(NULL != pHandoffNode);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (pNeighborRoamInfo->is11rAssoc)
+ {
+ /* Always the BSS info in the head is the handoff candidate */
+ pBssNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, &pNeighborRoamInfo->FTRoamInfo.preAuthDoneList, NULL);
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG1, FL("Number of Handoff candidates = %d"), csrLLCount(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList));
+ }
+ else
+#endif
+#ifdef FEATURE_WLAN_CCX
+ if (pNeighborRoamInfo->isCCXAssoc)
+ {
+ /* Always the BSS info in the head is the handoff candidate */
+ pBssNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, &pNeighborRoamInfo->FTRoamInfo.preAuthDoneList, NULL);
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG1, FL("Number of Handoff candidates = %d"), csrLLCount(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList));
+ }
+ else
+#endif
+ {
+ pBssNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, &pNeighborRoamInfo->roamableAPList, NULL);
+ NEIGHBOR_ROAM_DEBUG(pMac, LOG1, FL("Number of Handoff candidates = %d"), csrLLCount(&pNeighborRoamInfo->roamableAPList));
+ }
+ vos_mem_copy(pHandoffNode, pBssNode, sizeof(tCsrNeighborRoamBSSInfo));
+
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+ \brief This function returns TRUE if preauth is completed
+
+ \param pMac - The handle returned by macOpen.
+
+ \return boolean
+
+---------------------------------------------------------------------------*/
+tANI_BOOLEAN csrNeighborRoamStatePreauthDone(tpAniSirGlobal pMac)
+{
+ return (pMac->roam.neighborRoamInfo.neighborRoamState ==
+ eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE);
+}
+
+/* ---------------------------------------------------------------------------
+ \brief In the event that we are associated with AP1 and we have
+ completed pre auth with AP2. Then we receive a deauth/disassoc from
+ AP1.
+ At this point neighbor roam is in pre auth done state, pre auth timer
+ is running. We now handle this case by stopping timer and clearing
+ the pre-auth state. We basically clear up and just go to disconnected
+ state.
+
+ \param pMac - The handle returned by macOpen.
+
+ \return boolean
+---------------------------------------------------------------------------*/
+void csrNeighborRoamTranistionPreauthDoneToDisconnected(tpAniSirGlobal pMac)
+{
+ if (pMac->roam.neighborRoamInfo.neighborRoamState !=
+ eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE) return;
+
+ // Stop timer
+ palTimerStop(pMac->hHdd, pMac->ft.ftSmeContext.preAuthReassocIntvlTimer);
+
+ // Transition to init state
+ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT)
+}
+
+#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */
diff --git a/CORE/SME/src/csr/csrUtil.c b/CORE/SME/src/csr/csrUtil.c
new file mode 100644
index 0000000..5910069
--- /dev/null
+++ b/CORE/SME/src/csr/csrUtil.c
@@ -0,0 +1,5846 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/** ------------------------------------------------------------------------- *
+ ------------------------------------------------------------------------- *
+
+
+ \file csrUtil.c
+
+ Implementation supporting routines for CSR.
+
+
+ Copyright (C) 2006 Airgo Networks, Incorporated
+ ========================================================================== */
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include "halInternal.h" //Check if the below include of aniGobal.h is sufficient for Volans too.
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include "aniGlobal.h"
+#endif
+
+#include "palApi.h"
+#include "csrSupport.h"
+#include "csrInsideApi.h"
+#include "smsDebug.h"
+#include "smeQosInternal.h"
+#ifdef FEATURE_WLAN_CCX
+#include "vos_utils.h"
+#include "csrCcx.h"
+#endif /* FEATURE_WLAN_CCX */
+
+tANI_U8 csrWpaOui[][ CSR_WPA_OUI_SIZE ] = {
+ { 0x00, 0x50, 0xf2, 0x00 },
+ { 0x00, 0x50, 0xf2, 0x01 },
+ { 0x00, 0x50, 0xf2, 0x02 },
+ { 0x00, 0x50, 0xf2, 0x03 },
+ { 0x00, 0x50, 0xf2, 0x04 },
+ { 0x00, 0x50, 0xf2, 0x05 },
+#ifdef FEATURE_WLAN_CCX
+ { 0x00, 0x40, 0x96, 0x00 }, // CCKM
+#endif /* FEATURE_WLAN_CCX */
+};
+
+tANI_U8 csrRSNOui[][ CSR_RSN_OUI_SIZE ] = {
+ { 0x00, 0x0F, 0xAC, 0x00 }, // group cipher
+ { 0x00, 0x0F, 0xAC, 0x01 }, // WEP-40 or RSN
+ { 0x00, 0x0F, 0xAC, 0x02 }, // TKIP or RSN-PSK
+ { 0x00, 0x0F, 0xAC, 0x03 }, // Reserved
+ { 0x00, 0x0F, 0xAC, 0x04 }, // AES-CCMP
+ { 0x00, 0x0F, 0xAC, 0x05 }, // WEP-104
+#ifdef WLAN_FEATURE_11W
+ { 0x00, 0x0F, 0xAC, 0x06 }, // BIP(encryption type) or (RSN-PSK-SHA256(authentication type)
+#endif
+#ifdef FEATURE_WLAN_CCX
+ { 0x00, 0x40, 0x96, 0x00 } // CCKM
+#endif /* FEATURE_WLAN_CCX */
+
+};
+
+#ifdef FEATURE_WLAN_WAPI
+tANI_U8 csrWapiOui[][ CSR_WAPI_OUI_SIZE ] = {
+ { 0x00, 0x14, 0x72, 0x00 }, // Reserved
+ { 0x00, 0x14, 0x72, 0x01 }, // WAI certificate or SMS4
+ { 0x00, 0x14, 0x72, 0x02 } // WAI PSK
+};
+#endif /* FEATURE_WLAN_WAPI */
+tANI_U8 csrWmeInfoOui[ CSR_WME_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x02 };
+tANI_U8 csrWmeParmOui[ CSR_WME_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x02 };
+
+static tCsrIELenInfo gCsrIELengthTable[] = {
+/* 000 */ { SIR_MAC_SSID_EID_MIN, SIR_MAC_SSID_EID_MAX },
+/* 001 */ { SIR_MAC_RATESET_EID_MIN, SIR_MAC_RATESET_EID_MAX },
+/* 002 */ { SIR_MAC_FH_PARAM_SET_EID_MIN, SIR_MAC_FH_PARAM_SET_EID_MAX },
+/* 003 */ { SIR_MAC_DS_PARAM_SET_EID_MIN, SIR_MAC_DS_PARAM_SET_EID_MAX },
+/* 004 */ { SIR_MAC_CF_PARAM_SET_EID_MIN, SIR_MAC_CF_PARAM_SET_EID_MAX },
+/* 005 */ { SIR_MAC_TIM_EID_MIN, SIR_MAC_TIM_EID_MAX },
+/* 006 */ { SIR_MAC_IBSS_PARAM_SET_EID_MIN, SIR_MAC_IBSS_PARAM_SET_EID_MAX },
+/* 007 */ { SIR_MAC_COUNTRY_EID_MIN, SIR_MAC_COUNTRY_EID_MAX },
+/* 008 */ { SIR_MAC_FH_PARAMS_EID_MIN, SIR_MAC_FH_PARAMS_EID_MAX },
+/* 009 */ { SIR_MAC_FH_PATTERN_EID_MIN, SIR_MAC_FH_PATTERN_EID_MAX },
+/* 010 */ { SIR_MAC_REQUEST_EID_MIN, SIR_MAC_REQUEST_EID_MAX },
+/* 011 */ { SIR_MAC_QBSS_LOAD_EID_MIN, SIR_MAC_QBSS_LOAD_EID_MAX },
+/* 012 */ { SIR_MAC_EDCA_PARAM_SET_EID_MIN, SIR_MAC_EDCA_PARAM_SET_EID_MAX },
+/* 013 */ { SIR_MAC_TSPEC_EID_MIN, SIR_MAC_TSPEC_EID_MAX },
+/* 014 */ { SIR_MAC_TCLAS_EID_MIN, SIR_MAC_TCLAS_EID_MAX },
+/* 015 */ { SIR_MAC_QOS_SCHEDULE_EID_MIN, SIR_MAC_QOS_SCHEDULE_EID_MAX },
+/* 016 */ { SIR_MAC_CHALLENGE_TEXT_EID_MIN, SIR_MAC_CHALLENGE_TEXT_EID_MAX },
+/* 017 */ { 0, 255 },
+/* 018 */ { 0, 255 },
+/* 019 */ { 0, 255 },
+/* 020 */ { 0, 255 },
+/* 021 */ { 0, 255 },
+/* 022 */ { 0, 255 },
+/* 023 */ { 0, 255 },
+/* 024 */ { 0, 255 },
+/* 025 */ { 0, 255 },
+/* 026 */ { 0, 255 },
+/* 027 */ { 0, 255 },
+/* 028 */ { 0, 255 },
+/* 029 */ { 0, 255 },
+/* 030 */ { 0, 255 },
+/* 031 */ { 0, 255 },
+/* 032 */ { SIR_MAC_PWR_CONSTRAINT_EID_MIN, SIR_MAC_PWR_CONSTRAINT_EID_MAX },
+/* 033 */ { SIR_MAC_PWR_CAPABILITY_EID_MIN, SIR_MAC_PWR_CAPABILITY_EID_MAX },
+/* 034 */ { SIR_MAC_TPC_REQ_EID_MIN, SIR_MAC_TPC_REQ_EID_MAX },
+/* 035 */ { SIR_MAC_TPC_RPT_EID_MIN, SIR_MAC_TPC_RPT_EID_MAX },
+/* 036 */ { SIR_MAC_SPRTD_CHNLS_EID_MIN, SIR_MAC_SPRTD_CHNLS_EID_MAX },
+/* 037 */ { SIR_MAC_CHNL_SWITCH_ANN_EID_MIN, SIR_MAC_CHNL_SWITCH_ANN_EID_MAX },
+/* 038 */ { SIR_MAC_MEAS_REQ_EID_MIN, SIR_MAC_MEAS_REQ_EID_MAX },
+/* 039 */ { SIR_MAC_MEAS_RPT_EID_MIN, SIR_MAC_MEAS_RPT_EID_MAX },
+/* 040 */ { SIR_MAC_QUIET_EID_MIN, SIR_MAC_QUIET_EID_MAX },
+/* 041 */ { SIR_MAC_IBSS_DFS_EID_MIN, SIR_MAC_IBSS_DFS_EID_MAX },
+/* 042 */ { SIR_MAC_ERP_INFO_EID_MIN, SIR_MAC_ERP_INFO_EID_MAX },
+/* 043 */ { SIR_MAC_TS_DELAY_EID_MIN, SIR_MAC_TS_DELAY_EID_MAX },
+/* 044 */ { SIR_MAC_TCLAS_PROC_EID_MIN, SIR_MAC_TCLAS_PROC_EID_MAX },
+/* 045 */ { SIR_MAC_QOS_ACTION_EID_MIN, SIR_MAC_QOS_ACTION_EID_MAX },
+/* 046 */ { SIR_MAC_QOS_CAPABILITY_EID_MIN, SIR_MAC_QOS_CAPABILITY_EID_MAX },
+/* 047 */ { 0, 255 },
+/* 048 */ { SIR_MAC_RSN_EID_MIN, SIR_MAC_RSN_EID_MAX },
+/* 049 */ { 0, 255 },
+/* 050 */ { SIR_MAC_EXTENDED_RATE_EID_MIN, SIR_MAC_EXTENDED_RATE_EID_MAX },
+/* 051 */ { 0, 255 },
+/* 052 */ { 0, 255 },
+/* 053 */ { 0, 255 },
+/* 054 */ { 0, 255 },
+/* 055 */ { 0, 255 },
+/* 056 */ { 0, 255 },
+/* 057 */ { 0, 255 },
+/* 058 */ { 0, 255 },
+/* 059 */ { 0, 255 },
+/* 060 */ { 0, 255 },
+/* 061 */ { 0, 255 },
+/* 062 */ { 0, 255 },
+/* 063 */ { 0, 255 },
+/* 064 */ { 0, 255 },
+/* 065 */ { 0, 255 },
+/* 066 */ { 0, 255 },
+/* 067 */ { 0, 255 },
+#ifdef FEATURE_WLAN_WAPI
+/* 068 */ { DOT11F_EID_WAPI, DOT11F_IE_WAPI_MAX_LEN },
+#else
+/* 068 */ { 0, 255 },
+#endif /* FEATURE_WLAN_WAPI */
+/* 069 */ { 0, 255 },
+/* 070 */ { 0, 255 },
+/* 071 */ { 0, 255 },
+/* 072 */ { 0, 255 },
+/* 073 */ { 0, 255 },
+/* 074 */ { 0, 255 },
+/* 075 */ { 0, 255 },
+/* 076 */ { 0, 255 },
+/* 077 */ { 0, 255 },
+/* 078 */ { 0, 255 },
+/* 079 */ { 0, 255 },
+/* 080 */ { 0, 255 },
+/* 081 */ { 0, 255 },
+/* 082 */ { 0, 255 },
+/* 083 */ { 0, 255 },
+/* 084 */ { 0, 255 },
+/* 085 */ { 0, 255 },
+/* 086 */ { 0, 255 },
+/* 087 */ { 0, 255 },
+/* 088 */ { 0, 255 },
+/* 089 */ { 0, 255 },
+/* 090 */ { 0, 255 },
+/* 091 */ { 0, 255 },
+/* 092 */ { 0, 255 },
+/* 093 */ { 0, 255 },
+/* 094 */ { 0, 255 },
+/* 095 */ { 0, 255 },
+/* 096 */ { 0, 255 },
+/* 097 */ { 0, 255 },
+/* 098 */ { 0, 255 },
+/* 099 */ { 0, 255 },
+/* 100 */ { 0, 255 },
+/* 101 */ { 0, 255 },
+/* 102 */ { 0, 255 },
+/* 103 */ { 0, 255 },
+/* 104 */ { 0, 255 },
+/* 105 */ { 0, 255 },
+/* 106 */ { 0, 255 },
+/* 107 */ { 0, 255 },
+/* 108 */ { 0, 255 },
+/* 109 */ { 0, 255 },
+/* 110 */ { 0, 255 },
+/* 111 */ { 0, 255 },
+/* 112 */ { 0, 255 },
+/* 113 */ { 0, 255 },
+/* 114 */ { 0, 255 },
+/* 115 */ { 0, 255 },
+/* 116 */ { 0, 255 },
+/* 117 */ { 0, 255 },
+/* 118 */ { 0, 255 },
+/* 119 */ { 0, 255 },
+/* 120 */ { 0, 255 },
+/* 121 */ { 0, 255 },
+/* 122 */ { 0, 255 },
+/* 123 */ { 0, 255 },
+/* 124 */ { 0, 255 },
+/* 125 */ { 0, 255 },
+/* 126 */ { 0, 255 },
+/* 127 */ { 0, 255 },
+/* 128 */ { 0, 255 },
+/* 129 */ { 0, 255 },
+/* 130 */ { 0, 255 },
+/* 131 */ { 0, 255 },
+/* 132 */ { 0, 255 },
+/* 133 */ { 0, 255 },
+/* 134 */ { 0, 255 },
+/* 135 */ { 0, 255 },
+/* 136 */ { 0, 255 },
+/* 137 */ { 0, 255 },
+/* 138 */ { 0, 255 },
+/* 139 */ { 0, 255 },
+/* 140 */ { 0, 255 },
+/* 141 */ { 0, 255 },
+/* 142 */ { 0, 255 },
+/* 143 */ { 0, 255 },
+/* 144 */ { 0, 255 },
+/* 145 */ { 0, 255 },
+/* 146 */ { 0, 255 },
+/* 147 */ { 0, 255 },
+/* 148 */ { 0, 255 },
+/* 149 */ { 0, 255 },
+/* 150 */ { 0, 255 },
+/* 151 */ { 0, 255 },
+/* 152 */ { 0, 255 },
+/* 153 */ { 0, 255 },
+/* 154 */ { 0, 255 },
+/* 155 */ { 0, 255 },
+/* 156 */ { 0, 255 },
+/* 157 */ { 0, 255 },
+/* 158 */ { 0, 255 },
+/* 159 */ { 0, 255 },
+/* 160 */ { 0, 255 },
+/* 161 */ { 0, 255 },
+/* 162 */ { 0, 255 },
+/* 163 */ { 0, 255 },
+/* 164 */ { 0, 255 },
+/* 165 */ { 0, 255 },
+/* 166 */ { 0, 255 },
+/* 167 */ { 0, 255 },
+/* 168 */ { 0, 255 },
+/* 169 */ { 0, 255 },
+/* 170 */ { 0, 255 },
+/* 171 */ { 0, 255 },
+/* 172 */ { 0, 255 },
+/* 173 */ { 0, 255 },
+/* 174 */ { 0, 255 },
+/* 175 */ { 0, 255 },
+/* 176 */ { 0, 255 },
+/* 177 */ { 0, 255 },
+/* 178 */ { 0, 255 },
+/* 179 */ { 0, 255 },
+/* 180 */ { 0, 255 },
+/* 181 */ { 0, 255 },
+/* 182 */ { 0, 255 },
+/* 183 */ { 0, 255 },
+/* 184 */ { 0, 255 },
+/* 185 */ { 0, 255 },
+/* 186 */ { 0, 255 },
+/* 187 */ { 0, 255 },
+/* 188 */ { 0, 255 },
+/* 189 */ { 0, 255 },
+/* 190 */ { 0, 255 },
+/* 191 */ { 0, 255 },
+/* 192 */ { 0, 255 },
+/* 193 */ { 0, 255 },
+/* 194 */ { 0, 255 },
+/* 195 */ { 0, 255 },
+/* 196 */ { 0, 255 },
+/* 197 */ { 0, 255 },
+/* 198 */ { 0, 255 },
+/* 199 */ { 0, 255 },
+/* 200 */ { 0, 255 },
+/* 201 */ { 0, 255 },
+/* 202 */ { 0, 255 },
+/* 203 */ { 0, 255 },
+/* 204 */ { 0, 255 },
+/* 205 */ { 0, 255 },
+/* 206 */ { 0, 255 },
+/* 207 */ { 0, 255 },
+/* 208 */ { 0, 255 },
+/* 209 */ { 0, 255 },
+/* 210 */ { 0, 255 },
+/* 211 */ { 0, 255 },
+/* 212 */ { 0, 255 },
+/* 213 */ { 0, 255 },
+/* 214 */ { 0, 255 },
+/* 215 */ { 0, 255 },
+/* 216 */ { 0, 255 },
+/* 217 */ { 0, 255 },
+/* 218 */ { 0, 255 },
+/* 219 */ { 0, 255 },
+/* 220 */ { 0, 255 },
+/* 221 */ { SIR_MAC_WPA_EID_MIN, SIR_MAC_WPA_EID_MAX },
+/* 222 */ { 0, 255 },
+/* 223 */ { 0, 255 },
+/* 224 */ { 0, 255 },
+/* 225 */ { 0, 255 },
+/* 226 */ { 0, 255 },
+/* 227 */ { 0, 255 },
+/* 228 */ { 0, 255 },
+/* 229 */ { 0, 255 },
+/* 230 */ { 0, 255 },
+/* 231 */ { 0, 255 },
+/* 232 */ { 0, 255 },
+/* 233 */ { 0, 255 },
+/* 234 */ { 0, 255 },
+/* 235 */ { 0, 255 },
+/* 236 */ { 0, 255 },
+/* 237 */ { 0, 255 },
+/* 238 */ { 0, 255 },
+/* 239 */ { 0, 255 },
+/* 240 */ { 0, 255 },
+/* 241 */ { 0, 255 },
+/* 242 */ { 0, 255 },
+/* 243 */ { 0, 255 },
+/* 244 */ { 0, 255 },
+/* 245 */ { 0, 255 },
+/* 246 */ { 0, 255 },
+/* 247 */ { 0, 255 },
+/* 248 */ { 0, 255 },
+/* 249 */ { 0, 255 },
+/* 250 */ { 0, 255 },
+/* 251 */ { 0, 255 },
+/* 252 */ { 0, 255 },
+/* 253 */ { 0, 255 },
+/* 254 */ { 0, 255 },
+/* 255 */ { SIR_MAC_ANI_WORKAROUND_EID_MIN, SIR_MAC_ANI_WORKAROUND_EID_MAX }
+};
+
+#if 0
+//Don't not insert entry into the table, put it to the end. If you have to insert, make sure it is also
+//reflected in eCsrCountryIndex
+static tCsrCountryInfo gCsrCountryInfo[eCSR_NUM_COUNTRY_INDEX] =
+{
+ {REG_DOMAIN_FCC, {'U', 'S', ' '}}, //USA/******The "US" MUST be at index 0*******/
+ {REG_DOMAIN_WORLD, {'A', 'D', ' '}}, //ANDORRA
+ {REG_DOMAIN_WORLD, {'A', 'E', ' '}}, //UAE
+ {REG_DOMAIN_WORLD, {'A', 'F', ' '}}, //AFGHANISTAN
+ {REG_DOMAIN_WORLD, {'A', 'G', ' '}}, //ANTIGUA AND BARBUDA
+ {REG_DOMAIN_WORLD, {'A', 'I', ' '}}, //ANGUILLA
+ {REG_DOMAIN_HI_5GHZ, {'A', 'L', ' '}}, //ALBANIA
+ {REG_DOMAIN_WORLD, {'A', 'M', ' '}}, //ARMENIA
+ {REG_DOMAIN_WORLD, {'A', 'N', ' '}}, //NETHERLANDS ANTILLES
+ {REG_DOMAIN_WORLD, {'A', 'O', ' '}}, //ANGOLA
+ {REG_DOMAIN_WORLD, {'A', 'Q', ' '}}, //ANTARCTICA
+ {REG_DOMAIN_HI_5GHZ, {'A', 'R', ' '}}, //ARGENTINA
+ {REG_DOMAIN_FCC, {'A', 'S', ' '}}, //AMERICAN SOMOA
+ {REG_DOMAIN_ETSI, {'A', 'T', ' '}}, //AUSTRIA
+ {REG_DOMAIN_ETSI, {'A', 'U', ' '}}, //AUSTRALIA
+ {REG_DOMAIN_WORLD, {'A', 'W', ' '}}, //ARUBA
+ {REG_DOMAIN_WORLD, {'A', 'X', ' '}}, //ALAND ISLANDS
+ {REG_DOMAIN_WORLD, {'A', 'Z', ' '}}, //AZERBAIJAN
+ {REG_DOMAIN_WORLD, {'B', 'A', ' '}}, //BOSNIA AND HERZEGOVINA
+ {REG_DOMAIN_WORLD, {'B', 'B', ' '}}, //BARBADOS
+ {REG_DOMAIN_WORLD, {'B', 'D', ' '}}, //BANGLADESH
+ {REG_DOMAIN_ETSI, {'B', 'E', ' '}}, //BELGIUM
+ {REG_DOMAIN_WORLD, {'B', 'F', ' '}}, //BURKINA FASO
+ {REG_DOMAIN_HI_5GHZ, {'B', 'G', ' '}}, //BULGARIA
+ {REG_DOMAIN_WORLD, {'B', 'H', ' '}}, //BAHRAIN
+ {REG_DOMAIN_WORLD, {'B', 'I', ' '}}, //BURUNDI
+ {REG_DOMAIN_WORLD, {'B', 'J', ' '}}, //BENIN
+ {REG_DOMAIN_WORLD, {'B', 'L', ' '}}, //SAINT BARTHELEMY
+ {REG_DOMAIN_ETSI, {'B', 'M', ' '}}, //BERMUDA
+ {REG_DOMAIN_WORLD, {'B', 'N', ' '}}, //BRUNEI DARUSSALAM
+ {REG_DOMAIN_WORLD, {'B', 'O', ' '}}, //BOLIVIA
+ {REG_DOMAIN_WORLD, {'B', 'R', ' '}}, //BRAZIL
+ {REG_DOMAIN_WORLD, {'B', 'S', ' '}}, //BAHAMAS
+ {REG_DOMAIN_WORLD, {'B', 'T', ' '}}, //BHUTAN
+ {REG_DOMAIN_WORLD, {'B', 'V', ' '}}, //BOUVET ISLAND
+ {REG_DOMAIN_WORLD, {'B', 'W', ' '}}, //BOTSWANA
+ {REG_DOMAIN_WORLD, {'B', 'Y', ' '}}, //BELARUS
+ {REG_DOMAIN_WORLD, {'B', 'Z', ' '}}, //BELIZE
+ {REG_DOMAIN_FCC, {'C', 'A', ' '}}, //CANADA
+ {REG_DOMAIN_WORLD, {'C', 'C', ' '}}, //COCOS (KEELING) ISLANDS
+ {REG_DOMAIN_WORLD, {'C', 'D', ' '}}, //CONGO, THE DEMOCRATIC REPUBLIC OF THE
+ {REG_DOMAIN_WORLD, {'C', 'F', ' '}}, //CENTRAL AFRICAN REPUBLIC
+ {REG_DOMAIN_WORLD, {'C', 'G', ' '}}, //CONGO
+ {REG_DOMAIN_ETSI, {'C', 'H', ' '}}, //SWITZERLAND
+ {REG_DOMAIN_WORLD, {'C', 'I', ' '}}, //COTE D'IVOIRE
+ {REG_DOMAIN_WORLD, {'C', 'K', ' '}}, //COOK ISLANDS
+ {REG_DOMAIN_WORLD, {'C', 'L', ' '}}, //CHILE
+ {REG_DOMAIN_WORLD, {'C', 'M', ' '}}, //CAMEROON
+ {REG_DOMAIN_HI_5GHZ, {'C', 'N', ' '}}, //CHINA
+ {REG_DOMAIN_WORLD, {'C', 'O', ' '}}, //COLOMBIA
+ {REG_DOMAIN_WORLD, {'C', 'R', ' '}}, //COSTA RICA
+ {REG_DOMAIN_WORLD, {'C', 'U', ' '}}, //CUBA
+ {REG_DOMAIN_WORLD, {'C', 'V', ' '}}, //CAPE VERDE
+ {REG_DOMAIN_WORLD, {'C', 'X', ' '}}, //CHRISTMAS ISLAND
+ {REG_DOMAIN_WORLD, {'C', 'Y', ' '}}, //CYPRUS
+ {REG_DOMAIN_HI_5GHZ, {'C', 'Z', ' '}}, //CZECH REPUBLIC
+ {REG_DOMAIN_ETSI, {'D', 'E', ' '}}, //GERMANY
+ {REG_DOMAIN_WORLD, {'D', 'J', ' '}}, //DJIBOUTI
+ {REG_DOMAIN_ETSI, {'D', 'K', ' '}}, //DENMARK
+ {REG_DOMAIN_WORLD, {'D', 'M', ' '}}, //DOMINICA
+ {REG_DOMAIN_WORLD, {'D', 'O', ' '}}, //DOMINICAN REPUBLIC
+ {REG_DOMAIN_WORLD, {'D', 'Z', ' '}}, //ALGERIA
+ {REG_DOMAIN_WORLD, {'E', 'C', ' '}}, //ECUADOR
+ {REG_DOMAIN_HI_5GHZ, {'E', 'E', ' '}}, //ESTONIA
+ {REG_DOMAIN_WORLD, {'E', 'G', ' '}}, //EGYPT
+ {REG_DOMAIN_WORLD, {'E', 'H', ' '}}, //WESTERN SAHARA
+ {REG_DOMAIN_WORLD, {'E', 'R', ' '}}, //ERITREA
+ {REG_DOMAIN_ETSI, {'E', 'S', ' '}}, //SPAIN
+ {REG_DOMAIN_WORLD, {'E', 'T', ' '}}, //ETHIOPIA
+ {REG_DOMAIN_WORLD, {'F', 'I', ' '}}, //FINLAND
+ {REG_DOMAIN_WORLD, {'F', 'J', ' '}}, //FIJI
+ {REG_DOMAIN_WORLD, {'F', 'K', ' '}}, //FALKLAND ISLANDS (MALVINAS)
+ {REG_DOMAIN_WORLD, {'F', 'M', ' '}}, //MICRONESIA, FEDERATED STATES OF
+ {REG_DOMAIN_WORLD, {'F', 'O', ' '}}, //FAROE ISLANDS
+ {REG_DOMAIN_ETSI, {'F', 'R', ' '}}, //FRANCE
+ {REG_DOMAIN_WORLD, {'G', 'A', ' '}}, //GABON
+ {REG_DOMAIN_ETSI, {'G', 'B', ' '}}, //UNITED KINGDOM
+ {REG_DOMAIN_WORLD, {'G', 'D', ' '}}, //GRENADA
+ {REG_DOMAIN_HI_5GHZ, {'G', 'E', ' '}}, //GEORGIA
+ {REG_DOMAIN_WORLD, {'G', 'F', ' '}}, //FRENCH GUIANA
+ {REG_DOMAIN_ETSI, {'G', 'G', ' '}}, //GUERNSEY
+ {REG_DOMAIN_WORLD, {'G', 'H', ' '}}, //GHANA
+ {REG_DOMAIN_WORLD, {'G', 'I', ' '}}, //GIBRALTAR
+ {REG_DOMAIN_WORLD, {'G', 'L', ' '}}, //GREENLAND
+ {REG_DOMAIN_WORLD, {'G', 'M', ' '}}, //GAMBIA
+ {REG_DOMAIN_WORLD, {'G', 'N', ' '}}, //GUINEA
+ {REG_DOMAIN_WORLD, {'G', 'P', ' '}}, //GUADELOUPE
+ {REG_DOMAIN_WORLD, {'G', 'Q', ' '}}, //EQUATORIAL GUINEA
+ {REG_DOMAIN_ETSI, {'G', 'R', ' '}}, //GREECE
+ {REG_DOMAIN_WORLD, {'G', 'S', ' '}}, //SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS
+ {REG_DOMAIN_WORLD, {'G', 'T', ' '}}, //GUATEMALA
+ {REG_DOMAIN_WORLD, {'G', 'U', ' '}}, //GUAM
+ {REG_DOMAIN_WORLD, {'G', 'W', ' '}}, //GUINEA-BISSAU
+ {REG_DOMAIN_WORLD, {'G', 'Y', ' '}}, //GUYANA
+ {REG_DOMAIN_WORLD, {'H', 'K', ' '}}, //HONGKONG
+ {REG_DOMAIN_WORLD, {'H', 'M', ' '}}, //HEARD ISLAND AND MCDONALD ISLANDS
+ {REG_DOMAIN_WORLD, {'H', 'N', ' '}}, //HONDURAS
+ {REG_DOMAIN_HI_5GHZ, {'H', 'R', ' '}}, //CROATIA
+ {REG_DOMAIN_WORLD, {'H', 'T', ' '}}, //HAITI
+ {REG_DOMAIN_HI_5GHZ, {'H', 'U', ' '}}, //HUNGARY
+ {REG_DOMAIN_APAC, {'I', 'D', ' '}}, //INDONESIA
+ {REG_DOMAIN_ETSI, {'I', 'E', ' '}}, //IRELAND
+ {REG_DOMAIN_WORLD, {'I', 'L', ' '}}, //ISREAL
+ {REG_DOMAIN_ETSI, {'I', 'M', ' '}}, //ISLE OF MAN
+ {REG_DOMAIN_WORLD, {'I', 'N', ' '}}, //INDIA
+ {REG_DOMAIN_ETSI, {'I', 'O', ' '}}, //BRITISH INDIAN OCEAN TERRITORY
+ {REG_DOMAIN_WORLD, {'I', 'Q', ' '}}, //IRAQ
+ {REG_DOMAIN_WORLD, {'I', 'R', ' '}}, //IRAN, ISLAMIC REPUBLIC OF
+ {REG_DOMAIN_WORLD, {'I', 'S', ' '}}, //ICELAND
+ {REG_DOMAIN_ETSI, {'I', 'T', ' '}}, //ITALY
+ {REG_DOMAIN_ETSI, {'J', 'E', ' '}}, //JERSEY
+ {REG_DOMAIN_WORLD, {'J', 'M', ' '}}, //JAMAICA
+ {REG_DOMAIN_WORLD, {'J', 'O', ' '}}, //JORDAN
+ {REG_DOMAIN_JAPAN, {'J', 'P', ' '}}, //JAPAN
+ {REG_DOMAIN_WORLD, {'K', 'E', ' '}}, //KENYA
+ {REG_DOMAIN_WORLD, {'K', 'G', ' '}}, //KYRGYZSTAN
+ {REG_DOMAIN_WORLD, {'K', 'H', ' '}}, //CAMBODIA
+ {REG_DOMAIN_WORLD, {'K', 'I', ' '}}, //KIRIBATI
+ {REG_DOMAIN_WORLD, {'K', 'M', ' '}}, //COMOROS
+ {REG_DOMAIN_WORLD, {'K', 'N', ' '}}, //SAINT KITTS AND NEVIS
+ {REG_DOMAIN_KOREA, {'K', 'P', ' '}}, //KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF
+ {REG_DOMAIN_KOREA, {'K', 'R', ' '}}, //KOREA, REPUBLIC OF
+ {REG_DOMAIN_WORLD, {'K', 'W', ' '}}, //KUWAIT
+ {REG_DOMAIN_WORLD, {'K', 'Y', ' '}}, //CAYMAN ISLANDS
+ {REG_DOMAIN_WORLD, {'K', 'Z', ' '}}, //KAZAKHSTAN
+ {REG_DOMAIN_WORLD, {'L', 'A', ' '}}, //LAO PEOPLE'S DEMOCRATIC REPUBLIC
+ {REG_DOMAIN_WORLD, {'L', 'B', ' '}}, //LEBANON
+ {REG_DOMAIN_WORLD, {'L', 'C', ' '}}, //SAINT LUCIA
+ {REG_DOMAIN_ETSI, {'L', 'I', ' '}}, //LIECHTENSTEIN
+ {REG_DOMAIN_WORLD, {'L', 'K', ' '}}, //SRI LANKA
+ {REG_DOMAIN_WORLD, {'L', 'R', ' '}}, //LIBERIA
+ {REG_DOMAIN_WORLD, {'L', 'S', ' '}}, //LESOTHO
+ {REG_DOMAIN_HI_5GHZ, {'L', 'T', ' '}}, //LITHUANIA
+ {REG_DOMAIN_ETSI, {'L', 'U', ' '}}, //LUXEMBOURG
+ {REG_DOMAIN_HI_5GHZ, {'L', 'V', ' '}}, //LATVIA
+ {REG_DOMAIN_WORLD, {'L', 'Y', ' '}}, //LIBYAN ARAB JAMAHIRIYA
+ {REG_DOMAIN_WORLD, {'M', 'A', ' '}}, //MOROCCO
+ {REG_DOMAIN_ETSI, {'M', 'C', ' '}}, //MONACO
+ {REG_DOMAIN_WORLD, {'M', 'D', ' '}}, //MOLDOVA, REPUBLIC OF
+ {REG_DOMAIN_WORLD, {'M', 'E', ' '}}, //MONTENEGRO
+ {REG_DOMAIN_WORLD, {'M', 'G', ' '}}, //MADAGASCAR
+ {REG_DOMAIN_WORLD, {'M', 'H', ' '}}, //MARSHALL ISLANDS
+ {REG_DOMAIN_WORLD, {'M', 'K', ' '}}, //MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF
+ {REG_DOMAIN_WORLD, {'M', 'L', ' '}}, //MALI
+ {REG_DOMAIN_WORLD, {'M', 'M', ' '}}, //MYANMAR
+ {REG_DOMAIN_HI_5GHZ, {'M', 'N', ' '}}, //MONGOLIA
+ {REG_DOMAIN_WORLD, {'M', 'O', ' '}}, //MACAO
+ {REG_DOMAIN_WORLD, {'M', 'P', ' '}}, //NORTHERN MARIANA ISLANDS
+ {REG_DOMAIN_WORLD, {'M', 'Q', ' '}}, //MARTINIQUE
+ {REG_DOMAIN_WORLD, {'M', 'R', ' '}}, //MAURITANIA
+ {REG_DOMAIN_WORLD, {'M', 'S', ' '}}, //MONTSERRAT
+ {REG_DOMAIN_WORLD, {'M', 'T', ' '}}, //MALTA
+ {REG_DOMAIN_WORLD, {'M', 'U', ' '}}, //MAURITIUS
+ {REG_DOMAIN_WORLD, {'M', 'V', ' '}}, //MALDIVES
+ {REG_DOMAIN_WORLD, {'M', 'W', ' '}}, //MALAWI
+ {REG_DOMAIN_WORLD, {'M', 'X', ' '}}, //MEXICO
+ {REG_DOMAIN_HI_5GHZ, {'M', 'Y', ' '}}, //MALAYSIA
+ {REG_DOMAIN_WORLD, {'M', 'Z', ' '}}, //MOZAMBIQUE
+ {REG_DOMAIN_WORLD, {'N', 'A', ' '}}, //NAMIBIA
+ {REG_DOMAIN_WORLD, {'N', 'C', ' '}}, //NEW CALEDONIA
+ {REG_DOMAIN_WORLD, {'N', 'E', ' '}}, //NIGER
+ {REG_DOMAIN_WORLD, {'N', 'F', ' '}}, //NORFOLD ISLAND
+ {REG_DOMAIN_WORLD, {'N', 'G', ' '}}, //NIGERIA
+ {REG_DOMAIN_WORLD, {'N', 'I', ' '}}, //NICARAGUA
+ {REG_DOMAIN_ETSI, {'N', 'L', ' '}}, //NETHERLANDS
+ {REG_DOMAIN_WORLD, {'N', 'O', ' '}}, //NORWAY
+ {REG_DOMAIN_WORLD, {'N', 'P', ' '}}, //NEPAL
+ {REG_DOMAIN_WORLD, {'N', 'R', ' '}}, //NAURU
+ {REG_DOMAIN_WORLD, {'N', 'U', ' '}}, //NIUE
+ {REG_DOMAIN_ETSI, {'N', 'Z', ' '}}, //NEW ZEALAND
+ {REG_DOMAIN_WORLD, {'O', 'M', ' '}}, //OMAN
+ {REG_DOMAIN_WORLD, {'P', 'A', ' '}}, //PANAMA
+ {REG_DOMAIN_WORLD, {'P', 'E', ' '}}, //PERU
+ {REG_DOMAIN_WORLD, {'P', 'F', ' '}}, //FRENCH POLYNESIA
+ {REG_DOMAIN_WORLD, {'P', 'G', ' '}}, //PAPUA NEW GUINEA
+ {REG_DOMAIN_WORLD, {'P', 'H', ' '}}, //PHILIPPINES
+ {REG_DOMAIN_WORLD, {'P', 'K', ' '}}, //PAKISTAN
+ {REG_DOMAIN_WORLD, {'P', 'L', ' '}}, //POLAND
+ {REG_DOMAIN_WORLD, {'P', 'M', ' '}}, //SAINT PIERRE AND MIQUELON
+ {REG_DOMAIN_WORLD, {'P', 'N', ' '}}, //PITCAIRN
+ {REG_DOMAIN_FCC, {'P', 'R', ' '}}, //PUERTO RICO
+ {REG_DOMAIN_WORLD, {'P', 'S', ' '}}, //PALESTINIAN TERRITORY, OCCUPIED
+ {REG_DOMAIN_ETSI, {'P', 'T', ' '}}, //PORTUGAL
+ {REG_DOMAIN_WORLD, {'P', 'W', ' '}}, //PALAU
+ {REG_DOMAIN_WORLD, {'P', 'Y', ' '}}, //PARAGUAY
+ {REG_DOMAIN_WORLD, {'Q', 'A', ' '}}, //QATAR
+ {REG_DOMAIN_WORLD, {'R', 'E', ' '}}, //REUNION
+ {REG_DOMAIN_HI_5GHZ, {'R', 'O', ' '}}, //ROMANIA
+ {REG_DOMAIN_HI_5GHZ, {'R', 'S', ' '}}, //SERBIA
+ {REG_DOMAIN_WORLD, {'R', 'U', ' '}}, //RUSSIA
+ {REG_DOMAIN_WORLD, {'R', 'W', ' '}}, //RWANDA
+ {REG_DOMAIN_WORLD, {'S', 'A', ' '}}, //SAUDI ARABIA
+ {REG_DOMAIN_WORLD, {'S', 'B', ' '}}, //SOLOMON ISLANDS
+ {REG_DOMAIN_ETSI, {'S', 'C', ' '}}, //SEYCHELLES
+ {REG_DOMAIN_WORLD, {'S', 'D', ' '}}, //SUDAN
+ {REG_DOMAIN_ETSI, {'S', 'E', ' '}}, //SWEDEN
+ {REG_DOMAIN_APAC, {'S', 'G', ' '}}, //SINGAPORE
+ {REG_DOMAIN_WORLD, {'S', 'H', ' '}}, //SAINT HELENA
+ {REG_DOMAIN_HI_5GHZ, {'S', 'I', ' '}}, //SLOVENNIA
+ {REG_DOMAIN_WORLD, {'S', 'J', ' '}}, //SVALBARD AND JAN MAYEN
+ {REG_DOMAIN_HI_5GHZ, {'S', 'K', ' '}}, //SLOVAKIA
+ {REG_DOMAIN_WORLD, {'S', 'L', ' '}}, //SIERRA LEONE
+ {REG_DOMAIN_WORLD, {'S', 'M', ' '}}, //SAN MARINO
+ {REG_DOMAIN_WORLD, {'S', 'N', ' '}}, //SENEGAL
+ {REG_DOMAIN_WORLD, {'S', 'O', ' '}}, //SOMALIA
+ {REG_DOMAIN_WORLD, {'S', 'R', ' '}}, //SURINAME
+ {REG_DOMAIN_WORLD, {'S', 'T', ' '}}, //SAO TOME AND PRINCIPE
+ {REG_DOMAIN_WORLD, {'S', 'V', ' '}}, //EL SALVADOR
+ {REG_DOMAIN_WORLD, {'S', 'Y', ' '}}, //SYRIAN ARAB REPUBLIC
+ {REG_DOMAIN_WORLD, {'S', 'Z', ' '}}, //SWAZILAND
+ {REG_DOMAIN_WORLD, {'T', 'C', ' '}}, //TURKS AND CAICOS ISLANDS
+ {REG_DOMAIN_WORLD, {'T', 'D', ' '}}, //CHAD
+ {REG_DOMAIN_WORLD, {'T', 'F', ' '}}, //FRENCH SOUTHERN TERRITORIES
+ {REG_DOMAIN_WORLD, {'T', 'G', ' '}}, //TOGO
+ {REG_DOMAIN_WORLD, {'T', 'H', ' '}}, //THAILAND
+ {REG_DOMAIN_WORLD, {'T', 'J', ' '}}, //TAJIKISTAN
+ {REG_DOMAIN_WORLD, {'T', 'K', ' '}}, //TOKELAU
+ {REG_DOMAIN_WORLD, {'T', 'L', ' '}}, //TIMOR-LESTE
+ {REG_DOMAIN_WORLD, {'T', 'M', ' '}}, //TURKMENISTAN
+ {REG_DOMAIN_WORLD, {'T', 'N', ' '}}, //TUNISIA
+ {REG_DOMAIN_WORLD, {'T', 'O', ' '}}, //TONGA
+ {REG_DOMAIN_WORLD, {'T', 'R', ' '}}, //TURKEY
+ {REG_DOMAIN_WORLD, {'T', 'T', ' '}}, //TRINIDAD AND TOBAGO
+ {REG_DOMAIN_WORLD, {'T', 'V', ' '}}, //TUVALU
+ {REG_DOMAIN_HI_5GHZ, {'T', 'W', ' '}}, //TAIWAN, PROVINCE OF CHINA
+ {REG_DOMAIN_WORLD, {'T', 'Z', ' '}}, //TANZANIA, UNITED REPUBLIC OF
+ {REG_DOMAIN_HI_5GHZ, {'U', 'A', ' '}}, //UKRAINE
+ {REG_DOMAIN_WORLD, {'U', 'G', ' '}}, //UGANDA
+ {REG_DOMAIN_FCC, {'U', 'M', ' '}}, //UNITED STATES MINOR OUTLYING ISLANDS
+ {REG_DOMAIN_WORLD, {'U', 'Y', ' '}}, //URUGUAY
+ {REG_DOMAIN_HI_5GHZ, {'U', 'Z', ' '}}, //UZBEKISTAN
+ {REG_DOMAIN_ETSI, {'V', 'A', ' '}}, //HOLY SEE (VATICAN CITY STATE)
+ {REG_DOMAIN_WORLD, {'V', 'C', ' '}}, //SAINT VINCENT AND THE GRENADINES
+ {REG_DOMAIN_HI_5GHZ, {'V', 'E', ' '}}, //VENEZUELA
+ {REG_DOMAIN_ETSI, {'V', 'G', ' '}}, //VIRGIN ISLANDS, BRITISH
+ {REG_DOMAIN_FCC, {'V', 'I', ' '}}, //VIRGIN ISLANDS, US
+ {REG_DOMAIN_WORLD, {'V', 'N', ' '}}, //VIET NAM
+ {REG_DOMAIN_WORLD, {'V', 'U', ' '}}, //VANUATU
+ {REG_DOMAIN_WORLD, {'W', 'F', ' '}}, //WALLIS AND FUTUNA
+ {REG_DOMAIN_WORLD, {'W', 'S', ' '}}, //SOMOA
+ {REG_DOMAIN_WORLD, {'Y', 'E', ' '}}, //YEMEN
+ {REG_DOMAIN_WORLD, {'Y', 'T', ' '}}, //MAYOTTE
+ {REG_DOMAIN_WORLD, {'Z', 'A', ' '}}, //SOUTH AFRICA
+ {REG_DOMAIN_WORLD, {'Z', 'M', ' '}}, //ZAMBIA
+ {REG_DOMAIN_WORLD, {'Z', 'W', ' '}}, //ZIMBABWE
+
+ {REG_DOMAIN_KOREA, {'K', '1', ' '}}, //Korea alternate 1
+ {REG_DOMAIN_KOREA, {'K', '2', ' '}}, //Korea alternate 2
+ {REG_DOMAIN_KOREA, {'K', '3', ' '}}, //Korea alternate 3
+ {REG_DOMAIN_KOREA, {'K', '4', ' '}}, //Korea alternate 4
+};
+
+
+//The channels listed here doesn't mean they are valid channels for certain domain. They are here only to present
+//whether they should be passive scanned.
+tCsrDomainChnInfo gCsrDomainChnInfo[NUM_REG_DOMAINS] =
+{
+ //REG_DOMAIN_FCC
+ {
+ REG_DOMAIN_FCC,
+ 45, //Num channels
+ //Channels
+ {
+ //5GHz
+ //5180 - 5240
+ {36, eSIR_ACTIVE_SCAN},
+ {40, eSIR_ACTIVE_SCAN},
+ {44, eSIR_ACTIVE_SCAN},
+ {48, eSIR_ACTIVE_SCAN},
+ //5250 to 5350
+ {52, eSIR_PASSIVE_SCAN},
+ {56, eSIR_PASSIVE_SCAN},
+ {60, eSIR_PASSIVE_SCAN},
+ {64, eSIR_PASSIVE_SCAN},
+ //5470 to 5725
+ {100, eSIR_PASSIVE_SCAN},
+ {104, eSIR_PASSIVE_SCAN},
+ {108, eSIR_PASSIVE_SCAN},
+ {112, eSIR_PASSIVE_SCAN},
+ {116, eSIR_PASSIVE_SCAN},
+ {120, eSIR_PASSIVE_SCAN},
+ {124, eSIR_PASSIVE_SCAN},
+ {128, eSIR_PASSIVE_SCAN},
+ {132, eSIR_PASSIVE_SCAN},
+ {136, eSIR_PASSIVE_SCAN},
+ {140, eSIR_PASSIVE_SCAN},
+ //5745 - 5825
+ {149, eSIR_ACTIVE_SCAN},
+ {153, eSIR_ACTIVE_SCAN},
+ {157, eSIR_ACTIVE_SCAN},
+ {161, eSIR_ACTIVE_SCAN},
+ {165, eSIR_ACTIVE_SCAN},
+ //4.9GHz
+ //4920 - 5080
+ {240, eSIR_ACTIVE_SCAN},
+ {244, eSIR_ACTIVE_SCAN},
+ {248, eSIR_ACTIVE_SCAN},
+ {252, eSIR_ACTIVE_SCAN},
+ {208, eSIR_ACTIVE_SCAN},
+ {212, eSIR_ACTIVE_SCAN},
+ {216, eSIR_ACTIVE_SCAN},
+ //2,4GHz
+ {1, eSIR_ACTIVE_SCAN},
+ {2, eSIR_ACTIVE_SCAN},
+ {3, eSIR_ACTIVE_SCAN},
+ {4, eSIR_ACTIVE_SCAN},
+ {5, eSIR_ACTIVE_SCAN},
+ {6, eSIR_ACTIVE_SCAN},
+ {7, eSIR_ACTIVE_SCAN},
+ {8, eSIR_ACTIVE_SCAN},
+ {9, eSIR_ACTIVE_SCAN},
+ {10, eSIR_ACTIVE_SCAN},
+ {11, eSIR_ACTIVE_SCAN},
+ {12, eSIR_ACTIVE_SCAN},
+ {13, eSIR_ACTIVE_SCAN},
+ {14, eSIR_ACTIVE_SCAN},
+ }
+ },
+ //REG_DOMAIN_ETSI
+ {
+ REG_DOMAIN_ETSI,
+ 45, //Num channels
+ //Channels
+ {
+ //5GHz
+ //5180 - 5240
+ {36, eSIR_ACTIVE_SCAN},
+ {40, eSIR_ACTIVE_SCAN},
+ {44, eSIR_ACTIVE_SCAN},
+ {48, eSIR_ACTIVE_SCAN},
+ //5250 to 5350
+ {52, eSIR_PASSIVE_SCAN},
+ {56, eSIR_PASSIVE_SCAN},
+ {60, eSIR_PASSIVE_SCAN},
+ {64, eSIR_PASSIVE_SCAN},
+ //5470 to 5725
+ {100, eSIR_PASSIVE_SCAN},
+ {104, eSIR_PASSIVE_SCAN},
+ {108, eSIR_PASSIVE_SCAN},
+ {112, eSIR_PASSIVE_SCAN},
+ {116, eSIR_PASSIVE_SCAN},
+ {120, eSIR_PASSIVE_SCAN},
+ {124, eSIR_PASSIVE_SCAN},
+ {128, eSIR_PASSIVE_SCAN},
+ {132, eSIR_PASSIVE_SCAN},
+ {136, eSIR_PASSIVE_SCAN},
+ {140, eSIR_PASSIVE_SCAN},
+ //5745 - 5825
+ {149, eSIR_ACTIVE_SCAN},
+ {153, eSIR_ACTIVE_SCAN},
+ {157, eSIR_ACTIVE_SCAN},
+ {161, eSIR_ACTIVE_SCAN},
+ {165, eSIR_ACTIVE_SCAN},
+ //4.9GHz
+ //4920 - 5080
+ {240, eSIR_ACTIVE_SCAN},
+ {244, eSIR_ACTIVE_SCAN},
+ {248, eSIR_ACTIVE_SCAN},
+ {252, eSIR_ACTIVE_SCAN},
+ {208, eSIR_ACTIVE_SCAN},
+ {212, eSIR_ACTIVE_SCAN},
+ {216, eSIR_ACTIVE_SCAN},
+ //2,4GHz
+ {1, eSIR_ACTIVE_SCAN},
+ {2, eSIR_ACTIVE_SCAN},
+ {3, eSIR_ACTIVE_SCAN},
+ {4, eSIR_ACTIVE_SCAN},
+ {5, eSIR_ACTIVE_SCAN},
+ {6, eSIR_ACTIVE_SCAN},
+ {7, eSIR_ACTIVE_SCAN},
+ {8, eSIR_ACTIVE_SCAN},
+ {9, eSIR_ACTIVE_SCAN},
+ {10, eSIR_ACTIVE_SCAN},
+ {11, eSIR_ACTIVE_SCAN},
+ {12, eSIR_ACTIVE_SCAN},
+ {13, eSIR_ACTIVE_SCAN},
+ {14, eSIR_ACTIVE_SCAN},
+ }
+ },
+ //REG_DOMAIN_JAPAN
+ {
+ REG_DOMAIN_JAPAN,
+ 45, //Num channels
+ //Channels
+ {
+ //5GHz
+ //5180 - 5240
+ {36, eSIR_ACTIVE_SCAN},
+ {40, eSIR_ACTIVE_SCAN},
+ {44, eSIR_ACTIVE_SCAN},
+ {48, eSIR_ACTIVE_SCAN},
+ //5250 to 5350
+ {52, eSIR_PASSIVE_SCAN},
+ {56, eSIR_PASSIVE_SCAN},
+ {60, eSIR_PASSIVE_SCAN},
+ {64, eSIR_PASSIVE_SCAN},
+ //5470 to 5725
+ {100, eSIR_PASSIVE_SCAN},
+ {104, eSIR_PASSIVE_SCAN},
+ {108, eSIR_PASSIVE_SCAN},
+ {112, eSIR_PASSIVE_SCAN},
+ {116, eSIR_PASSIVE_SCAN},
+ {120, eSIR_PASSIVE_SCAN},
+ {124, eSIR_PASSIVE_SCAN},
+ {128, eSIR_PASSIVE_SCAN},
+ {132, eSIR_PASSIVE_SCAN},
+ {136, eSIR_PASSIVE_SCAN},
+ {140, eSIR_PASSIVE_SCAN},
+ //5745 - 5825
+ {149, eSIR_ACTIVE_SCAN},
+ {153, eSIR_ACTIVE_SCAN},
+ {157, eSIR_ACTIVE_SCAN},
+ {161, eSIR_ACTIVE_SCAN},
+ {165, eSIR_ACTIVE_SCAN},
+ //4.9GHz
+ //4920 - 5080
+ {240, eSIR_ACTIVE_SCAN},
+ {244, eSIR_ACTIVE_SCAN},
+ {248, eSIR_ACTIVE_SCAN},
+ {252, eSIR_ACTIVE_SCAN},
+ {208, eSIR_ACTIVE_SCAN},
+ {212, eSIR_ACTIVE_SCAN},
+ {216, eSIR_ACTIVE_SCAN},
+ //2,4GHz
+ {1, eSIR_ACTIVE_SCAN},
+ {2, eSIR_ACTIVE_SCAN},
+ {3, eSIR_ACTIVE_SCAN},
+ {4, eSIR_ACTIVE_SCAN},
+ {5, eSIR_ACTIVE_SCAN},
+ {6, eSIR_ACTIVE_SCAN},
+ {7, eSIR_ACTIVE_SCAN},
+ {8, eSIR_ACTIVE_SCAN},
+ {9, eSIR_ACTIVE_SCAN},
+ {10, eSIR_ACTIVE_SCAN},
+ {11, eSIR_ACTIVE_SCAN},
+ {12, eSIR_ACTIVE_SCAN},
+ {13, eSIR_ACTIVE_SCAN},
+ {14, eSIR_ACTIVE_SCAN},
+ }
+ },
+ //REG_DOMAIN_WORLD
+ {
+ REG_DOMAIN_WORLD,
+ 45, //Num channels
+ //Channels
+ {
+ //5GHz
+ //5180 - 5240
+ {36, eSIR_ACTIVE_SCAN},
+ {40, eSIR_ACTIVE_SCAN},
+ {44, eSIR_ACTIVE_SCAN},
+ {48, eSIR_ACTIVE_SCAN},
+ //5250 to 5350
+ {52, eSIR_ACTIVE_SCAN},
+ {56, eSIR_ACTIVE_SCAN},
+ {60, eSIR_ACTIVE_SCAN},
+ {64, eSIR_ACTIVE_SCAN},
+ //5470 to 5725
+ {100, eSIR_ACTIVE_SCAN},
+ {104, eSIR_ACTIVE_SCAN},
+ {108, eSIR_ACTIVE_SCAN},
+ {112, eSIR_ACTIVE_SCAN},
+ {116, eSIR_ACTIVE_SCAN},
+ {120, eSIR_ACTIVE_SCAN},
+ {124, eSIR_ACTIVE_SCAN},
+ {128, eSIR_ACTIVE_SCAN},
+ {132, eSIR_ACTIVE_SCAN},
+ {136, eSIR_ACTIVE_SCAN},
+ {140, eSIR_ACTIVE_SCAN},
+ //5745 - 5825
+ {149, eSIR_ACTIVE_SCAN},
+ {153, eSIR_ACTIVE_SCAN},
+ {157, eSIR_ACTIVE_SCAN},
+ {161, eSIR_ACTIVE_SCAN},
+ {165, eSIR_ACTIVE_SCAN},
+ //4.9GHz
+ //4920 - 5080
+ {240, eSIR_ACTIVE_SCAN},
+ {244, eSIR_ACTIVE_SCAN},
+ {248, eSIR_ACTIVE_SCAN},
+ {252, eSIR_ACTIVE_SCAN},
+ {208, eSIR_ACTIVE_SCAN},
+ {212, eSIR_ACTIVE_SCAN},
+ {216, eSIR_ACTIVE_SCAN},
+ //2,4GHz
+ {1, eSIR_ACTIVE_SCAN},
+ {2, eSIR_ACTIVE_SCAN},
+ {3, eSIR_ACTIVE_SCAN},
+ {4, eSIR_ACTIVE_SCAN},
+ {5, eSIR_ACTIVE_SCAN},
+ {6, eSIR_ACTIVE_SCAN},
+ {7, eSIR_ACTIVE_SCAN},
+ {8, eSIR_ACTIVE_SCAN},
+ {9, eSIR_ACTIVE_SCAN},
+ {10, eSIR_ACTIVE_SCAN},
+ {11, eSIR_ACTIVE_SCAN},
+ {12, eSIR_ACTIVE_SCAN},
+ {13, eSIR_ACTIVE_SCAN},
+ {14, eSIR_ACTIVE_SCAN},
+ }
+ },
+ //REG_DOMAIN_N_AMER_EXC_FCC
+ {
+ REG_DOMAIN_N_AMER_EXC_FCC,
+ 45, //Num channels
+ //Channels
+ {
+ //5GHz
+ //5180 - 5240
+ {36, eSIR_ACTIVE_SCAN},
+ {40, eSIR_ACTIVE_SCAN},
+ {44, eSIR_ACTIVE_SCAN},
+ {48, eSIR_ACTIVE_SCAN},
+ //5250 to 5350
+ {52, eSIR_PASSIVE_SCAN},
+ {56, eSIR_PASSIVE_SCAN},
+ {60, eSIR_PASSIVE_SCAN},
+ {64, eSIR_PASSIVE_SCAN},
+ //5470 to 5725
+ {100, eSIR_ACTIVE_SCAN},
+ {104, eSIR_ACTIVE_SCAN},
+ {108, eSIR_ACTIVE_SCAN},
+ {112, eSIR_ACTIVE_SCAN},
+ {116, eSIR_ACTIVE_SCAN},
+ {120, eSIR_ACTIVE_SCAN},
+ {124, eSIR_ACTIVE_SCAN},
+ {128, eSIR_ACTIVE_SCAN},
+ {132, eSIR_ACTIVE_SCAN},
+ {136, eSIR_ACTIVE_SCAN},
+ {140, eSIR_ACTIVE_SCAN},
+ //5745 - 5825
+ {149, eSIR_ACTIVE_SCAN},
+ {153, eSIR_ACTIVE_SCAN},
+ {157, eSIR_ACTIVE_SCAN},
+ {161, eSIR_ACTIVE_SCAN},
+ {165, eSIR_ACTIVE_SCAN},
+ //4.9GHz
+ //4920 - 5080
+ {240, eSIR_ACTIVE_SCAN},
+ {244, eSIR_ACTIVE_SCAN},
+ {248, eSIR_ACTIVE_SCAN},
+ {252, eSIR_ACTIVE_SCAN},
+ {208, eSIR_ACTIVE_SCAN},
+ {212, eSIR_ACTIVE_SCAN},
+ {216, eSIR_ACTIVE_SCAN},
+ //2,4GHz
+ {1, eSIR_ACTIVE_SCAN},
+ {2, eSIR_ACTIVE_SCAN},
+ {3, eSIR_ACTIVE_SCAN},
+ {4, eSIR_ACTIVE_SCAN},
+ {5, eSIR_ACTIVE_SCAN},
+ {6, eSIR_ACTIVE_SCAN},
+ {7, eSIR_ACTIVE_SCAN},
+ {8, eSIR_ACTIVE_SCAN},
+ {9, eSIR_ACTIVE_SCAN},
+ {10, eSIR_ACTIVE_SCAN},
+ {11, eSIR_ACTIVE_SCAN},
+ {12, eSIR_ACTIVE_SCAN},
+ {13, eSIR_ACTIVE_SCAN},
+ {14, eSIR_ACTIVE_SCAN},
+ }
+ },
+ //REG_DOMAIN_APAC
+ {
+ REG_DOMAIN_APAC,
+ 45, //Num channels
+ //Channels
+ {
+ //5GHz
+ //5180 - 5240
+ {36, eSIR_ACTIVE_SCAN},
+ {40, eSIR_ACTIVE_SCAN},
+ {44, eSIR_ACTIVE_SCAN},
+ {48, eSIR_ACTIVE_SCAN},
+ //5250 to 5350
+ {52, eSIR_PASSIVE_SCAN},
+ {56, eSIR_PASSIVE_SCAN},
+ {60, eSIR_PASSIVE_SCAN},
+ {64, eSIR_PASSIVE_SCAN},
+ //5470 to 5725
+ {100, eSIR_ACTIVE_SCAN},
+ {104, eSIR_ACTIVE_SCAN},
+ {108, eSIR_ACTIVE_SCAN},
+ {112, eSIR_ACTIVE_SCAN},
+ {116, eSIR_ACTIVE_SCAN},
+ {120, eSIR_ACTIVE_SCAN},
+ {124, eSIR_ACTIVE_SCAN},
+ {128, eSIR_ACTIVE_SCAN},
+ {132, eSIR_ACTIVE_SCAN},
+ {136, eSIR_ACTIVE_SCAN},
+ {140, eSIR_ACTIVE_SCAN},
+ //5745 - 5825
+ {149, eSIR_ACTIVE_SCAN},
+ {153, eSIR_ACTIVE_SCAN},
+ {157, eSIR_ACTIVE_SCAN},
+ {161, eSIR_ACTIVE_SCAN},
+ {165, eSIR_ACTIVE_SCAN},
+ //4.9GHz
+ //4920 - 5080
+ {240, eSIR_ACTIVE_SCAN},
+ {244, eSIR_ACTIVE_SCAN},
+ {248, eSIR_ACTIVE_SCAN},
+ {252, eSIR_ACTIVE_SCAN},
+ {208, eSIR_ACTIVE_SCAN},
+ {212, eSIR_ACTIVE_SCAN},
+ {216, eSIR_ACTIVE_SCAN},
+ //2,4GHz
+ {1, eSIR_ACTIVE_SCAN},
+ {2, eSIR_ACTIVE_SCAN},
+ {3, eSIR_ACTIVE_SCAN},
+ {4, eSIR_ACTIVE_SCAN},
+ {5, eSIR_ACTIVE_SCAN},
+ {6, eSIR_ACTIVE_SCAN},
+ {7, eSIR_ACTIVE_SCAN},
+ {8, eSIR_ACTIVE_SCAN},
+ {9, eSIR_ACTIVE_SCAN},
+ {10, eSIR_ACTIVE_SCAN},
+ {11, eSIR_ACTIVE_SCAN},
+ {12, eSIR_ACTIVE_SCAN},
+ {13, eSIR_ACTIVE_SCAN},
+ {14, eSIR_ACTIVE_SCAN},
+ }
+ },
+ //REG_DOMAIN_KOREA
+ {
+ REG_DOMAIN_KOREA,
+ 45, //Num channels
+ //Channels
+ {
+ //5GHz
+ //5180 - 5240
+ {36, eSIR_ACTIVE_SCAN},
+ {40, eSIR_ACTIVE_SCAN},
+ {44, eSIR_ACTIVE_SCAN},
+ {48, eSIR_ACTIVE_SCAN},
+ //5250 to 5350
+ {52, eSIR_PASSIVE_SCAN},
+ {56, eSIR_PASSIVE_SCAN},
+ {60, eSIR_PASSIVE_SCAN},
+ {64, eSIR_PASSIVE_SCAN},
+ //5470 to 5725
+ {100, eSIR_PASSIVE_SCAN},
+ {104, eSIR_PASSIVE_SCAN},
+ {108, eSIR_PASSIVE_SCAN},
+ {112, eSIR_PASSIVE_SCAN},
+ {116, eSIR_PASSIVE_SCAN},
+ {120, eSIR_PASSIVE_SCAN},
+ {124, eSIR_PASSIVE_SCAN},
+ {128, eSIR_PASSIVE_SCAN},
+ {132, eSIR_PASSIVE_SCAN},
+ {136, eSIR_PASSIVE_SCAN},
+ {140, eSIR_PASSIVE_SCAN},
+ //5745 - 5825
+ {149, eSIR_ACTIVE_SCAN},
+ {153, eSIR_ACTIVE_SCAN},
+ {157, eSIR_ACTIVE_SCAN},
+ {161, eSIR_ACTIVE_SCAN},
+ {165, eSIR_ACTIVE_SCAN},
+ //4.9GHz
+ //4920 - 5080
+ {240, eSIR_ACTIVE_SCAN},
+ {244, eSIR_ACTIVE_SCAN},
+ {248, eSIR_ACTIVE_SCAN},
+ {252, eSIR_ACTIVE_SCAN},
+ {208, eSIR_ACTIVE_SCAN},
+ {212, eSIR_ACTIVE_SCAN},
+ {216, eSIR_ACTIVE_SCAN},
+ //2,4GHz
+ {1, eSIR_ACTIVE_SCAN},
+ {2, eSIR_ACTIVE_SCAN},
+ {3, eSIR_ACTIVE_SCAN},
+ {4, eSIR_ACTIVE_SCAN},
+ {5, eSIR_ACTIVE_SCAN},
+ {6, eSIR_ACTIVE_SCAN},
+ {7, eSIR_ACTIVE_SCAN},
+ {8, eSIR_ACTIVE_SCAN},
+ {9, eSIR_ACTIVE_SCAN},
+ {10, eSIR_ACTIVE_SCAN},
+ {11, eSIR_ACTIVE_SCAN},
+ {12, eSIR_ACTIVE_SCAN},
+ {13, eSIR_ACTIVE_SCAN},
+ {14, eSIR_ACTIVE_SCAN},
+ }
+ },
+ //REG_DOMAIN_HI_5GHZ
+ {
+ REG_DOMAIN_HI_5GHZ,
+ 45, //Num channels
+ //Channels
+ {
+ //5GHz
+ //5180 - 5240
+ {36, eSIR_ACTIVE_SCAN},
+ {40, eSIR_ACTIVE_SCAN},
+ {44, eSIR_ACTIVE_SCAN},
+ {48, eSIR_ACTIVE_SCAN},
+ //5250 to 5350
+ {52, eSIR_ACTIVE_SCAN},
+ {56, eSIR_ACTIVE_SCAN},
+ {60, eSIR_ACTIVE_SCAN},
+ {64, eSIR_ACTIVE_SCAN},
+ //5470 to 5725
+ {100, eSIR_ACTIVE_SCAN},
+ {104, eSIR_ACTIVE_SCAN},
+ {108, eSIR_ACTIVE_SCAN},
+ {112, eSIR_ACTIVE_SCAN},
+ {116, eSIR_ACTIVE_SCAN},
+ {120, eSIR_ACTIVE_SCAN},
+ {124, eSIR_ACTIVE_SCAN},
+ {128, eSIR_ACTIVE_SCAN},
+ {132, eSIR_ACTIVE_SCAN},
+ {136, eSIR_ACTIVE_SCAN},
+ {140, eSIR_ACTIVE_SCAN},
+ //5745 - 5825
+ {149, eSIR_ACTIVE_SCAN},
+ {153, eSIR_ACTIVE_SCAN},
+ {157, eSIR_ACTIVE_SCAN},
+ {161, eSIR_ACTIVE_SCAN},
+ {165, eSIR_ACTIVE_SCAN},
+ //4.9GHz
+ //4920 - 5080
+ {240, eSIR_ACTIVE_SCAN},
+ {244, eSIR_ACTIVE_SCAN},
+ {248, eSIR_ACTIVE_SCAN},
+ {252, eSIR_ACTIVE_SCAN},
+ {208, eSIR_ACTIVE_SCAN},
+ {212, eSIR_ACTIVE_SCAN},
+ {216, eSIR_ACTIVE_SCAN},
+ //2,4GHz
+ {1, eSIR_ACTIVE_SCAN},
+ {2, eSIR_ACTIVE_SCAN},
+ {3, eSIR_ACTIVE_SCAN},
+ {4, eSIR_ACTIVE_SCAN},
+ {5, eSIR_ACTIVE_SCAN},
+ {6, eSIR_ACTIVE_SCAN},
+ {7, eSIR_ACTIVE_SCAN},
+ {8, eSIR_ACTIVE_SCAN},
+ {9, eSIR_ACTIVE_SCAN},
+ {10, eSIR_ACTIVE_SCAN},
+ {11, eSIR_ACTIVE_SCAN},
+ {12, eSIR_ACTIVE_SCAN},
+ {13, eSIR_ACTIVE_SCAN},
+ {14, eSIR_ACTIVE_SCAN},
+ }
+ },
+ //REG_DOMAIN_NO_5GHZ
+ {
+ REG_DOMAIN_NO_5GHZ,
+ 45, //Num channels
+ //Channels
+ {
+ //5GHz
+ //5180 - 5240
+ {36, eSIR_ACTIVE_SCAN},
+ {40, eSIR_ACTIVE_SCAN},
+ {44, eSIR_ACTIVE_SCAN},
+ {48, eSIR_ACTIVE_SCAN},
+ //5250 to 5350
+ {52, eSIR_ACTIVE_SCAN},
+ {56, eSIR_ACTIVE_SCAN},
+ {60, eSIR_ACTIVE_SCAN},
+ {64, eSIR_ACTIVE_SCAN},
+ //5470 to 5725
+ {100, eSIR_ACTIVE_SCAN},
+ {104, eSIR_ACTIVE_SCAN},
+ {108, eSIR_ACTIVE_SCAN},
+ {112, eSIR_ACTIVE_SCAN},
+ {116, eSIR_ACTIVE_SCAN},
+ {120, eSIR_ACTIVE_SCAN},
+ {124, eSIR_ACTIVE_SCAN},
+ {128, eSIR_ACTIVE_SCAN},
+ {132, eSIR_ACTIVE_SCAN},
+ {136, eSIR_ACTIVE_SCAN},
+ {140, eSIR_ACTIVE_SCAN},
+ //5745 - 5825
+ {149, eSIR_ACTIVE_SCAN},
+ {153, eSIR_ACTIVE_SCAN},
+ {157, eSIR_ACTIVE_SCAN},
+ {161, eSIR_ACTIVE_SCAN},
+ {165, eSIR_ACTIVE_SCAN},
+ //4.9GHz
+ //4920 - 5080
+ {240, eSIR_ACTIVE_SCAN},
+ {244, eSIR_ACTIVE_SCAN},
+ {248, eSIR_ACTIVE_SCAN},
+ {252, eSIR_ACTIVE_SCAN},
+ {208, eSIR_ACTIVE_SCAN},
+ {212, eSIR_ACTIVE_SCAN},
+ {216, eSIR_ACTIVE_SCAN},
+ //2,4GHz
+ {1, eSIR_ACTIVE_SCAN},
+ {2, eSIR_ACTIVE_SCAN},
+ {3, eSIR_ACTIVE_SCAN},
+ {4, eSIR_ACTIVE_SCAN},
+ {5, eSIR_ACTIVE_SCAN},
+ {6, eSIR_ACTIVE_SCAN},
+ {7, eSIR_ACTIVE_SCAN},
+ {8, eSIR_ACTIVE_SCAN},
+ {9, eSIR_ACTIVE_SCAN},
+ {10, eSIR_ACTIVE_SCAN},
+ {11, eSIR_ACTIVE_SCAN},
+ {12, eSIR_ACTIVE_SCAN},
+ {13, eSIR_ACTIVE_SCAN},
+ {14, eSIR_ACTIVE_SCAN},
+ }
+ },
+};
+#endif
+
+extern const tRfChannelProps rfChannels[NUM_RF_CHANNELS];
+
+
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * \var gPhyRatesSuppt
+ *
+ * \brief Rate support lookup table
+ *
+ *
+ * This is a lookup table indexing rates & configuration parameters to
+ * support. Given a rate (in unites of 0.5Mpbs) & three booleans (MIMO
+ * Enabled, Channel Bonding Enabled, & Concatenation Enabled), one can
+ * determine whether the given rate is supported by computing two
+ * indices. The first maps the rate to table row as indicated below
+ * (i.e. eHddSuppRate_6Mbps maps to row zero, eHddSuppRate_9Mbps to row
+ * 1, and so on). Index two can be computed like so:
+ *
+ * \code
+ idx2 = ( fEsf ? 0x4 : 0x0 ) |
+ ( fCb ? 0x2 : 0x0 ) |
+ ( fMimo ? 0x1 : 0x0 );
+ * \endcode
+ *
+ *
+ * Given that:
+ *
+ \code
+ fSupported = gPhyRatesSuppt[idx1][idx2];
+ \endcode
+ *
+ *
+ * This table is based on the document "PHY Supported Rates.doc". This
+ * table is permissive in that a rate is reflected as being supported
+ * even when turning off an enabled feature would be required. For
+ * instance, "PHY Supported Rates" lists 42Mpbs as unsupported when CB,
+ * ESF, & MIMO are all on. However, if we turn off either of CB or
+ * MIMO, it then becomes supported. Therefore, we mark it as supported
+ * even in index 7 of this table.
+ *
+ *
+ */
+
+static const tANI_BOOLEAN gPhyRatesSuppt[24][8] = {
+
+ // SSF SSF SSF SSF ESF ESF ESF ESF
+ // SIMO MIMO SIMO MIMO SIMO MIMO SIMO MIMO
+ // No CB No CB CB CB No CB No CB CB CB
+ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 6Mbps
+ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 9Mbps
+ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 12Mbps
+ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 18Mbps
+ { FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE }, // 20Mbps
+ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 24Mbps
+ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 36Mbps
+ { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 40Mbps
+ { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 42Mbps
+ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 48Mbps
+ { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 54Mbps
+ { FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 72Mbps
+ { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 80Mbps
+ { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 84Mbps
+ { FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 96Mbps
+ { FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 108Mbps
+ { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 120Mbps
+ { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 126Mbps
+ { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 144Mbps
+ { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 160Mbps
+ { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 168Mbps
+ { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 192Mbps
+ { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 216Mbps
+ { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 240Mbps
+
+};
+
+#define CASE_RETURN_STR(n) case (n): return (#n)
+
+const char *
+get_eRoamCmdStatus_str(eRoamCmdStatus val)
+{
+ switch (val)
+ {
+ CASE_RETURN_STR(eCSR_ROAM_CANCELLED);
+ CASE_RETURN_STR(eCSR_ROAM_ROAMING_START);
+ CASE_RETURN_STR(eCSR_ROAM_ROAMING_COMPLETION);
+ CASE_RETURN_STR(eCSR_ROAM_ASSOCIATION_START);
+ CASE_RETURN_STR(eCSR_ROAM_ASSOCIATION_COMPLETION);
+ CASE_RETURN_STR(eCSR_ROAM_DISASSOCIATED);
+ CASE_RETURN_STR(eCSR_ROAM_SHOULD_ROAM);
+ CASE_RETURN_STR(eCSR_ROAM_SCAN_FOUND_NEW_BSS);
+ CASE_RETURN_STR(eCSR_ROAM_LOSTLINK);
+ default:
+ return "unknown";
+ }
+}
+
+const char *
+get_eCsrRoamResult_str(eCsrRoamResult val)
+{
+ switch (val)
+ {
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_NONE);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_FAILURE);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_ASSOCIATED);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_NOT_ASSOCIATED);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_MIC_FAILURE);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_FORCED);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_DISASSOC_IND);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_DEAUTH_IND);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_CAP_CHANGED);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_IBSS_CONNECT);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_IBSS_INACTIVE);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_IBSS_NEW_PEER);
+ CASE_RETURN_STR(eCSR_ROAM_RESULT_IBSS_COALESCED);
+ default:
+ return "unknown";
+ }
+}
+
+
+
+tANI_BOOLEAN csrGetBssIdBssDesc( tHalHandle hHal, tSirBssDescription *pSirBssDesc, tCsrBssid *pBssId )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ palCopyMemory( pMac->hHdd, pBssId, &pSirBssDesc->bssId[ 0 ], sizeof(tCsrBssid) );
+ return( TRUE );
+}
+
+
+tANI_BOOLEAN csrIsBssIdEqual( tHalHandle hHal, tSirBssDescription *pSirBssDesc1, tSirBssDescription *pSirBssDesc2 )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN fEqual = FALSE;
+ tCsrBssid bssId1;
+ tCsrBssid bssId2;
+
+ do {
+ if ( !pSirBssDesc1 ) break;
+ if ( !pSirBssDesc2 ) break;
+
+ if ( !csrGetBssIdBssDesc( pMac, pSirBssDesc1, &bssId1 ) ) break;
+ if ( !csrGetBssIdBssDesc( pMac, pSirBssDesc2, &bssId2 ) ) break;
+
+ //sirCompareMacAddr
+ fEqual = csrIsMacAddressEqual(pMac, &bssId1, &bssId2);
+
+ } while( 0 );
+
+ return( fEqual );
+}
+
+tANI_BOOLEAN csrIsConnStateConnectedIbss( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return( eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED == pMac->roam.roamSession[sessionId].connectState );
+}
+
+tANI_BOOLEAN csrIsConnStateDisconnectedIbss( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return( eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED == pMac->roam.roamSession[sessionId].connectState );
+}
+
+tANI_BOOLEAN csrIsConnStateConnectedInfra( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return( eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED == pMac->roam.roamSession[sessionId].connectState );
+}
+
+tANI_BOOLEAN csrIsConnStateConnected( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ if( csrIsConnStateConnectedIbss( pMac, sessionId ) || csrIsConnStateConnectedInfra( pMac, sessionId ) || csrIsConnStateConnectedWds( pMac, sessionId) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+tANI_BOOLEAN csrIsConnStateInfra( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return( csrIsConnStateConnectedInfra( pMac, sessionId ) );
+}
+
+tANI_BOOLEAN csrIsConnStateIbss( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return( csrIsConnStateConnectedIbss( pMac, sessionId ) || csrIsConnStateDisconnectedIbss( pMac, sessionId ) );
+}
+
+
+tANI_BOOLEAN csrIsConnStateConnectedWds( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return( eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED == pMac->roam.roamSession[sessionId].connectState );
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+tANI_BOOLEAN csrIsConnStateConnectedInfraAp( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return( (eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED == pMac->roam.roamSession[sessionId].connectState) ||
+ (eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED == pMac->roam.roamSession[sessionId].connectState ) );
+}
+#endif
+
+tANI_BOOLEAN csrIsConnStateDisconnectedWds( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return( eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED == pMac->roam.roamSession[sessionId].connectState );
+}
+
+tANI_BOOLEAN csrIsConnStateWds( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return( csrIsConnStateConnectedWds( pMac, sessionId ) ||
+ csrIsConnStateDisconnectedWds( pMac, sessionId ) );
+}
+
+tANI_BOOLEAN csrIsAnySessionInConnectState( tpAniSirGlobal pMac )
+{
+ tANI_U32 i;
+ tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE;
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) &&
+ ( csrIsConnStateInfra( pMac, i ) || csrIsConnStateIbss( pMac, i ) ) )
+ {
+ fRc = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+
+ return ( fRc );
+}
+
+tANI_S8 csrGetInfraSessionId( tpAniSirGlobal pMac )
+{
+ tANI_U8 i;
+ tANI_S8 sessionid = -1;
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateInfra( pMac, i ) )
+ {
+ sessionid = i;
+ break;
+ }
+ }
+
+ return ( sessionid );
+}
+
+tANI_U8 csrGetInfraOperationChannel( tpAniSirGlobal pMac, tANI_U8 sessionId)
+{
+ tANI_U8 channel;
+
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ))
+ {
+ channel = pMac->roam.roamSession[sessionId].connectedProfile.operationChannel;
+ }
+ else
+ {
+ channel = 0;
+ }
+ return channel;
+}
+
+//This routine will return operating channel on FIRST BSS that is active/operating to be used for concurrency mode.
+//If other BSS is not up or not connected it will return 0
+
+tANI_U8 csrGetConcurrentOperationChannel( tpAniSirGlobal pMac )
+{
+ tCsrRoamSession *pSession = NULL;
+ tANI_U8 i = 0;
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) )
+ {
+ pSession = CSR_GET_SESSION( pMac, i );
+
+ if (NULL != pSession->pCurRoamProfile)
+ {
+ if (
+ (((pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE) ||
+ (pSession->pCurRoamProfile->csrPersona == VOS_P2P_CLIENT_MODE)) &&
+ (pSession->connectState == eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED))
+ ||
+ (((pSession->pCurRoamProfile->csrPersona == VOS_P2P_GO_MODE) ||
+ (pSession->pCurRoamProfile->csrPersona == VOS_STA_SAP_MODE)) &&
+ (pSession->connectState != eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED))
+ )
+ return (pSession->connectedProfile.operationChannel);
+ }
+
+ }
+ }
+ return 0;
+}
+
+tANI_BOOLEAN csrIsAllSessionDisconnected( tpAniSirGlobal pMac )
+{
+ tANI_U32 i;
+ tANI_BOOLEAN fRc = eANI_BOOLEAN_TRUE;
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) && !csrIsConnStateDisconnected( pMac, i ) )
+ {
+ fRc = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ }
+
+ return ( fRc );
+}
+
+
+tANI_BOOLEAN csrIsInfraConnected( tpAniSirGlobal pMac )
+{
+ tANI_U32 i;
+ tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE;
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateConnectedInfra( pMac, i ) )
+ {
+ fRc = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+
+ return ( fRc );
+}
+
+tANI_BOOLEAN csrIsConcurrentInfraConnected( tpAniSirGlobal pMac )
+{
+ tANI_U32 i, noOfConnectedInfra = 0;
+
+ tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE;
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateConnectedInfra( pMac, i ) )
+ {
+ ++noOfConnectedInfra;
+ }
+ }
+
+ // More than one Infra Sta Connected
+ if(noOfConnectedInfra > 1)
+ {
+ fRc = eANI_BOOLEAN_TRUE;
+ }
+
+ return ( fRc );
+}
+
+tANI_BOOLEAN csrIsIBSSStarted( tpAniSirGlobal pMac )
+{
+ tANI_U32 i;
+ tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE;
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateIbss( pMac, i ) )
+ {
+ fRc = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+
+ return ( fRc );
+}
+
+
+tANI_BOOLEAN csrIsBTAMPStarted( tpAniSirGlobal pMac )
+{
+ tANI_U32 i;
+ tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE;
+
+ for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateConnectedWds( pMac, i ) )
+ {
+ fRc = eANI_BOOLEAN_TRUE;
+ break;
+ }
+ }
+
+ return ( fRc );
+}
+
+tANI_BOOLEAN csrIsBTAMP( tpAniSirGlobal pMac, tANI_U32 sessionId )
+{
+ return ( csrIsConnStateConnectedWds( pMac, sessionId ) );
+}
+
+
+tANI_BOOLEAN csrIsConnStateDisconnected(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ return (eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED == pMac->roam.roamSession[sessionId].connectState);
+}
+
+tANI_BOOLEAN csrIsValidMcConcurrentSession(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ tCsrRoamSession *pSession = NULL;
+ tANI_U8 Index = 0, ConnId = 0;
+ tVOS_CON_MODE Mode[CSR_ROAM_SESSION_MAX];
+
+ //Check for MCC support
+ if (!pMac->roam.configParam.fenableMCCMode)
+ {
+ return eANI_BOOLEAN_FALSE;
+ }
+
+ for( Index = 0; Index < CSR_ROAM_SESSION_MAX; Index++ )
+ Mode[Index] = VOS_MAX_NO_OF_MODE;
+
+ for( Index = 0; Index < CSR_ROAM_SESSION_MAX; Index++ )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, Index ) )
+ {
+ pSession = CSR_GET_SESSION( pMac, Index );
+
+ if (NULL != pSession->pCurRoamProfile)
+ {
+ Mode[ConnId] = pSession->pCurRoamProfile->csrPersona;
+ ConnId++;
+ }
+ }
+ }
+
+ Index = 0;
+ if (Mode[Index] == VOS_STA_MODE && ConnId > Index)
+ {
+ switch (Mode[Index+1])
+ {
+ case VOS_P2P_CLIENT_MODE :
+ return eANI_BOOLEAN_TRUE;
+ case VOS_MAX_NO_OF_MODE :
+ default :
+ break;
+ }
+ }
+ else if (Mode[Index] == VOS_P2P_CLIENT_MODE && ConnId > Index)
+ {
+ switch (Mode[Index +1])
+ {
+ case VOS_STA_MODE :
+ return eANI_BOOLEAN_TRUE;
+ case VOS_MAX_NO_OF_MODE :
+ default :
+ break;
+ }
+ }
+
+ return eANI_BOOLEAN_FALSE;
+}
+
+static tSirMacCapabilityInfo csrGetBssCapabilities( tSirBssDescription *pSirBssDesc )
+{
+ tSirMacCapabilityInfo dot11Caps;
+
+ //tSirMacCapabilityInfo is 16-bit
+ pal_get_U16( (tANI_U8 *)&pSirBssDesc->capabilityInfo, (tANI_U16 *)&dot11Caps );
+
+ return( dot11Caps );
+}
+
+tANI_BOOLEAN csrIsInfraBssDesc( tSirBssDescription *pSirBssDesc )
+{
+ tSirMacCapabilityInfo dot11Caps = csrGetBssCapabilities( pSirBssDesc );
+
+ return( (tANI_BOOLEAN)dot11Caps.ess );
+}
+
+
+tANI_BOOLEAN csrIsIbssBssDesc( tSirBssDescription *pSirBssDesc )
+{
+ tSirMacCapabilityInfo dot11Caps = csrGetBssCapabilities( pSirBssDesc );
+
+ return( (tANI_BOOLEAN)dot11Caps.ibss );
+}
+
+tANI_BOOLEAN csrIsQoSBssDesc( tSirBssDescription *pSirBssDesc )
+{
+ tSirMacCapabilityInfo dot11Caps = csrGetBssCapabilities( pSirBssDesc );
+
+ return( (tANI_BOOLEAN)dot11Caps.qos );
+}
+
+tANI_BOOLEAN csrIsPrivacy( tSirBssDescription *pSirBssDesc )
+{
+ tSirMacCapabilityInfo dot11Caps = csrGetBssCapabilities( pSirBssDesc );
+
+ return( (tANI_BOOLEAN)dot11Caps.privacy );
+}
+
+
+tANI_BOOLEAN csrIs11dSupported(tpAniSirGlobal pMac)
+{
+ return(pMac->roam.configParam.Is11dSupportEnabled);
+}
+
+
+tANI_BOOLEAN csrIs11hSupported(tpAniSirGlobal pMac)
+{
+ return(pMac->roam.configParam.Is11hSupportEnabled);
+}
+
+
+tANI_BOOLEAN csrIs11eSupported(tpAniSirGlobal pMac)
+{
+ return(pMac->roam.configParam.Is11eSupportEnabled);
+}
+
+tANI_BOOLEAN csrIsMCCSupported ( tpAniSirGlobal pMac )
+{
+ return(pMac->roam.configParam.fenableMCCMode);
+
+}
+
+tANI_BOOLEAN csrIsWmmSupported(tpAniSirGlobal pMac)
+{
+ if(eCsrRoamWmmNoQos == pMac->roam.configParam.WMMSupportMode)
+ {
+ return eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ return eANI_BOOLEAN_TRUE;
+ }
+}
+
+
+
+
+//pIes is the IEs for pSirBssDesc2
+tANI_BOOLEAN csrIsSsidEqual( tHalHandle hHal, tSirBssDescription *pSirBssDesc1,
+ tSirBssDescription *pSirBssDesc2, tDot11fBeaconIEs *pIes2 )
+{
+ tANI_BOOLEAN fEqual = FALSE;
+ tSirMacSSid Ssid1, Ssid2;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tDot11fBeaconIEs *pIes1 = NULL;
+ tDot11fBeaconIEs *pIesLocal = pIes2;
+
+ do {
+ if( ( NULL == pSirBssDesc1 ) || ( NULL == pSirBssDesc2 ) ) break;
+ if( !pIesLocal && !HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc2, &pIesLocal)) )
+ {
+ smsLog(pMac, LOGE, FL(" fail to parse IEs\n"));
+ break;
+ }
+ if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc1, &pIes1)))
+ {
+ break;
+ }
+ if( ( !pIes1->SSID.present ) || ( !pIesLocal->SSID.present ) ) break;
+ if ( pIes1->SSID.num_ssid != pIesLocal->SSID.num_ssid ) break;
+ palCopyMemory(pMac->hHdd, Ssid1.ssId, pIes1->SSID.ssid, pIes1->SSID.num_ssid);
+ palCopyMemory(pMac->hHdd, Ssid2.ssId, pIesLocal->SSID.ssid, pIesLocal->SSID.num_ssid);
+
+ fEqual = palEqualMemory(pMac->hHdd, Ssid1.ssId, Ssid2.ssId, pIesLocal->SSID.num_ssid );
+
+ } while( 0 );
+ if(pIes1)
+ {
+ palFreeMemory(pMac->hHdd, pIes1);
+ }
+ if( pIesLocal && !pIes2 )
+ {
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+
+ return( fEqual );
+}
+
+tANI_BOOLEAN csrIsAniWmeSupported(tDot11fIEAirgo *pIeAirgo)
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
+
+ if(pIeAirgo && pIeAirgo->present && pIeAirgo->PropCapability.present)
+ {
+ fRet = (tANI_BOOLEAN)(PROP_CAPABILITY_GET( WME, pIeAirgo->PropCapability.capability ));
+ }
+
+ return fRet;
+}
+
+
+
+
+//pIes can be passed in as NULL if the caller doesn't have one prepared
+tANI_BOOLEAN csrIsBssDescriptionWme( tHalHandle hHal, tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ // Assume that WME is found...
+ tANI_BOOLEAN fWme = TRUE;
+ tDot11fBeaconIEs *pIesTemp = pIes;
+
+ do
+ {
+ if(pIesTemp == NULL)
+ {
+ if( !HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesTemp)) )
+ {
+ fWme = FALSE;
+ break;
+ }
+ }
+ // if the AirgoProprietary indicator is found, then WME is supported...
+ if ( csrIsAniWmeSupported(&pIesTemp->Airgo) ) break;
+ // if the Wme Info IE is found, then WME is supported...
+ if ( CSR_IS_QOS_BSS(pIesTemp) ) break;
+ // if none of these are found, then WME is NOT supported...
+ fWme = FALSE;
+ } while( 0 );
+ if( !csrIsWmmSupported( pMac ) && fWme)
+ {
+ if( !pIesTemp->HTCaps.present )
+ {
+ fWme = FALSE;
+ }
+ }
+ if( ( pIes == NULL ) && ( NULL != pIesTemp ) )
+ {
+ //we allocate memory here so free it before returning
+ palFreeMemory(pMac->hHdd, pIesTemp);
+ }
+
+ return( fWme );
+}
+
+tANI_BOOLEAN csrIsHcfEnabled( tDot11fIEAirgo *pIeAirgo )
+{
+ tANI_BOOLEAN fHcfSupported = FALSE;
+
+ fHcfSupported = ((tANI_BOOLEAN)(PROP_CAPABILITY_GET( WME, pIeAirgo->PropCapability.capability )) ||
+ (pIeAirgo->present && pIeAirgo->HCF.present && pIeAirgo->HCF.enabled));
+
+ return( fHcfSupported );
+}
+
+
+eCsrMediaAccessType csrGetQoSFromBssDesc( tHalHandle hHal, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes )
+{
+ eCsrMediaAccessType qosType = eCSR_MEDIUM_ACCESS_DCF;
+
+#if defined(VOSS_ENABLED)
+ VOS_ASSERT( pIes != NULL );
+#endif
+
+ do
+ {
+ // if we find WMM in the Bss Description, then we let this
+ // override and use WMM.
+ if ( csrIsBssDescriptionWme( hHal, pSirBssDesc, pIes ) )
+ {
+ qosType = eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP;
+ }
+ else
+ {
+ // if the QoS bit is on, then the AP is advertising 11E QoS...
+ if ( csrIsQoSBssDesc( pSirBssDesc ) )
+ {
+ // which could be HCF or eDCF.
+ if ( csrIsHcfEnabled( &pIes->Airgo ) )
+ {
+ qosType = eCSR_MEDIUM_ACCESS_11e_HCF;
+ }
+ else
+ {
+ qosType = eCSR_MEDIUM_ACCESS_11e_eDCF;
+ }
+ }
+ else
+ {
+ qosType = eCSR_MEDIUM_ACCESS_DCF;
+ }
+ // scale back based on the types turned on for the adapter...
+ if ( eCSR_MEDIUM_ACCESS_11e_eDCF == qosType && !csrIs11eSupported( hHal ) )
+ {
+ qosType = eCSR_MEDIUM_ACCESS_DCF;
+ }
+ }
+
+ } while(0);
+
+ return( qosType );
+}
+
+
+
+
+//Caller allocates memory for pIEStruct
+eHalStatus csrParseBssDescriptionIEs(tHalHandle hHal, tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIEStruct)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ int ieLen = (int)(pBssDesc->length + sizeof( pBssDesc->length ) - GET_FIELD_OFFSET( tSirBssDescription, ieFields ));
+
+ if(ieLen > 0 && pIEStruct)
+ {
+ if(!DOT11F_FAILED(dot11fUnpackBeaconIEs( pMac, (tANI_U8 *)pBssDesc->ieFields, ieLen, pIEStruct )))
+ {
+ status = eHAL_STATUS_SUCCESS;
+ }
+ }
+
+ return (status);
+}
+
+
+//This function will allocate memory for the parsed IEs to the caller. Caller must free the memory
+//after it is done with the data only if this function succeeds
+eHalStatus csrGetParsedBssDescriptionIEs(tHalHandle hHal, tSirBssDescription *pBssDesc, tDot11fBeaconIEs **ppIEStruct)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if(pBssDesc && ppIEStruct)
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)ppIEStruct, sizeof(tDot11fBeaconIEs));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, (void *)*ppIEStruct, sizeof(tDot11fBeaconIEs));
+ status = csrParseBssDescriptionIEs(hHal, pBssDesc, *ppIEStruct);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ palFreeMemory(pMac->hHdd, *ppIEStruct);
+ *ppIEStruct = NULL;
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" failed to allocate memory\n") );
+ VOS_ASSERT( 0 );
+ }
+ }
+
+ return (status);
+}
+
+
+
+
+tANI_BOOLEAN csrIsNULLSSID( tANI_U8 *pBssSsid, tANI_U8 len )
+{
+ tANI_BOOLEAN fNullSsid = FALSE;
+
+ tANI_U32 SsidLength;
+ tANI_U8 *pSsidStr;
+
+ do
+ {
+ if ( 0 == len )
+ {
+ fNullSsid = TRUE;
+ break;
+ }
+
+ //Consider 0 or space for hidden SSID
+ if ( 0 == pBssSsid[0] )
+ {
+ fNullSsid = TRUE;
+ break;
+ }
+
+ SsidLength = len;
+ pSsidStr = pBssSsid;
+
+ while ( SsidLength )
+ {
+ if( *pSsidStr )
+ break;
+
+ pSsidStr++;
+ SsidLength--;
+ }
+
+ if( 0 == SsidLength )
+ {
+ fNullSsid = TRUE;
+ break;
+ }
+ }
+ while( 0 );
+
+ return fNullSsid;
+}
+
+
+tANI_U32 csrGetFragThresh( tHalHandle hHal )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return pMac->roam.configParam.FragmentationThreshold;
+}
+
+tANI_U32 csrGetRTSThresh( tHalHandle hHal )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return pMac->roam.configParam.RTSThreshold;
+}
+
+eCsrPhyMode csrTranslateToPhyModeFromBssDesc( tSirBssDescription *pSirBssDesc )
+{
+ eCsrPhyMode phyMode;
+
+ switch ( pSirBssDesc->nwType )
+ {
+ case eSIR_11A_NW_TYPE:
+ phyMode = eCSR_DOT11_MODE_11a;
+ break;
+
+ case eSIR_11B_NW_TYPE:
+ phyMode = eCSR_DOT11_MODE_11b;
+ break;
+
+ case eSIR_11G_NW_TYPE:
+ phyMode = eCSR_DOT11_MODE_11g;
+ break;
+
+ case eSIR_11N_NW_TYPE:
+ default:
+ phyMode = eCSR_DOT11_MODE_11n;
+ break;
+ }
+
+ return( phyMode );
+}
+
+
+tANI_U32 csrTranslateToWNICfgDot11Mode(tpAniSirGlobal pMac, eCsrCfgDot11Mode csrDot11Mode)
+{
+ tANI_U32 ret;
+
+ switch(csrDot11Mode)
+ {
+ case eCSR_CFG_DOT11_MODE_AUTO:
+ smsLog(pMac, LOGW, FL(" Warning: sees eCSR_CFG_DOT11_MODE_AUTO \n"));
+ //We cannot decide until now.
+ if(pMac->roam.configParam.ProprietaryRatesEnabled)
+ {
+ ret = WNI_CFG_DOT11_MODE_TAURUS;
+ }
+ else
+ {
+ ret = WNI_CFG_DOT11_MODE_11N;
+ }
+ break;
+ case eCSR_CFG_DOT11_MODE_TAURUS:
+ ret = WNI_CFG_DOT11_MODE_TAURUS;
+ break;
+ case eCSR_CFG_DOT11_MODE_11A:
+ ret = WNI_CFG_DOT11_MODE_11A;
+ break;
+ case eCSR_CFG_DOT11_MODE_11B:
+ ret = WNI_CFG_DOT11_MODE_11B;
+ break;
+ case eCSR_CFG_DOT11_MODE_11G:
+ ret = WNI_CFG_DOT11_MODE_11G;
+ break;
+ case eCSR_CFG_DOT11_MODE_11N:
+ ret = WNI_CFG_DOT11_MODE_11N;
+ break;
+ case eCSR_CFG_DOT11_MODE_POLARIS:
+ ret = WNI_CFG_DOT11_MODE_POLARIS;
+ break;
+ case eCSR_CFG_DOT11_MODE_TITAN:
+ ret = WNI_CFG_DOT11_MODE_TITAN;
+ break;
+#ifdef WLAN_SOFTAP_FEATURE
+ case eCSR_CFG_DOT11_MODE_11G_ONLY:
+ ret = WNI_CFG_DOT11_MODE_11G_ONLY;
+ break;
+ case eCSR_CFG_DOT11_MODE_11N_ONLY:
+ ret = WNI_CFG_DOT11_MODE_11N_ONLY;
+ break;
+#endif
+ default:
+ smsLog(pMac, LOGW, FL("doesn't expect %d as csrDo11Mode\n"), csrDot11Mode);
+ if(eCSR_BAND_24 == pMac->roam.configParam.eBand)
+ {
+ ret = WNI_CFG_DOT11_MODE_11G;
+ }
+ else
+ {
+ ret = WNI_CFG_DOT11_MODE_11A;
+ }
+ break;
+ }
+
+ return (ret);
+}
+
+
+//This function should only return the super set of supported modes. 11n implies 11b/g/a/n.
+eHalStatus csrGetPhyModeFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBSSDescription,
+ eCsrPhyMode *pPhyMode, tDot11fBeaconIEs *pIes)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ eCsrPhyMode phyMode = csrTranslateToPhyModeFromBssDesc(pBSSDescription);
+
+ if( pIes )
+ {
+ if(pIes->Airgo.present)
+ {
+ if(pIes->Airgo.PropCapability.present)
+ {
+ if( PROP_CAPABILITY_GET( TAURUS, pIes->Airgo.PropCapability.capability ))
+ {
+ phyMode = eCSR_DOT11_MODE_TAURUS;
+ }
+ }
+ }
+ if(pIes->HTCaps.present && (eCSR_DOT11_MODE_TAURUS != phyMode))
+ {
+ phyMode = eCSR_DOT11_MODE_11n;
+ }
+ *pPhyMode = phyMode;
+ }
+
+ return (status);
+
+}
+
+
+//This function returns the correct eCSR_CFG_DOT11_MODE is the two phyModes matches
+//bssPhyMode is the mode derived from the BSS description
+//f5GhzBand is derived from the channel id of BSS description
+tANI_BOOLEAN csrGetPhyModeInUse( eCsrPhyMode phyModeIn, eCsrPhyMode bssPhyMode, tANI_BOOLEAN f5GhzBand,
+ eCsrCfgDot11Mode *pCfgDot11ModeToUse )
+{
+ tANI_BOOLEAN fMatch = FALSE;
+ eCsrCfgDot11Mode cfgDot11Mode;
+
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; // to suppress compiler warning
+
+ switch( phyModeIn )
+ {
+ case eCSR_DOT11_MODE_abg: //11a or 11b or 11g
+ if( f5GhzBand )
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
+ }
+ else if( eCSR_DOT11_MODE_11b == bssPhyMode )
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
+ }
+ else
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
+ }
+ break;
+
+ case eCSR_DOT11_MODE_11a: //11a
+ if( f5GhzBand )
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
+ }
+ break;
+
+ case eCSR_DOT11_MODE_11a_ONLY: //11a
+ if( eCSR_DOT11_MODE_11a == bssPhyMode )
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
+ }
+ break;
+
+ case eCSR_DOT11_MODE_11g:
+ if(!f5GhzBand)
+ {
+ if( eCSR_DOT11_MODE_11b == bssPhyMode )
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
+ }
+ else
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
+ }
+ }
+ break;
+
+ case eCSR_DOT11_MODE_11g_ONLY:
+ if( eCSR_DOT11_MODE_11g == bssPhyMode )
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
+ }
+ break;
+
+ case eCSR_DOT11_MODE_11b:
+ if( !f5GhzBand )
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
+ }
+ break;
+
+ case eCSR_DOT11_MODE_11b_ONLY:
+ if( eCSR_DOT11_MODE_11b == bssPhyMode )
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
+ }
+ break;
+
+ case eCSR_DOT11_MODE_11n:
+ fMatch = TRUE;
+ switch(bssPhyMode)
+ {
+ case eCSR_DOT11_MODE_11g:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
+ break;
+ case eCSR_DOT11_MODE_11b:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
+ break;
+ case eCSR_DOT11_MODE_11a:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
+ break;
+ case eCSR_DOT11_MODE_11n:
+ case eCSR_DOT11_MODE_TAURUS:
+ default:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
+ break;
+ }
+ break;
+
+ case eCSR_DOT11_MODE_11n_ONLY:
+ if((eCSR_DOT11_MODE_11n == bssPhyMode) || (eCSR_DOT11_MODE_TAURUS == bssPhyMode))
+ {
+ fMatch = TRUE;
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
+ }
+ break;
+
+ case eCSR_DOT11_MODE_TAURUS:
+ default:
+ fMatch = TRUE;
+ switch(bssPhyMode)
+ {
+ case eCSR_DOT11_MODE_11g:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
+ break;
+ case eCSR_DOT11_MODE_11b:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
+ break;
+ case eCSR_DOT11_MODE_11a:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
+ break;
+ case eCSR_DOT11_MODE_11n:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
+ break;
+ case eCSR_DOT11_MODE_TAURUS:
+ default:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_TAURUS;
+ break;
+ }
+ break;
+
+ }
+
+ if ( fMatch && pCfgDot11ModeToUse )
+ {
+ *pCfgDot11ModeToUse = cfgDot11Mode;
+ }
+
+ return( fMatch );
+}
+
+
+//This function decides whether the one of the bit of phyMode is matching the mode in the BSS and allowed by the user
+//setting, pMac->roam.configParam.uCfgDot11Mode. It returns the mode that fits the criteria.
+tANI_BOOLEAN csrIsPhyModeMatch( tpAniSirGlobal pMac, tANI_U32 phyMode,
+ tSirBssDescription *pSirBssDesc, tCsrRoamProfile *pProfile,
+ eCsrCfgDot11Mode *pReturnCfgDot11Mode,
+ tDot11fBeaconIEs *pIes)
+{
+ tANI_BOOLEAN fMatch = FALSE;
+ eCsrPhyMode phyModeInBssDesc, phyMode2;
+ eCsrCfgDot11Mode cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_TAURUS;
+ tANI_U32 bitMask, loopCount;
+
+ if(HAL_STATUS_SUCCESS(csrGetPhyModeFromBss(pMac, pSirBssDesc, &phyModeInBssDesc, pIes )))
+ {
+ //In case some change change eCSR_DOT11_MODE_TAURUS to non-0
+ if ( (0 == phyMode) || (eCSR_DOT11_MODE_AUTO & phyMode) || (eCSR_DOT11_MODE_TAURUS & phyMode))
+ {
+ //Taurus means anything
+ if ( eCSR_CFG_DOT11_MODE_ABG == pMac->roam.configParam.uCfgDot11Mode )
+ {
+ phyMode = eCSR_DOT11_MODE_abg;
+ }
+ else if(eCSR_CFG_DOT11_MODE_AUTO == pMac->roam.configParam.uCfgDot11Mode)
+ {
+ if(pMac->roam.configParam.ProprietaryRatesEnabled)
+ {
+ phyMode = eCSR_DOT11_MODE_TAURUS;
+ }
+ else
+ {
+ phyMode = eCSR_DOT11_MODE_11n;
+ }
+ }
+ else
+ {
+ //user's pick
+ phyMode = pMac->roam.configParam.phyMode;
+ }
+ }
+ if ( (0 == phyMode) || (eCSR_DOT11_MODE_AUTO & phyMode) || (eCSR_DOT11_MODE_TAURUS & phyMode) )
+ {
+ if(0 != phyMode)
+ {
+ if(eCSR_DOT11_MODE_AUTO & phyMode)
+ {
+ phyMode2 = eCSR_DOT11_MODE_AUTO & phyMode;
+ }
+ else
+ {
+ phyMode2 = eCSR_DOT11_MODE_TAURUS & phyMode;
+ }
+ }
+ else
+ {
+ phyMode2 = phyMode;
+ }
+ fMatch = csrGetPhyModeInUse( phyMode2, phyModeInBssDesc, CSR_IS_CHANNEL_5GHZ(pSirBssDesc->channelId),
+ &cfgDot11ModeToUse );
+ }
+ else
+ {
+ bitMask = 1;
+ loopCount = 0;
+ while(loopCount < eCSR_NUM_PHY_MODE)
+ {
+ if(0 != ( phyMode2 = (phyMode & (bitMask << loopCount++)) ))
+ {
+ fMatch = csrGetPhyModeInUse( phyMode2, phyModeInBssDesc, CSR_IS_CHANNEL_5GHZ(pSirBssDesc->channelId),
+ &cfgDot11ModeToUse );
+ if(fMatch) break;
+ }
+ }
+ }
+ if ( fMatch && pReturnCfgDot11Mode )
+ {
+ if( pProfile )
+ {
+ /* IEEE 11n spec (8.4.3): HT STA shall eliminate TKIP as a
+ * choice for the pairwise cipher suite if CCMP is advertised
+ * by the AP or if the AP included an HT capabilities element
+ * in its Beacons and Probe Response.
+ */
+ if( (!CSR_IS_11n_ALLOWED( pProfile->negotiatedUCEncryptionType )) &&
+ ((eCSR_CFG_DOT11_MODE_11N == cfgDot11ModeToUse) ||
+ (eCSR_CFG_DOT11_MODE_TAURUS == cfgDot11ModeToUse)) )
+ {
+ //We cannot do 11n here
+ if( !CSR_IS_CHANNEL_5GHZ(pSirBssDesc->channelId) )
+ {
+ cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11G;
+ }
+ else
+ {
+ cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11A;
+ }
+ }
+ }
+ *pReturnCfgDot11Mode = cfgDot11ModeToUse;
+ }
+ }
+
+ return( fMatch );
+}
+
+
+eCsrCfgDot11Mode csrFindBestPhyMode( tpAniSirGlobal pMac, tANI_U32 phyMode )
+{
+ eCsrCfgDot11Mode cfgDot11ModeToUse;
+ eCsrBand eBand = pMac->roam.configParam.eBand;
+
+ if ( (0 == phyMode) || (eCSR_DOT11_MODE_AUTO & phyMode) || (eCSR_DOT11_MODE_TAURUS & phyMode))
+ {
+ cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11N;
+ }
+ else
+ {
+ if( ( eCSR_DOT11_MODE_11n | eCSR_DOT11_MODE_11n_ONLY ) & phyMode )
+ {
+ cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11N;
+ }
+ else if ( eCSR_DOT11_MODE_abg & phyMode )
+ {
+ if( eCSR_BAND_24 != eBand )
+ {
+ cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11A;
+ }
+ else
+ {
+ cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11G;
+ }
+ }
+ else if( ( eCSR_DOT11_MODE_11a | eCSR_DOT11_MODE_11a_ONLY ) & phyMode )
+ {
+ cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11A;
+ }
+ else if( ( eCSR_DOT11_MODE_11g | eCSR_DOT11_MODE_11g_ONLY ) & phyMode )
+ {
+ cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11G;
+ }
+ else
+ {
+ cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11B;
+ }
+ }
+
+ return ( cfgDot11ModeToUse );
+}
+
+
+
+
+tANI_U32 csrGet11hPowerConstraint( tHalHandle hHal, tDot11fIEPowerConstraints *pPowerConstraint )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U32 localPowerConstraint = 0;
+
+ // check if .11h support is enabled, if not, the power constraint is 0.
+ if(pMac->roam.configParam.Is11hSupportEnabled && pPowerConstraint->present)
+ {
+ localPowerConstraint = pPowerConstraint->localPowerConstraints;
+ }
+
+ return( localPowerConstraint );
+}
+
+
+tANI_BOOLEAN csrIsProfileWpa( tCsrRoamProfile *pProfile )
+{
+ tANI_BOOLEAN fWpaProfile = FALSE;
+
+ switch ( pProfile->negotiatedAuthType )
+ {
+ case eCSR_AUTH_TYPE_WPA:
+ case eCSR_AUTH_TYPE_WPA_PSK:
+ case eCSR_AUTH_TYPE_WPA_NONE:
+#ifdef FEATURE_WLAN_CCX
+ case eCSR_AUTH_TYPE_CCKM_WPA:
+#endif
+ fWpaProfile = TRUE;
+ break;
+
+ default:
+ fWpaProfile = FALSE;
+ break;
+ }
+
+ if ( fWpaProfile )
+ {
+ switch ( pProfile->negotiatedUCEncryptionType )
+ {
+ case eCSR_ENCRYPT_TYPE_WEP40:
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ case eCSR_ENCRYPT_TYPE_TKIP:
+ case eCSR_ENCRYPT_TYPE_AES:
+ fWpaProfile = TRUE;
+ break;
+
+ default:
+ fWpaProfile = FALSE;
+ break;
+ }
+ }
+ return( fWpaProfile );
+}
+
+tANI_BOOLEAN csrIsProfileRSN( tCsrRoamProfile *pProfile )
+{
+ tANI_BOOLEAN fRSNProfile = FALSE;
+
+ switch ( pProfile->negotiatedAuthType )
+ {
+ case eCSR_AUTH_TYPE_RSN:
+ case eCSR_AUTH_TYPE_RSN_PSK:
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eCSR_AUTH_TYPE_FT_RSN:
+ case eCSR_AUTH_TYPE_FT_RSN_PSK:
+#endif
+#ifdef FEATURE_WLAN_CCX
+ case eCSR_AUTH_TYPE_CCKM_RSN:
+#endif
+ fRSNProfile = TRUE;
+ break;
+
+ default:
+ fRSNProfile = FALSE;
+ break;
+ }
+
+ if ( fRSNProfile )
+ {
+ switch ( pProfile->negotiatedUCEncryptionType )
+ {
+ // !!REVIEW - For WPA2, use of RSN IE mandates
+ // use of AES as encryption. Here, we qualify
+ // even if encryption type is WEP or TKIP
+ case eCSR_ENCRYPT_TYPE_WEP40:
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ case eCSR_ENCRYPT_TYPE_TKIP:
+ case eCSR_ENCRYPT_TYPE_AES:
+ fRSNProfile = TRUE;
+ break;
+
+ default:
+ fRSNProfile = FALSE;
+ break;
+ }
+ }
+ return( fRSNProfile );
+}
+
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/* Function to return TRUE if the authtype is 11r */
+tANI_BOOLEAN csrIsAuthType11r( eCsrAuthType AuthType )
+{
+ switch ( AuthType )
+ {
+ case eCSR_AUTH_TYPE_FT_RSN_PSK:
+ case eCSR_AUTH_TYPE_FT_RSN:
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+/* Function to return TRUE if the profile is 11r */
+tANI_BOOLEAN csrIsProfile11r( tCsrRoamProfile *pProfile )
+{
+ return csrIsAuthType11r( pProfile->negotiatedAuthType );
+}
+
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+
+/* Function to return TRUE if the authtype is CCX */
+tANI_BOOLEAN csrIsAuthTypeCCX( eCsrAuthType AuthType )
+{
+ switch ( AuthType )
+ {
+ case eCSR_AUTH_TYPE_CCKM_WPA:
+ case eCSR_AUTH_TYPE_CCKM_RSN:
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+/* Function to return TRUE if the profile is CCX */
+tANI_BOOLEAN csrIsProfileCCX( tCsrRoamProfile *pProfile )
+{
+ return (csrIsAuthTypeCCX( pProfile->negotiatedAuthType ));
+}
+
+#endif
+
+#ifdef FEATURE_WLAN_WAPI
+tANI_BOOLEAN csrIsProfileWapi( tCsrRoamProfile *pProfile )
+{
+ tANI_BOOLEAN fWapiProfile = FALSE;
+
+ switch ( pProfile->negotiatedAuthType )
+ {
+ case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
+ case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
+ fWapiProfile = TRUE;
+ break;
+
+ default:
+ fWapiProfile = FALSE;
+ break;
+ }
+
+ if ( fWapiProfile )
+ {
+ switch ( pProfile->negotiatedUCEncryptionType )
+ {
+ case eCSR_ENCRYPT_TYPE_WPI:
+ fWapiProfile = TRUE;
+ break;
+
+ default:
+ fWapiProfile = FALSE;
+ break;
+ }
+ }
+ return( fWapiProfile );
+}
+
+static tANI_BOOLEAN csrIsWapiOuiEqual( tpAniSirGlobal pMac, tANI_U8 *Oui1, tANI_U8 *Oui2 )
+{
+ return( palEqualMemory(pMac->hHdd, Oui1, Oui2, CSR_WAPI_OUI_SIZE ) );
+}
+
+static tANI_BOOLEAN csrIsWapiOuiMatch( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WAPI_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Cypher[],
+ tANI_U8 Oui[] )
+{
+ tANI_BOOLEAN fYes = FALSE;
+ tANI_U8 idx;
+
+ for ( idx = 0; idx < cAllCyphers; idx++ )
+ {
+ if ( csrIsWapiOuiEqual( pMac, AllCyphers[ idx ], Cypher ) )
+ {
+ fYes = TRUE;
+ break;
+ }
+ }
+
+ if ( fYes && Oui )
+ {
+ palCopyMemory( pMac->hHdd, Oui, AllCyphers[ idx ], CSR_WAPI_OUI_SIZE );
+ }
+
+ return( fYes );
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+static tANI_BOOLEAN csrIsWpaOuiEqual( tpAniSirGlobal pMac, tANI_U8 *Oui1, tANI_U8 *Oui2 )
+{
+ return( palEqualMemory(pMac->hHdd, Oui1, Oui2, CSR_WPA_OUI_SIZE ) );
+}
+
+static tANI_BOOLEAN csrIsOuiMatch( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Cypher[],
+ tANI_U8 Oui[] )
+{
+ tANI_BOOLEAN fYes = FALSE;
+ tANI_U8 idx;
+
+ for ( idx = 0; idx < cAllCyphers; idx++ )
+ {
+ if ( csrIsWpaOuiEqual( pMac, AllCyphers[ idx ], Cypher ) )
+ {
+ fYes = TRUE;
+ break;
+ }
+ }
+
+ if ( fYes && Oui )
+ {
+ palCopyMemory( pMac->hHdd, Oui, AllCyphers[ idx ], CSR_WPA_OUI_SIZE );
+ }
+
+ return( fYes );
+}
+
+static tANI_BOOLEAN csrMatchRSNOUIIndex( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllCyphers, tANI_U8 ouiIndex,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrRSNOui[ouiIndex], Oui ) );
+
+}
+
+#ifdef FEATURE_WLAN_WAPI
+static tANI_BOOLEAN csrMatchWapiOUIIndex( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WAPI_OUI_SIZE],
+ tANI_U8 cAllCyphers, tANI_U8 ouiIndex,
+ tANI_U8 Oui[] )
+{
+ return( csrIsWapiOuiMatch( pMac, AllCyphers, cAllCyphers, csrWapiOui[ouiIndex], Oui ) );
+
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+static tANI_BOOLEAN csrMatchWPAOUIIndex( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllCyphers, tANI_U8 ouiIndex,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrWpaOui[ouiIndex], Oui ) );
+
+}
+
+#if 0
+static tANI_BOOLEAN csrIsRSNUnicastNone( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrRSNOui00, Oui ) );
+}
+
+static tANI_BOOLEAN csrIsRSNMulticastWep( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ tANI_BOOLEAN fYes = FALSE;
+
+ // Check Wep 104 first, if fails, then check Wep40.
+ fYes = csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrRSNOui05, Oui );
+
+ if ( !fYes )
+ {
+ // if not Wep-104, check Wep-40
+ fYes = csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrRSNOui01, Oui );
+ }
+
+ return( fYes );
+}
+
+
+static tANI_BOOLEAN csrIsRSNUnicastTkip( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrRSNOui02, Oui ) );
+}
+
+
+static tANI_BOOLEAN csrIsRSNMulticastTkip( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrRSNOui02, Oui ) );
+}
+
+static tANI_BOOLEAN csrIsRSNUnicastAes( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrRSNOui04, Oui ) );
+}
+
+static tANI_BOOLEAN csrIsRSNMulticastAes( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrRSNOui04, Oui ) );
+}
+#endif
+#ifdef FEATURE_WLAN_WAPI
+static tANI_BOOLEAN csrIsAuthWapiCert( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WAPI_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+ return( csrIsWapiOuiMatch( pMac, AllSuites, cAllSuites, csrWapiOui[1], Oui ) );
+}
+static tANI_BOOLEAN csrIsAuthWapiPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WAPI_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+ return( csrIsWapiOuiMatch( pMac, AllSuites, cAllSuites, csrWapiOui[2], Oui ) );
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+
+/*
+ * Function for 11R FT Authentication. We match the FT Authentication Cipher suite
+ * here. This matches for FT Auth with the 802.1X exchange.
+ *
+ */
+static tANI_BOOLEAN csrIsFTAuthRSN( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[03], Oui ) );
+}
+
+/*
+ * Function for 11R FT Authentication. We match the FT Authentication Cipher suite
+ * here. This matches for FT Auth with the PSK.
+ *
+ */
+static tANI_BOOLEAN csrIsFTAuthRSNPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[04], Oui ) );
+}
+
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+
+/*
+ * Function for CCX CCKM AKM Authentication. We match the CCKM AKM Authentication Key Management suite
+ * here. This matches for CCKM AKM Auth with the 802.1X exchange.
+ *
+ */
+static tANI_BOOLEAN csrIsCcxCckmAuthRSN( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[06], Oui ) );
+}
+
+static tANI_BOOLEAN csrIsCcxCckmAuthWpa( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrWpaOui[06], Oui ) );
+}
+
+#endif
+
+static tANI_BOOLEAN csrIsAuthRSN( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+#ifdef WLAN_FEATURE_11W
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[01], Oui ) ||
+ csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[05], Oui ));
+#else
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[01], Oui ) );
+#endif
+}
+static tANI_BOOLEAN csrIsAuthRSNPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+#ifdef WLAN_FEATURE_11W
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[02], Oui ) ||
+ csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[06], Oui ) );
+#else
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[02], Oui ) );
+#endif
+}
+
+static tANI_BOOLEAN csrIsAuthWpa( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrWpaOui[01], Oui ) );
+}
+
+#ifdef NOT_CURRENTLY_USED
+static tANI_BOOLEAN csrIsAuth802_1x( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrWpaOui[00], Oui ) );
+}
+#endif // NOT_CURRENTLY_USED
+
+static tANI_BOOLEAN csrIsAuthWpaPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllSuites,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrWpaOui[02], Oui ) );
+}
+#if 0
+static tANI_BOOLEAN csrIsUnicastNone( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrWpaOui00, Oui ) );
+}
+
+static tANI_BOOLEAN csrIsUnicastTkip( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrWpaOui02, Oui ) );
+}
+
+static tANI_BOOLEAN csrIsUnicastAes( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrWpaOui04, Oui ) );
+}
+
+
+static tANI_BOOLEAN csrIsMulticastWep( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ tANI_BOOLEAN fYes = FALSE;
+
+ // Check Wep 104 first, if fails, then check Wep40.
+ fYes = csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrWpaOui05, Oui );
+
+ if ( !fYes )
+ {
+ // if not Wep-104, check Wep-40
+ fYes = csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrWpaOui01, Oui );
+ }
+
+ return( fYes );
+}
+
+
+static tANI_BOOLEAN csrIsMulticastTkip( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrWpaOui02, Oui ) );
+}
+
+
+static tANI_BOOLEAN csrIsMulticastAes( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WPA_OUI_SIZE],
+ tANI_U8 cAllCyphers,
+ tANI_U8 Oui[] )
+{
+ return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrWpaOui04, Oui ) );
+}
+
+#endif
+
+tANI_U8 csrGetOUIIndexFromCipher( eCsrEncryptionType enType )
+{
+ tANI_U8 OUIIndex;
+
+ switch ( enType )
+ {
+ case eCSR_ENCRYPT_TYPE_WEP40:
+ case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
+ OUIIndex = CSR_OUI_WEP40_OR_1X_INDEX;
+ break;
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
+ OUIIndex = CSR_OUI_WEP104_INDEX;
+ break;
+ case eCSR_ENCRYPT_TYPE_TKIP:
+ OUIIndex = CSR_OUI_TKIP_OR_PSK_INDEX;
+ break;
+ case eCSR_ENCRYPT_TYPE_AES:
+ OUIIndex = CSR_OUI_AES_INDEX;
+ break;
+ case eCSR_ENCRYPT_TYPE_NONE:
+ OUIIndex = CSR_OUI_USE_GROUP_CIPHER_INDEX;
+ break;
+#ifdef FEATURE_WLAN_WAPI
+ case eCSR_ENCRYPT_TYPE_WPI:
+ OUIIndex = CSR_OUI_WAPI_WAI_CERT_OR_SMS4_INDEX;
+ break;
+#endif /* FEATURE_WLAN_WAPI */
+ default: //HOWTO handle this?
+ OUIIndex = CSR_OUI_RESERVED_INDEX;
+ break;
+ }//switch
+
+ return OUIIndex;
+}
+
+tANI_BOOLEAN csrGetRSNInformation( tHalHandle hHal, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pMCEncryption,
+ tDot11fIERSN *pRSNIe,
+ tANI_U8 *UnicastCypher,
+ tANI_U8 *MulticastCypher,
+ tANI_U8 *AuthSuite,
+ tCsrRSNCapabilities *Capabilities,
+ eCsrAuthType *pNegotiatedAuthtype,
+ eCsrEncryptionType *pNegotiatedMCCipher )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN fAcceptableCyphers = FALSE;
+ tANI_U8 cUnicastCyphers = 0;
+ tANI_U8 cMulticastCyphers = 0;
+ tANI_U8 cAuthSuites = 0, i;
+ tANI_U8 Unicast[ CSR_RSN_OUI_SIZE ];
+ tANI_U8 Multicast[ CSR_RSN_OUI_SIZE ];
+ tANI_U8 AuthSuites[ CSR_RSN_MAX_AUTH_SUITES ][ CSR_RSN_OUI_SIZE ];
+ tANI_U8 Authentication[ CSR_RSN_OUI_SIZE ];
+ tANI_U8 MulticastCyphers[ CSR_RSN_MAX_MULTICAST_CYPHERS ][ CSR_RSN_OUI_SIZE ];
+ eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN;
+
+ do{
+ if ( pRSNIe->present )
+ {
+ cMulticastCyphers++;
+ palCopyMemory(pMac->hHdd, MulticastCyphers, pRSNIe->gp_cipher_suite, CSR_RSN_OUI_SIZE);
+ cUnicastCyphers = (tANI_U8)(pRSNIe->pwise_cipher_suite_count);
+ cAuthSuites = (tANI_U8)(pRSNIe->akm_suite_count);
+ for(i = 0; i < cAuthSuites && i < CSR_RSN_MAX_AUTH_SUITES; i++)
+ {
+ palCopyMemory(pMac->hHdd, (void *)&AuthSuites[i],
+ (void *)&pRSNIe->akm_suites[i], CSR_RSN_OUI_SIZE);
+ }
+
+ //Check - Is requested Unicast Cipher supported by the BSS.
+ fAcceptableCyphers = csrMatchRSNOUIIndex( pMac, pRSNIe->pwise_cipher_suites, cUnicastCyphers,
+ csrGetOUIIndexFromCipher( enType ), Unicast );
+
+ if( !fAcceptableCyphers ) break;
+
+
+ //Unicast is supported. Pick the first matching Group cipher, if any.
+ for( i = 0 ; i < pMCEncryption->numEntries ; i++ )
+ {
+ fAcceptableCyphers = csrMatchRSNOUIIndex( pMac, MulticastCyphers, cMulticastCyphers,
+ csrGetOUIIndexFromCipher( pMCEncryption->encryptionType[i] ), Multicast );
+ if(fAcceptableCyphers)
+ {
+ break;
+ }
+ }
+ if( !fAcceptableCyphers ) break;
+
+ if( pNegotiatedMCCipher )
+ *pNegotiatedMCCipher = pMCEncryption->encryptionType[i];
+
+ /* Initializing with FALSE as it has TRUE value already */
+ fAcceptableCyphers = FALSE;
+ for (i = 0 ; i < pAuthType->numEntries; i++)
+ {
+ //Ciphers are supported, Match authentication algorithm and pick first matching authtype.
+ #ifdef WLAN_FEATURE_VOWIFI_11R
+ /* Changed the AKM suites according to order of preference */
+ if ( csrIsFTAuthRSN( pMac, AuthSuites, cAuthSuites, Authentication ) )
+ {
+ if (eCSR_AUTH_TYPE_FT_RSN == pAuthType->authType[i])
+ negAuthType = eCSR_AUTH_TYPE_FT_RSN;
+ }
+ if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsFTAuthRSNPsk( pMac, AuthSuites, cAuthSuites, Authentication ) )
+ {
+ if (eCSR_AUTH_TYPE_FT_RSN_PSK == pAuthType->authType[i])
+ negAuthType = eCSR_AUTH_TYPE_FT_RSN_PSK;
+ }
+#endif
+#ifdef FEATURE_WLAN_CCX
+ /* CCX only supports 802.1X. No PSK. */
+ if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsCcxCckmAuthRSN( pMac, AuthSuites, cAuthSuites, Authentication ) )
+ {
+ if (eCSR_AUTH_TYPE_CCKM_RSN == pAuthType->authType[i])
+ negAuthType = eCSR_AUTH_TYPE_CCKM_RSN;
+ }
+#endif
+ if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsAuthRSN( pMac, AuthSuites, cAuthSuites, Authentication ) )
+ {
+ if (eCSR_AUTH_TYPE_RSN == pAuthType->authType[i])
+ negAuthType = eCSR_AUTH_TYPE_RSN;
+ }
+ if ((negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsAuthRSNPsk( pMac, AuthSuites, cAuthSuites, Authentication ) )
+ {
+ if (eCSR_AUTH_TYPE_RSN_PSK == pAuthType->authType[i])
+ negAuthType = eCSR_AUTH_TYPE_RSN_PSK;
+ }
+
+ // The 1st auth type in the APs RSN IE, to match stations connecting
+ // profiles auth type will cause us to exit this loop
+ // This is added as some APs advertise multiple akms in the RSN IE.
+ if (eCSR_AUTH_TYPE_UNKNOWN != negAuthType)
+ {
+ fAcceptableCyphers = TRUE;
+ break;
+ }
+ } // for
+ }
+
+ }while (0);
+
+ if ( fAcceptableCyphers )
+ {
+ if ( MulticastCypher )
+ {
+ palCopyMemory( pMac->hHdd, MulticastCypher, Multicast, CSR_RSN_OUI_SIZE );
+ }
+
+ if ( UnicastCypher )
+ {
+ palCopyMemory( pMac->hHdd, UnicastCypher, Unicast, CSR_RSN_OUI_SIZE );
+ }
+
+ if ( AuthSuite )
+ {
+ palCopyMemory( pMac->hHdd, AuthSuite, Authentication, CSR_RSN_OUI_SIZE );
+ }
+
+ if ( pNegotiatedAuthtype )
+ {
+ *pNegotiatedAuthtype = negAuthType;
+ }
+ if ( Capabilities )
+ {
+ Capabilities->PreAuthSupported = pRSNIe->preauth;
+ Capabilities->NoPairwise = pRSNIe->no_pwise;
+ Capabilities->PTKSAReplayCounter = pRSNIe->PTKSA_replay_counter;
+ Capabilities->GTKSAReplayCounter = pRSNIe->GTKSA_replay_counter;
+ Capabilities->Reserved = pRSNIe->reserved;
+ }
+ }
+ return( fAcceptableCyphers );
+}
+
+
+tANI_BOOLEAN csrIsRSNMatch( tHalHandle hHal, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pEnMcType,
+ tDot11fBeaconIEs *pIes, eCsrAuthType *pNegotiatedAuthType, eCsrEncryptionType *pNegotiatedMCCipher )
+{
+ tANI_BOOLEAN fRSNMatch = FALSE;
+
+ // See if the cyphers in the Bss description match with the settings in the profile.
+ fRSNMatch = csrGetRSNInformation( hHal, pAuthType, enType, pEnMcType, &pIes->RSN, NULL, NULL, NULL, NULL,
+ pNegotiatedAuthType, pNegotiatedMCCipher );
+
+ return( fRSNMatch );
+}
+
+
+tANI_BOOLEAN csrLookupPMKID( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U8 *pBSSId, tANI_U8 *pPMKId )
+{
+ tANI_BOOLEAN fRC = FALSE, fMatchFound = FALSE;
+ tANI_U32 Index;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ do
+ {
+ for( Index=0; Index < pSession->NumPmkidCache; Index++ )
+ {
+ smsLog(pMac, LOGW, "match PMKID %02X-%02X-%02X-%02X-%02X-%02X to \n",
+ pBSSId[0], pBSSId[1], pBSSId[2], pBSSId[3], pBSSId[4], pBSSId[5]);
+ if( palEqualMemory( pMac->hHdd, pBSSId, pSession->PmkidCacheInfo[Index].BSSID, sizeof(tCsrBssid) ) )
+ {
+ // match found
+ fMatchFound = TRUE;
+ break;
+ }
+ }
+
+ if( !fMatchFound ) break;
+
+ palCopyMemory( pMac->hHdd, pPMKId, pSession->PmkidCacheInfo[Index].PMKID, CSR_RSN_PMKID_SIZE );
+
+ fRC = TRUE;
+ }
+ while( 0 );
+ smsLog(pMac, LOGW, "csrLookupPMKID called return match = %d pMac->roam.NumPmkidCache = %d",
+ fRC, pSession->NumPmkidCache);
+
+ return fRC;
+}
+
+
+tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrRSNIe *pRSNIe )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN fRSNMatch;
+ tANI_U8 cbRSNIe = 0;
+ tANI_U8 UnicastCypher[ CSR_RSN_OUI_SIZE ];
+ tANI_U8 MulticastCypher[ CSR_RSN_OUI_SIZE ];
+ tANI_U8 AuthSuite[ CSR_RSN_OUI_SIZE ];
+ tCsrRSNAuthIe *pAuthSuite;
+ tCsrRSNCapabilities RSNCapabilities;
+ tCsrRSNPMKIe *pPMK;
+ tANI_U8 PMKId[CSR_RSN_PMKID_SIZE];
+ tDot11fBeaconIEs *pIesLocal = pIes;
+
+ do
+ {
+ if ( !csrIsProfileRSN( pProfile ) ) break;
+
+ if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) )
+ {
+ break;
+ }
+
+ // See if the cyphers in the Bss description match with the settings in the profile.
+ fRSNMatch = csrGetRSNInformation( hHal, &pProfile->AuthType, pProfile->negotiatedUCEncryptionType,
+ &pProfile->mcEncryptionType, &pIesLocal->RSN,
+ UnicastCypher, MulticastCypher, AuthSuite, &RSNCapabilities, NULL, NULL );
+ if ( !fRSNMatch ) break;
+
+ pRSNIe->IeHeader.ElementID = SIR_MAC_RSN_EID;
+
+ pRSNIe->Version = CSR_RSN_VERSION_SUPPORTED;
+
+ palCopyMemory( pMac->hHdd, pRSNIe->MulticastOui, MulticastCypher, sizeof( MulticastCypher ) );
+
+ pRSNIe->cUnicastCyphers = 1;
+
+ palCopyMemory( pMac->hHdd, &pRSNIe->UnicastOui[ 0 ], UnicastCypher, sizeof( UnicastCypher ) );
+
+ pAuthSuite = (tCsrRSNAuthIe *)( &pRSNIe->UnicastOui[ pRSNIe->cUnicastCyphers ] );
+
+ pAuthSuite->cAuthenticationSuites = 1;
+ palCopyMemory( pMac->hHdd, &pAuthSuite->AuthOui[ 0 ], AuthSuite, sizeof( AuthSuite ) );
+
+ // RSN capabilities follows the Auth Suite (two octects)
+ // !!REVIEW - What should STA put in RSN capabilities, currently
+ // just putting back APs capabilities
+ // For one, we shouldn't EVER be sending out "pre-auth supported". It is an AP only capability
+ RSNCapabilities.PreAuthSupported = 0;
+ *(tANI_U16 *)( &pAuthSuite->AuthOui[ 1 ] ) = *((tANI_U16 *)(&RSNCapabilities));
+
+ pPMK = (tCsrRSNPMKIe *)( ((tANI_U8 *)(&pAuthSuite->AuthOui[ 1 ])) + sizeof(tANI_U16) );
+
+ if( csrLookupPMKID( pMac, sessionId, pSirBssDesc->bssId, &(PMKId[0]) ) )
+ {
+ pPMK->cPMKIDs = 1;
+
+ palCopyMemory( pMac->hHdd, pPMK->PMKIDList[0].PMKID, PMKId, CSR_RSN_PMKID_SIZE );
+ }
+ else
+ {
+ pPMK->cPMKIDs = 0;
+ }
+
+ // Add in the fixed fields plus 1 Unicast cypher, less the IE Header length
+ // Add in the size of the Auth suite (count plus a single OUI)
+ // Add in the RSN caps field.
+ // Add PMKID count and PMKID (if any)
+ pRSNIe->IeHeader.Length = (tANI_U8) (sizeof( *pRSNIe ) - sizeof ( pRSNIe->IeHeader ) +
+ sizeof( *pAuthSuite ) +
+ sizeof( tCsrRSNCapabilities ));
+ if(pPMK->cPMKIDs)
+ {
+ pRSNIe->IeHeader.Length += (tANI_U8)(sizeof( tANI_U16 ) +
+ (pPMK->cPMKIDs * CSR_RSN_PMKID_SIZE));
+ }
+ // return the size of the IE header (total) constructed...
+ cbRSNIe = pRSNIe->IeHeader.Length + sizeof( pRSNIe->IeHeader );
+
+ } while( 0 );
+
+ if( !pIes && pIesLocal )
+ {
+ //locally allocated
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+
+ return( cbRSNIe );
+}
+
+
+#ifdef FEATURE_WLAN_WAPI
+tANI_BOOLEAN csrGetWapiInformation( tHalHandle hHal, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pMCEncryption,
+ tDot11fIEWAPI *pWapiIe,
+ tANI_U8 *UnicastCypher,
+ tANI_U8 *MulticastCypher,
+ tANI_U8 *AuthSuite,
+ eCsrAuthType *pNegotiatedAuthtype,
+ eCsrEncryptionType *pNegotiatedMCCipher )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN fAcceptableCyphers = FALSE;
+ tANI_U8 cUnicastCyphers = 0;
+ tANI_U8 cMulticastCyphers = 0;
+ tANI_U8 cAuthSuites = 0, i;
+ tANI_U8 Unicast[ CSR_WAPI_OUI_SIZE ];
+ tANI_U8 Multicast[ CSR_WAPI_OUI_SIZE ];
+ tANI_U8 AuthSuites[ CSR_WAPI_MAX_AUTH_SUITES ][ CSR_WAPI_OUI_SIZE ];
+ tANI_U8 Authentication[ CSR_WAPI_OUI_SIZE ];
+ tANI_U8 MulticastCyphers[ CSR_WAPI_MAX_MULTICAST_CYPHERS ][ CSR_WAPI_OUI_SIZE ];
+ eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN;
+
+ do{
+ if ( pWapiIe->present )
+ {
+ cMulticastCyphers++;
+ palCopyMemory(pMac->hHdd, MulticastCyphers, pWapiIe->multicast_cipher_suite, CSR_WAPI_OUI_SIZE);
+ cUnicastCyphers = (tANI_U8)(pWapiIe->unicast_cipher_suite_count);
+ cAuthSuites = (tANI_U8)(pWapiIe->akm_suite_count);
+ for(i = 0; i < cAuthSuites && i < CSR_WAPI_MAX_AUTH_SUITES; i++)
+ {
+ palCopyMemory(pMac->hHdd, (void *)&AuthSuites[i],
+ (void *)&pWapiIe->akm_suites[i], CSR_WAPI_OUI_SIZE);
+ }
+
+ //Check - Is requested Unicast Cipher supported by the BSS.
+ fAcceptableCyphers = csrMatchWapiOUIIndex( pMac, pWapiIe->unicast_cipher_suites, cUnicastCyphers,
+ csrGetOUIIndexFromCipher( enType ), Unicast );
+
+ if( !fAcceptableCyphers ) break;
+
+
+ //Unicast is supported. Pick the first matching Group cipher, if any.
+ for( i = 0 ; i < pMCEncryption->numEntries ; i++ )
+ {
+ fAcceptableCyphers = csrMatchWapiOUIIndex( pMac, MulticastCyphers, cMulticastCyphers,
+ csrGetOUIIndexFromCipher( pMCEncryption->encryptionType[i] ), Multicast );
+ if(fAcceptableCyphers)
+ {
+ break;
+ }
+ }
+ if( !fAcceptableCyphers ) break;
+
+ if( pNegotiatedMCCipher )
+ *pNegotiatedMCCipher = pMCEncryption->encryptionType[i];
+
+ //Ciphers are supported, Match authentication algorithm and pick first matching authtype.
+ if ( csrIsAuthWapiCert( pMac, AuthSuites, cAuthSuites, Authentication ) )
+ {
+ negAuthType = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
+ }
+ else if ( csrIsAuthWapiPsk( pMac, AuthSuites, cAuthSuites, Authentication ) )
+ {
+ negAuthType = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
+ }
+ else
+ {
+ fAcceptableCyphers = FALSE;
+ negAuthType = eCSR_AUTH_TYPE_UNKNOWN;
+ }
+ if( ( 0 == pAuthType->numEntries ) || ( FALSE == fAcceptableCyphers ) )
+ {
+ //Caller doesn't care about auth type, or BSS doesn't match
+ break;
+ }
+ fAcceptableCyphers = FALSE;
+ for( i = 0 ; i < pAuthType->numEntries; i++ )
+ {
+ if( pAuthType->authType[i] == negAuthType )
+ {
+ fAcceptableCyphers = TRUE;
+ break;
+ }
+ }
+ }
+ }while (0);
+
+ if ( fAcceptableCyphers )
+ {
+ if ( MulticastCypher )
+ {
+ palCopyMemory( pMac->hHdd, MulticastCypher, Multicast, CSR_WAPI_OUI_SIZE );
+ }
+
+ if ( UnicastCypher )
+ {
+ palCopyMemory( pMac->hHdd, UnicastCypher, Unicast, CSR_WAPI_OUI_SIZE );
+ }
+
+ if ( AuthSuite )
+ {
+ palCopyMemory( pMac->hHdd, AuthSuite, Authentication, CSR_WAPI_OUI_SIZE );
+ }
+
+ if ( pNegotiatedAuthtype )
+ {
+ *pNegotiatedAuthtype = negAuthType;
+ }
+ }
+ return( fAcceptableCyphers );
+}
+
+tANI_BOOLEAN csrIsWapiMatch( tHalHandle hHal, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pEnMcType,
+ tDot11fBeaconIEs *pIes, eCsrAuthType *pNegotiatedAuthType, eCsrEncryptionType *pNegotiatedMCCipher )
+{
+ tANI_BOOLEAN fWapiMatch = FALSE;
+
+ // See if the cyphers in the Bss description match with the settings in the profile.
+ fWapiMatch = csrGetWapiInformation( hHal, pAuthType, enType, pEnMcType, &pIes->WAPI, NULL, NULL, NULL,
+ pNegotiatedAuthType, pNegotiatedMCCipher );
+
+ return( fWapiMatch );
+}
+
+tANI_BOOLEAN csrLookupBKID( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U8 *pBSSId, tANI_U8 *pBKId )
+{
+ tANI_BOOLEAN fRC = FALSE, fMatchFound = FALSE;
+ tANI_U32 Index;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ do
+ {
+ for( Index=0; Index < pSession->NumBkidCache; Index++ )
+ {
+ smsLog(pMac, LOGW, "match BKID %02X-%02X-%02X-%02X-%02X-%02X to \n",
+ pBSSId[0], pBSSId[1], pBSSId[2], pBSSId[3], pBSSId[4], pBSSId[5]);
+ if( palEqualMemory( pMac->hHdd, pBSSId, pSession->BkidCacheInfo[Index].BSSID, sizeof(tCsrBssid) ) )
+ {
+ // match found
+ fMatchFound = TRUE;
+ break;
+ }
+ }
+
+ if( !fMatchFound ) break;
+
+ palCopyMemory( pMac->hHdd, pBKId, pSession->BkidCacheInfo[Index].BKID, CSR_WAPI_BKID_SIZE );
+
+ fRC = TRUE;
+ }
+ while( 0 );
+ smsLog(pMac, LOGW, "csrLookupBKID called return match = %d pMac->roam.NumBkidCache = %d", fRC, pSession->NumBkidCache);
+
+ return fRC;
+}
+
+tANI_U8 csrConstructWapiIe( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe )
+{
+ tANI_BOOLEAN fWapiMatch = FALSE;
+ tANI_U8 cbWapiIe = 0;
+ tANI_U8 UnicastCypher[ CSR_WAPI_OUI_SIZE ];
+ tANI_U8 MulticastCypher[ CSR_WAPI_OUI_SIZE ];
+ tANI_U8 AuthSuite[ CSR_WAPI_OUI_SIZE ];
+ tANI_U8 BKId[CSR_WAPI_BKID_SIZE];
+ tANI_U8 *pWapi = NULL;
+ tANI_BOOLEAN fBKIDFound = FALSE;
+ tDot11fBeaconIEs *pIesLocal = pIes;
+
+ do
+ {
+ if ( !csrIsProfileWapi( pProfile ) ) break;
+
+ if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) )
+ {
+ break;
+ }
+
+ // See if the cyphers in the Bss description match with the settings in the profile.
+ fWapiMatch = csrGetWapiInformation( pMac, &pProfile->AuthType, pProfile->negotiatedUCEncryptionType,
+ &pProfile->mcEncryptionType, &pIesLocal->WAPI,
+ UnicastCypher, MulticastCypher, AuthSuite, NULL, NULL );
+ if ( !fWapiMatch ) break;
+
+ palZeroMemory(pMac->hHdd, pWapiIe, sizeof(tCsrWapiIe));
+
+ pWapiIe->IeHeader.ElementID = DOT11F_EID_WAPI;
+
+ pWapiIe->Version = CSR_WAPI_VERSION_SUPPORTED;
+
+ pWapiIe->cAuthenticationSuites = 1;
+ palCopyMemory( pMac->hHdd, &pWapiIe->AuthOui[ 0 ], AuthSuite, sizeof( AuthSuite ) );
+
+ pWapi = (tANI_U8 *) (&pWapiIe->AuthOui[ 1 ]);
+
+ *pWapi = (tANI_U16)1; //cUnicastCyphers
+ pWapi+=2;
+ palCopyMemory( pMac->hHdd, pWapi, UnicastCypher, sizeof( UnicastCypher ) );
+ pWapi += sizeof( UnicastCypher );
+
+ palCopyMemory( pMac->hHdd, pWapi, MulticastCypher, sizeof( MulticastCypher ) );
+ pWapi += sizeof( MulticastCypher );
+
+
+ // WAPI capabilities follows the Auth Suite (two octects)
+ // we shouldn't EVER be sending out "pre-auth supported". It is an AP only capability
+ // & since we already did a memset pWapiIe to 0, skip these fields
+ pWapi +=2;
+
+ fBKIDFound = csrLookupBKID( pMac, sessionId, pSirBssDesc->bssId, &(BKId[0]) );
+
+
+ if( fBKIDFound )
+ {
+ /* Do we need to change the endianness here */
+ *pWapi = (tANI_U16)1; //cBKIDs
+ pWapi+=2;
+ palCopyMemory( pMac->hHdd, pWapi, BKId, CSR_WAPI_BKID_SIZE );
+ }
+ else
+ {
+ *pWapi = 0;
+ pWapi+=1;
+ *pWapi = 0;
+ pWapi+=1;
+ }
+
+ // Add in the IE fields except the IE header
+ // Add BKID count and BKID (if any)
+ pWapiIe->IeHeader.Length = (tANI_U8) (sizeof( *pWapiIe ) - sizeof ( pWapiIe->IeHeader ));
+
+ /*2 bytes for BKID Count field*/
+ pWapiIe->IeHeader.Length += sizeof( tANI_U16 );
+
+ if(fBKIDFound)
+ {
+ pWapiIe->IeHeader.Length += CSR_WAPI_BKID_SIZE;
+ }
+ // return the size of the IE header (total) constructed...
+ cbWapiIe = pWapiIe->IeHeader.Length + sizeof( pWapiIe->IeHeader );
+
+ } while( 0 );
+
+ if( !pIes && pIesLocal )
+ {
+ //locally allocated
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+
+ return( cbWapiIe );
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+tANI_BOOLEAN csrGetWpaCyphers( tpAniSirGlobal pMac, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pMCEncryption,
+ tDot11fIEWPA *pWpaIe,
+ tANI_U8 *UnicastCypher,
+ tANI_U8 *MulticastCypher,
+ tANI_U8 *AuthSuite,
+ eCsrAuthType *pNegotiatedAuthtype,
+ eCsrEncryptionType *pNegotiatedMCCipher )
+{
+ tANI_BOOLEAN fAcceptableCyphers = FALSE;
+ tANI_U8 cUnicastCyphers = 0;
+ tANI_U8 cMulticastCyphers = 0;
+ tANI_U8 cAuthSuites = 0;
+ tANI_U8 Unicast[ CSR_WPA_OUI_SIZE ];
+ tANI_U8 Multicast[ CSR_WPA_OUI_SIZE ];
+ tANI_U8 Authentication[ CSR_WPA_OUI_SIZE ];
+ tANI_U8 MulticastCyphers[ 1 ][ CSR_WPA_OUI_SIZE ];
+ tANI_U8 i;
+ eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN;
+
+ do
+ {
+ if ( pWpaIe->present )
+ {
+ cMulticastCyphers = 1;
+ palCopyMemory(pMac->hHdd, MulticastCyphers, pWpaIe->multicast_cipher, CSR_WPA_OUI_SIZE);
+ cUnicastCyphers = (tANI_U8)(pWpaIe->unicast_cipher_count);
+ cAuthSuites = (tANI_U8)(pWpaIe->auth_suite_count);
+
+ //Check - Is requested Unicast Cipher supported by the BSS.
+ fAcceptableCyphers = csrMatchWPAOUIIndex( pMac, pWpaIe->unicast_ciphers, cUnicastCyphers,
+ csrGetOUIIndexFromCipher( enType ), Unicast );
+
+ if( !fAcceptableCyphers ) break;
+
+
+ //Unicast is supported. Pick the first matching Group cipher, if any.
+ for( i = 0 ; i < pMCEncryption->numEntries ; i++ )
+ {
+ fAcceptableCyphers = csrMatchWPAOUIIndex( pMac, MulticastCyphers, cMulticastCyphers,
+ csrGetOUIIndexFromCipher( pMCEncryption->encryptionType[i]), Multicast );
+ if(fAcceptableCyphers)
+ {
+ break;
+ }
+ }
+ if( !fAcceptableCyphers ) break;
+
+ if( pNegotiatedMCCipher )
+ *pNegotiatedMCCipher = pMCEncryption->encryptionType[i];
+
+ /* Initializing with FALSE as it has TRUE value already */
+ fAcceptableCyphers = FALSE;
+ for (i = 0 ; i < pAuthType->numEntries; i++)
+ {
+ //Ciphers are supported, Match authentication algorithm and pick first matching authtype.
+ if ( csrIsAuthWpa( pMac, pWpaIe->auth_suites, cAuthSuites, Authentication ) )
+ {
+ if (eCSR_AUTH_TYPE_WPA == pAuthType->authType[i])
+ negAuthType = eCSR_AUTH_TYPE_WPA;
+ }
+ if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsAuthWpaPsk( pMac, pWpaIe->auth_suites, cAuthSuites, Authentication ) )
+ {
+ if (eCSR_AUTH_TYPE_WPA_PSK == pAuthType->authType[i])
+ negAuthType = eCSR_AUTH_TYPE_WPA_PSK;
+ }
+#ifdef FEATURE_WLAN_CCX
+ if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsCcxCckmAuthWpa( pMac, pWpaIe->auth_suites, cAuthSuites, Authentication ) )
+ {
+ if (eCSR_AUTH_TYPE_CCKM_WPA == pAuthType->authType[i])
+ negAuthType = eCSR_AUTH_TYPE_CCKM_WPA;
+ }
+#endif /* FEATURE_WLAN_CCX */
+
+ // The 1st auth type in the APs WPA IE, to match stations connecting
+ // profiles auth type will cause us to exit this loop
+ // This is added as some APs advertise multiple akms in the WPA IE.
+ if (eCSR_AUTH_TYPE_UNKNOWN != negAuthType)
+ {
+ fAcceptableCyphers = TRUE;
+ break;
+ }
+ } // for
+ }
+ }while(0);
+
+ if ( fAcceptableCyphers )
+ {
+ if ( MulticastCypher )
+ {
+ palCopyMemory( pMac->hHdd, (tANI_U8 **)MulticastCypher, Multicast, CSR_WPA_OUI_SIZE );
+ }
+
+ if ( UnicastCypher )
+ {
+ palCopyMemory( pMac->hHdd, (tANI_U8 **)UnicastCypher, Unicast, CSR_WPA_OUI_SIZE );
+ }
+
+ if ( AuthSuite )
+ {
+ palCopyMemory( pMac->hHdd, (tANI_U8 **)AuthSuite, Authentication, CSR_WPA_OUI_SIZE );
+ }
+
+ if( pNegotiatedAuthtype )
+ {
+ *pNegotiatedAuthtype = negAuthType;
+ }
+ }
+
+ return( fAcceptableCyphers );
+}
+
+
+
+tANI_BOOLEAN csrIsWpaEncryptionMatch( tpAniSirGlobal pMac, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pEnMcType,
+ tDot11fBeaconIEs *pIes, eCsrAuthType *pNegotiatedAuthtype, eCsrEncryptionType *pNegotiatedMCCipher )
+{
+ tANI_BOOLEAN fWpaMatch = eANI_BOOLEAN_FALSE;
+
+ // See if the cyphers in the Bss description match with the settings in the profile.
+ fWpaMatch = csrGetWpaCyphers( pMac, pAuthType, enType, pEnMcType, &pIes->WPA, NULL, NULL, NULL, pNegotiatedAuthtype, pNegotiatedMCCipher );
+
+ return( fWpaMatch );
+}
+
+
+tANI_U8 csrConstructWpaIe( tHalHandle hHal, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN fWpaMatch;
+ tANI_U8 cbWpaIe = 0;
+ tANI_U8 UnicastCypher[ CSR_WPA_OUI_SIZE ];
+ tANI_U8 MulticastCypher[ CSR_WPA_OUI_SIZE ];
+ tANI_U8 AuthSuite[ CSR_WPA_OUI_SIZE ];
+ tCsrWpaAuthIe *pAuthSuite;
+ tDot11fBeaconIEs *pIesLocal = pIes;
+
+ do
+ {
+ if ( !csrIsProfileWpa( pProfile ) ) break;
+
+ if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) )
+ {
+ break;
+ }
+ // See if the cyphers in the Bss description match with the settings in the profile.
+ fWpaMatch = csrGetWpaCyphers( hHal, &pProfile->AuthType, pProfile->negotiatedUCEncryptionType, &pProfile->mcEncryptionType,
+ &pIesLocal->WPA, UnicastCypher, MulticastCypher, AuthSuite, NULL, NULL );
+ if ( !fWpaMatch ) break;
+
+ pWpaIe->IeHeader.ElementID = SIR_MAC_WPA_EID;
+
+ palCopyMemory( pMac->hHdd, pWpaIe->Oui, csrWpaOui[01], sizeof( pWpaIe->Oui ) );
+
+ pWpaIe->Version = CSR_WPA_VERSION_SUPPORTED;
+
+ palCopyMemory( pMac->hHdd, pWpaIe->MulticastOui, MulticastCypher, sizeof( MulticastCypher ) );
+
+ pWpaIe->cUnicastCyphers = 1;
+
+ palCopyMemory( pMac->hHdd, &pWpaIe->UnicastOui[ 0 ], UnicastCypher, sizeof( UnicastCypher ) );
+
+ pAuthSuite = (tCsrWpaAuthIe *)( &pWpaIe->UnicastOui[ pWpaIe->cUnicastCyphers ] );
+
+ pAuthSuite->cAuthenticationSuites = 1;
+ palCopyMemory( pMac->hHdd, &pAuthSuite->AuthOui[ 0 ], AuthSuite, sizeof( AuthSuite ) );
+
+ // 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:
+ // http://gold.woodsidenet.com/bugzilla/show_bug.cgi?id=15234
+
+ // Add in the fixed fields plus 1 Unicast cypher, less the IE Header length
+ // Add in the size of the Auth suite (count plus a single OUI)
+ pWpaIe->IeHeader.Length = sizeof( *pWpaIe ) - sizeof ( pWpaIe->IeHeader ) +
+ sizeof( *pAuthSuite );
+
+ // return the size of the IE header (total) constructed...
+ cbWpaIe = pWpaIe->IeHeader.Length + sizeof( pWpaIe->IeHeader );
+
+ } while( 0 );
+
+ if( !pIes && pIesLocal )
+ {
+ //locally allocated
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+
+ return( cbWpaIe );
+}
+
+
+tANI_BOOLEAN csrGetWpaRsnIe( tHalHandle hHal, tANI_U8 *pIes, tANI_U32 len,
+ tANI_U8 *pWpaIe, tANI_U8 *pcbWpaIe, tANI_U8 *pRSNIe, tANI_U8 *pcbRSNIe)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tDot11IEHeader *pIEHeader;
+ tSirMacPropIE *pSirMacPropIE;
+ tANI_U32 cbParsed;
+ tANI_U32 cbIE;
+ int cExpectedIEs = 0;
+ int cFoundIEs = 0;
+ int cbPropIETotal;
+
+ pIEHeader = (tDot11IEHeader *)pIes;
+ if(pWpaIe) cExpectedIEs++;
+ if(pRSNIe) cExpectedIEs++;
+
+ // bss description length includes all fields other than the length itself
+ cbParsed = 0;
+
+ // Loop as long as there is data left in the IE of the Bss Description
+ // and the number of Expected IEs is NOT found yet.
+ while( ( (cbParsed + sizeof( *pIEHeader )) <= len ) && ( cFoundIEs < cExpectedIEs ) )
+ {
+ cbIE = sizeof( *pIEHeader ) + pIEHeader->Length;
+
+ if ( ( cbIE + cbParsed ) > len ) break;
+
+ if ( ( pIEHeader->Length >= gCsrIELengthTable[ pIEHeader->ElementID ].min ) &&
+ ( pIEHeader->Length <= gCsrIELengthTable[ pIEHeader->ElementID ].max ) )
+ {
+ switch( pIEHeader->ElementID )
+ {
+ // Parse the 221 (0xdd) Proprietary IEs here...
+ // Note that the 221 IE is overloaded, containing the WPA IE, WMM/WME IE, and the
+ // Airgo proprietary IE information.
+ case SIR_MAC_WPA_EID:
+ {
+ tANI_U32 aniOUI;
+ tANI_U8 *pOui = (tANI_U8 *)&aniOUI;
+
+ pOui++;
+ aniOUI = ANI_OUI;
+ aniOUI = i_ntohl( aniOUI );
+
+ pSirMacPropIE = ( tSirMacPropIE *)pIEHeader;
+ cbPropIETotal = pSirMacPropIE->length;
+
+ // Validate the ANI OUI is in the OUI field in the proprietary IE...
+ if ( ( pSirMacPropIE->length >= WNI_CFG_MANUFACTURER_OUI_LEN ) &&
+ pOui[ 0 ] == pSirMacPropIE->oui[ 0 ] &&
+ pOui[ 1 ] == pSirMacPropIE->oui[ 1 ] &&
+ pOui[ 2 ] == pSirMacPropIE->oui[ 2 ] )
+ {
+ }
+ else
+ {
+ tCsrWpaIe *pIe = ( tCsrWpaIe * )pIEHeader;
+
+ if(!pWpaIe || !pcbWpaIe) break;
+ // Check if this is a valid WPA IE. Then check that the
+ // WPA OUI is in place and the version is one that we support.
+ if ( ( pIe->IeHeader.Length >= SIR_MAC_WPA_IE_MIN_LENGTH ) &&
+ ( palEqualMemory(pMac->hHdd, pIe->Oui, (void *)csrWpaOui[1], sizeof( pIe->Oui ) ) ) &&
+ ( pIe->Version <= CSR_WPA_VERSION_SUPPORTED ) )
+ {
+ palCopyMemory(pMac->hHdd, pWpaIe, pIe, pIe->IeHeader.Length + sizeof( pIe->IeHeader ) );
+ *pcbWpaIe = pIe->IeHeader.Length + sizeof( pIe->IeHeader );
+ cFoundIEs++;
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case SIR_MAC_RSN_EID:
+ {
+ tCsrRSNIe *pIe;
+
+ if(!pcbRSNIe || !pRSNIe) break;
+ pIe = (tCsrRSNIe *)pIEHeader;
+
+ // Check the length of the RSN Ie to assure it is valid. Then check that the
+ // version is one that we support.
+
+ if ( pIe->IeHeader.Length < SIR_MAC_RSN_IE_MIN_LENGTH ) break;
+ if ( pIe->Version > CSR_RSN_VERSION_SUPPORTED ) break;
+
+ cFoundIEs++;
+
+ // if there is enough room in the WpaIE passed in, then copy the Wpa IE into
+ // the buffer passed in.
+ if ( *pcbRSNIe < pIe->IeHeader.Length + sizeof( pIe->IeHeader ) ) break;
+ palCopyMemory(pMac->hHdd, pRSNIe, pIe, pIe->IeHeader.Length + sizeof( pIe->IeHeader ) );
+ *pcbRSNIe = pIe->IeHeader.Length + sizeof( pIe->IeHeader );
+
+ break;
+ }
+
+ // Add support for other IE here...
+ default:
+ break;
+ }
+ }
+
+ cbParsed += cbIE;
+
+ pIEHeader = (tDot11IEHeader *)( ((tANI_U8 *)pIEHeader) + cbIE );
+
+ }
+
+ // return a BOOL that tells if all of the IEs asked for were found...
+ return( cFoundIEs == cExpectedIEs );
+}
+
+
+//If a WPAIE exists in the profile, just use it. Or else construct one from the BSS
+//Caller allocated memory for pWpaIe and guarrantee it can contain a max length WPA IE
+tANI_U8 csrRetrieveWpaIe( tHalHandle hHal, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U8 cbWpaIe = 0;
+
+ do
+ {
+ if ( !csrIsProfileWpa( pProfile ) ) break;
+ if(pProfile->nWPAReqIELength && pProfile->pWPAReqIE)
+ {
+ if(SIR_MAC_WPA_IE_MAX_LENGTH >= pProfile->nWPAReqIELength)
+ {
+ cbWpaIe = (tANI_U8)pProfile->nWPAReqIELength;
+ palCopyMemory(pMac->hHdd, pWpaIe, pProfile->pWPAReqIE, cbWpaIe);
+ }
+ else
+ {
+ smsLog(pMac, LOGW, " csrRetrieveWpaIe detect invalid WPA IE length (%d) \n", pProfile->nWPAReqIELength);
+ }
+ }
+ else
+ {
+ cbWpaIe = csrConstructWpaIe(pMac, pProfile, pSirBssDesc, pIes, pWpaIe);
+ }
+ }while(0);
+
+ return (cbWpaIe);
+}
+
+
+//If a RSNIE exists in the profile, just use it. Or else construct one from the BSS
+//Caller allocated memory for pWpaIe and guarrantee it can contain a max length WPA IE
+tANI_U8 csrRetrieveRsnIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
+ tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrRSNIe *pRsnIe )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U8 cbRsnIe = 0;
+
+ do
+ {
+ if ( !csrIsProfileRSN( pProfile ) ) break;
+ if(pProfile->nRSNReqIELength && pProfile->pRSNReqIE)
+ {
+ if(SIR_MAC_WPA_IE_MAX_LENGTH >= pProfile->nRSNReqIELength)
+ {
+ cbRsnIe = (tANI_U8)pProfile->nRSNReqIELength;
+ palCopyMemory(pMac->hHdd, pRsnIe, pProfile->pRSNReqIE, cbRsnIe);
+ }
+ else
+ {
+ smsLog(pMac, LOGW, " csrRetrieveRsnIe detect invalid RSN IE length (%d) \n", pProfile->nRSNReqIELength);
+ }
+ }
+ else
+ {
+ cbRsnIe = csrConstructRSNIe(pMac, sessionId, pProfile, pSirBssDesc, pIes, pRsnIe);
+ }
+ }while(0);
+
+ return (cbRsnIe);
+}
+
+
+#ifdef FEATURE_WLAN_WAPI
+//If a WAPI IE exists in the profile, just use it. Or else construct one from the BSS
+//Caller allocated memory for pWapiIe and guarrantee it can contain a max length WAPI IE
+tANI_U8 csrRetrieveWapiIe( tHalHandle hHal, tANI_U32 sessionId,
+ tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc,
+ tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U8 cbWapiIe = 0;
+
+ do
+ {
+ if ( !csrIsProfileWapi( pProfile ) ) break;
+ if(pProfile->nWAPIReqIELength && pProfile->pWAPIReqIE)
+ {
+ if(DOT11F_IE_WAPI_MAX_LEN >= pProfile->nWAPIReqIELength)
+ {
+ cbWapiIe = (tANI_U8)pProfile->nWAPIReqIELength;
+ palCopyMemory(pMac->hHdd, pWapiIe, pProfile->pWAPIReqIE, cbWapiIe);
+ }
+ else
+ {
+ smsLog(pMac, LOGW, " csrRetrieveWapiIe detect invalid WAPI IE length (%d) \n", pProfile->nWAPIReqIELength);
+ }
+ }
+ else
+ {
+ cbWapiIe = csrConstructWapiIe(pMac, sessionId, pProfile, pSirBssDesc, pIes, pWapiIe);
+ }
+ }while(0);
+
+ return (cbWapiIe);
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+tANI_BOOLEAN csrSearchChannelListForTxPower(tHalHandle hHal, tSirBssDescription *pBssDescription, tCsrChannelSet *returnChannelGroup)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tListElem *pEntry;
+ tANI_U16 i;
+ tANI_U16 startingChannel;
+ tANI_BOOLEAN found = FALSE;
+ tCsrChannelSet *pChannelGroup;
+
+ pEntry = csrLLPeekHead( &pMac->roam.channelList5G, LL_ACCESS_LOCK );
+
+ while ( pEntry )
+ {
+ pChannelGroup = GET_BASE_ADDR( pEntry, tCsrChannelSet, channelListLink );
+ startingChannel = pChannelGroup->firstChannel;
+ for ( i = 0; i < pChannelGroup->numChannels; i++ )
+ {
+ if ( startingChannel + i * pChannelGroup->interChannelOffset == pBssDescription->channelId )
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if ( found )
+ {
+ palCopyMemory(pMac->hHdd, returnChannelGroup, pChannelGroup, sizeof(tCsrChannelSet));
+ break;
+ }
+ else
+ {
+ pEntry = csrLLNext( &pMac->roam.channelList5G, pEntry, LL_ACCESS_LOCK );
+ }
+ }
+
+ return( found );
+}
+
+tANI_BOOLEAN csrRatesIsDot11Rate11bSupportedRate( tANI_U8 dot11Rate )
+{
+ tANI_BOOLEAN fSupported = FALSE;
+ tANI_U16 nonBasicRate = (tANI_U16)( BITS_OFF( dot11Rate, CSR_DOT11_BASIC_RATE_MASK ) );
+
+ switch ( nonBasicRate )
+ {
+ case eCsrSuppRate_1Mbps:
+ case eCsrSuppRate_2Mbps:
+ case eCsrSuppRate_5_5Mbps:
+ case eCsrSuppRate_11Mbps:
+ fSupported = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ return( fSupported );
+}
+
+tANI_BOOLEAN csrRatesIsDot11Rate11aSupportedRate( tANI_U8 dot11Rate )
+{
+ tANI_BOOLEAN fSupported = FALSE;
+ tANI_U16 nonBasicRate = (tANI_U16)( BITS_OFF( dot11Rate, CSR_DOT11_BASIC_RATE_MASK ) );
+
+ switch ( nonBasicRate )
+ {
+ case eCsrSuppRate_6Mbps:
+ case eCsrSuppRate_9Mbps:
+ case eCsrSuppRate_12Mbps:
+ case eCsrSuppRate_18Mbps:
+ case eCsrSuppRate_24Mbps:
+ case eCsrSuppRate_36Mbps:
+ case eCsrSuppRate_48Mbps:
+ case eCsrSuppRate_54Mbps:
+ fSupported = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ return( fSupported );
+}
+
+
+
+tAniEdType csrTranslateEncryptTypeToEdType( eCsrEncryptionType EncryptType )
+{
+ tAniEdType edType;
+
+ switch ( EncryptType )
+ {
+ default:
+ case eCSR_ENCRYPT_TYPE_NONE:
+ edType = eSIR_ED_NONE;
+ break;
+
+ case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
+ case eCSR_ENCRYPT_TYPE_WEP40:
+ edType = eSIR_ED_WEP40;
+ break;
+
+ case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ edType = eSIR_ED_WEP104;
+ break;
+
+ case eCSR_ENCRYPT_TYPE_TKIP:
+ edType = eSIR_ED_TKIP;
+ break;
+
+ case eCSR_ENCRYPT_TYPE_AES:
+ edType = eSIR_ED_CCMP;
+ break;
+#ifdef FEATURE_WLAN_WAPI
+ case eCSR_ENCRYPT_TYPE_WPI:
+ edType = eSIR_ED_WPI;
+#endif
+#ifdef WLAN_FEATURE_11W
+ //11w BIP
+ case eCSR_ENCRYPT_TYPE_AES_CMAC:
+ edType = eSIR_ED_AES_128_CMAC;
+ break;
+#endif
+ }
+
+ return( edType );
+}
+
+
+//pIes can be NULL
+tANI_BOOLEAN csrValidateWep( tpAniSirGlobal pMac, eCsrEncryptionType ucEncryptionType,
+ tCsrAuthList *pAuthList, tCsrEncryptionList *pMCEncryptionList,
+ eCsrAuthType *pNegotiatedAuthType, eCsrEncryptionType *pNegotiatedMCEncryption,
+ tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes )
+{
+ tANI_U32 idx;
+ tANI_BOOLEAN fMatch = FALSE;
+ eCsrAuthType negotiatedAuth = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+ eCsrEncryptionType negotiatedMCCipher = eCSR_ENCRYPT_TYPE_UNKNOWN;
+
+ //This function just checks whether HDD is giving correct values for Multicast cipher and Auth.
+
+ do
+ {
+ //If privacy bit is not set, consider no match
+ if ( !csrIsPrivacy( pSirBssDesc ) ) break;
+
+ for( idx = 0; idx < pMCEncryptionList->numEntries; idx++ )
+ {
+ switch( pMCEncryptionList->encryptionType[idx] )
+ {
+ case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
+ case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
+ case eCSR_ENCRYPT_TYPE_WEP40:
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ /* Multicast list may contain WEP40/WEP104. Check whether it matches UC.
+ */
+ if( ucEncryptionType == pMCEncryptionList->encryptionType[idx] )
+ {
+ fMatch = TRUE;
+ negotiatedMCCipher = pMCEncryptionList->encryptionType[idx];
+ }
+ break;
+ default:
+ fMatch = FALSE;
+ break;
+ }
+ if(fMatch) break;
+ }
+
+ if(!fMatch) break;
+
+ for( idx = 0; idx < pAuthList->numEntries; idx++ )
+ {
+ switch( pAuthList->authType[idx] )
+ {
+ case eCSR_AUTH_TYPE_OPEN_SYSTEM:
+ case eCSR_AUTH_TYPE_SHARED_KEY:
+ case eCSR_AUTH_TYPE_AUTOSWITCH:
+ fMatch = TRUE;
+ negotiatedAuth = pAuthList->authType[idx];
+ break;
+ default:
+ fMatch = FALSE;
+ }
+ if (fMatch) break;
+ }
+
+ if(!fMatch) break;
+ //In case of WPA / WPA2, check whether it supports WEP as well
+ if(pIes)
+ {
+ //Prepare the encryption type for WPA/WPA2 functions
+ if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == ucEncryptionType )
+ {
+ ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP40;
+ }
+ else if( eCSR_ENCRYPT_TYPE_WEP104 == ucEncryptionType )
+ {
+ ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP104;
+ }
+ //else we can use the encryption type directly
+ if( pIes->WPA.present )
+ {
+ fMatch = palEqualMemory(pMac->hHdd, pIes->WPA.multicast_cipher,
+ csrWpaOui[csrGetOUIIndexFromCipher( ucEncryptionType )], CSR_WPA_OUI_SIZE );
+ if( fMatch ) break;
+ }
+ if( pIes->RSN.present )
+ {
+ fMatch = palEqualMemory(pMac->hHdd, pIes->RSN.gp_cipher_suite,
+ csrRSNOui[csrGetOUIIndexFromCipher( ucEncryptionType )], CSR_RSN_OUI_SIZE );
+ }
+ }
+
+ }while(0);
+
+ if( fMatch )
+ {
+ if( pNegotiatedAuthType )
+ *pNegotiatedAuthType = negotiatedAuth;
+
+ if( pNegotiatedMCEncryption )
+ *pNegotiatedMCEncryption = negotiatedMCCipher;
+ }
+
+
+ return fMatch;
+}
+
+
+//pIes shall contain IEs from pSirBssDesc. It shall be returned from function csrGetParsedBssDescriptionIEs
+tANI_BOOLEAN csrIsSecurityMatch( tHalHandle hHal, tCsrAuthList *authType, tCsrEncryptionList *pUCEncryptionType, tCsrEncryptionList *pMCEncryptionType,
+ tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes,
+ eCsrAuthType *negotiatedAuthtype, eCsrEncryptionType *negotiatedUCCipher, eCsrEncryptionType *negotiatedMCCipher )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN fMatch = FALSE;
+ tANI_U8 i,idx;
+ eCsrEncryptionType mcCipher = eCSR_ENCRYPT_TYPE_UNKNOWN, ucCipher = eCSR_ENCRYPT_TYPE_UNKNOWN;
+ eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN;
+
+ for( i = 0 ; ((i < pUCEncryptionType->numEntries) && (!fMatch)) ; i++ )
+ {
+ ucCipher = pUCEncryptionType->encryptionType[i];
+ // If the Bss description shows the Privacy bit is on, then we must have some sort of encryption configured
+ // for the profile to work. Don't attempt to join networks with Privacy bit set when profiles say NONE for
+ // encryption type.
+ switch ( ucCipher )
+ {
+ case eCSR_ENCRYPT_TYPE_NONE:
+ {
+ // for NO encryption, if the Bss description has the Privacy bit turned on, then encryption is
+ // required so we have to reject this Bss.
+ if ( csrIsPrivacy( pSirBssDesc ) )
+ {
+ fMatch = FALSE;
+ }
+ else
+ {
+ fMatch = TRUE;
+ }
+
+ if ( fMatch )
+ {
+ fMatch = FALSE;
+ //Check Multicast cipher requested and Auth type requested.
+ for( idx = 0 ; idx < pMCEncryptionType->numEntries ; idx++ )
+ {
+ if( eCSR_ENCRYPT_TYPE_NONE == pMCEncryptionType->encryptionType[idx] )
+ {
+ fMatch = TRUE; //Multicast can only be none.
+ mcCipher = pMCEncryptionType->encryptionType[idx];
+ break;
+ }
+ }
+ if (!fMatch) break;
+
+ fMatch = FALSE;
+ //Check Auth list. It should contain AuthOpen.
+ for( idx = 0 ; idx < authType->numEntries ; idx++ )
+ {
+ if( eCSR_AUTH_TYPE_OPEN_SYSTEM == authType->authType[idx] )
+ {
+ fMatch = TRUE;
+ negAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+ break;
+ }
+ }
+ if (!fMatch) break;
+
+ }
+ break;
+ }
+
+ case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
+ case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
+ // !! might want to check for WEP keys set in the Profile.... ?
+ // !! don't need to have the privacy bit in the Bss description. Many AP policies make legacy
+ // encryption 'optional' so we don't know if we can associate or not. The AP will reject if
+ // encryption is not allowed without the Privacy bit turned on.
+ fMatch = csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes);
+
+ break;
+
+ // these are all of the WPA encryption types...
+ case eCSR_ENCRYPT_TYPE_WEP40:
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ fMatch = csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes);
+ break;
+
+ case eCSR_ENCRYPT_TYPE_TKIP:
+ case eCSR_ENCRYPT_TYPE_AES:
+ {
+ if(pIes)
+ {
+ // First check if there is a RSN match
+ fMatch = csrIsRSNMatch( pMac, authType, ucCipher, pMCEncryptionType, pIes, &negAuthType, &mcCipher );
+ if( !fMatch )
+ {
+ // If not RSN, then check if there is a WPA match
+ fMatch = csrIsWpaEncryptionMatch( pMac, authType, ucCipher, pMCEncryptionType, pIes,
+ &negAuthType, &mcCipher );
+ }
+ }
+ else
+ {
+ fMatch = FALSE;
+ }
+ break;
+ }
+#ifdef FEATURE_WLAN_WAPI
+ case eCSR_ENCRYPT_TYPE_WPI://WAPI
+ {
+ if(pIes)
+ {
+ fMatch = csrIsWapiMatch( hHal, authType, ucCipher, pMCEncryptionType, pIes, &negAuthType, &mcCipher );
+ }
+ else
+ {
+ fMatch = FALSE;
+ }
+ break;
+ }
+#endif /* FEATURE_WLAN_WAPI */
+ case eCSR_ENCRYPT_TYPE_ANY:
+ default:
+ {
+ tANI_BOOLEAN fMatchAny = eANI_BOOLEAN_FALSE;
+
+ fMatch = eANI_BOOLEAN_TRUE;
+ //It is allowed to match anything. Try the more secured ones first.
+ if(pIes)
+ {
+ //Check AES first
+ ucCipher = eCSR_ENCRYPT_TYPE_AES;
+ fMatchAny = csrIsRSNMatch( hHal, authType, ucCipher, pMCEncryptionType, pIes, &negAuthType, &mcCipher );
+ if(!fMatchAny)
+ {
+ //Check TKIP
+ ucCipher = eCSR_ENCRYPT_TYPE_TKIP;
+ fMatchAny = csrIsRSNMatch( hHal, authType, ucCipher, pMCEncryptionType, pIes, &negAuthType, &mcCipher );
+ }
+#ifdef FEATURE_WLAN_WAPI
+ if(!fMatchAny)
+ {
+ //Check WAPI
+ ucCipher = eCSR_ENCRYPT_TYPE_WPI;
+ fMatchAny = csrIsWapiMatch( hHal, authType, ucCipher, pMCEncryptionType, pIes, &negAuthType, &mcCipher );
+ }
+#endif /* FEATURE_WLAN_WAPI */
+ }
+ if(!fMatchAny)
+ {
+ ucCipher = eCSR_ENCRYPT_TYPE_WEP104;
+ if(!csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes))
+ {
+ ucCipher = eCSR_ENCRYPT_TYPE_WEP40;
+ if(!csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes))
+ {
+ ucCipher = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
+ if(!csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes))
+ {
+ ucCipher = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ if(!csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes))
+ {
+ //It must be open and no encryption
+ if ( csrIsPrivacy( pSirBssDesc ) )
+ {
+ //This is not right
+ fMatch = eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ negAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+ mcCipher = eCSR_ENCRYPT_TYPE_NONE;
+ ucCipher = eCSR_ENCRYPT_TYPE_NONE;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ }
+
+ if( fMatch )
+ {
+ if( negotiatedUCCipher )
+ *negotiatedUCCipher = ucCipher;
+
+ if( negotiatedMCCipher )
+ *negotiatedMCCipher = mcCipher;
+
+ if( negotiatedAuthtype )
+ *negotiatedAuthtype = negAuthType;
+ }
+
+ return( fMatch );
+}
+
+
+tANI_BOOLEAN csrIsSsidMatch( tpAniSirGlobal pMac, tANI_U8 *ssid1, tANI_U8 ssid1Len, tANI_U8 *bssSsid,
+ tANI_U8 bssSsidLen, tANI_BOOLEAN fSsidRequired )
+{
+ tANI_BOOLEAN fMatch = FALSE;
+
+ do {
+
+ // There are a few special cases. If the Bss description has a Broadcast SSID,
+ // then our Profile must have a single SSID without Wildcards so we can program
+ // the SSID.
+ // SSID could be suppressed in beacons. In that case SSID IE has valid length
+ // but the SSID value is all NULL characters. That condition is trated same
+ // as NULL SSID
+ if ( csrIsNULLSSID( bssSsid, bssSsidLen ) )
+ {
+ if ( eANI_BOOLEAN_FALSE == fSsidRequired )
+ {
+ fMatch = TRUE;
+ }
+ break;
+ }
+
+ // Check for the specification of the Broadcast SSID at the beginning of the list.
+ // If specified, then all SSIDs are matches (broadcast SSID means accept all SSIDs).
+ if ( ssid1Len == 0 )
+ {
+ fMatch = TRUE;
+ break;
+ }
+
+ if(ssid1Len != bssSsidLen) break;
+ if(palEqualMemory(pMac->hHdd, bssSsid, ssid1, bssSsidLen))
+ {
+ fMatch = TRUE;
+ break;
+ }
+
+ } while( 0 );
+
+ return( fMatch );
+}
+
+
+//Null ssid means match
+tANI_BOOLEAN csrIsSsidInList( tHalHandle hHal, tSirMacSSid *pSsid, tCsrSSIDs *pSsidList )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN fMatch = FALSE;
+ tANI_U32 i;
+
+ if ( pSsidList && pSsid )
+ {
+ for(i = 0; i < pSsidList->numOfSSIDs; i++)
+ {
+ if(csrIsNULLSSID(pSsidList->SSIDList[i].SSID.ssId, pSsidList->SSIDList[i].SSID.length) ||
+ ((pSsidList->SSIDList[i].SSID.length == pSsid->length) &&
+ palEqualMemory(pMac->hHdd, pSsid->ssId, pSsidList->SSIDList[i].SSID.ssId, pSsid->length)))
+ {
+ fMatch = TRUE;
+ break;
+ }
+ }
+ }
+
+ return (fMatch);
+}
+
+//like to use sirCompareMacAddr
+tANI_BOOLEAN csrIsMacAddressZero( tpAniSirGlobal pMac, tCsrBssid *pMacAddr )
+{
+ tANI_U8 bssid[WNI_CFG_BSSID_LEN] = {0, 0, 0, 0, 0, 0};
+
+ return( palEqualMemory(pMac->hHdd, bssid, pMacAddr, WNI_CFG_BSSID_LEN));
+}
+
+//like to use sirCompareMacAddr
+tANI_BOOLEAN csrIsMacAddressBroadcast( tpAniSirGlobal pMac, tCsrBssid *pMacAddr )
+{
+ tANI_U8 bssid[WNI_CFG_BSSID_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ return( palEqualMemory(pMac->hHdd, bssid, pMacAddr, WNI_CFG_BSSID_LEN));
+}
+
+
+//like to use sirCompareMacAddr
+tANI_BOOLEAN csrIsMacAddressEqual( tpAniSirGlobal pMac, tCsrBssid *pMacAddr1, tCsrBssid *pMacAddr2 )
+{
+ return( palEqualMemory(pMac->hHdd, pMacAddr1, pMacAddr2, sizeof(tCsrBssid)) );
+}
+
+
+tANI_BOOLEAN csrIsBssidMatch( tHalHandle hHal, tCsrBssid *pProfBssid, tCsrBssid *BssBssid )
+{
+ tANI_BOOLEAN fMatch = FALSE;
+ tCsrBssid ProfileBssid;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ // for efficiency of the MAC_ADDRESS functions, move the
+ // Bssid's into MAC_ADDRESS structs.
+ palCopyMemory( pMac->hHdd, &ProfileBssid, pProfBssid, sizeof(tCsrBssid) );
+
+ do {
+
+ // Give the profile the benefit of the doubt... accept either all 0 or
+ // the real broadcast Bssid (all 0xff) as broadcast Bssids (meaning to
+ // match any Bssids).
+ if ( csrIsMacAddressZero( pMac, &ProfileBssid ) ||
+ csrIsMacAddressBroadcast( pMac, &ProfileBssid ) )
+ {
+ fMatch = TRUE;
+ break;
+ }
+
+ if ( csrIsMacAddressEqual( pMac, BssBssid, &ProfileBssid ) )
+ {
+ fMatch = TRUE;
+ break;
+ }
+
+ } while( 0 );
+
+ return( fMatch );
+}
+
+
+tANI_BOOLEAN csrIsBSSTypeMatch(eCsrRoamBssType bssType1, eCsrRoamBssType bssType2)
+{
+ if((eCSR_BSS_TYPE_ANY != bssType1 && eCSR_BSS_TYPE_ANY != bssType2) && (bssType1 != bssType2))
+ return eANI_BOOLEAN_FALSE;
+ else
+ return eANI_BOOLEAN_TRUE;
+}
+
+
+tANI_BOOLEAN csrIsBssTypeIBSS(eCsrRoamBssType bssType)
+{
+ return((tANI_BOOLEAN)(eCSR_BSS_TYPE_START_IBSS == bssType || eCSR_BSS_TYPE_IBSS == bssType));
+}
+
+tANI_BOOLEAN csrIsBssTypeWDS(eCsrRoamBssType bssType)
+{
+ return((tANI_BOOLEAN)(eCSR_BSS_TYPE_WDS_STA == bssType || eCSR_BSS_TYPE_WDS_AP == bssType));
+}
+
+tANI_BOOLEAN csrIsBSSTypeCapsMatch( eCsrRoamBssType bssType, tSirBssDescription *pSirBssDesc )
+{
+ tANI_BOOLEAN fMatch = TRUE;
+
+ do
+ {
+ switch( bssType )
+ {
+ case eCSR_BSS_TYPE_ANY:
+ break;
+
+ case eCSR_BSS_TYPE_INFRASTRUCTURE:
+ case eCSR_BSS_TYPE_WDS_STA:
+ if( !csrIsInfraBssDesc( pSirBssDesc ) )
+ fMatch = FALSE;
+
+ break;
+
+ case eCSR_BSS_TYPE_IBSS:
+ case eCSR_BSS_TYPE_START_IBSS:
+ if( !csrIsIbssBssDesc( pSirBssDesc ) )
+ fMatch = FALSE;
+
+ break;
+
+ case eCSR_BSS_TYPE_WDS_AP: //For WDS AP, no need to match anything
+ default:
+ fMatch = FALSE;
+ break;
+ }
+ }
+ while( 0 );
+
+
+ return( fMatch );
+}
+
+static tANI_BOOLEAN csrIsCapabilitiesMatch( tpAniSirGlobal pMac, eCsrRoamBssType bssType, tSirBssDescription *pSirBssDesc )
+{
+ return( csrIsBSSTypeCapsMatch( bssType, pSirBssDesc ) );
+}
+
+
+
+static tANI_BOOLEAN csrIsSpecificChannelMatch( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, tANI_U8 Channel )
+{
+ tANI_BOOLEAN fMatch = TRUE;
+
+ do
+ {
+ // if the channel is ANY, then always match...
+ if ( eCSR_OPERATING_CHANNEL_ANY == Channel ) break;
+ if ( Channel == pSirBssDesc->channelId ) break;
+
+ // didn't match anything.. so return NO match
+ fMatch = FALSE;
+
+ } while( 0 );
+
+ return( fMatch );
+}
+
+
+tANI_BOOLEAN csrIsChannelBandMatch( tpAniSirGlobal pMac, tANI_U8 channelId, tSirBssDescription *pSirBssDesc )
+{
+ tANI_BOOLEAN fMatch = TRUE;
+
+ do
+ {
+ // if the profile says Any channel AND the global settings says ANY channel, then we
+ // always match...
+ if ( eCSR_OPERATING_CHANNEL_ANY == channelId ) break;
+
+ if ( eCSR_OPERATING_CHANNEL_ANY != channelId )
+ {
+ fMatch = csrIsSpecificChannelMatch( pMac, pSirBssDesc, channelId );
+ }
+
+ } while( 0 );
+
+ return( fMatch );
+}
+
+
+/**
+ * \brief Enquire as to whether a given rate is supported by the
+ * adapter as currently configured
+ *
+ *
+ * \param nRate A rate in units of 500kbps
+ *
+ * \return TRUE if the adapter is currently capable of supporting this
+ * rate, FALSE else
+ *
+ *
+ * The rate encoding is just as in 802.11 Information Elements, except
+ * that the high bit is \em not interpreted as indicating a Basic Rate,
+ * and proprietary rates are allowed, too.
+ *
+ * Note that if the adapter's dot11Mode is g, we don't restrict the
+ * rates. According to hwReadEepromParameters, this will happen when:
+ *
+ * ... the card is configured for ALL bands through the property
+ * page. If this occurs, and the card is not an ABG card ,then this
+ * code is setting the dot11Mode to assume the mode that the
+ * hardware can support. For example, if the card is an 11BG card
+ * and we are configured to support ALL bands, then we change the
+ * dot11Mode to 11g because ALL in this case is only what the
+ * hardware can support.
+ *
+ *
+ */
+
+static tANI_BOOLEAN csrIsAggregateRateSupported( tpAniSirGlobal pMac, tANI_U16 rate )
+{
+ tANI_BOOLEAN fSupported = eANI_BOOLEAN_FALSE;
+ tANI_U16 idx, newRate;
+
+ //In case basic rate flag is set
+ newRate = BITS_OFF(rate, CSR_DOT11_BASIC_RATE_MASK);
+ if ( eCSR_CFG_DOT11_MODE_11A == pMac->roam.configParam.uCfgDot11Mode )
+ {
+ switch ( newRate )
+ {
+ case eCsrSuppRate_6Mbps:
+ case eCsrSuppRate_9Mbps:
+ case eCsrSuppRate_12Mbps:
+ case eCsrSuppRate_18Mbps:
+ case eCsrSuppRate_24Mbps:
+ case eCsrSuppRate_36Mbps:
+ case eCsrSuppRate_48Mbps:
+ case eCsrSuppRate_54Mbps:
+ fSupported = TRUE;
+ break;
+ default:
+ fSupported = FALSE;
+ break;
+ }
+
+ }
+ else if( eCSR_CFG_DOT11_MODE_11B == pMac->roam.configParam.uCfgDot11Mode )
+ {
+ switch ( newRate )
+ {
+ case eCsrSuppRate_1Mbps:
+ case eCsrSuppRate_2Mbps:
+ case eCsrSuppRate_5_5Mbps:
+ case eCsrSuppRate_11Mbps:
+ fSupported = TRUE;
+ break;
+ default:
+ fSupported = FALSE;
+ break;
+ }
+ }
+ else if ( !pMac->roam.configParam.ProprietaryRatesEnabled )
+ {
+
+ switch ( newRate )
+ {
+ case eCsrSuppRate_1Mbps:
+ case eCsrSuppRate_2Mbps:
+ case eCsrSuppRate_5_5Mbps:
+ case eCsrSuppRate_6Mbps:
+ case eCsrSuppRate_9Mbps:
+ case eCsrSuppRate_11Mbps:
+ case eCsrSuppRate_12Mbps:
+ case eCsrSuppRate_18Mbps:
+ case eCsrSuppRate_24Mbps:
+ case eCsrSuppRate_36Mbps:
+ case eCsrSuppRate_48Mbps:
+ case eCsrSuppRate_54Mbps:
+ fSupported = TRUE;
+ break;
+ default:
+ fSupported = FALSE;
+ break;
+ }
+
+ }
+ else {
+
+ if ( eCsrSuppRate_1Mbps == newRate ||
+ eCsrSuppRate_2Mbps == newRate ||
+ eCsrSuppRate_5_5Mbps == newRate ||
+ eCsrSuppRate_11Mbps == newRate )
+ {
+ fSupported = TRUE;
+ }
+ else {
+ idx = 0x1;
+
+ switch ( newRate )
+ {
+ case eCsrSuppRate_6Mbps:
+ fSupported = gPhyRatesSuppt[0][idx];
+ break;
+ case eCsrSuppRate_9Mbps:
+ fSupported = gPhyRatesSuppt[1][idx];
+ break;
+ case eCsrSuppRate_12Mbps:
+ fSupported = gPhyRatesSuppt[2][idx];
+ break;
+ case eCsrSuppRate_18Mbps:
+ fSupported = gPhyRatesSuppt[3][idx];
+ break;
+ case eCsrSuppRate_20Mbps:
+ fSupported = gPhyRatesSuppt[4][idx];
+ break;
+ case eCsrSuppRate_24Mbps:
+ fSupported = gPhyRatesSuppt[5][idx];
+ break;
+ case eCsrSuppRate_36Mbps:
+ fSupported = gPhyRatesSuppt[6][idx];
+ break;
+ case eCsrSuppRate_40Mbps:
+ fSupported = gPhyRatesSuppt[7][idx];
+ break;
+ case eCsrSuppRate_42Mbps:
+ fSupported = gPhyRatesSuppt[8][idx];
+ break;
+ case eCsrSuppRate_48Mbps:
+ fSupported = gPhyRatesSuppt[9][idx];
+ break;
+ case eCsrSuppRate_54Mbps:
+ fSupported = gPhyRatesSuppt[10][idx];
+ break;
+ case eCsrSuppRate_72Mbps:
+ fSupported = gPhyRatesSuppt[11][idx];
+ break;
+ case eCsrSuppRate_80Mbps:
+ fSupported = gPhyRatesSuppt[12][idx];
+ break;
+ case eCsrSuppRate_84Mbps:
+ fSupported = gPhyRatesSuppt[13][idx];
+ break;
+ case eCsrSuppRate_96Mbps:
+ fSupported = gPhyRatesSuppt[14][idx];
+ break;
+ case eCsrSuppRate_108Mbps:
+ fSupported = gPhyRatesSuppt[15][idx];
+ break;
+ case eCsrSuppRate_120Mbps:
+ fSupported = gPhyRatesSuppt[16][idx];
+ break;
+ case eCsrSuppRate_126Mbps:
+ fSupported = gPhyRatesSuppt[17][idx];
+ break;
+ case eCsrSuppRate_144Mbps:
+ fSupported = gPhyRatesSuppt[18][idx];
+ break;
+ case eCsrSuppRate_160Mbps:
+ fSupported = gPhyRatesSuppt[19][idx];
+ break;
+ case eCsrSuppRate_168Mbps:
+ fSupported = gPhyRatesSuppt[20][idx];
+ break;
+ case eCsrSuppRate_192Mbps:
+ fSupported = gPhyRatesSuppt[21][idx];
+ break;
+ case eCsrSuppRate_216Mbps:
+ fSupported = gPhyRatesSuppt[22][idx];
+ break;
+ case eCsrSuppRate_240Mbps:
+ fSupported = gPhyRatesSuppt[23][idx];
+ break;
+ default:
+ fSupported = FALSE;
+ break;
+ }
+ }
+ }
+
+ return fSupported;
+}
+
+
+
+static tANI_BOOLEAN csrIsRateSetMatch( tpAniSirGlobal pMac,
+ tDot11fIESuppRates *pBssSuppRates,
+ tDot11fIEExtSuppRates *pBssExtSuppRates )
+{
+ tANI_BOOLEAN fMatch = TRUE;
+ tANI_U32 i;
+
+
+ // Validate that all of the Basic rates advertised in the Bss description are supported.
+ if ( pBssSuppRates )
+ {
+ for( i = 0; i < pBssSuppRates->num_rates; i++ )
+ {
+ if ( CSR_IS_BASIC_RATE( pBssSuppRates->rates[ i ] ) )
+ {
+ if ( !csrIsAggregateRateSupported( pMac, pBssSuppRates->rates[ i ] ) )
+ {
+ fMatch = FALSE;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( fMatch && pBssExtSuppRates )
+ {
+ for( i = 0; i < pBssExtSuppRates->num_rates; i++ )
+ {
+ if ( CSR_IS_BASIC_RATE( pBssExtSuppRates->rates[ i ] ) )
+ {
+ if ( !csrIsAggregateRateSupported( pMac, pBssExtSuppRates->rates[ i ] ) )
+ {
+ fMatch = FALSE;
+ break;
+ }
+ }
+ }
+ }
+
+ return( fMatch );
+
+}
+
+
+//ppIes can be NULL. If caller want to get the *ppIes allocated by this function, pass in *ppIes = NULL
+tANI_BOOLEAN csrMatchBSS( tHalHandle hHal, tSirBssDescription *pBssDesc, tCsrScanResultFilter *pFilter,
+ eCsrAuthType *pNegAuth, eCsrEncryptionType *pNegUc, eCsrEncryptionType *pNegMc,
+ tDot11fBeaconIEs **ppIes)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN fRC = eANI_BOOLEAN_FALSE, fCheck;
+ tANI_U32 i;
+ tDot11fBeaconIEs *pIes = NULL;
+ tANI_U8 *pb;
+
+ do {
+ if( ( NULL == ppIes ) || ( *ppIes ) == NULL )
+ {
+ //If no IEs passed in, get our own.
+ if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes)))
+ {
+ break;
+ }
+ }
+ else
+ {
+ //Save the one pass in for local use
+ pIes = *ppIes;
+ }
+
+ //Check if caller wants P2P
+ fCheck = (!pFilter->p2pResult || pIes->P2PBeaconProbeRes.present);
+ if(!fCheck) break;
+
+ if(pIes->SSID.present)
+ {
+ for(i = 0; i < pFilter->SSIDs.numOfSSIDs; i++)
+ {
+ fCheck = csrIsSsidMatch( pMac, pFilter->SSIDs.SSIDList[i].SSID.ssId, pFilter->SSIDs.SSIDList[i].SSID.length,
+ pIes->SSID.ssid,
+ pIes->SSID.num_ssid, eANI_BOOLEAN_TRUE );
+ if ( fCheck ) break;
+ }
+ if(!fCheck) break;
+ }
+ fCheck = eANI_BOOLEAN_TRUE;
+ for(i = 0; i < pFilter->BSSIDs.numOfBSSIDs; i++)
+ {
+ fCheck = csrIsBssidMatch( pMac, (tCsrBssid *)&pFilter->BSSIDs.bssid[i], (tCsrBssid *)pBssDesc->bssId );
+ if ( fCheck ) break;
+
+ if (pFilter->p2pResult && pIes->P2PBeaconProbeRes.present)
+ {
+ fCheck = csrIsBssidMatch( pMac, (tCsrBssid *)&pFilter->BSSIDs.bssid[i],
+ (tCsrBssid *)pIes->P2PBeaconProbeRes.P2PDeviceInfo.P2PDeviceAddress );
+
+ if ( fCheck ) break;
+ }
+ }
+ if(!fCheck) break;
+
+ fCheck = eANI_BOOLEAN_TRUE;
+ for(i = 0; i < pFilter->ChannelInfo.numOfChannels; i++)
+ {
+ fCheck = csrIsChannelBandMatch( pMac, pFilter->ChannelInfo.ChannelList[i], pBssDesc );
+ if ( fCheck ) break;
+ }
+ if(!fCheck)
+ break;
+#if defined WLAN_FEATURE_VOWIFI
+ /* If this is for measurement filtering */
+ if( pFilter->fMeasurement )
+ {
+ fRC = eANI_BOOLEAN_TRUE;
+ break;
+ }
+#endif
+ if ( !csrIsPhyModeMatch( pMac, pFilter->phyMode, pBssDesc, NULL, NULL, pIes ) ) break;
+ if ( (!pFilter->bWPSAssociation) &&
+ !csrIsSecurityMatch( pMac, &pFilter->authType, &pFilter->EncryptionType, &pFilter->mcEncryptionType,
+ pBssDesc, pIes, pNegAuth, pNegUc, pNegMc ) ) break;
+ if ( !csrIsCapabilitiesMatch( pMac, pFilter->BSSType, pBssDesc ) ) break;
+ if ( !csrIsRateSetMatch( pMac, &pIes->SuppRates, &pIes->ExtSuppRates ) ) break;
+ //Tush-QoS: validate first if asked for APSD or WMM association
+ if ( (eCsrRoamWmmQbssOnly == pMac->roam.configParam.WMMSupportMode) &&
+ !CSR_IS_QOS_BSS(pIes) )
+ break;
+ //Check country. check even when pb is NULL because we may want to make sure
+ //AP has a country code in it if fEnforceCountryCodeMatch is set.
+ pb = ( pFilter->countryCode[0] ) ? ( pFilter->countryCode) : NULL;
+
+ fCheck = csrMatchCountryCode( pMac, pb, pIes );
+ if(!fCheck)
+ break;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (pFilter->MDID.mdiePresent)
+ {
+ if (pBssDesc->mdiePresent)
+ {
+ if (pFilter->MDID.mobilityDomain != (pBssDesc->mdie[1] << 8 | pBssDesc->mdie[0]))
+ break;
+ }
+ else
+ break;
+ }
+#endif
+ fRC = eANI_BOOLEAN_TRUE;
+
+ } while( 0 );
+ if( ppIes )
+ {
+ *ppIes = pIes;
+ }
+ else if( pIes )
+ {
+ palFreeMemory(pMac->hHdd, pIes);
+ }
+
+ return( fRC );
+}
+
+tANI_BOOLEAN csrMatchConnectedBSSSecurity( tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile,
+ tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes)
+{
+ tCsrEncryptionList ucEncryptionList, mcEncryptionList;
+ tCsrAuthList authList;
+
+ ucEncryptionList.numEntries = 1;
+ ucEncryptionList.encryptionType[0] = pProfile->EncryptionType;
+
+ mcEncryptionList.numEntries = 1;
+ mcEncryptionList.encryptionType[0] = pProfile->mcEncryptionType;
+
+ authList.numEntries = 1;
+ authList.authType[0] = pProfile->AuthType;
+
+ return( csrIsSecurityMatch( pMac, &authList, &ucEncryptionList, &mcEncryptionList, pBssDesc, pIes, NULL, NULL, NULL ));
+
+}
+
+
+tANI_BOOLEAN csrMatchBSSToConnectProfile( tHalHandle hHal, tCsrRoamConnectedProfile *pProfile,
+ tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN fRC = eANI_BOOLEAN_FALSE, fCheck;
+ tDot11fBeaconIEs *pIesLocal = pIes;
+
+ do {
+ if( !pIes )
+ {
+ if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal)))
+ {
+ break;
+ }
+ }
+ fCheck = eANI_BOOLEAN_TRUE;
+ if(pIesLocal->SSID.present)
+ {
+ tANI_BOOLEAN fCheckSsid = eANI_BOOLEAN_FALSE;
+ if(pProfile->SSID.length)
+ {
+ fCheckSsid = eANI_BOOLEAN_TRUE;
+ }
+ fCheck = csrIsSsidMatch( pMac, pProfile->SSID.ssId, pProfile->SSID.length,
+ pIesLocal->SSID.ssid, pIesLocal->SSID.num_ssid, fCheckSsid );
+ if(!fCheck) break;
+ }
+ if ( !csrMatchConnectedBSSSecurity( pMac, pProfile, pBssDesc, pIesLocal) ) break;
+ if ( !csrIsCapabilitiesMatch( pMac, pProfile->BSSType, pBssDesc ) ) break;
+ if ( !csrIsRateSetMatch( pMac, &pIesLocal->SuppRates, &pIesLocal->ExtSuppRates ) ) break;
+ fCheck = csrIsChannelBandMatch( pMac, pProfile->operationChannel, pBssDesc );
+ if(!fCheck)
+ break;
+
+ fRC = eANI_BOOLEAN_TRUE;
+
+ } while( 0 );
+
+ if( !pIes && pIesLocal )
+ {
+ //locally allocated
+ palFreeMemory(pMac->hHdd, pIesLocal);
+ }
+
+ return( fRC );
+}
+
+
+
+tANI_BOOLEAN csrRatesIsDot11RateSupported( tHalHandle hHal, tANI_U8 rate )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U16 n = BITS_OFF( rate, CSR_DOT11_BASIC_RATE_MASK );
+
+ return csrIsAggregateRateSupported( pMac, n );
+}
+
+
+tANI_U16 csrRatesMacPropToDot11( tANI_U16 Rate )
+{
+ tANI_U16 ConvertedRate = Rate;
+
+ switch( Rate )
+ {
+ case SIR_MAC_RATE_1:
+ ConvertedRate = 2;
+ break;
+ case SIR_MAC_RATE_2:
+ ConvertedRate = 4;
+ break;
+ case SIR_MAC_RATE_5_5:
+ ConvertedRate = 11;
+ break;
+ case SIR_MAC_RATE_11:
+ ConvertedRate = 22;
+ break;
+
+ case SIR_MAC_RATE_6:
+ ConvertedRate = 12;
+ break;
+ case SIR_MAC_RATE_9:
+ ConvertedRate = 18;
+ break;
+ case SIR_MAC_RATE_12:
+ ConvertedRate = 24;
+ break;
+ case SIR_MAC_RATE_18:
+ ConvertedRate = 36;
+ break;
+ case SIR_MAC_RATE_24:
+ ConvertedRate = 48;
+ break;
+ case SIR_MAC_RATE_36:
+ ConvertedRate = 72;
+ break;
+ case SIR_MAC_RATE_42:
+ ConvertedRate = 84;
+ break;
+ case SIR_MAC_RATE_48:
+ ConvertedRate = 96;
+ break;
+ case SIR_MAC_RATE_54:
+ ConvertedRate = 108;
+ break;
+
+ case SIR_MAC_RATE_72:
+ ConvertedRate = 144;
+ break;
+ case SIR_MAC_RATE_84:
+ ConvertedRate = 168;
+ break;
+ case SIR_MAC_RATE_96:
+ ConvertedRate = 192;
+ break;
+ case SIR_MAC_RATE_108:
+ ConvertedRate = 216;
+ break;
+ case SIR_MAC_RATE_126:
+ ConvertedRate = 252;
+ break;
+ case SIR_MAC_RATE_144:
+ ConvertedRate = 288;
+ break;
+ case SIR_MAC_RATE_168:
+ ConvertedRate = 336;
+ break;
+ case SIR_MAC_RATE_192:
+ ConvertedRate = 384;
+ break;
+ case SIR_MAC_RATE_216:
+ ConvertedRate = 432;
+ break;
+ case SIR_MAC_RATE_240:
+ ConvertedRate = 480;
+ break;
+
+ case 0xff:
+ ConvertedRate = 0;
+ break;
+ }
+
+ return ConvertedRate;
+}
+
+
+tANI_U16 csrRatesFindBestRate( tSirMacRateSet *pSuppRates, tSirMacRateSet *pExtRates, tSirMacPropRateSet *pPropRates )
+{
+ tANI_U8 i;
+ tANI_U16 nBest;
+
+ nBest = pSuppRates->rate[ 0 ] & ( ~CSR_DOT11_BASIC_RATE_MASK );
+
+ if(pSuppRates->numRates > SIR_MAC_RATESET_EID_MAX)
+ {
+ pSuppRates->numRates = SIR_MAC_RATESET_EID_MAX;
+ }
+
+ for ( i = 1U; i < pSuppRates->numRates; ++i )
+ {
+ nBest = (tANI_U16)CSR_MAX( nBest, pSuppRates->rate[ i ] & ( ~CSR_DOT11_BASIC_RATE_MASK ) );
+ }
+
+ if ( NULL != pExtRates )
+ {
+ for ( i = 0U; i < pExtRates->numRates; ++i )
+ {
+ nBest = (tANI_U16)CSR_MAX( nBest, pExtRates->rate[ i ] & ( ~CSR_DOT11_BASIC_RATE_MASK ) );
+ }
+ }
+
+ if ( NULL != pPropRates )
+ {
+ for ( i = 0U; i < pPropRates->numPropRates; ++i )
+ {
+ nBest = (tANI_U16)CSR_MAX( nBest, csrRatesMacPropToDot11( pPropRates->propRate[ i ] ) );
+ }
+ }
+
+ return nBest;
+}
+
+
+void csrReleaseProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile)
+{
+ if(pProfile)
+ {
+ if(pProfile->BSSIDs.bssid)
+ {
+ palFreeMemory(pMac->hHdd, pProfile->BSSIDs.bssid);
+ pProfile->BSSIDs.bssid = NULL;
+ }
+ if(pProfile->SSIDs.SSIDList)
+ {
+ palFreeMemory(pMac->hHdd, pProfile->SSIDs.SSIDList);
+ pProfile->SSIDs.SSIDList = NULL;
+ }
+ if(pProfile->pWPAReqIE)
+ {
+ palFreeMemory(pMac->hHdd, pProfile->pWPAReqIE);
+ pProfile->pWPAReqIE = NULL;
+ }
+ if(pProfile->pRSNReqIE)
+ {
+ palFreeMemory(pMac->hHdd, pProfile->pRSNReqIE);
+ pProfile->pRSNReqIE = NULL;
+ }
+#ifdef FEATURE_WLAN_WAPI
+ if(pProfile->pWAPIReqIE)
+ {
+ palFreeMemory(pMac->hHdd, pProfile->pWAPIReqIE);
+ pProfile->pWAPIReqIE = NULL;
+ }
+#endif /* FEATURE_WLAN_WAPI */
+
+ if(pProfile->pAddIEScan)
+ {
+ palFreeMemory(pMac->hHdd, pProfile->pAddIEScan);
+ pProfile->pAddIEScan = NULL;
+ }
+
+ if(pProfile->pAddIEAssoc)
+ {
+ palFreeMemory(pMac->hHdd, pProfile->pAddIEAssoc);
+ pProfile->pAddIEAssoc = NULL;
+ }
+ {
+ palFreeMemory(pMac->hHdd, pProfile->pAddIEAssoc);
+ pProfile->pAddIEAssoc = NULL;
+ }
+
+ if(pProfile->ChannelInfo.ChannelList)
+ {
+ palFreeMemory(pMac->hHdd, pProfile->ChannelInfo.ChannelList);
+ pProfile->ChannelInfo.ChannelList = NULL;
+ }
+
+
+ palZeroMemory(pMac->hHdd, pProfile, sizeof(tCsrRoamProfile));
+ }
+}
+
+void csrFreeScanFilter(tpAniSirGlobal pMac, tCsrScanResultFilter *pScanFilter)
+{
+ if(pScanFilter->BSSIDs.bssid)
+ {
+ palFreeMemory(pMac->hHdd, pScanFilter->BSSIDs.bssid);
+ pScanFilter->BSSIDs.bssid = NULL;
+ }
+ if(pScanFilter->ChannelInfo.ChannelList)
+ {
+ palFreeMemory(pMac->hHdd, pScanFilter->ChannelInfo.ChannelList);
+ pScanFilter->ChannelInfo.ChannelList = NULL;
+ }
+ if(pScanFilter->SSIDs.SSIDList)
+ {
+ palFreeMemory(pMac->hHdd, pScanFilter->SSIDs.SSIDList);
+ pScanFilter->SSIDs.SSIDList = NULL;
+ }
+}
+
+
+void csrFreeRoamProfile(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId];
+
+ if(pSession->pCurRoamProfile)
+ {
+ csrReleaseProfile(pMac, pSession->pCurRoamProfile);
+ palFreeMemory(pMac->hHdd, pSession->pCurRoamProfile);
+ pSession->pCurRoamProfile = NULL;
+ }
+}
+
+
+void csrFreeConnectBssDesc(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId];
+
+ if(pSession->pConnectBssDesc)
+ {
+ palFreeMemory(pMac->hHdd, pSession->pConnectBssDesc);
+ pSession->pConnectBssDesc = NULL;
+ }
+}
+
+
+
+tSirResultCodes csrGetDisassocRspStatusCode( tSirSmeDisassocRsp *pSmeDisassocRsp )
+{
+ tANI_U8 *pBuffer = (tANI_U8 *)pSmeDisassocRsp;
+ tANI_U32 ret;
+
+ pBuffer += (sizeof(tANI_U16) + sizeof(tANI_U16) + sizeof(tSirMacAddr));
+ //tSirResultCodes is an enum, assuming is 32bit
+ //If we cannot make this assumption, use copymemory
+ pal_get_U32( pBuffer, &ret );
+
+ return( ( tSirResultCodes )ret );
+}
+
+
+tSirResultCodes csrGetDeAuthRspStatusCode( tSirSmeDeauthRsp *pSmeRsp )
+{
+ tANI_U8 *pBuffer = (tANI_U8 *)pSmeRsp;
+ tANI_U32 ret;
+
+ pBuffer += (sizeof(tANI_U16) + sizeof(tANI_U16) + sizeof(tSirMacAddr));
+ //tSirResultCodes is an enum, assuming is 32bit
+ //If we cannot make this assumption, use copymemory
+ pal_get_U32( pBuffer, &ret );
+
+ return( ( tSirResultCodes )ret );
+}
+
+#if 0
+tSirScanType csrGetScanType(tANI_U8 chnId, eRegDomainId domainId, tANI_U8 *countryCode)
+{
+ tSirScanType scanType = eSIR_PASSIVE_SCAN;
+ tANI_U8 cc = 0;
+
+ while (cc++ < gCsrDomainChnInfo[domainId].numChannels)
+ {
+ if(chnId == gCsrDomainChnInfo[domainId].chnInfo[cc].chnId)
+ {
+ scanType = gCsrDomainChnInfo[domainId].chnInfo[cc].scanType;
+ break;
+ }
+ }
+
+ return (scanType);
+}
+#endif
+
+tSirScanType csrGetScanType(tpAniSirGlobal pMac, tANI_U8 chnId)
+{
+ tSirScanType scanType = eSIR_PASSIVE_SCAN;
+ eNVChannelEnabledType channelEnabledType;
+
+ channelEnabledType = vos_nv_getChannelEnabledState(chnId);
+ if( NV_CHANNEL_ENABLE == channelEnabledType)
+ {
+ scanType = eSIR_ACTIVE_SCAN;
+ }
+ return (scanType);
+}
+
+
+tANI_U8 csrToUpper( tANI_U8 ch )
+{
+ tANI_U8 chOut;
+
+ if ( ch >= 'a' && ch <= 'z' )
+ {
+ chOut = ch - 'a' + 'A';
+ }
+ else
+ {
+ chOut = ch;
+ }
+ return( chOut );
+}
+
+
+tSirBssType csrTranslateBsstypeToMacType(eCsrRoamBssType csrtype)
+{
+ tSirBssType ret;
+
+ switch(csrtype)
+ {
+ case eCSR_BSS_TYPE_INFRASTRUCTURE:
+ ret = eSIR_INFRASTRUCTURE_MODE;
+ break;
+ case eCSR_BSS_TYPE_IBSS:
+ case eCSR_BSS_TYPE_START_IBSS:
+ ret = eSIR_IBSS_MODE;
+ break;
+ case eCSR_BSS_TYPE_WDS_AP:
+ ret = eSIR_BTAMP_AP_MODE;
+ break;
+ case eCSR_BSS_TYPE_WDS_STA:
+ ret = eSIR_BTAMP_STA_MODE;
+ break;
+#ifdef WLAN_SOFTAP_FEATURE
+ case eCSR_BSS_TYPE_INFRA_AP:
+ ret = eSIR_INFRA_AP_MODE;
+ break;
+#endif
+ case eCSR_BSS_TYPE_ANY:
+ default:
+ ret = eSIR_AUTO_MODE;
+ break;
+ }
+
+ return (ret);
+}
+
+
+//This function use the parameters to decide the CFG value.
+//CSR never sets WNI_CFG_DOT11_MODE_ALL to the CFG
+//So PE should not see WNI_CFG_DOT11_MODE_ALL when it gets the CFG value
+#ifdef WLAN_SOFTAP_FEATURE
+eCsrCfgDot11Mode csrGetCfgDot11ModeFromCsrPhyMode(tCsrRoamProfile *pProfile, eCsrPhyMode phyMode, tANI_BOOLEAN fProprietary)
+#else
+eCsrCfgDot11Mode csrGetCfgDot11ModeFromCsrPhyMode(eCsrPhyMode phyMode, tANI_BOOLEAN fProprietary)
+#endif
+{
+ tANI_U32 cfgDot11Mode = eCSR_CFG_DOT11_MODE_ABG;
+
+ switch(phyMode)
+ {
+ case eCSR_DOT11_MODE_11a:
+ case eCSR_DOT11_MODE_11a_ONLY:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
+ break;
+ case eCSR_DOT11_MODE_11b:
+ case eCSR_DOT11_MODE_11b_ONLY:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
+ break;
+ case eCSR_DOT11_MODE_11g:
+ case eCSR_DOT11_MODE_11g_ONLY:
+#ifdef WLAN_SOFTAP_FEATURE
+ if(pProfile && (CSR_IS_INFRA_AP(pProfile)) && (phyMode == eCSR_DOT11_MODE_11g_ONLY))
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G_ONLY;
+ else
+#endif
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
+ break;
+ case eCSR_DOT11_MODE_11n:
+ if(fProprietary)
+ {
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_TAURUS;
+ }
+ else
+ {
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
+ }
+ break;
+ case eCSR_DOT11_MODE_11n_ONLY:
+#ifdef WLAN_SOFTAP_FEATURE
+ if(pProfile && CSR_IS_INFRA_AP(pProfile))
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N_ONLY;
+ else
+#endif
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
+ break;
+ case eCSR_DOT11_MODE_TAURUS:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_TAURUS;
+ break;
+ case eCSR_DOT11_MODE_abg:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_ABG;
+ break;
+ case eCSR_DOT11_MODE_AUTO:
+ cfgDot11Mode = eCSR_CFG_DOT11_MODE_AUTO;
+ break;
+ default:
+ //No need to assign anything here
+ break;
+ }
+
+ return (cfgDot11Mode);
+}
+
+
+eHalStatus csrSetRegulatoryDomain(tpAniSirGlobal pMac, v_REGDOMAIN_t domainId, tANI_BOOLEAN *pfRestartNeeded)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_BOOLEAN fRestart;
+
+ if(pMac->scan.domainIdCurrent == domainId)
+ {
+ //no change
+ fRestart = eANI_BOOLEAN_FALSE;
+ }
+ else if( !pMac->roam.configParam.fEnforceDefaultDomain )
+ {
+ pMac->scan.domainIdCurrent = domainId;
+ fRestart = eANI_BOOLEAN_TRUE;
+ }
+ else
+ {
+ //We cannot change the domain
+ status = eHAL_STATUS_CSR_WRONG_STATE;
+ fRestart = eANI_BOOLEAN_FALSE;
+ }
+ if(pfRestartNeeded)
+ {
+ *pfRestartNeeded = fRestart;
+ }
+
+ return (status);
+}
+
+
+v_REGDOMAIN_t csrGetCurrentRegulatoryDomain(tpAniSirGlobal pMac)
+{
+ return (pMac->scan.domainIdCurrent);
+}
+
+#if 0
+eHalStatus csrGetRegulatoryDomainForCountry(tpAniSirGlobal pMac, tANI_U8 *pCountry, eRegDomainId *pDomainId)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_U32 i, count = sizeof( gCsrCountryInfo ) / sizeof( gCsrCountryInfo[0] );
+
+ if(pCountry)
+ {
+ for(i = 0; i < count; i++)
+ {
+ if(palEqualMemory(pMac->hHdd, gCsrCountryInfo[i].countryCode, pCountry, 2))
+ {
+ if( pDomainId )
+ {
+ *pDomainId = gCsrCountryInfo[i].domainId;
+ }
+ break;
+ }
+ }
+ if(i == count)
+ {
+ smsLog(pMac, LOGW, FL(" doesn't match country %c%c\n"), pCountry[0], pCountry[1]);
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ return (status);
+}
+#endif
+
+eHalStatus csrGetRegulatoryDomainForCountry(tpAniSirGlobal pMac, tANI_U8 *pCountry, v_REGDOMAIN_t *pDomainId)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ VOS_STATUS vosStatus;
+ v_COUNTRYCODE_t countryCode;
+ v_REGDOMAIN_t domainId;
+
+ if(pCountry)
+ {
+ countryCode[0] = pCountry[0];
+ countryCode[1] = pCountry[1];
+ vosStatus = vos_nv_getRegDomainFromCountryCode( &domainId, countryCode );
+ if( VOS_IS_STATUS_SUCCESS(vosStatus) )
+ {
+ if( pDomainId )
+ {
+ *pDomainId = domainId;
+ }
+ status = eHAL_STATUS_SUCCESS;
+ }
+ else
+ {
+ smsLog(pMac, LOGW, FL(" doesn't match country %c%c\n"), pCountry[0], pCountry[1]);
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ return (status);
+}
+
+//To check whether a country code matches the one in the IE
+//Only check the first two characters, ignoring in/outdoor
+//pCountry -- caller allocated buffer contain the country code that is checking against
+//the one in pIes. It can be NULL.
+//caller must provide pIes, it cannot be NULL
+//This function always return TRUE if 11d support is not turned on.
+tANI_BOOLEAN csrMatchCountryCode( tpAniSirGlobal pMac, tANI_U8 *pCountry, tDot11fBeaconIEs *pIes )
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_TRUE;
+ v_REGDOMAIN_t domainId = NUM_REG_DOMAINS; //This is init to invalid value
+ eHalStatus status;
+
+ do
+ {
+ if( !csrIs11dSupported( pMac) )
+ {
+ break;
+ }
+ if( !pIes )
+ {
+ smsLog(pMac, LOGE, FL(" No IEs\n"));
+ break;
+ }
+ //Make sure this country is recognizable
+ if( pIes->Country.present )
+ {
+ status = csrGetRegulatoryDomainForCountry( pMac, pIes->Country.country,(v_REGDOMAIN_t *) &domainId );
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ fRet = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ }
+ //check whether it is needed to enforce to the default regulatory domain first
+ if( pMac->roam.configParam.fEnforceDefaultDomain )
+ {
+ if( domainId != pMac->scan.domainIdCurrent )
+ {
+ fRet = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ }
+ if( pMac->roam.configParam.fEnforceCountryCodeMatch )
+ {
+ if( domainId >= NUM_REG_DOMAINS )
+ {
+ fRet = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ }
+ if( pCountry )
+ {
+ tANI_U32 i;
+
+ if( !pIes->Country.present )
+ {
+ fRet = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ // Convert the CountryCode characters to upper
+ for ( i = 0; i < WNI_CFG_COUNTRY_CODE_LEN - 1; i++ )
+ {
+ pCountry[i] = csrToUpper( pCountry[i] );
+ }
+ if( !palEqualMemory(pMac->hHdd, pIes->Country.country, pCountry, WNI_CFG_COUNTRY_CODE_LEN - 1) )
+ {
+ fRet = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ }
+ } while(0);
+
+ return (fRet);
+}
+
+#if 0
+eHalStatus csrSetCountryDomainMapping(tpAniSirGlobal pMac, tCsrCountryDomainMapping *pCountryDomainMapping)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tANI_U32 i, j;
+ tANI_BOOLEAN fDomainChanged = eANI_BOOLEAN_FALSE;
+ tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN];
+
+ i = WNI_CFG_COUNTRY_CODE_LEN;
+ //Get the currently used country code
+ status = ccmCfgGetStr(pMac, WNI_CFG_COUNTRY_CODE, countryCode, &i);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ if(pCountryDomainMapping && pCountryDomainMapping->numEntry)
+ {
+ for(i = 0; i < pCountryDomainMapping->numEntry; i++)
+ {
+ for(j = 0; j < eCSR_NUM_COUNTRY_INDEX; j++)
+ {
+ if(palEqualMemory(pMac->hHdd, gCsrCountryInfo[j].countryCode,
+ pCountryDomainMapping->pCountryInfo[i].countryCode, 2))
+ {
+ if(gCsrCountryInfo[j].domainId != pCountryDomainMapping->pCountryInfo[i].domainId)
+ {
+ gCsrCountryInfo[j].domainId = pCountryDomainMapping->pCountryInfo[i].domainId;
+ //Check whether it matches the currently used country code
+ //If matching, need to update base on the new domain setting.
+ if(palEqualMemory(pMac->hHdd, countryCode,
+ pCountryDomainMapping->pCountryInfo[i].countryCode, 2))
+ {
+ fDomainChanged = eANI_BOOLEAN_TRUE;
+ }
+ }
+ break;
+ }
+ }
+ }
+ status = eHAL_STATUS_SUCCESS;
+ if(fDomainChanged)
+ {
+ tCsrChannel *pChannelList;
+
+ if(pMac->scan.f11dInfoApplied)
+ {
+ //11d info already applied. Let's reapply with the new domain setting
+ if(pMac->scan.channels11d.numChannels)
+ {
+ pChannelList = &pMac->scan.channels11d;
+ }
+ else
+ {
+ pChannelList = &pMac->scan.base20MHzChannels;
+ }
+ }
+ else
+ {
+ //no 11d so we use the base channelist from EEPROM
+ pChannelList = &pMac->scan.base20MHzChannels;
+ }
+ //set the new domain's scan requirement to CFG
+ csrSetCfgScanControlList(pMac, countryCode, pChannelList);
+ }
+ }
+ }
+
+ return (status);
+}
+
+eHalStatus csrSetDomainScanSetting(tpAniSirGlobal pMac, tCsrDomainFreqInfo *pDomainFreqInfo)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tANI_U32 i, j;
+ tANI_U16 freq;
+
+ if(pDomainFreqInfo && pDomainFreqInfo->numEntry && (pDomainFreqInfo->domainId < NUM_REG_DOMAINS))
+ {
+ tCsrDomainChnInfo *pDomainChnInfo = &gCsrDomainChnInfo[pDomainFreqInfo->domainId];
+
+ for(j = 0; j < pDomainChnInfo->numChannels; j++)
+ {
+ if(HAL_STATUS_SUCCESS(halPhyChIdToFreqConversion(pDomainChnInfo->chnInfo[j].chnId, &freq)))
+ {
+ for(i = 0; i < pDomainFreqInfo->numEntry; i++)
+ {
+ if((pDomainFreqInfo->pCsrScanFreqInfo[i].nStartFreq <= freq) &&
+ (freq <= pDomainFreqInfo->pCsrScanFreqInfo[i].nEndFreq))
+ {
+ pDomainChnInfo->chnInfo[j].scanType = pDomainFreqInfo->pCsrScanFreqInfo[i].scanType;
+ break;
+ }
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGW, " Failed to get frequency of channel %d", pDomainChnInfo->chnInfo[j].chnId);
+ }
+ }
+ status = eHAL_STATUS_SUCCESS;
+ }
+
+ return (status);
+}
+#endif
+
+eHalStatus csrGetModifyProfileFields(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tCsrRoamModifyProfileFields *pModifyProfileFields)
+{
+
+ if(!pModifyProfileFields)
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+
+ palCopyMemory( pMac->hHdd, pModifyProfileFields,
+ &pMac->roam.roamSession[sessionId].connectedProfile.modifyProfileFields,
+ sizeof(tCsrRoamModifyProfileFields) );
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+eHalStatus csrSetModifyProfileFields(tpAniSirGlobal pMac, tANI_U32 sessionId,
+ tCsrRoamModifyProfileFields *pModifyProfileFields)
+{
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ palCopyMemory( pMac->hHdd, &pSession->connectedProfile.modifyProfileFields,
+ pModifyProfileFields,
+ sizeof(tCsrRoamModifyProfileFields) );
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+#if 0
+/* ---------------------------------------------------------------------------
+ \fn csrGetSupportedCountryCode
+ \brief this function is to get a list of the country code current being supported
+ \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return,
+ this has the country code list. 3 bytes for each country code. This may be NULL if
+ caller wants to know the needed bytes.
+ \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return,
+ this contains the length of the data in pBuf
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrGetSupportedCountryCode(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U32 *pbLen)
+{
+ tANI_U32 numOfCountry = sizeof( gCsrCountryInfo ) / sizeof( gCsrCountryInfo[0] );
+ tANI_U32 numBytes = 0;
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+
+ if( pbLen )
+ {
+ numBytes = *pbLen;
+ //Consider it ok, at least we can return the number of bytes needed;
+ *pbLen = numOfCountry * WNI_CFG_COUNTRY_CODE_LEN;
+ status = eHAL_STATUS_SUCCESS;
+ if( pBuf && ( numBytes >= *pbLen ) )
+ {
+ //The ugly part starts.
+ //We may need to alter the data structure and find a way to make this faster.
+ tANI_U32 i;
+
+ for( i = 0; i < numOfCountry; i++ )
+ {
+ palCopyMemory( pMac->hHdd, pBuf + ( i * WNI_CFG_COUNTRY_CODE_LEN ),
+ gCsrCountryInfo[i].countryCode, WNI_CFG_COUNTRY_CODE_LEN );
+ }
+ }
+ }
+
+ return ( status );
+}
+#endif
+
+/* ---------------------------------------------------------------------------
+ \fn csrGetSupportedCountryCode
+ \brief this function is to get a list of the country code current being supported
+ \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return,
+ this has the country code list. 3 bytes for each country code. This may be NULL if
+ caller wants to know the needed bytes.
+ \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return,
+ this contains the length of the data in pBuf
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus csrGetSupportedCountryCode(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U32 *pbLen)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vosStatus;
+ v_SIZE_t size = (v_SIZE_t)*pbLen;
+
+ vosStatus = vos_nv_getSupportedCountryCode( pBuf, &size, 1 );
+ //eiter way, return the value back
+ *pbLen = (tANI_U32)size;
+
+ //If pBuf is NULL, caller just want to get the size, consider it success
+ if(pBuf)
+ {
+ if( VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ tANI_U32 i, n = *pbLen / 3;
+
+ for( i = 0; i < n; i++ )
+ {
+ pBuf[i*3 + 2] = ' ';
+ }
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ }
+
+ return (status);
+}
+
+
+
+//Upper layer to get the list of the base channels to scan for passively 11d info from csr
+eHalStatus csrScanGetBaseChannels( tpAniSirGlobal pMac, tCsrChannelInfo * pChannelInfo )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+
+ do
+ {
+
+ if(!pMac->scan.baseChannels.numChannels || !pChannelInfo)
+ {
+ break;
+ }
+ status = palAllocateMemory( pMac->hHdd, (void **)&pChannelInfo->ChannelList,
+ pMac->scan.baseChannels.numChannels );
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, FL("csrScanGetBaseChannels: fail to allocate memory\n") );
+ break;
+ }
+ status = palCopyMemory( pMac->hHdd, pChannelInfo->ChannelList, pMac->scan.baseChannels.channelList,
+ pMac->scan.baseChannels.numChannels );
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ break;
+ }
+ pChannelInfo->numOfChannels = pMac->scan.baseChannels.numChannels;
+
+ }while(0);
+
+ return ( status );
+}
+
+
+tANI_BOOLEAN csrIsSetKeyAllowed(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ tANI_BOOLEAN fRet = eANI_BOOLEAN_TRUE;
+#ifdef WLAN_SOFTAP_FEATURE
+ tCsrRoamSession *pSession;
+
+ pSession =CSR_GET_SESSION(pMac, sessionId);
+
+ /*This condition is not working for infra state. When infra is in not-connected state
+ * the pSession->pCurRoamProfile is NULL. And this function returns TRUE, that is incorrect.
+ * Since SAP requires to set key without any BSS started, it needs this condition to be met.
+ * In other words, this function is useless.
+ * The current work-around is to process setcontext_rsp and removekey_rsp no matter what the
+ * state is.
+ */
+ smsLog( pMac, LOGE, FL(" is not what it intends to. Must be revisit or removed\n") );
+ if( (NULL == pSession) ||
+ ( csrIsConnStateDisconnected( pMac, sessionId ) &&
+ (pSession->pCurRoamProfile != NULL) &&
+ (!(CSR_IS_INFRA_AP(pSession->pCurRoamProfile))) )
+ )
+ {
+ fRet = eANI_BOOLEAN_FALSE;
+ }
+#else
+ fRet = !( csrIsConnStateDisconnected( pMac, sessionId ) );
+#endif
+
+ return ( fRet );
+}
+
+//no need to acquire lock for this basic function
+tANI_U16 sme_ChnToFreq(tANI_U8 chanNum)
+{
+ int i;
+
+ for (i = 0; i < NUM_RF_CHANNELS; i++)
+ {
+ if (rfChannels[i].channelNum == chanNum)
+ {
+ return rfChannels[i].targetFreq;
+ }
+ }
+
+ return (0);
+}
+
+/* Disconnect all active sessions by sending disassoc. This is mainly used to disconnect the remaining session when we
+ * transition from concurrent sessions to a single session. The use case is Infra STA and wifi direct multiple sessions are up and
+ * P2P session is removed. The Infra STA session remains and should resume BMPS if BMPS is enabled by default. However, there
+ * are some issues seen with BMPS resume during this transition and this is a workaround which will allow the Infra STA session to
+ * disconnect and auto connect back and enter BMPS this giving the same effect as resuming BMPS
+ */
+void csrDisconnectAllActiveSessions(tpAniSirGlobal pMac)
+{
+ tANI_U8 i;
+
+ /* Disconnect all the active sessions */
+ for (i=0; i<CSR_ROAM_SESSION_MAX; i++)
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) && !csrIsConnStateDisconnected( pMac, i ) )
+ {
+ csrRoamDisconnectInternal(pMac, i, eCSR_DISCONNECT_REASON_UNSPECIFIED);
+ }
+ }
+}
diff --git a/CORE/SME/src/meas/measApi.c b/CORE/SME/src/meas/measApi.c
new file mode 100644
index 0000000..1e9b029
--- /dev/null
+++ b/CORE/SME/src/meas/measApi.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
diff --git a/CORE/SME/src/p2p/p2p_Api.c b/CORE/SME/src/p2p/p2p_Api.c
new file mode 100644
index 0000000..057f013
--- /dev/null
+++ b/CORE/SME/src/p2p/p2p_Api.c
@@ -0,0 +1,2243 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/*
+ * Copyright (c) 2008 QUALCOMM Incorporated. All Rights Reserved.
+ * Qualcomm Confidential and Proprietary
+ */
+
+#if defined WLAN_FEATURE_P2P
+
+#include "sme_Api.h"
+#include "smsDebug.h"
+#include "csrInsideApi.h"
+#include "smeInside.h"
+#include "p2p_Api.h"
+#include "limApi.h"
+#include "cfgApi.h"
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+#include "p2p_ie.h"
+#include "p2pFsm.h"
+
+extern tp2pie gP2PIe;
+
+static eHalStatus p2pSendActionFrame(tpAniSirGlobal pMac, tANI_U8 SessionID, eP2PFrameType actionFrameType);
+static eHalStatus p2pListenStateDiscoverableCallback(tHalHandle halHandle, void *pContext, eHalStatus retStatus);
+static eHalStatus p2pRemainOnChannelReadyCallback(tHalHandle halHandle, void *pContext, eHalStatus scan_status);
+static tANI_BOOLEAN p2pIsGOportEnabled(tpAniSirGlobal pMac);
+#endif
+
+eHalStatus p2pProcessNoAReq(tpAniSirGlobal pMac, tSmeCmd *pNoACmd);
+/*------------------------------------------------------------------
+ *
+ * handle SME remain on channel request.
+ *
+ *------------------------------------------------------------------*/
+
+eHalStatus p2pProcessRemainOnChannelCmd(tpAniSirGlobal pMac, tSmeCmd *p2pRemainonChn)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirRemainOnChnReq* pMsg;
+ tANI_U16 len;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, p2pRemainonChn->sessionId );
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ tANI_U8 P2PsessionId = getP2PSessionIdFromSMESessionId(pMac, p2pRemainonChn->sessionId);
+ tp2pContext *p2pContext = &pMac->p2pContext[P2PsessionId];
+ tANI_U32 ieLen = 0;
+#endif
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ if( !pSession->sessionActive || (CSR_SESSION_ID_INVALID == P2PsessionId))
+ {
+ smsLog(pMac, LOGE, FL(" session %d (P2P session %d) is invalid or listen is disabled "),
+ p2pRemainonChn->sessionId, P2PsessionId);
+ return eHAL_STATUS_FAILURE;
+ }
+#else
+ if(!pSession->sessionActive)
+ {
+ smsLog(pMac, LOGE, FL(" session %d is invalid or listen is disabled "),
+ p2pRemainonChn->sessionId);
+ return eHAL_STATUS_FAILURE;
+ }
+#endif
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ P2P_GetIE(p2pContext,
+ p2pContext->sessionId, eP2P_PROBE_RSP,
+ &p2pContext->probeRspIe, &ieLen);
+ p2pContext->probeRspIeLength = ieLen;
+ len = sizeof(tSirRemainOnChnReq) + ieLen;
+#else
+ len = sizeof(tSirRemainOnChnReq) + pMac->p2pContext.probeRspIeLength;
+#endif
+
+ status = palAllocateMemory(pMac->hHdd, (void**)&pMsg, len );
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s call\n", __FUNCTION__);
+ palZeroMemory(pMac->hHdd, pMsg, sizeof(tSirRemainOnChnReq));
+ pMsg->messageType = eWNI_SME_REMAIN_ON_CHANNEL_REQ;
+ pMsg->length = len;
+ palCopyMemory( pMac, pMsg->selfMacAddr, pSession->selfMacAddr, sizeof(tSirMacAddr) );
+ pMsg->chnNum = p2pRemainonChn->u.remainChlCmd.chn;
+ pMsg->phyMode = p2pRemainonChn->u.remainChlCmd.phyMode;
+ pMsg->duration = p2pRemainonChn->u.remainChlCmd.duration;
+ pMsg->sessionId = p2pRemainonChn->sessionId;
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ pMsg->sessionId = pSession->sessionId;
+ if( p2pContext->probeRspIeLength )
+ {
+ palCopyMemory(pMac->hHdd, (void *)pMsg->probeRspIe,
+ (void *)p2pContext->probeRspIe,
+ p2pContext->probeRspIeLength);
+ }
+#else
+ if( pMac->p2pContext.probeRspIeLength )
+ palCopyMemory(pMac->hHdd, (void *)pMsg->probeRspIe, (void *)pMac->p2pContext.probeRspIe, pMac->p2pContext.probeRspIeLength);
+#endif
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+
+ return status;
+}
+
+
+/*------------------------------------------------------------------
+ *
+ * handle LIM remain on channel rsp: Success/failure.
+ *
+ *------------------------------------------------------------------*/
+
+eHalStatus sme_remainOnChnRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tListElem *pEntry = NULL;
+ tSmeCmd *pCommand = NULL;
+
+ pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
+ if( pEntry )
+ {
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ if( eSmeCommandRemainOnChannel == pCommand->command )
+ {
+ remainOnChanCallback callback = pCommand->u.remainChlCmd.callback;
+ /* process the msg */
+ if( callback )
+ callback(pMac, pCommand->u.remainChlCmd.callbackCtx, 0);
+
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
+ {
+ //Now put this command back on the avilable command list
+ smeReleaseCommand(pMac, pCommand);
+ }
+ smeProcessPendingQueue( pMac );
+ }
+ }
+ return status;
+}
+
+
+/*------------------------------------------------------------------
+ *
+ * Handle the Mgmt frm ind from LIM and forward to HDD.
+ *
+ *------------------------------------------------------------------*/
+
+eHalStatus sme_mgmtFrmInd( tHalHandle hHal, tpSirSmeMgmtFrameInd pSmeMgmtFrm)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tCsrRoamInfo pRoamInfo = {0};
+#ifndef WLAN_FEATURE_P2P_INTERNAL
+ tANI_U32 SessionId = pSmeMgmtFrm->sessionId;
+#endif
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ tANI_U8 i;
+
+ //For now, only action frames are needed.
+ if(SIR_MAC_MGMT_ACTION == pSmeMgmtFrm->frameType)
+ {
+ pRoamInfo.nFrameLength = pSmeMgmtFrm->mesgLen - sizeof(tSirSmeMgmtFrameInd);
+ pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf;
+ pRoamInfo.frameType = pSmeMgmtFrm->frameType;
+ pRoamInfo.rxChan = pSmeMgmtFrm->rxChan;
+
+ //Somehow we don't get the right sessionId.
+ for(i = 0; i < CSR_ROAM_SESSION_MAX; i++)
+ {
+ if( CSR_IS_SESSION_VALID( pMac, i ) )
+ {
+ status = eHAL_STATUS_SUCCESS;
+ /* forward the mgmt frame to all active sessions*/
+ csrRoamCallCallback(pMac, i, &pRoamInfo, 0, eCSR_ROAM_INDICATE_MGMT_FRAME, 0);
+ }
+ }
+ }
+#else
+ pRoamInfo.nFrameLength = pSmeMgmtFrm->mesgLen - sizeof(tSirSmeMgmtFrameInd);
+ pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf;
+ pRoamInfo.frameType = pSmeMgmtFrm->frameType;
+ pRoamInfo.rxChan = pSmeMgmtFrm->rxChan;
+
+ /* forward the mgmt frame to HDD */
+ csrRoamCallCallback(pMac, SessionId, &pRoamInfo, 0, eCSR_ROAM_INDICATE_MGMT_FRAME, 0);
+#endif
+
+ return status;
+}
+
+
+/*------------------------------------------------------------------
+ *
+ * Handle the remain on channel ready indication from PE
+ *
+ *------------------------------------------------------------------*/
+
+eHalStatus sme_remainOnChnReady( tHalHandle hHal, tANI_U8* pMsg)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tListElem *pEntry = NULL;
+ tSmeCmd *pCommand = NULL;
+ tCsrRoamInfo RoamInfo;
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ tSirSmeRsp *pRsp = (tSirSmeRsp *)pMsg;
+ //pRsp->sessionId is SME's session index
+ tANI_U8 P2PSessionID = getP2PSessionIdFromSMESessionId(pMac, pRsp->sessionId);
+
+ if(CSR_SESSION_ID_INVALID == P2PSessionID)
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+#endif
+
+ pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
+ if( pEntry )
+ {
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+ if( eSmeCommandRemainOnChannel == pCommand->command )
+ {
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ if (pMac->p2pContext[P2PSessionID].PeerFound)
+ {
+ p2pRemainOnChannelReadyCallback(pMac, &pMac->p2pContext[P2PSessionID], eHAL_STATUS_SUCCESS);
+ }
+#else
+ /* forward the indication to HDD */
+ RoamInfo.pRemainCtx = pCommand->u.remainChlCmd.callbackCtx;
+ csrRoamCallCallback(pMac, ((tSirSmeRsp*)pMsg)->sessionId, &RoamInfo,
+ 0, eCSR_ROAM_REMAIN_CHAN_READY, 0);
+#endif
+ }
+ }
+
+ return status;
+}
+
+
+eHalStatus sme_sendActionCnf( tHalHandle hHal, tANI_U8* pMsg)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tCsrRoamInfo RoamInfo;
+ tSirSmeRsp* pSmeRsp = (tSirSmeRsp*)pMsg;
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ tSirResultCodes rspStatus = pSmeRsp->statusCode;
+ tANI_U8 HDDsessionId = getP2PSessionIdFromSMESessionId(pMac, pSmeRsp->sessionId);
+ tANI_U8 *pBuf = NULL;
+ tp2pContext *pP2pContext;
+
+ if(CSR_SESSION_ID_INVALID == HDDsessionId)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ " %s fail to get HDD sessionID (SMESessionID %d)", __FUNCTION__, pSmeRsp->sessionId);
+ return eHAL_STATUS_INVALID_PARAMETER;
+ }
+
+ pP2pContext = &pMac->p2pContext[HDDsessionId];
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s status %d Action Frame %d actionFrameTimeout %d\n",
+ __FUNCTION__, pSmeRsp->statusCode, pP2pContext->actionFrameType
+ , pP2pContext->actionFrameTimeout);
+ vos_mem_zero(&RoamInfo, sizeof(tCsrRoamInfo));
+
+ if (pSmeRsp->statusCode != eSIR_SME_SUCCESS && !pP2pContext->actionFrameTimeout
+ && pP2pContext->pSentActionFrame)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s Action frame:Ack not received. Retransmitting\n", __FUNCTION__);
+
+ if(NULL == pP2pContext->pNextActionFrm)
+ {
+ status = palTimerStart(pMac->hHdd, pP2pContext->retryActionFrameTimer,
+ ACTION_FRAME_RETRY_TIMEOUT * PAL_TIMER_TO_MS_UNIT, eANI_BOOLEAN_FALSE);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, " %s fail to start retryActionFrameTimerHandler\n",
+ __FUNCTION__, pP2pContext->NextActionFrameType);
+ }
+ return status;
+ }
+ //In case if there is new frame to send, finish the current frame
+ else
+ {
+ smsLog(pMac, LOGE, " %s send next action frame type %d Last frame status (%d)",
+ __FUNCTION__, rspStatus);
+ //Force it to be success
+ rspStatus = eSIR_SME_SUCCESS;
+ }
+ }
+
+ if (pP2pContext->actionFrameTimer)
+ {
+ status = palTimerStop(pMac, pP2pContext->actionFrameTimer);
+ }
+
+ if (pP2pContext->retryActionFrameTimer)
+ {
+ status = palTimerStop(pMac, pP2pContext->retryActionFrameTimer);
+ }
+
+ if(pP2pContext->pSentActionFrame)
+ {
+ csrRoamCallCallback((tpAniSirGlobal)pP2pContext->hHal,
+ pP2pContext->SMEsessionId, &RoamInfo, 0,
+ eCSR_ROAM_SEND_ACTION_CNF,
+ ((rspStatus == eSIR_SME_SUCCESS) ?
+ eCSR_ROAM_RESULT_NONE: eCSR_ROAM_RESULT_SEND_ACTION_FAIL));
+ }
+
+ if(VOS_IS_STATUS_SUCCESS(vos_spin_lock_acquire(&pP2pContext->lState)))
+ {
+ if(pP2pContext->pSentActionFrame)
+ {
+ pBuf = pP2pContext->pSentActionFrame;
+ pP2pContext->pSentActionFrame = NULL;
+ }
+ vos_spin_lock_release(&pP2pContext->lState);
+
+ if(NULL != pBuf)
+ {
+ vos_mem_free(pBuf);
+ pBuf = NULL;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, "%s pSentActionFrame is null \n", __FUNCTION__);
+ }
+ if(pP2pContext->pNextActionFrm)
+ {
+ //need to send the next action frame
+ pP2pContext->pSentActionFrame = pP2pContext->pNextActionFrm;
+ pP2pContext->ActionFrameLen = pP2pContext->nNextFrmLen;
+ pP2pContext->actionFrameType = pP2pContext->NextActionFrameType;
+ pP2pContext->pNextActionFrm = NULL;
+ pP2pContext->ActionFrameSendTimeout = pP2pContext->nNextFrameTimeOut;
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s cannot get lock1", __FUNCTION__);
+ }
+
+ if(NULL != pP2pContext->pSentActionFrame)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, " sending next frame %d type\n",
+ pP2pContext->NextActionFrameType);
+ status = palTimerStart(pMac->hHdd, pP2pContext->actionFrameTimer,
+ pP2pContext->ActionFrameSendTimeout * PAL_TIMER_TO_MS_UNIT, eANI_BOOLEAN_FALSE);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL(" %s fail to start timer status %d"), __FUNCTION__, status);
+ //Without the timer we cannot continue
+ csrRoamCallCallback((tpAniSirGlobal)pP2pContext->hHal,
+ pP2pContext->SMEsessionId, &RoamInfo, 0,
+ eCSR_ROAM_SEND_ACTION_CNF,
+ eCSR_ROAM_RESULT_SEND_ACTION_FAIL);
+ vos_spin_lock_acquire(&pP2pContext->lState);
+ pBuf = pP2pContext->pSentActionFrame;
+ pP2pContext->pSentActionFrame = NULL;
+ vos_spin_lock_release(&pP2pContext->lState);
+ vos_mem_free(pBuf);
+ pBuf = NULL;
+ p2pFsm(pP2pContext, eP2P_TRIGGER_DISCONNECTED);
+ return status;
+ }
+ status = p2pSendActionFrame(pMac, pP2pContext->sessionId, pP2pContext->actionFrameType);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, " sending next frame %d type\n",
+ pP2pContext->NextActionFrameType);
+ status = palTimerStart(pMac->hHdd, pP2pContext->retryActionFrameTimer,
+ ACTION_FRAME_RETRY_TIMEOUT * PAL_TIMER_TO_MS_UNIT, eANI_BOOLEAN_FALSE);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, " %s fail to start retryActionFrameTimerHandler\n", __FUNCTION__);
+ }
+ }
+ }
+ else
+ {
+ p2pFsm(pP2pContext, eP2P_TRIGGER_DISCONNECTED);
+ }
+
+#else
+ /* forward the indication to HDD */
+ //RoamInfo can be passed as NULL....todo
+ csrRoamCallCallback(pMac, pSmeRsp->sessionId, &RoamInfo, 0,
+ eCSR_ROAM_SEND_ACTION_CNF,
+ (pSmeRsp->statusCode == eSIR_SME_SUCCESS) ? 0:
+ eCSR_ROAM_RESULT_SEND_ACTION_FAIL);
+#endif
+ return status;
+}
+
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+void p2pResetContext(tp2pContext *pP2pContext)
+{
+ if(NULL != pP2pContext)
+ {
+ tpAniSirGlobal pMac = PMAC_STRUCT(pP2pContext->hHal);
+ int i;
+
+ //When it is resetting a GO or client session, we
+ //need to reset the group capability back to the original one
+ if( (OPERATION_MODE_P2P_GROUP_OWNER == pP2pContext->operatingmode) ||
+ (OPERATION_MODE_P2P_CLIENT == pP2pContext->operatingmode) )
+ {
+ for( i = 0; i < MAX_NO_OF_P2P_SESSIONS; i++ )
+ {
+ if(OPERATION_MODE_P2P_DEVICE == pMac->p2pContext[i].operatingmode)
+ {
+ gP2PIe[i].p2pCapabilityAttrib.groupCapability = pMac->p2pContext[i].OriginalGroupCapability;
+ }
+ }
+ }
+
+ pP2pContext->state = eP2P_STATE_DISCONNECTED;
+ pP2pContext->currentSearchIndex = 0;
+ pP2pContext->listenIndex = 1;
+
+ pP2pContext->actionFrameType = eP2P_INVALID_FRM;
+
+ pP2pContext->dialogToken = 0;
+ pP2pContext->PeerFound = FALSE;
+ pP2pContext->GroupFormationPending = FALSE;
+ pP2pContext->directedDiscovery = FALSE;
+ pP2pContext->listenDiscoverableState = eStateDisabled;
+
+
+ if(pP2pContext->pSentActionFrame)
+ {
+ vos_mem_free(pP2pContext->pSentActionFrame);
+ pP2pContext->pSentActionFrame = NULL;
+ }
+ if(pP2pContext->pNextActionFrm)
+ {
+ vos_mem_free(pP2pContext->pSentActionFrame);
+ pP2pContext->pSentActionFrame = NULL;
+ }
+ if( pP2pContext->probeRspIe )
+ {
+ vos_mem_free( pP2pContext->probeRspIe );
+ pP2pContext->probeRspIe = NULL;
+ pP2pContext->probeRspIeLength = 0;
+ }
+
+ if( pP2pContext->DiscoverReqIeField )
+ {
+ vos_mem_free(pP2pContext->DiscoverReqIeField );
+ pP2pContext->DiscoverReqIeField = NULL;
+ pP2pContext->DiscoverReqIeLength = 0;
+ }
+
+ if( pP2pContext->GoNegoCnfIeField )
+ {
+ vos_mem_free( pP2pContext->GoNegoCnfIeField);
+ pP2pContext->GoNegoCnfIeField = NULL;
+ pP2pContext->GoNegoCnfIeLength = 0;
+ }
+
+ if( pP2pContext->GoNegoReqIeField )
+ {
+ vos_mem_free( pP2pContext->GoNegoReqIeField );
+ pP2pContext->GoNegoReqIeField = NULL;
+ pP2pContext->GoNegoReqIeLength = 0;
+ }
+
+ if( pP2pContext->GoNegoResIeField )
+ {
+ vos_mem_free( pP2pContext->GoNegoResIeField );
+ pP2pContext->GoNegoResIeField = NULL;
+ pP2pContext->GoNegoResIeLength = 0;
+ }
+
+ if( pP2pContext->ProvDiscReqIeField )
+ {
+ vos_mem_free( pP2pContext->ProvDiscReqIeField );
+ pP2pContext->ProvDiscReqIeField = NULL;
+ pP2pContext->ProvDiscReqIeLength = 0;
+ }
+
+ if( pP2pContext->ProvDiscResIeField )
+ {
+ vos_mem_free( pP2pContext->ProvDiscResIeField );
+ pP2pContext->ProvDiscResIeLength = 0;
+ pP2pContext->ProvDiscResIeField = NULL;
+ }
+
+ if (pP2pContext->actionFrameTimer)
+ {
+ palTimerStop(pMac->hHdd, pP2pContext->actionFrameTimer);
+ }
+
+ if (pP2pContext->discoverTimer)
+ {
+ palTimerStop(pMac->hHdd, pP2pContext->discoverTimer);
+ }
+
+ if (pP2pContext->listenTimerHandler)
+ {
+ palTimerStop(pMac->hHdd, pP2pContext->listenTimerHandler);
+ }
+
+ if (pP2pContext->WPSRegistrarCheckTimerHandler)
+ {
+ palTimerStop(pMac->hHdd, pP2pContext->WPSRegistrarCheckTimerHandler);
+ }
+
+ if (pP2pContext->directedDiscoveryFilter)
+ {
+ pP2pContext->uNumDeviceFilterAllocated = 0;
+ vos_mem_free(pP2pContext->directedDiscoveryFilter);
+ pP2pContext->directedDiscoveryFilter = NULL;
+ }
+
+ vos_mem_zero(pP2pContext->peerMacAddress, P2P_MAC_ADDRESS_LEN);
+ }
+}
+#endif
+
+
+eHalStatus sme_p2pOpen( tHalHandle hHal )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ int i;
+ tp2pContext *pP2pContext;
+
+ for ( i=0; i < MAX_NO_OF_P2P_SESSIONS; i++ )
+ {
+ pP2pContext = &pMac->p2pContext[i];
+ pP2pContext->hHal = hHal;
+
+ pP2pContext->socialChannel[0] = 1;
+ pP2pContext->socialChannel[1] = 6;
+ pP2pContext->socialChannel[2] = 11;
+
+ vos_spin_lock_init(&pP2pContext->lState);
+
+ p2pResetContext(pP2pContext);
+
+ status = palTimerAlloc(pMac->hHdd, &pP2pContext->actionFrameTimer,
+ p2pActionFrameTimerHandler, pP2pContext);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, " %s fail to alloc actionFrame timer for session %d\n", __FUNCTION__, i);
+ break;
+ }
+ status = palTimerAlloc(pMac->hHdd, &pP2pContext->listenTimerHandler,
+ p2pListenDiscoverTimerHandler, pP2pContext);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, " %s fail to alloc listen timer for session %d\n", __FUNCTION__, i);
+ break;
+ }
+ status = palTimerAlloc(pMac->hHdd, &pP2pContext->discoverTimer, p2pDiscoverTimerHandler, pP2pContext);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, " %s fail to alloc discover timer for session %d\n", __FUNCTION__, i);
+ break;
+ }
+
+ status = palTimerAlloc(pMac->hHdd, &pP2pContext->retryActionFrameTimer,
+ p2pRetryActionFrameTimerHandler, pP2pContext);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, " %s fail to alloc retryActionFrameTimerHandler timer for session %d\n", __FUNCTION__, i);
+ break;
+ }
+
+ p2pCreateDefaultIEs(hHal, i);
+ }
+#else
+ //If static structure is too big, Need to change this function to allocate memory dynamically
+ vos_mem_zero( &pMac->p2pContext, sizeof( tp2pContext ) );
+#endif
+
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ sme_p2pClose(hHal);
+ }
+
+ return status;
+}
+
+
+eHalStatus p2pStop( tHalHandle hHal )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ int i;
+
+ for ( i = 0; i < MAX_NO_OF_P2P_SESSIONS; i++ )
+ {
+ p2pCloseSession(pMac, i);
+ }
+#else
+ if( pMac->p2pContext.probeRspIe )
+ {
+ vos_mem_free( pMac->p2pContext.probeRspIe );
+ pMac->p2pContext.probeRspIe = NULL;
+ }
+
+ pMac->p2pContext.probeRspIeLength = 0;
+#endif
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+eHalStatus sme_p2pClose( tHalHandle hHal )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ tp2pContext *pContext;
+ int i;
+
+ p2pStop(hHal);
+
+ for ( i = 0; i < MAX_NO_OF_P2P_SESSIONS; i++ )
+ {
+ p2pCloseSession(pMac, i);
+ pContext = &pMac->p2pContext[i];
+ if (pContext->actionFrameTimer)
+ {
+ palTimerFree(hHal, pContext->actionFrameTimer);
+ pContext->actionFrameTimer = NULL;
+ }
+
+ if (pContext->discoverTimer)
+ {
+ palTimerFree(hHal, pContext->discoverTimer);
+ pContext->discoverTimer = NULL;
+ }
+
+ if (pContext->listenTimerHandler)
+ {
+ palTimerFree(hHal, pContext->listenTimerHandler);
+ pContext->listenTimerHandler = NULL;
+ }
+
+ if (pContext->WPSRegistrarCheckTimerHandler)
+ {
+ palTimerFree(hHal, pContext->WPSRegistrarCheckTimerHandler);
+ pContext->WPSRegistrarCheckTimerHandler = NULL;
+ }
+
+ vos_spin_lock_destroy(&pContext->lState);
+ }
+#else
+ if( pMac->p2pContext.probeRspIe )
+ {
+ vos_mem_free( pMac->p2pContext.probeRspIe );
+ pMac->p2pContext.probeRspIe = NULL;
+ }
+
+ pMac->p2pContext.probeRspIeLength = 0;
+#endif
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+tSirRFBand GetRFBand(tANI_U8 channel)
+{
+ if ((channel >= SIR_11A_CHANNEL_BEGIN) &&
+ (channel <= SIR_11A_CHANNEL_END))
+ return SIR_BAND_5_GHZ;
+
+ if ((channel >= SIR_11B_CHANNEL_BEGIN) &&
+ (channel <= SIR_11B_CHANNEL_END))
+ return SIR_BAND_2_4_GHZ;
+
+ return SIR_BAND_UNKNOWN;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn p2pRemainOnChannel
+ \brief API to post the remain on channel command.
+ \param hHal - The handle returned by macOpen.
+ \param sessinId - HDD session ID.
+ \param channel - Channel to remain on channel.
+ \param duration - Duration for which we should remain on channel
+ \param callback - callback function.
+ \param pContext - argument to the callback function
+ \return eHalStatus
+
+ -------------------------------------------------------------------------------*/
+eHalStatus p2pRemainOnChannel(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U8 channel, tANI_U32 duration,
+ remainOnChanCallback callback,
+ void *pContext
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ , eP2PRemainOnChnReason reason
+#endif
+ )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tSmeCmd *pRemainChlCmd = NULL;
+ tANI_U32 phyMode;
+
+ pRemainChlCmd = smeGetCommandBuffer(pMac);
+ if(pRemainChlCmd == NULL)
+ return eHAL_STATUS_FAILURE;
+
+ if (SIR_BAND_5_GHZ == GetRFBand(channel))
+ {
+ phyMode = WNI_CFG_PHY_MODE_11A;
+ }
+ else
+ {
+ phyMode = WNI_CFG_PHY_MODE_11G;
+ }
+
+ cfgSetInt(pMac, WNI_CFG_PHY_MODE, phyMode);
+
+ do
+ {
+ /* call set in context */
+ pRemainChlCmd->command = eSmeCommandRemainOnChannel;
+ pRemainChlCmd->sessionId = sessionId;
+ pRemainChlCmd->u.remainChlCmd.chn = channel;
+ pRemainChlCmd->u.remainChlCmd.duration = duration;
+ pRemainChlCmd->u.remainChlCmd.callback = callback;
+ pRemainChlCmd->u.remainChlCmd.callbackCtx = pContext;
+
+ //Put it at the head of the Q if we just finish finding the peer and ready to send a frame
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ smePushCommand(pMac, pRemainChlCmd, (eP2PRemainOnChnReasonSendFrame == reason));
+#else
+ csrQueueSmeCommand(pMac, pRemainChlCmd, eANI_BOOLEAN_FALSE);
+#endif
+ } while(0);
+
+ smsLog(pMac, LOGW, "exiting function %s\n", __FUNCTION__);
+
+ return(status);
+}
+
+eHalStatus p2pSendAction(tHalHandle hHal, tANI_U8 sessionId,
+ const tANI_U8 *pBuf, tANI_U32 len)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tSirMbMsgP2p *pMsg;
+ tANI_U16 msgLen;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ " %s sends action frame", __FUNCTION__);
+ msgLen = (tANI_U16)((sizeof( tSirMbMsg )) + len);
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, (void *)pMsg, msgLen);
+ pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_SEND_ACTION_FRAME_IND);
+ pMsg->msgLen = pal_cpu_to_be16(msgLen);
+ pMsg->sessionId = sessionId;
+ palCopyMemory( pMac->hHdd, pMsg->data, pBuf, len );
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+
+ return( status );
+}
+
+eHalStatus p2pCancelRemainOnChannel(tHalHandle hHal, tANI_U8 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tSirMbMsg *pMsg;
+ tANI_U16 msgLen;
+
+ //Need to check session ID to support concurrency
+
+ msgLen = (tANI_U16)(sizeof( tSirMbMsg ));
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, (void *)pMsg, msgLen);
+ pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_ABORT_REMAIN_ON_CHAN_IND);
+ pMsg->msgLen = pal_cpu_to_be16(msgLen);
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+
+ return( status );
+}
+
+eHalStatus p2pSetPs(tHalHandle hHal, tP2pPsConfig *pNoA)
+{
+ tpP2pPsConfig pNoAParam;
+ tSirMsgQ msg;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = palAllocateMemory(pMac->hHdd, (void**)&pNoAParam, sizeof(tP2pPsConfig));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pNoAParam, sizeof(tP2pPsConfig));
+ palCopyMemory(pMac->hHdd, pNoAParam, pNoA, sizeof(tP2pPsConfig));
+ msg.type = eWNI_SME_UPDATE_NOA;
+ msg.bodyval = 0;
+ msg.bodyptr = pNoAParam;
+ limPostMsgApi(pMac, &msg);
+ }
+ return status;
+}
+
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+eHalStatus p2pGetConfigParam(tHalHandle hHal, tP2PConfigParam *pParam)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ if(pParam)
+ {
+ pParam->P2PListenChannel = pMac->p2pContext[0].P2PListenChannel;
+ pParam->P2POperatingChannel = pMac->p2pContext[0].P2POperatingChannel;
+ pParam->P2POpPSCTWindow = pMac->p2pContext[0].pNoA.ctWindow;
+ pParam->P2PPSSelection = pMac->p2pContext[0].pNoA.psSelection;
+ pParam->P2POpPSCTWindow = pMac->p2pContext[0].pNoA.ctWindow;
+ pParam->P2PNoADuration = pMac->p2pContext[0].pNoA.duration;
+ pParam->P2PNoACount = pMac->p2pContext[0].pNoA.count;
+ pParam->P2PNoAInterval = pMac->p2pContext[0].pNoA.interval;
+
+ status = eHAL_STATUS_SUCCESS;
+ }
+
+ return (status);
+}
+
+eHalStatus p2pChangeDefaultConfigParam(tHalHandle hHal, tP2PConfigParam *pParam)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ int i;
+ tANI_U8 pBuf[P2P_COUNTRY_CODE_LEN];
+ tANI_U8 uBufLen = P2P_COUNTRY_CODE_LEN;
+ tP2P_OperatingChannel p2pChannel;
+
+ status = sme_GetCountryCode( pMac, pBuf, &uBufLen );
+ if ( !HAL_STATUS_SUCCESS( status ) )
+ {
+ status = eHAL_STATUS_FAILURE;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s Cannot get the country code\n", __FUNCTION__);
+ }
+
+ vos_mem_copy(p2pChannel.countryString, pBuf, sizeof(pBuf));
+ p2pChannel.regulatoryClass = 0x51;
+
+ if(pParam)
+ {
+ for ( i=0; i < MAX_NO_OF_P2P_SESSIONS; i++ )
+ {
+ if (pParam->P2PListenChannel == 1 || pParam->P2PListenChannel == 6
+ || pParam->P2PListenChannel == 11)
+ {
+ pMac->p2pContext[i].P2PListenChannel = pParam->P2PListenChannel;
+ }
+ else
+ {
+ pMac->p2pContext[i].P2PListenChannel = P2P_OPERATING_CHANNEL;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Invalid P2P Listen Channel in config. Switch to default Listen Channel %d\n",
+ __FUNCTION__, P2P_OPERATING_CHANNEL);
+ }
+
+ if(csrRoamIsChannelValid(pMac, pParam->P2POperatingChannel))
+ {
+ pMac->p2pContext[i].P2POperatingChannel = pParam->P2POperatingChannel;
+ }
+ else
+ {
+ pMac->p2pContext[i].P2POperatingChannel = P2P_OPERATING_CHANNEL;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Invalid P2P Operating Channel in config. Switch to default Channel %d\n",
+ __FUNCTION__, P2P_OPERATING_CHANNEL);
+ }
+ pMac->p2pContext[i].pNoA.ctWindow = pParam->P2POpPSCTWindow;
+ pMac->p2pContext[i].pNoA.psSelection = pParam->P2PPSSelection;
+ pMac->p2pContext[i].pNoA.ctWindow = pParam->P2POpPSCTWindow;
+ pMac->p2pContext[i].pNoA.duration = pParam->P2PNoADuration;
+ pMac->p2pContext[i].pNoA.count = pParam->P2PNoACount;
+ pMac->p2pContext[i].pNoA.interval = pParam->P2PNoAInterval;
+
+ p2pChannel.channel = pMac->p2pContext[i].P2POperatingChannel;
+ P2P_UpdateIE(pMac, i, eWFD_OPERATING_CHANNEL, &p2pChannel, 1);
+ p2pChannel.channel = pMac->p2pContext[i].P2PListenChannel;
+ P2P_UpdateIE(pMac, i, eWFD_LISTEN_CHANNEL, &p2pChannel, 1);
+ }
+ }
+
+ return status;
+}
+
+eHalStatus p2pPS(tHalHandle hHal, tANI_U8 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tP2pPsConfig pNoA;
+
+ /* call set in context */
+ pNoA.psSelection = pMac->p2pContext[sessionId].pNoA.psSelection;
+ pNoA.sessionid = sessionId;
+
+ if (pMac->p2pContext[sessionId].pNoA.psSelection == P2P_CLEAR_POWERSAVE)
+ {
+ return status;
+ }
+
+ if (pMac->p2pContext[sessionId].pNoA.psSelection == P2P_OPPORTUNISTIC_PS)
+ {
+ pNoA.opp_ps = TRUE;
+ pNoA.ctWindow = pMac->p2pContext[sessionId].pNoA.ctWindow;
+ pNoA.count = 0;
+ pNoA.duration = 0;
+ pNoA.interval = 0;
+ pNoA.single_noa_duration = 0;
+ }
+ else if (pMac->p2pContext[sessionId].pNoA.psSelection == P2P_PERIODIC_NOA)
+ {
+ pNoA.opp_ps = 0;
+ pNoA.ctWindow = 0;
+ pNoA.count = pMac->p2pContext[sessionId].pNoA.count;
+ pNoA.duration = pMac->p2pContext[sessionId].pNoA.duration;
+ pNoA.interval = pMac->p2pContext[sessionId].pNoA.interval;
+ pNoA.single_noa_duration = 0;
+ }
+ else if(pMac->p2pContext[sessionId].pNoA.psSelection == P2P_SINGLE_NOA)
+ {
+ pNoA.opp_ps = 0;
+ pNoA.ctWindow = 0;
+ pNoA.count = 0;
+ pNoA.duration = 0;
+ pNoA.interval = 0;
+ pNoA.single_noa_duration = pMac->p2pContext[sessionId].pNoA.duration;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ " %s HDDSession %d set NoA parameters. Selection %d, opp_ps %d, ctWindow %d, count %d, "
+ "duration %d, interval %d single NoA duration %d",
+ __FUNCTION__, sessionId, pMac->p2pContext[sessionId].pNoA.psSelection,
+ pNoA.opp_ps, pNoA.ctWindow, pNoA.count, pNoA.duration,
+ pNoA.interval, pNoA.single_noa_duration );
+
+ status = sme_p2pSetPs(pMac, &pNoA);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL(" sme_p2pSetPs fail with status %d"), status);
+ return status;
+ }
+
+ return status;
+}
+
+void P2P_UpdateMacHdr(tHalHandle hHal, tANI_U8 SessionID, tANI_U8 *pBuf)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tSirMacMgmtHdr *macHdr = (tSirMacMgmtHdr *)pBuf;
+
+ macHdr->fc.protVer = 0;
+ macHdr->fc.type = 0;
+ macHdr->fc.subType = 13;
+ macHdr->durationLo = 0;
+ macHdr->durationHi = 0;
+ vos_mem_copy(macHdr->da, pMac->p2pContext[SessionID].peerMacAddress, P2P_MAC_ADDRESS_LEN);
+ vos_mem_copy(macHdr->sa, pMac->p2pContext[SessionID].selfMacAddress, P2P_MAC_ADDRESS_LEN);
+ vos_mem_copy(macHdr->bssId, pMac->p2pContext[SessionID].peerMacAddress, P2P_MAC_ADDRESS_LEN);
+
+ return;
+}
+
+static eHalStatus p2pRemainOnChannelReadyCallback(tHalHandle halHandle,
+ void *pContext,
+ eHalStatus scan_status)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tp2pContext *p2pContext = (tp2pContext*) pContext;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s GroupFormationPending %d PeerFound %d\n",
+ __FUNCTION__, p2pContext->GroupFormationPending, p2pContext->PeerFound);
+
+ if (p2pContext->PeerFound)
+ {
+ p2pContext->PeerFound = FALSE;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s Sending actionframe\n", __FUNCTION__);
+ if (p2pContext->pSentActionFrame)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s calling p2pSendAction\n", __FUNCTION__);
+ p2pSendAction(halHandle, p2pContext->SMEsessionId, (tANI_U8 *)p2pContext->pSentActionFrame, p2pContext->ActionFrameLen);
+ }
+ }
+
+ return status;
+}
+
+eHalStatus p2pGrpFormationRemainOnChanRspCallback(tHalHandle halHandle, void *pContext, tANI_U32 scanId, eCsrScanStatus scan_status)
+{
+ return eHAL_STATUS_SUCCESS;
+}
+
+tANI_U8 p2pGetDialogToken(tHalHandle hHal, tANI_U8 SessionID, eP2PFrameType actionFrameType)
+{
+ tANI_U8 dialogToken = 0;
+
+ dialogToken = (tANI_U8) vos_timer_get_system_ticks();
+
+ return(dialogToken);
+}
+
+void p2pRetryActionFrameTimerHandler(void *pContext)
+{
+ tp2pContext *p2pContext = (tp2pContext*) pContext;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT( p2pContext->hHal );
+
+ p2pContext->PeerFound = TRUE;
+ smsLog( pMac, LOGE, "%s Calling remain on channel \n", __FUNCTION__);
+ status = p2pRemainOnChannel( pMac, p2pContext->SMEsessionId, p2pContext->P2PListenChannel/*pScanResult->BssDescriptor.channelId*/, P2P_REMAIN_ON_CHAN_TIMEOUT_LOW,
+ NULL, NULL, eP2PRemainOnChnReasonSendFrame);
+ if(status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog( pMac, LOGE, "%s remain on channel failed\n", __FUNCTION__);
+ }
+
+ return;
+}
+
+void p2pActionFrameTimerHandler(void *pContext)
+{
+ tp2pContext *p2pContext = (tp2pContext*) pContext;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_U8 *pBuf = NULL, *pNextBuf = NULL;
+ tCsrRoamInfo roamInfo;
+
+
+ if(p2pContext->pSentActionFrame)
+ {
+ vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo));
+ csrRoamCallCallback((tpAniSirGlobal)p2pContext->hHal, p2pContext->SMEsessionId, &roamInfo, 0,
+ eCSR_ROAM_SEND_ACTION_CNF,
+ eCSR_ROAM_RESULT_SEND_ACTION_FAIL);
+ }
+
+ if(VOS_IS_STATUS_SUCCESS(vos_spin_lock_acquire(&p2pContext->lState)))
+ {
+ if(p2pContext->pSentActionFrame)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ " %s actionframe timeout type %d", __FUNCTION__, p2pContext->actionFrameType);
+ pBuf = p2pContext->pSentActionFrame;
+ p2pContext->pSentActionFrame = NULL;
+ }
+ if(p2pContext->pNextActionFrm)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
+ " %s next actionframe timeout type %d", __FUNCTION__, p2pContext->NextActionFrameType);
+ pNextBuf = p2pContext->pNextActionFrm;
+ p2pContext->pNextActionFrm = NULL;
+ }
+ vos_spin_lock_release(&p2pContext->lState);
+
+ if(pBuf)
+ {
+ vos_mem_free(pBuf);
+ }
+ if(pNextBuf)
+ {
+ //Inform the failure of the next frame.
+ p2pContext->pSentActionFrame = pNextBuf;
+ p2pContext->ActionFrameLen = p2pContext->nNextFrmLen;
+ p2pContext->actionFrameType = p2pContext->NextActionFrameType;
+ vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo));
+ csrRoamCallCallback((tpAniSirGlobal)p2pContext->hHal, p2pContext->SMEsessionId, &roamInfo, 0,
+ eCSR_ROAM_SEND_ACTION_CNF,
+ eCSR_ROAM_RESULT_SEND_ACTION_FAIL);
+ p2pContext->pSentActionFrame = NULL;
+ vos_mem_free(pNextBuf);
+ }
+ }
+ status = p2pFsm(p2pContext, eP2P_TRIGGER_DISCONNECTED);
+ p2pContext->actionFrameTimeout = TRUE;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s timedout\n", __FUNCTION__);
+
+ return;
+}
+
+
+eHalStatus p2pCreateActionFrame(tpAniSirGlobal pMac, tANI_U8 SessionID, void *p2pactionframe,
+ eP2PFrameType actionFrameType, tANI_U8 **ppFrm)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_U32 len = 0;
+ tANI_U32 nActionFrmlen = 0, pendingFrameLen;
+ tANI_U8 *pActionFrm = NULL;
+ tANI_U8 *pBuf = NULL, *pLocal = NULL;
+ eP2PFrameType pendingActionFrameType;
+ tp2pContext *pP2pContext = &pMac->p2pContext[SessionID];
+
+ if(NULL == ppFrm)
+ {
+ smsLog(pMac, LOGE, FL(" invalid parameters"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ csrScanAbortMacScan(pMac);
+
+ switch (actionFrameType)
+ {
+ case eP2P_GONEGO_REQ:
+ status = P2P_UpdateIE(pMac, SessionID, eWFD_SEND_GO_NEGOTIATION_REQUEST, p2pactionframe, len);
+ break;
+
+ case eP2P_GONEGO_RES:
+ status = P2P_UpdateIE(pMac, SessionID, eWFD_SEND_GO_NEGOTIATION_RESPONSE, p2pactionframe, len);
+ break;
+
+ case eP2P_GONEGO_CNF:
+ status = P2P_UpdateIE(pMac, SessionID, eWFD_SEND_GO_NEGOTIATION_CONFIRMATION, p2pactionframe, len);
+ break;
+
+ case eP2P_PROVISION_DISCOVERY_REQUEST:
+ status = P2P_UpdateIE(pMac, SessionID, eWFD_SEND_PROVISION_DISCOVERY_REQUEST, p2pactionframe, len);
+ break;
+
+ case eP2P_PROVISION_DISCOVERY_RESPONSE:
+ status = P2P_UpdateIE(pMac, SessionID, eWFD_SEND_PROVISION_DISCOVERY_RESPONSE, p2pactionframe, len);
+ break;
+
+ case eP2P_INVITATION_REQ:
+ status = P2P_UpdateIE(pMac, SessionID, eWFD_SEND_INVITATION_REQUEST, p2pactionframe, len);
+ break;
+
+ case eP2P_INVITATION_RSP:
+ status = P2P_UpdateIE(pMac, SessionID, eWFD_SEND_INVITATION_RESPONSE, p2pactionframe, len);
+ break;
+ default:
+ return status;
+ }
+
+ status = P2P_GetActionFrame(pMac, SessionID, actionFrameType, &pActionFrm, &nActionFrmlen);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL(" P2P_GetActionFrame fail with status %d"), status);
+ return status;
+ }
+
+ P2P_UpdateMacHdr(pMac, SessionID, pActionFrm);
+
+ pBuf = (tANI_U8 *)vos_mem_malloc( nActionFrmlen);
+ if(NULL == pBuf)
+ {
+ smsLog(pMac, LOGE, FL(" fail to allocate memory"));
+ if (pActionFrm)
+ vos_mem_free(pActionFrm);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ vos_mem_copy(pBuf, pActionFrm, nActionFrmlen);
+ vos_mem_free(pActionFrm);
+
+ if( !VOS_IS_STATUS_SUCCESS(vos_spin_lock_acquire(&pP2pContext->lState)))
+ {
+ smsLog(pMac, LOGE, FL(" fail to acquire spinlock"));
+ vos_mem_free(pBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if(NULL != pP2pContext->pSentActionFrame)
+ {
+ //If there is one pending frame already. Drop that one and save the new one
+ pLocal = pP2pContext->pNextActionFrm;
+ pendingActionFrameType = pP2pContext->NextActionFrameType;
+ pendingFrameLen = pP2pContext->nNextFrmLen;
+ pP2pContext->pNextActionFrm = pBuf;
+ pP2pContext->nNextFrmLen = nActionFrmlen;
+ pP2pContext->NextActionFrameType = actionFrameType;
+ *ppFrm = NULL;
+ }
+ else
+ {
+ pP2pContext->pSentActionFrame = pBuf;
+ pP2pContext->ActionFrameLen = nActionFrmlen;
+ pP2pContext->actionFrameType = actionFrameType;
+ *ppFrm = pBuf;
+ }
+ vos_spin_lock_release(&pP2pContext->lState);
+
+ if(NULL != pLocal)
+ {
+ smsLog(pMac, LOGE, FL(" Drop a waiting action frame 0x%x, type %d lenth %d"),
+ pLocal, pendingActionFrameType, pendingFrameLen);
+ vos_mem_free(pLocal);
+ }
+
+ return status;
+}
+
+
+extern eHalStatus p2pGetSSID(tANI_U8 *ssId, tANI_U32 *ssIdLen, tANI_U8 SessionID);
+
+static eHalStatus p2pSendActionFrame(tpAniSirGlobal pMac, tANI_U8 HDDSessionID, eP2PFrameType actionFrameType)
+{
+ tCsrScanResultFilter filter;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tScanResultHandle hScanResult = NULL;
+ tCsrScanResultInfo *pScanResult = NULL;
+ tANI_U8 ssId[SIR_MAC_MAX_SSID_LENGTH];
+ tANI_U32 ssIdLen = 0;
+ tp2pContext *pP2pContext = &pMac->p2pContext[HDDSessionID];
+
+ pP2pContext->GroupFormationPending = TRUE;
+ if (actionFrameType == eP2P_GONEGO_REQ || actionFrameType == eP2P_PROVISION_DISCOVERY_REQUEST
+ || actionFrameType == eP2P_INVITATION_REQ)
+ {
+ vos_mem_zero(&filter, sizeof(filter));
+ filter.BSSIDs.numOfBSSIDs = 1;
+ filter.BSSIDs.bssid = &pP2pContext->peerMacAddress;
+ filter.bWPSAssociation = TRUE;
+ filter.BSSType = eCSR_BSS_TYPE_ANY;
+
+ status = csrScanGetResult(pMac, &filter, &hScanResult);
+
+ if (hScanResult)
+ {
+ pScanResult = csrScanResultGetFirst(pMac, hScanResult );
+ if(pScanResult)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, "%s found match on channel %d",
+ __FUNCTION__, pScanResult->BssDescriptor.channelId);
+ pP2pContext->formationReq.targetListenChannel = pScanResult->BssDescriptor.channelId;
+ if(pP2pContext->P2PListenChannel != pScanResult->BssDescriptor.channelId)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s adapt listen channel to %d",
+ __FUNCTION__, pScanResult->BssDescriptor.channelId);
+ p2pSetListenChannel(pMac, pP2pContext->sessionId, pScanResult->BssDescriptor.channelId);
+ }
+ vos_mem_copy(pP2pContext->formationReq.deviceAddress, pScanResult->BssDescriptor.bssId, P2P_MAC_ADDRESS_LEN);
+ }
+ csrScanResultPurge(pMac, hScanResult);
+ }
+ else
+ {
+ vos_mem_zero(&filter, sizeof(filter));
+ filter.bWPSAssociation = TRUE;
+ filter.BSSType = eCSR_BSS_TYPE_ANY;
+ filter.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
+ if( filter.SSIDs.SSIDList == NULL )
+ {
+ smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") );
+ pP2pContext->GroupFormationPending = FALSE;
+ return eHAL_STATUS_FAILURE;
+ }
+ vos_mem_zero( filter.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) );
+ p2pGetSSID(ssId, &ssIdLen, HDDSessionID);
+
+ if (ssIdLen)
+ {
+ filter.SSIDs.SSIDList->SSID.length = ssIdLen;
+ vos_mem_copy(&filter.SSIDs.SSIDList[0].SSID.ssId, &ssId, ssIdLen);
+ filter.SSIDs.numOfSSIDs = 1;
+ status = csrScanGetResult(pMac, &filter, &hScanResult);
+ if (hScanResult)
+ {
+ pScanResult = csrScanResultGetFirst(pMac, hScanResult );
+ pP2pContext->formationReq.targetListenChannel = pScanResult->BssDescriptor.channelId;
+ vos_mem_copy(pP2pContext->formationReq.deviceAddress, pScanResult->BssDescriptor.bssId, P2P_MAC_ADDRESS_LEN);
+ csrScanResultPurge(pMac, hScanResult);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s not found match\n", __FUNCTION__);
+ pP2pContext->formationReq.targetListenChannel = 0;
+ vos_mem_copy(pP2pContext->formationReq.deviceAddress, pP2pContext->peerMacAddress, P2P_MAC_ADDRESS_LEN);
+ status = eHAL_STATUS_SUCCESS;
+ }
+ vos_mem_free(filter.SSIDs.SSIDList);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s not found match\n", __FUNCTION__);
+ pP2pContext->formationReq.targetListenChannel = 0;
+ vos_mem_copy(pP2pContext->formationReq.deviceAddress, pP2pContext->peerMacAddress, P2P_MAC_ADDRESS_LEN);
+ status = eHAL_STATUS_SUCCESS;
+ }
+ }
+ sme_CancelRemainOnChannel(pMac, pP2pContext->SMEsessionId );
+ p2pFsm(pP2pContext, eP2P_TRIGGER_GROUP_FORMATION);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, " %s send action frame %d timeout %d\n",
+ __FUNCTION__, actionFrameType, pP2pContext->ActionFrameSendTimeout);
+ }
+ else
+ {
+ pP2pContext->PeerFound = TRUE;
+
+ status = p2pSendAction(pMac, pP2pContext->SMEsessionId, (tANI_U8 *)pP2pContext->pSentActionFrame,
+ pP2pContext->ActionFrameLen);
+ if(status != eHAL_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s p2pSendAction failed to send frame type %d\n", __FUNCTION__, actionFrameType);
+ pP2pContext->GroupFormationPending = FALSE;
+ return status;
+ }
+
+ if ( actionFrameType == eP2P_GONEGO_RES )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s Calling p2pRemainOnChannel with duration"
+ "%d on channel %d\n", __FUNCTION__, P2P_REMAIN_ON_CHAN_TIMEOUT, pP2pContext->P2PListenChannel);
+
+ if(p2pRemainOnChannel( pMac, pP2pContext->SMEsessionId,
+ pP2pContext->P2PListenChannel, P2P_REMAIN_ON_CHAN_TIMEOUT_LOW,
+ NULL, NULL, eP2PRemainOnChnReasonSendFrame))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s remain on channel failed\n", __FUNCTION__);
+ }
+ }
+ }
+
+ return(status);
+}
+
+
+#define WLAN_P2P_DEF_ACTION_FRM_TIMEOUT_VALUE 1000 //1s
+
+eHalStatus p2pCreateSendActionFrame(tHalHandle hHal, tANI_U8 HDDSessionID,
+ void *p2pactionframe, eP2PFrameType actionFrameType, tANI_U32 timeout)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tANI_U8 *pBuf = NULL;
+ tp2pContext *pP2pContext = &pMac->p2pContext[HDDSessionID];
+
+ status = p2pCreateActionFrame(pMac, HDDSessionID, p2pactionframe, actionFrameType, &pBuf);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL(" fail to create action frame"));
+ return status;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, " %s send action frame %d timeout %d\n",
+ __FUNCTION__, actionFrameType, timeout);
+
+ if(NULL != pBuf)
+ {
+ if (timeout)
+ {
+ pP2pContext->ActionFrameSendTimeout = timeout;
+ }
+ else
+ {
+ pP2pContext->ActionFrameSendTimeout = WLAN_P2P_DEF_ACTION_FRM_TIMEOUT_VALUE;
+ }
+
+ status = palTimerStart(pMac->hHdd, pP2pContext->actionFrameTimer,
+ pP2pContext->ActionFrameSendTimeout * PAL_TIMER_TO_MS_UNIT, eANI_BOOLEAN_FALSE);
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ tCsrRoamInfo RoamInfo;
+
+ vos_mem_zero(&RoamInfo, sizeof(tCsrRoamInfo));
+ smsLog(pMac, LOGE, FL(" %s fail to start timer status %d"), __FUNCTION__, status);
+ //Without the timer we cannot continue
+ csrRoamCallCallback((tpAniSirGlobal)pP2pContext->hHal,
+ pP2pContext->SMEsessionId, &RoamInfo, 0,
+ eCSR_ROAM_SEND_ACTION_CNF,
+ eCSR_ROAM_RESULT_SEND_ACTION_FAIL);
+ vos_spin_lock_acquire(&pP2pContext->lState);
+ pBuf = pP2pContext->pSentActionFrame;
+ pP2pContext->pSentActionFrame = NULL;
+ vos_spin_lock_release(&pP2pContext->lState);
+ vos_mem_free(pBuf);
+ pBuf = NULL;
+ p2pFsm(pP2pContext, eP2P_TRIGGER_DISCONNECTED);
+ return status;
+ }
+ //We can send this frame now
+ status = p2pSendActionFrame(pMac, HDDSessionID, actionFrameType);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ smsLog(pMac, LOGE, FL(" fail to send action frame status %d"), status);
+ }
+ //Let them retry
+ pP2pContext->actionFrameTimeout = FALSE;
+ }
+ else
+ {
+ //An action frame is pedning at lower layer
+ smsLog(pMac, LOGW, FL(" An action frame is pending while trying to send frametype %d"), actionFrameType);
+ if (timeout)
+ {
+ pP2pContext->nNextFrameTimeOut = timeout;
+ }
+ else
+ {
+ pP2pContext->nNextFrameTimeOut = WLAN_P2P_DEF_ACTION_FRM_TIMEOUT_VALUE;
+ }
+ }
+
+ return status;
+}
+
+
+void p2pListenDiscoverTimerHandlerCB(void *pContext)
+{
+}
+
+void p2pListenDiscoverTimerHandler(void *pContext)
+{
+ tp2pContext *p2pContext = (tp2pContext*) pContext;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ if( (eP2P_STATE_DISCONNECTED == p2pContext->state) &&
+ (eStateDisabled != p2pContext->listenDiscoverableState) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s Calling RemainOnChannel with duration %d on channel %d\n",
+ __FUNCTION__, p2pContext->listenDuration, p2pContext->P2PListenChannel);
+ status = p2pRemainOnChannel( p2pContext->hHal, p2pContext->SMEsessionId, p2pContext->P2PListenChannel, p2pContext->listenDuration,
+ p2pListenStateDiscoverableCallback, p2pContext, eP2PRemainOnChnReasonListen);
+ }
+ else
+ {
+ smsLog(((tpAniSirGlobal)p2pContext->hHal), LOGW, FL(" cannot call p2pRemainOnChannel state %d\n"), p2pContext->state);
+ }
+
+ return;
+}
+
+
+static eHalStatus p2pListenStateDiscoverableCallback(tHalHandle halHandle, void *pContext, eHalStatus retStatus)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(halHandle);
+ tp2pContext *p2pContext = (tp2pContext*) pContext;
+
+ if( (eP2P_STATE_DISCONNECTED == p2pContext->state) &&
+ (eStateDisabled != p2pContext->listenDiscoverableState) &&
+ (NULL == p2pContext->p2pDiscoverCBFunc) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s restart listen timer expire time %d\n",
+ __FUNCTION__, p2pContext->expire_time);
+ //We can restart the listening
+ status = palTimerStart(pMac->hHdd, p2pContext->listenTimerHandler, p2pContext->expire_time, eANI_BOOLEAN_FALSE);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ VOS_ASSERT(status);
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s not restart listen timer state (%d)\n",
+ __FUNCTION__, p2pContext->state);
+ }
+
+ return status;
+}
+
+
+eHalStatus P2P_ListenStateDiscoverable(tHalHandle hHal, tANI_U8 sessionId,
+ ep2pListenStateDiscoverability listenState)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ switch (listenState)
+ {
+ case P2P_DEVICE_NOT_DISCOVERABLE:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s P2P_NOT_DISCOVERABLE\n", __FUNCTION__);
+ pMac->p2pContext[sessionId].listenDiscoverableState = eStateDisabled;
+ pMac->p2pContext[sessionId].DiscoverableCfg = listenState;
+ if (pMac->p2pContext[sessionId].state == eP2P_STATE_DISCONNECTED)
+ {
+ sme_CancelRemainOnChannel(hHal, sessionId );
+
+ if (pMac->p2pContext[sessionId].listenTimerHandler)
+ {
+ status = palTimerStop(pMac->hHdd, pMac->p2pContext[sessionId].listenTimerHandler);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s Timer Stop status %d\n",
+ __FUNCTION__, status);
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, "%s P2P_NOT_DISCOVERABLE not in right state (%d)",
+ __FUNCTION__, pMac->p2pContext[sessionId].state);
+ }
+ break;
+
+ case P2P_DEVICE_AUTO_AVAILABILITY:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s P2P_AUTO_AVAILABILITY\n",__FUNCTION__);
+ pMac->p2pContext[sessionId].listenDiscoverableState = eStateEnabled;
+ pMac->p2pContext[sessionId].DiscoverableCfg = listenState;
+ pMac->p2pContext[sessionId].expire_time = P2P_LISTEN_TIMEOUT_AUTO * PAL_TIMER_TO_MS_UNIT;
+ pMac->p2pContext[sessionId].listenDuration = P2P_LISTEN_TIMEOUT;
+ if (pMac->p2pContext[sessionId].state == eP2P_STATE_DISCONNECTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s Calling RemainOnChannel with diration %d on channel %d\n",
+ __FUNCTION__, pMac->p2pContext[sessionId].listenDuration, pMac->p2pContext[sessionId].P2PListenChannel);
+ p2pRemainOnChannel( pMac, pMac->p2pContext[sessionId].SMEsessionId, pMac->p2pContext[sessionId].P2PListenChannel,
+ pMac->p2pContext[sessionId].listenDuration, p2pListenStateDiscoverableCallback,
+ &pMac->p2pContext[sessionId], eP2PRemainOnChnReasonListen);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, "%s P2P_AUTO_DISCOVERABLE not in right state (%d)",
+ __FUNCTION__, pMac->p2pContext[sessionId].state);
+ }
+ break;
+
+ case P2P_DEVICE_HIGH_AVAILABILITY:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s P2P_HIGH_AVAILABILITY\n",__FUNCTION__);
+ pMac->p2pContext[sessionId].listenDiscoverableState = eStateEnabled;
+ pMac->p2pContext[sessionId].DiscoverableCfg = listenState;
+ pMac->p2pContext[sessionId].expire_time = P2P_REMAIN_ON_CHAN_TIMEOUT_LOW * PAL_TIMER_TO_MS_UNIT;
+ pMac->p2pContext[sessionId].listenDuration = P2P_LISTEN_TIMEOUT_HIGH;
+ if (pMac->p2pContext[sessionId].state == eP2P_STATE_DISCONNECTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s Calling RemainOnChannel with diration %d on channel %d\n",
+ __FUNCTION__, pMac->p2pContext[sessionId].listenDuration, pMac->p2pContext[sessionId].P2PListenChannel);
+ p2pRemainOnChannel( pMac, pMac->p2pContext[sessionId].SMEsessionId, pMac->p2pContext[sessionId].P2PListenChannel,
+ pMac->p2pContext[sessionId].listenDuration, p2pListenStateDiscoverableCallback,
+ &pMac->p2pContext[sessionId], eP2PRemainOnChnReasonListen);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, "%s P2P_HIGH_DISCOVERABLE not in right state (%d)",
+ __FUNCTION__, pMac->p2pContext[sessionId].state);
+ }
+ break;
+
+ case 234: //Not to use this as it enabling GO to be concurrent with P2P device P2P_DEVICE_HIGH_AVAILABILITY:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s P2P_HIGH_AVAILABILITY\n",__FUNCTION__);
+ pMac->p2pContext[sessionId].listenDiscoverableState = eStateEnabled;
+ pMac->p2pContext[sessionId].DiscoverableCfg = listenState;
+
+ if ((pMac->p2pContext[sessionId].P2POperatingChannel != pMac->p2pContext[sessionId].P2PListenChannel)
+ && p2pIsGOportEnabled(pMac))
+ {
+ pMac->p2pContext[sessionId].expire_time = P2P_LISTEN_TIMEOUT_HIGH * PAL_TIMER_TO_MS_UNIT * 5;
+ pMac->p2pContext[sessionId].listenDuration = P2P_REMAIN_ON_CHAN_TIMEOUT_LOW;
+ }
+ else
+ {
+ pMac->p2pContext[sessionId].expire_time = P2P_LISTEN_TIMEOUT_HIGH * PAL_TIMER_TO_MS_UNIT;
+ pMac->p2pContext[sessionId].listenDuration = P2P_LISTEN_TIMEOUT;
+ }
+
+ if (pMac->p2pContext[sessionId].state == eP2P_STATE_DISCONNECTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s Calling RemainOnChannel with diration %d on channel %d\n",
+ __FUNCTION__, pMac->p2pContext[sessionId].listenDuration, pMac->p2pContext[sessionId].P2PListenChannel);
+ p2pRemainOnChannel( pMac, pMac->p2pContext[sessionId].SMEsessionId, pMac->p2pContext[sessionId].P2PListenChannel,
+ pMac->p2pContext[sessionId].listenDuration, p2pListenStateDiscoverableCallback,
+ &pMac->p2pContext[sessionId], eP2PRemainOnChnReasonListen);
+ }
+
+ break;
+
+ default:
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s Unknown listen setting",__FUNCTION__, listenState);
+ break;
+ }
+
+ return( status );
+}
+
+
+void p2pCallDiscoverCallback(tp2pContext *p2pContext, eP2PDiscoverStatus statusCode)
+{
+ if (p2pContext->p2pDiscoverCBFunc)
+ {
+ p2pDiscoverCompleteCallback pcallback = p2pContext->p2pDiscoverCBFunc;
+ p2pContext->p2pDiscoverCBFunc = NULL;
+ pcallback(p2pContext->hHal, p2pContext->pContext, statusCode);
+ }
+ p2pContext->directedDiscovery = FALSE;
+}
+
+
+void p2pDiscoverTimerHandler(void *pContext)
+{
+ tp2pContext *p2pContext = (tp2pContext*) pContext;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, "%s enter", __FUNCTION__);
+ p2pCallDiscoverCallback(p2pContext,
+ (p2pContext->directedDiscovery) ? eP2P_DIRECTED_DISCOVER : eP2P_DISCOVER_SUCCESS);
+
+ status = p2pFsm(p2pContext, eP2P_TRIGGER_DISCONNECTED);
+
+ return;
+}
+
+
+
+eHalStatus p2pGetResultFilter(tp2pContext *pP2pContext,
+ tCsrScanResultFilter *pFilter)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ v_U32_t uNumDeviceFilters;
+ tp2pDiscoverDeviceFilter *directedDiscoveryFilter;
+ int i;
+ tCsrBssid *bssid = NULL;
+
+ do
+ {
+ if( (NULL != pP2pContext) && (NULL != pFilter) )
+ {
+ vos_mem_zero(pFilter, sizeof(tCsrScanResultFilter));
+ uNumDeviceFilters = pP2pContext->uNumDeviceFilters;
+ directedDiscoveryFilter = pP2pContext->directedDiscoveryFilter;
+ for(i = 0; i < uNumDeviceFilters; i++)
+ {
+ if (directedDiscoveryFilter->ucBitmask & DISCOVERY_FILTER_BITMASK_DEVICE)
+ {
+ pFilter->BSSIDs.numOfBSSIDs++;
+ }
+
+ if ((directedDiscoveryFilter->ucBitmask != QCWLAN_P2P_DISCOVER_ANY)
+ && (directedDiscoveryFilter->ucBitmask & DISCOVERY_FILTER_BITMASK_GO))
+ {
+ //Matching Device ID and GroupSSID
+ pFilter->BSSIDs.numOfBSSIDs++;
+ if(directedDiscoveryFilter->GroupSSID.length)
+ {
+ pFilter->SSIDs.numOfSSIDs++;
+ }
+ }
+ directedDiscoveryFilter += sizeof(tp2pDiscoverDeviceFilter);
+ }
+
+ directedDiscoveryFilter = pP2pContext->directedDiscoveryFilter;
+ if (pFilter->BSSIDs.numOfBSSIDs)
+ {
+ bssid = ( tCsrBssid *) vos_mem_malloc( sizeof( tCsrBssid ) * pFilter->BSSIDs.numOfBSSIDs );
+ if(NULL == bssid)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ " %s fail to allocate bssid", __FUNCTION__);
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+
+ pFilter->BSSIDs.bssid = bssid;
+
+ for (i = 0; i < uNumDeviceFilters; i++)
+ {
+ vos_mem_copy(bssid, directedDiscoveryFilter->DeviceID, P2P_MAC_ADDRESS_LEN);
+ bssid += sizeof(tCsrBssid);
+ directedDiscoveryFilter += sizeof(tp2pDiscoverDeviceFilter);
+ }
+ }
+
+ directedDiscoveryFilter = pP2pContext->directedDiscoveryFilter;
+ if (pFilter->SSIDs.numOfSSIDs)
+ {
+ pFilter->SSIDs.SSIDList = (tCsrSSIDInfo *)vos_mem_malloc( sizeof( *pFilter->SSIDs.SSIDList ) *
+ pFilter->SSIDs.numOfSSIDs );
+ if(NULL == pFilter->SSIDs.SSIDList)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ " %s fail to allocate bssid", __FUNCTION__);
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+
+ if ( pFilter->SSIDs.SSIDList )
+ {
+ for ( i = 0; i < uNumDeviceFilters; i++ )
+ {
+ if (directedDiscoveryFilter->ucBitmask == DISCOVERY_FILTER_BITMASK_GO)
+ {
+ if(directedDiscoveryFilter->GroupSSID.length)
+ {
+ pFilter->SSIDs.SSIDList[i].SSID.length = directedDiscoveryFilter->GroupSSID.length;
+ vos_mem_copy( pFilter->SSIDs.SSIDList[i].SSID.ssId,
+ directedDiscoveryFilter->GroupSSID.ssId,
+ directedDiscoveryFilter->GroupSSID.length );
+ }
+ }
+ directedDiscoveryFilter += sizeof(tp2pDiscoverDeviceFilter);
+ }
+ }
+ }
+ }
+
+ pFilter->p2pResult = TRUE;
+ pFilter->bWPSAssociation = TRUE;
+ pFilter->BSSType = eCSR_BSS_TYPE_ANY;
+ } while(0);
+
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ if(pFilter->SSIDs.SSIDList)
+ {
+ vos_mem_free(pFilter->SSIDs.SSIDList);
+ pFilter->SSIDs.SSIDList = NULL;
+ }
+ if( pFilter->BSSIDs.bssid )
+ {
+ vos_mem_free(pFilter->BSSIDs.bssid);
+ pFilter->BSSIDs.bssid = NULL;
+ }
+ }
+
+ return status;
+}
+
+
+/*
+ @breif Function calls P2P_Fsm function to initiate the P2P Discover process
+
+ @param[in] hHal - Handle to MAC structure.
+ [in] sessionID - Session ID returned by sme_OpenSession
+ [in] pDiscoverRequest - pointer to the tp2pDiscoverRequest structure
+ whose parameters are filled in the HDD.
+ [in] callback - HDD callback function to be called when Discover
+ is complete
+ [in] pContext - a pointer passed in for the callback
+
+ @return eHAL_STATUS_FAILURE - If success.
+ eHAL_STATUS_SUCCESS - If failure.
+*/
+eHalStatus P2P_DiscoverRequest(tHalHandle hHal,
+ tANI_U8 SessionID,
+ tP2PDiscoverRequest *pDiscoverRequest,
+ p2pDiscoverCompleteCallback callback,
+ void *pContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tScanResultHandle hScanResult = NULL;
+ tCsrScanResultFilter filter;
+ tANI_U32 uNumDeviceFilters;
+ tp2pDiscoverDeviceFilter *pDeviceFilters;
+ tANI_U32 i = 0;
+ tp2pContext *pP2pContext = &pMac->p2pContext[SessionID];
+ tCsrBssid *bssid = NULL;
+ tp2pDiscoverDeviceFilter discoverFilter;
+ tANI_BOOLEAN fDirect = FALSE;
+
+ if (pDiscoverRequest == NULL)
+ {
+ return status;
+ }
+
+ pP2pContext->discoverType = pDiscoverRequest->discoverType;
+ pP2pContext->scanType = pDiscoverRequest->scanType;
+ pP2pContext->uDiscoverTimeout = pDiscoverRequest->uDiscoverTimeout;
+
+ if (pP2pContext->DiscoverReqIeField)
+ {
+ vos_mem_free(pP2pContext->DiscoverReqIeField);
+ pP2pContext->DiscoverReqIeLength = 0;
+ pP2pContext->DiscoverReqIeField = NULL;
+ }
+
+ if (pDiscoverRequest->uIELen)
+ {
+ pP2pContext->DiscoverReqIeField = (tANI_U8 *)vos_mem_malloc(pDiscoverRequest->uIELen);
+ vos_mem_copy((tANI_U8 *)pP2pContext->DiscoverReqIeField, pDiscoverRequest->pIEField, pDiscoverRequest->uIELen);
+ pP2pContext->DiscoverReqIeLength = pDiscoverRequest->uIELen;
+ }
+ else
+ {
+ pP2pContext->DiscoverReqIeLength = 0;
+ }
+
+ vos_mem_zero(&filter, sizeof(filter));
+
+ do
+ {
+ if (pDiscoverRequest->uNumDeviceFilters)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s directed\n", __FUNCTION__);
+ fDirect = TRUE;
+ uNumDeviceFilters = pDiscoverRequest->uNumDeviceFilters;
+
+ pP2pContext->uDiscoverTimeout = pP2pContext->uDiscoverTimeout;
+ pP2pContext->uNumDeviceFilters = pDiscoverRequest->uNumDeviceFilters;
+ if(pP2pContext->uNumDeviceFilterAllocated < pDiscoverRequest->uNumDeviceFilters)
+ {
+ if(pP2pContext->directedDiscoveryFilter)
+ {
+ pP2pContext->uNumDeviceFilterAllocated = 0;
+ vos_mem_free(pP2pContext->directedDiscoveryFilter);
+ pP2pContext->directedDiscoveryFilter = NULL;
+ }
+ pP2pContext->directedDiscoveryFilter = (tp2pDiscoverDeviceFilter *)
+ vos_mem_malloc(sizeof(tp2pDiscoverDeviceFilter) * uNumDeviceFilters);
+ if(NULL == pP2pContext->directedDiscoveryFilter)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s fail to allocate memory for discoverFilter", __FUNCTION__);
+ status = eHAL_STATUS_RESOURCES;
+ break;
+ }
+ pP2pContext->uNumDeviceFilterAllocated = uNumDeviceFilters;
+ }
+
+ pDeviceFilters = pDiscoverRequest->pDeviceFilters;
+ if(NULL != pDeviceFilters)
+ {
+ vos_mem_copy ( pP2pContext->directedDiscoveryFilter, pDeviceFilters,
+ sizeof(tp2pDiscoverDeviceFilter) * uNumDeviceFilters);
+
+ if(!HAL_STATUS_SUCCESS(status = p2pGetResultFilter(pP2pContext, &filter)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s fail to create filter", __FUNCTION__);
+ break;
+ }
+ }//if(NULL != pDeviceFilters)
+
+ status = csrScanGetResult(pMac, &filter, &hScanResult);
+ if (hScanResult)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s calling p2pDiscoverCompleteCallback\n", __FUNCTION__);
+ if (callback)
+ {
+ callback(hHal, pContext, eP2P_DIRECTED_DISCOVER);
+
+ }
+ status = eHAL_STATUS_SUCCESS;
+ break;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s Directed find did not find BSSID in cache\n", __FUNCTION__);
+ pP2pContext->formationReq.targetListenChannel = 0;
+ if (pDiscoverRequest->uNumDeviceFilters == 1 && filter.BSSIDs.numOfBSSIDs == 1)
+ {
+ vos_mem_copy(&pP2pContext->formationReq.deviceAddress,
+ pDiscoverRequest->pDeviceFilters->DeviceID, P2P_MAC_ADDRESS_LEN);
+ }
+ }
+ }
+
+ pP2pContext->p2pDiscoverCBFunc = callback;
+ pP2pContext->pContext = pContext;
+ pP2pContext->directedDiscovery = fDirect;
+ if(!pP2pContext->GroupFormationPending)
+ {
+ p2pFsm(&pMac->p2pContext[SessionID], eP2P_TRIGGER_DEVICE_MODE_DEVICE);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
+ "%s while group formation", __FUNCTION__);
+ }
+
+ pP2pContext->uDiscoverTimeout = pDiscoverRequest->uDiscoverTimeout;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, "%s Start discover", __FUNCTION__);
+ status = palTimerStart(pMac->hHdd, pP2pContext->discoverTimer,
+ pP2pContext->uDiscoverTimeout * 1000, eANI_BOOLEAN_FALSE);
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s failt to start discover timer", __FUNCTION__);
+ pP2pContext->p2pDiscoverCBFunc = NULL;
+ pP2pContext->pContext = NULL;
+ if(callback)
+ {
+ callback(pMac, pContext, eP2P_DISCOVER_FAILURE);
+ }
+ }
+ }while(0);
+
+ if(filter.SSIDs.SSIDList)
+ {
+ vos_mem_free(filter.SSIDs.SSIDList);
+ }
+ if( hScanResult )
+ {
+ sme_ScanResultPurge( pMac, hScanResult );
+ }
+ if( filter.BSSIDs.bssid )
+ {
+ vos_mem_free(filter.BSSIDs.bssid);
+ }
+
+ return status;
+}
+
+eHalStatus p2pScanRequest(tp2pContext *p2pContext, p2pDiscoverCompleteCallback callback, void *pContext)
+{
+ tCsrScanRequest scanRequest;
+ v_U32_t scanId = 0;
+ tANI_U32 len = 0;
+ tCsrSSIDInfo wcSSID = { {P2P_WILDCARD_SSID_LEN, P2P_WILDCARD_SSID}, 0, 0 };
+ tANI_U8 Channel;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tP2P_OperatingChannel p2pOperatingChannel;
+ tpAniSirGlobal pMac = PMAC_STRUCT(p2pContext->hHal);
+ tANI_U8 *p2pIe = NULL;
+ tANI_U32 p2pIeLen;
+
+ vos_mem_zero( &scanRequest, sizeof(scanRequest));
+
+ P2P_GetOperatingChannel(p2pContext->hHal, p2pContext->sessionId, &p2pOperatingChannel);
+ Channel = p2pOperatingChannel.channel;
+
+ if (Channel)
+ {
+ scanRequest.ChannelInfo.numOfChannels = 1;
+ scanRequest.ChannelInfo.ChannelList = &Channel;
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s Scan on channel %d p2pContext->sessionId %d\n",
+ __FUNCTION__, Channel, p2pContext->sessionId);
+ }
+ else
+ {
+ getChannelInfo(p2pContext, &scanRequest.ChannelInfo, WFD_DISCOVER_TYPE_AUTO);
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s Scan on all channels\n",
+ __FUNCTION__);
+ }
+
+ /* set the scan type to active */
+ scanRequest.scanType = eSIR_ACTIVE_SCAN;
+
+ vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
+
+ scanRequest.requestType = eCSR_SCAN_P2P_FIND_PEER;
+ /* set min and max channel time to zero */
+ scanRequest.minChnTime = 30;
+ scanRequest.maxChnTime = 100;
+
+ /* set BSSType to default type */
+ scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
+
+ scanRequest.SSIDs.numOfSSIDs = 1;
+ scanRequest.SSIDs.SSIDList = &wcSSID;
+ scanRequest.p2pSearch = VOS_FALSE;
+
+ P2P_GetIE(p2pContext, p2pContext->sessionId, eP2P_GROUP_ID, &p2pIe, &p2pIeLen);
+ vos_mem_copy(scanRequest.bssid, ((tP2PGroupId *)p2pIe)->deviceAddress, P2P_MAC_ADDRESS_LEN);
+
+ P2P_GetIE(p2pContext, p2pContext->sessionId, eP2P_PROBE_REQ, &scanRequest.pIEField, &len);
+
+ scanRequest.uIEFieldLen = len;
+
+ status = csrScanRequest( p2pContext->hHal, p2pContext->SMEsessionId, &scanRequest, &scanId, callback, pContext );
+
+ if(scanRequest.pIEField)
+ {
+ vos_mem_free(scanRequest.pIEField);
+ }
+
+ if(p2pIe)
+ {
+ vos_mem_free(p2pIe);
+ }
+ return status;
+}
+
+tANI_U8 getP2PSessionIdFromSMESessionId(tHalHandle hHal, tANI_U8 SessionID)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tANI_U8 num_session;
+
+ for (num_session = 0; num_session < MAX_NO_OF_P2P_SESSIONS; num_session++)
+ {
+ if(SessionID == pMac->p2pContext[num_session].SMEsessionId)
+ {
+ return pMac->p2pContext[num_session].sessionId;
+ }
+ }
+
+ return CSR_SESSION_ID_INVALID;
+}
+
+
+/* SessionID is HDD session id, not SME sessionId*/
+eHalStatus p2pCloseSession(tHalHandle hHal, tANI_U8 SessionID)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tp2pContext *pContext = &pMac->p2pContext[SessionID];
+
+ pContext->SMEsessionId = CSR_SESSION_ID_INVALID;
+ p2pResetContext(pContext);
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+eHalStatus p2pSetSessionId(tHalHandle hHal, tANI_U8 SessionID, tANI_U8 SmeSessionId)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ pMac->p2pContext[SessionID].sessionId = SessionID;
+ pMac->p2pContext[SessionID].SMEsessionId = SmeSessionId;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+static tANI_BOOLEAN p2pIsGOportEnabled(tpAniSirGlobal pMac)
+{
+
+ tANI_U8 num_session = 0;
+
+ for (num_session = 0; num_session < MAX_NO_OF_P2P_SESSIONS ; num_session++)
+ {
+ if (pMac->p2pContext[num_session].operatingmode == OPERATION_MODE_P2P_GROUP_OWNER)
+ {
+ return eANI_BOOLEAN_TRUE;
+ }
+ }
+
+ return eANI_BOOLEAN_FALSE;
+}
+
+tANI_BOOLEAN p2pIsOperatingChannEqualListenChann(tHalHandle hHal, tANI_U8 SessionID)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ if(pMac->p2pContext[SessionID].P2POperatingChannel == pMac->p2pContext[SessionID].P2PListenChannel)
+ {
+ return eANI_BOOLEAN_TRUE;
+ }
+
+ return eANI_BOOLEAN_FALSE;
+}
+
+eHalStatus p2pGetListenChannel(tHalHandle hHal, tANI_U8 SessionID, tANI_U8 *channel)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ *channel = pMac->p2pContext[SessionID].P2PListenChannel;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+eHalStatus p2pSetListenChannel(tHalHandle hHal, tANI_U8 SessionID, tANI_U8 channel)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tP2P_OperatingChannel p2pListenChannel;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ if(csrRoamIsChannelValid(pMac, channel))
+ {
+ pMac->p2pContext[SessionID].P2PListenChannel = channel;
+ p2pGetListenChannelAttrib(pMac, pMac->p2pContext[SessionID].sessionId, &p2pListenChannel);
+ p2pListenChannel.channel = channel;
+ p2pUpdateListenChannelAttrib(pMac, pMac->p2pContext[SessionID].sessionId, &p2pListenChannel);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ " %s fail with invalid channel %d", __FUNCTION__, channel);
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+
+ return status;
+}
+
+
+
+eHalStatus p2pStopDiscovery(tHalHandle hHal, tANI_U8 SessionID)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ status = palTimerStop(pMac->hHdd, pMac->p2pContext[SessionID].discoverTimer);
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s Timer Stop status %d\n", __FUNCTION__, status);
+ return status;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s Timer Stop status %d\n", __FUNCTION__, status);
+ p2pCallDiscoverCallback(&pMac->p2pContext[SessionID], eP2P_DIRECTED_DISCOVER);
+
+ status = p2pFsm( &pMac->p2pContext[SessionID], eP2P_TRIGGER_DISCONNECTED );
+
+ return status;
+}
+
+//Purge P2P device/GO from the list
+eHalStatus p2pPurgeDeviceList(tpAniSirGlobal pMac, tDblLinkList *pList)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tListElem *pEntry, *pNext;
+ tCsrScanResult *pBssResult;
+ tDot11fBeaconIEs *pIes;
+
+ csrLLLock(pList);
+
+ pEntry = csrLLPeekHead(pList, LL_ACCESS_NOLOCK);
+ while( NULL != pEntry )
+ {
+ pNext = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK);
+ pBssResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
+ pIes = NULL;
+ if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, &pBssResult->Result.BssDescriptor, &pIes)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ " %s fail to parse IEs. pEntry (0x%X)",
+ __FUNCTION__, pEntry);
+ pEntry = pNext;
+ continue;
+ }
+ if( pIes->P2PBeaconProbeRes.present )
+ {
+ //Found a P2P BSS
+ if(csrLLRemoveEntry(pList, pEntry, LL_ACCESS_NOLOCK) )
+ {
+ csrFreeScanResultEntry( pMac, pBssResult );
+ }
+ }
+ palFreeMemory(pMac->hHdd, pIes);
+ pEntry = pNext;
+ }
+
+ csrLLUnlock(pList);
+
+ return (status);
+}
+
+
+eHalStatus sme_p2pFlushDeviceList(tHalHandle hHal, tANI_U8 HDDSessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ smsLog(pMac, LOG2, FL("enter"));
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = p2pPurgeDeviceList(pMac, &pMac->scan.scanResultList);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+eHalStatus sme_p2pResetSession(tHalHandle hHal, tANI_U8 HDDSessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ smsLog(pMac, LOG2, FL("enter"));
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if(MAX_NO_OF_P2P_SESSIONS > HDDSessionId)
+ {
+ p2pResetContext(&pMac->p2pContext[HDDSessionId]);
+ status = eHAL_STATUS_SUCCESS;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+
+eHalStatus sme_p2pGetResultFilter(tHalHandle hHal, tANI_U8 HDDSessionId,
+ tCsrScanResultFilter *pFilter)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if(MAX_NO_OF_P2P_SESSIONS > HDDSessionId)
+ {
+ status = p2pGetResultFilter(&pMac->p2pContext[HDDSessionId], pFilter);
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return status;
+}
+
+
+
+#endif //WLAN_FEATURE_P2P_INTERNAL
+
+eHalStatus p2pProcessNoAReq(tpAniSirGlobal pMac, tSmeCmd *pNoACmd)
+{
+ tpP2pPsConfig pNoA;
+ tSirMsgQ msg;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ status = palAllocateMemory(pMac->hHdd, (void**)&pNoA, sizeof(tP2pPsConfig));
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pNoA, sizeof(tP2pPsConfig));
+ pNoA->opp_ps = pNoACmd->u.NoACmd.NoA.opp_ps;
+ pNoA->ctWindow = pNoACmd->u.NoACmd.NoA.ctWindow;
+ pNoA->duration = pNoACmd->u.NoACmd.NoA.duration;
+ pNoA->interval = pNoACmd->u.NoACmd.NoA.interval;
+ pNoA->count = pNoACmd->u.NoACmd.NoA.count;
+ pNoA->single_noa_duration = pNoACmd->u.NoACmd.NoA.single_noa_duration;
+ pNoA->psSelection = pNoACmd->u.NoACmd.NoA.psSelection;
+ pNoA->sessionid = pNoACmd->u.NoACmd.NoA.sessionid;
+ msg.type = eWNI_SME_UPDATE_NOA;
+ msg.bodyval = 0;
+ msg.bodyptr = pNoA;
+ limPostMsgApi(pMac, &msg);
+ }
+ return status;
+}
+
+
+
+
+#endif //WLAN_FEATURE_P2P
diff --git a/CORE/SME/src/pmc/pmc.c b/CORE/SME/src/pmc/pmc.c
new file mode 100644
index 0000000..5afc0db
--- /dev/null
+++ b/CORE/SME/src/pmc/pmc.c
@@ -0,0 +1,2588 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/******************************************************************************
+*
+* Name: pmc.c
+*
+* Description:
+ Power Management Control (PMC) processing routines.
+*
+* Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+* Qualcomm Confidential and Proprietary.
+*
+*
+******************************************************************************/
+
+#include "palTypes.h"
+#include "aniGlobal.h"
+#include "csrLinkList.h"
+#include "csrApi.h"
+#include "smeInside.h"
+#include "sme_Api.h"
+#include "smsDebug.h"
+#include "pmc.h"
+#include "wlan_ps_wow_diag.h"
+#include <vos_power.h>
+#include "csrInsideApi.h"
+
+static void pmcProcessDeferredMsg( tpAniSirGlobal pMac );
+
+/******************************************************************************
+*
+* Name: pmcEnterLowPowerState
+*
+* Description:
+* Have the device enter Low Power State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterLowPowerState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcEnterLowPowerState\n"));
+
+ /* If already in Low Power State, just return. */
+ if (pMac->pmc.pmcState == LOW_POWER)
+ return eHAL_STATUS_SUCCESS;
+
+ /* Cancel any running timers. */
+ if (palTimerStop(pMac->hHdd, pMac->pmc.hImpsTimer) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot cancel IMPS timer\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ pmcStopTrafficTimer(hHal);
+
+ if (palTimerStop(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot cancel exit power save mode timer\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Do all the callbacks. */
+ pmcDoCallbacks(hHal, eHAL_STATUS_FAILURE);
+
+ /* Change state. */
+ pMac->pmc.pmcState = LOW_POWER;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcExitLowPowerState
+*
+* Description:
+* Have the device exit the Low Power State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcExitLowPowerState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcExitLowPowerState\n"));
+
+ /* Must be in Low Power State if we are going to exit that state. */
+ if (pMac->pmc.pmcState != LOW_POWER)
+ {
+ smsLog(pMac, LOGE, FL("Cannot exit Low Power State if not in that state\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Both WLAN switches much be on to exit Low Power State. */
+ if ((pMac->pmc.hwWlanSwitchState == ePMC_SWITCH_OFF) || (pMac->pmc.swWlanSwitchState == ePMC_SWITCH_OFF))
+ return eHAL_STATUS_SUCCESS;
+
+ /* Change state. */
+ pMac->pmc.pmcState = FULL_POWER;
+ if(pmcShouldBmpsTimerRun(pMac))
+ {
+ if (pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcEnterFullPowerState
+*
+* Description:
+* Have the device enter the Full Power State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterFullPowerState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcEnterFullPowerState\n"));
+
+ /* Take action based on the current state. */
+ switch (pMac->pmc.pmcState)
+ {
+
+ /* Already in Full Power State. */
+ case FULL_POWER:
+ break;
+
+ /* Notify everyone that we are going to full power.
+ Change to Full Power State. */
+ case REQUEST_FULL_POWER:
+ case REQUEST_IMPS:
+ case REQUEST_BMPS:
+ case REQUEST_STANDBY:
+
+ /* Change state. */
+ pMac->pmc.pmcState = FULL_POWER;
+ pMac->pmc.requestFullPowerPending = FALSE;
+
+ if(pmcShouldBmpsTimerRun(pMac))
+ (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+
+ pmcProcessDeferredMsg( pMac );
+ /* Do all the callbacks. */
+ pmcDoCallbacks(hHal, eHAL_STATUS_SUCCESS);
+
+ /* Update registerd modules that we are entering Full Power. This is
+ only way to inform modules if PMC exited a power save mode because
+ of error conditions or if som other module requested full power */
+ pmcDoDeviceStateUpdateCallbacks(hHal, FULL_POWER);
+ break;
+
+ /* Cannot go directly to Full Power State from these states. */
+ default:
+ smsLog(pMac, LOGE, FL("Trying to enter Full Power State from state %d\n"), pMac->pmc.pmcState);
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ smsLog(pMac, LOGW, "PMC: Enter full power done: Cancel XO Core ON vote\n");
+ if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "Could not cancel XO Core ON vote. Not returning failure. "
+ "Power consumed will be high\n");
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcEnterRequestFullPowerState
+*
+* Description:
+* Have the device enter the Request Full Power State.
+*
+* Parameters:
+* hHal - HAL handle for device
+* fullPowerReason - Reason code for requesting full power
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterRequestFullPowerState (tHalHandle hHal, tRequestFullPowerReason fullPowerReason)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ vos_call_status_type callType;
+ VOS_STATUS status;
+
+ smsLog(pMac, LOG2, FL("Entering pmcEnterRequestFullPowerState\n"));
+
+ /* Take action based on the current state of the device. */
+ switch (pMac->pmc.pmcState)
+ {
+
+ /* Should not request full power if already there. */
+ case FULL_POWER:
+ smsLog(pMac, LOGE, FL("Requesting Full Power State when already there\n"));
+ return eHAL_STATUS_FAILURE;
+
+ /* Only power events can take device out of Low Power State. */
+ case LOW_POWER:
+ smsLog(pMac, LOGE, FL("Cannot request exit from Low Power State\n"));
+ return eHAL_STATUS_FAILURE;
+
+ /* Cannot go directly to Request Full Power state from these states.
+ Record that this is pending and take care of it later. */
+ case REQUEST_IMPS:
+ case REQUEST_START_UAPSD:
+ case REQUEST_STOP_UAPSD:
+ case REQUEST_STANDBY:
+ case REQUEST_BMPS:
+ case REQUEST_ENTER_WOWL:
+ case REQUEST_EXIT_WOWL:
+ smsLog(pMac, LOGW, FL("Request for full power is being buffered. "
+ "Current state is %d\n"), pMac->pmc.pmcState);
+ //Ignore the new reason if request for full power is already pending
+ if( !pMac->pmc.requestFullPowerPending )
+ {
+ pMac->pmc.requestFullPowerPending = TRUE;
+ pMac->pmc.requestFullPowerReason = fullPowerReason;
+ }
+ return eHAL_STATUS_SUCCESS;
+
+ /* Tell MAC to have device enter full power mode. */
+ case IMPS:
+ if ( pMac->pmc.rfSuppliesVotedOff )
+ {
+ status = vos_chipVoteOnRFSupply(&callType, NULL, NULL);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
+
+ status = vos_chipVoteOnXOBuffer(&callType, NULL, NULL);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
+
+ pMac->pmc.rfSuppliesVotedOff = FALSE;
+ }
+
+ if (pmcIssueCommand( pMac, eSmeCommandExitImps, NULL, 0, FALSE ) != eHAL_STATUS_SUCCESS)
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+
+ /* Tell MAC to have device enter full power mode. */
+ case BMPS:
+ {
+ tExitBmpsInfo exitBmpsInfo;
+ exitBmpsInfo.exitBmpsReason = fullPowerReason;
+
+ if (pmcIssueCommand(hHal, eSmeCommandExitBmps, &exitBmpsInfo, sizeof(tExitBmpsInfo), FALSE)
+ != eHAL_STATUS_SUCCESS)
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+ }
+ /* Already in Request Full Power State. */
+ case REQUEST_FULL_POWER:
+ return eHAL_STATUS_SUCCESS;
+
+ /* Tell MAC to have device enter full power mode. */
+ case STANDBY:
+ if ( pMac->pmc.rfSuppliesVotedOff )
+ {
+ status = vos_chipVoteOnXOBuffer(&callType, NULL, NULL);
+ if(VOS_STATUS_SUCCESS != status)
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+ status = vos_chipVoteOnRFSupply(&callType, NULL, NULL);
+ if(VOS_STATUS_SUCCESS != status)
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+
+ pMac->pmc.rfSuppliesVotedOff = FALSE;
+ }
+
+ if (pmcIssueCommand(hHal, eSmeCommandExitImps, NULL, 0, FALSE) !=
+ eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message "
+ "eWNI_PMC_EXIT_IMPS_REQ\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+
+ /* Tell MAC to have device exit UAPSD mode first */
+ case UAPSD:
+ //Need to save the reason code here in case later on we need to exit BMPS as well
+ if (pmcIssueCommand(hHal, eSmeCommandExitUapsd, &fullPowerReason, sizeof(tRequestFullPowerReason), FALSE) !=
+ eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message "
+ "eWNI_PMC_EXIT_UAPSD_REQ\n");
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+
+ /* Tell MAC to have device exit WOWL mode first */
+ case WOWL:
+ if (pmcIssueCommand(hHal, eSmeCommandExitWowl, &fullPowerReason, sizeof(tRequestFullPowerReason), FALSE) !=
+ eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGP, "PMC: failure to send message "
+ "eWNI_PMC_EXIT_WOWL_REQ\n");
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+
+ /* Cannot go directly to Request Full Power State from these states. */
+ default:
+ smsLog(pMac, LOGE, FL("Trying to enter Request Full Power State from state %d\n"), pMac->pmc.pmcState);
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+}
+
+
+/******************************************************************************
+*
+* Name: pmcEnterRequestImpsState
+*
+* Description:
+* Have the device enter the Request IMPS State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterRequestImpsState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcEnterRequestImpsState\n"));
+
+ /* Can enter Request IMPS State only from Full Power State. */
+ if (pMac->pmc.pmcState != FULL_POWER)
+ {
+ smsLog(pMac, LOGE, FL("Trying to enter Request IMPS State from state %d\n"), pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Make sure traffic timer that triggers bmps entry is not running */
+ pmcStopTrafficTimer(hHal);
+
+ /* Tell MAC to have device enter IMPS mode. */
+ if (pmcIssueCommand(hHal, eSmeCommandEnterImps, NULL, 0, FALSE) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_IMPS_REQ\n");
+ pMac->pmc.pmcState = FULL_POWER;
+ if(pmcShouldBmpsTimerRun(pMac))
+ (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ smsLog(pMac, LOGW, FL("eWNI_PMC_ENTER_IMPS_REQ sent to PE\n"));
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcEnterImpsState
+*
+* Description:
+* Have the device enter the IMPS State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterImpsState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ vos_call_status_type callType;
+ VOS_STATUS status;
+ smsLog(pMac, LOG2, FL("Entering pmcEnterImpsState\n"));
+
+ /* Can enter IMPS State only from Request IMPS State. */
+ if (pMac->pmc.pmcState != REQUEST_IMPS)
+ {
+ smsLog(pMac, LOGE, FL("Trying to enter IMPS State from state %d\n"), pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Change state. */
+ pMac->pmc.pmcState = IMPS;
+
+ /* If we have a reqeust for full power pending then we have to go
+ directly into full power. */
+ if (pMac->pmc.requestFullPowerPending)
+ {
+
+#if defined(ANI_OS_TYPE_WINDOWS) && !defined(GEN6_ONWARDS)
+ /* In Windows we cannot do this now since we are in DPC context and the message to the
+ SoftMAC to put the device into IMPS will be sent at the end of DPC processing. Instead
+ we set a short timer and start the IMPS exit sequence when the timer fires. */
+ if (palTimerStart(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer, 1000, FALSE) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot start exit power save mode timer\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+
+#else
+ /* Start exit IMPS sequence now. */
+ return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
+#endif
+ }
+
+ /* Set timer to come out of IMPS.only if impsPeriod is non-Zero*/
+ if(0 != pMac->pmc.impsPeriod)
+ {
+ if (palTimerStart(pMac->hHdd, pMac->pmc.hImpsTimer, pMac->pmc.impsPeriod * 1000, FALSE) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot start IMPS timer\n"));
+ PMC_ABORT;
+ pmcEnterRequestFullPowerState(hHal, eSME_REASON_OTHER);
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+
+ //Vote off RF supplies. Note RF supllies are not voted off if there is a
+ //pending request for full power already
+ status = vos_chipVoteOffRFSupply(&callType, NULL, NULL);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
+
+ status = vos_chipVoteOffXOBuffer(&callType, NULL, NULL);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
+
+ pMac->pmc.rfSuppliesVotedOff= TRUE;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcEnterRequestBmpsState
+*
+* Description:
+* Have the device enter the Request BMPS State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterRequestBmpsState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcEnterRequestBmpsState\n"));
+
+ /* Can enter Request BMPS State only from Full Power State. */
+ if (pMac->pmc.pmcState != FULL_POWER)
+ {
+ smsLog(pMac, LOGE, FL("Trying to enter Request BMPS State from state %d\n"), pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Stop Traffic timer if running. Note: timer could have expired because of possible
+ race conditions. So no need to check for errors. Just make sure timer is not running */
+ pmcStopTrafficTimer(hHal);
+
+ /* Tell MAC to have device enter BMPS mode. */
+ if ( !pMac->pmc.bmpsRequestQueued )
+ {
+ pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_TRUE;
+ if(pmcIssueCommand(hHal, eSmeCommandEnterBmps, NULL, 0, FALSE) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_BMPS_REQ\n");
+ pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
+ pMac->pmc.pmcState = FULL_POWER;
+ if(pmcShouldBmpsTimerRun(pMac))
+ {
+ (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ }
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "PMC: enter BMPS command already queued\n");
+ //restart the timer if needed
+ if(pmcShouldBmpsTimerRun(pMac))
+ {
+ (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ }
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ smsLog(pMac, LOGW, FL("eWNI_PMC_ENTER_BMPS_REQ sent to PE\n"));
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcEnterBmpsState
+*
+* Description:
+* Have the device enter the BMPS State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterBmpsState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcEnterBmpsState\n"));
+
+ /* Can enter BMPS State only from 5 states. */
+ if (pMac->pmc.pmcState != REQUEST_BMPS &&
+ pMac->pmc.pmcState != REQUEST_START_UAPSD &&
+ pMac->pmc.pmcState != REQUEST_STOP_UAPSD &&
+ pMac->pmc.pmcState != REQUEST_ENTER_WOWL &&
+ pMac->pmc.pmcState != REQUEST_EXIT_WOWL)
+ {
+ smsLog(pMac, LOGE, FL("Trying to enter BMPS State from state %d\n"), pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Change state. */
+ pMac->pmc.pmcState = BMPS;
+
+ /* Update registerd modules that we are entering BMPS. This is
+ only way to inform modules if PMC entered BMPS power save mode
+ on its own because of traffic timer */
+ pmcDoDeviceStateUpdateCallbacks(hHal, BMPS);
+
+ /* If we have a reqeust for full power pending then we have to go directly into full power. */
+ if (pMac->pmc.requestFullPowerPending)
+ {
+
+#if defined(ANI_OS_TYPE_WINDOWS) && !defined(GEN6_ONWARDS)
+ /* In Windows, we cannot do this now since we are in DPC context and the message to the
+ SoftMAC to put the device into BMPS will be sent at the end of DPC processing. Instead
+ we set a short timer and start the BMPS exit sequence when the timer fires. */
+ if (palTimerStart(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer, 1000, FALSE) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot start exit power save mode timer\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+
+#else
+ /* Start exit BMPS sequence now. */
+ smsLog(pMac, LOGW, FL("Pending Full Power request found on entering BMPS mode. "
+ "Start exit BMPS exit sequence\n"));
+ //Note: Reason must have been set when requestFullPowerPending flag was set.
+ pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
+ return eHAL_STATUS_SUCCESS;
+#endif
+ }
+
+ /*This should never happen ideally. WOWL and UAPSD not supported at the same time */
+ if (pMac->pmc.wowlModeRequired && pMac->pmc.uapsdSessionRequired)
+ {
+ smsLog(pMac, LOGW, FL("Both UAPSD and WOWL is required on entering BMPS mode. "
+ "UAPSD will be prioritized over WOWL\n"));
+ }
+
+ /* Do we need Uapsd?*/
+ if (pMac->pmc.uapsdSessionRequired)
+ {
+ smsLog(pMac, LOGW, FL("UAPSD session is required on entering BMPS mode. "
+ "Start UAPSD entry sequence\n"));
+ pmcEnterRequestStartUapsdState(hHal);
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ /* Do we need WOWL?*/
+ if (pMac->pmc.wowlModeRequired)
+ {
+ smsLog(pMac, LOGW, FL("WOWL is required on entering BMPS mode. "
+ "Start WOWL entry sequence\n"));
+ pmcRequestEnterWowlState(hHal, &(pMac->pmc.wowlEnterParams));
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcPowerSaveCheck
+*
+* Description:
+* Check if device is allowed to enter a power save mode.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* TRUE - entry is allowed
+* FALSE - entry is not allowed at this time
+*
+******************************************************************************/
+tANI_BOOLEAN pmcPowerSaveCheck (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tListElem *pEntry;
+ tpPowerSaveCheckEntry pPowerSaveCheckEntry;
+ tANI_BOOLEAN (*checkRoutine) (void *checkContext);
+ tANI_BOOLEAN bResult=FALSE;
+
+ smsLog(pMac, LOG2, FL("Entering pmcPowerSaveCheck\n"));
+
+ /* Call the routines in the power save check routine list. If any
+ return FALSE, then we cannot go into power save mode. */
+ pEntry = csrLLPeekHead(&pMac->pmc.powerSaveCheckList, FALSE);
+ while (pEntry != NULL)
+ {
+ pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link);
+ checkRoutine = pPowerSaveCheckEntry->checkRoutine;
+
+ /* If the checkRoutine is NULL for a paricular entry, proceed with other entries
+ * in the list */
+ if (NULL != checkRoutine)
+ {
+ if (!checkRoutine(pPowerSaveCheckEntry->checkContext))
+ {
+ smsLog(pMac, LOGE, FL("pmcPowerSaveCheck fail!\n"));
+ bResult = FALSE;
+ break;
+ }
+ else
+ {
+ bResult = TRUE;
+ }
+ }
+ pEntry = csrLLNext(&pMac->pmc.powerSaveCheckList, pEntry, FALSE);
+ }
+
+ return bResult;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcSendPowerSaveConfigMessage
+*
+* Description:
+* Send a message to PE/MAC to configure the power saving modes.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - message successfuly sent
+* eHAL_STATUS_FAILURE - error while sending message
+*
+******************************************************************************/
+eHalStatus pmcSendPowerSaveConfigMessage (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tSirPowerSaveCfg powerSaveConfig;
+
+ smsLog(pMac, LOG2, FL("Entering pmcSendPowerSaveConfigMessage\n"));
+
+ palZeroMemory(pMac->hHdd, &(powerSaveConfig), sizeof(tSirPowerSaveCfg));
+
+ switch (pMac->pmc.bmpsConfig.forwardBeacons)
+ {
+ case ePMC_NO_BEACONS:
+ powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NONE;
+ break;
+ case ePMC_BEACONS_WITH_TIM_SET:
+ powerSaveConfig.beaconFwd = ePM_BEACON_FWD_TIM;
+ break;
+ case ePMC_BEACONS_WITH_DTIM_SET:
+ powerSaveConfig.beaconFwd = ePM_BEACON_FWD_DTIM;
+ break;
+ case ePMC_NTH_BEACON:
+ powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NTH;
+ powerSaveConfig.nthBeaconFwd = (tANI_U16)pMac->pmc.bmpsConfig.valueOfN;
+ break;
+ case ePMC_ALL_BEACONS:
+ powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NTH;
+ powerSaveConfig.nthBeaconFwd = 1;
+ break;
+ }
+ powerSaveConfig.fEnablePwrSaveImmediately = pMac->pmc.bmpsConfig.setPmOnLastFrame;
+ powerSaveConfig.fPSPoll = pMac->pmc.bmpsConfig.usePsPoll;
+ powerSaveConfig.fEnableBeaconEarlyTermination =
+ pMac->pmc.bmpsConfig.enableBeaconEarlyTermination;
+ powerSaveConfig.bcnEarlyTermWakeInterval =
+ pMac->pmc.bmpsConfig.bcnEarlyTermWakeInterval;
+
+ /* setcfg for listenInterval. Make sure CFG is updated because PE reads this
+ from CFG at the time of assoc or reassoc */
+ ccmCfgSetInt(pMac, WNI_CFG_LISTEN_INTERVAL, pMac->pmc.bmpsConfig.bmpsPeriod,
+ NULL, eANI_BOOLEAN_FALSE);
+
+ if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS )
+ {
+ //Wake up the chip first
+ eHalStatus status = pmcDeferMsg( pMac, eWNI_PMC_PWR_SAVE_CFG,
+ &powerSaveConfig, sizeof(tSirPowerSaveCfg) );
+
+ if( eHAL_STATUS_PMC_PENDING == status )
+ {
+ return eHAL_STATUS_SUCCESS;
+ }
+ else
+ {
+ //either fail or already in full power
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ return ( status );
+ }
+ //else let it through because it is in full power state
+ }
+ }
+ /* Send a message so that FW System config is also updated and is in sync with
+ the CFG.*/
+ if (pmcSendMessage(hHal, eWNI_PMC_PWR_SAVE_CFG, &powerSaveConfig, sizeof(tSirPowerSaveCfg))
+ != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Send of eWNI_PMC_PWR_SAVE_CFG to PE failed\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcSendMessage
+*
+* Description:
+* Send a message to PE/MAC.
+*
+* Parameters:
+* hHal - HAL handle for device
+* messageType - message type to send
+* pMessageData - pointer to message data
+* messageSize - Size of the message data
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - message successfuly sent
+* eHAL_STATUS_FAILURE - error while sending message
+*
+******************************************************************************/
+eHalStatus pmcSendMessage (tpAniSirGlobal pMac, tANI_U16 messageType, void *pMessageData, tANI_U32 messageSize)
+{
+ tSirMbMsg *pMsg;
+
+ smsLog(pMac, LOG2, FL("Entering pmcSendMessage, message type %d\n"), messageType);
+
+ /* Allocate and fill in message. */
+ if (palAllocateMemory(pMac->hHdd, (void **)&pMsg, WNI_CFG_MB_HDR_LEN + messageSize) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot allocate memory for message\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+ pMsg->type = messageType;
+ pMsg->msgLen = (tANI_U16) (WNI_CFG_MB_HDR_LEN + messageSize);
+ if (messageSize > 0)
+ {
+ if (palCopyMemory(pMac->hHdd, pMsg->data, pMessageData, messageSize) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot copy message data\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+
+ /* Send message. */
+ if (palSendMBMessage(pMac->hHdd, pMsg) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot send message\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcDoCallbacks
+*
+* Description:
+* Call the IMPS callback routine and the routines in the request full
+* power callback routine list.
+*
+* Parameters:
+* hHal - HAL handle for device
+* callbackStatus - status to pass to the callback routines
+*
+* Returns:
+* nothing
+*
+******************************************************************************/
+void pmcDoCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tListElem *pEntry;
+ tpRequestFullPowerEntry pRequestFullPowerEntry;
+
+ smsLog(pMac, LOG2, FL("Entering pmcDoCallbacks\n"));
+
+ /* Call IMPS callback routine. */
+ if (pMac->pmc.impsCallbackRoutine != NULL)
+ {
+ pMac->pmc.impsCallbackRoutine(pMac->pmc.impsCallbackContext, callbackStatus);
+ pMac->pmc.impsCallbackRoutine = NULL;
+ }
+
+ /* Call the routines in the request full power callback routine list. */
+ while (NULL != (pEntry = csrLLRemoveHead(&pMac->pmc.requestFullPowerList, TRUE)))
+ {
+ pRequestFullPowerEntry = GET_BASE_ADDR(pEntry, tRequestFullPowerEntry, link);
+ if (pRequestFullPowerEntry->callbackRoutine)
+ pRequestFullPowerEntry->callbackRoutine(pRequestFullPowerEntry->callbackContext, callbackStatus);
+ if (palFreeMemory(pMac->hHdd, pRequestFullPowerEntry) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot free request full power routine list entry\n"));
+ PMC_ABORT;
+ }
+ }
+
+}
+
+
+/******************************************************************************
+*
+* Name: pmcStartTrafficTimer
+*
+* Description:
+* Start the timer used in Full Power State to measure traffic
+* levels and determine when to enter BMPS.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - timer successfuly started
+* eHAL_STATUS_FAILURE - error while starting timer
+*
+******************************************************************************/
+eHalStatus pmcStartTrafficTimer (tHalHandle hHal, tANI_U32 expirationTime)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ VOS_STATUS vosStatus;
+
+ smsLog(pMac, LOG2, FL("Entering pmcStartTrafficTimer\n"));
+
+ vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, expirationTime);
+ if ( !VOS_IS_STATUS_SUCCESS(vosStatus) )
+ {
+ if( VOS_STATUS_E_ALREADY == vosStatus )
+ {
+ //Consider this ok since the timer is already started.
+ smsLog(pMac, LOGW, FL(" traffic timer is already started\n"));
+ }
+ else
+ {
+ smsLog(pMac, LOGP, FL("Cannot start traffic timer\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcStopTrafficTimer
+*
+* Description:
+* Cancels the timer (if running) used in Full Power State to measure traffic
+* levels and determine when to enter BMPS.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+*
+******************************************************************************/
+void pmcStopTrafficTimer (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ smsLog(pMac, LOG2, FL("Entering pmcStopTrafficTimer\n"));
+ vos_timer_stop(&pMac->pmc.hTrafficTimer);
+}
+
+
+/******************************************************************************
+*
+* Name: pmcImpsTimerExpired
+*
+* Description:
+* Called when IMPS timer expires.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* nothing
+*
+******************************************************************************/
+void pmcImpsTimerExpired (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcImpsTimerExpired\n"));
+
+ /* If timer expires and we are in a state other than IMPS State then something is wrong. */
+ if (pMac->pmc.pmcState != IMPS)
+ {
+ smsLog(pMac, LOGE, FL("Got IMPS timer expiration in state %d\n"), pMac->pmc.pmcState);
+ PMC_ABORT;
+ return;
+ }
+
+ /* Start on the path of going back to full power. */
+ pmcEnterRequestFullPowerState(hHal, eSME_REASON_OTHER);
+}
+
+
+/******************************************************************************
+*
+* Name: pmcTrafficTimerExpired
+*
+* Description:
+* Called when traffic measurement timer expires.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* nothing
+*
+******************************************************************************/
+void pmcTrafficTimerExpired (tHalHandle hHal)
+{
+
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ VOS_STATUS vosStatus;
+
+ smsLog(pMac, LOGW, FL("BMPS Traffic timer expired"));
+
+ /* If timer expires and we are in a state other than Full Power State then something is wrong. */
+ if (pMac->pmc.pmcState != FULL_POWER)
+ {
+ smsLog(pMac, LOGE, FL("Got traffic timer expiration in state %d"), pMac->pmc.pmcState);
+ return;
+ }
+
+ /* Untill DHCP is not completed remain in power active */
+ if(pMac->pmc.remainInPowerActiveTillDHCP)
+ {
+ smsLog(pMac, LOGE, FL("BMPS Traffic Timer expired before DHCP completion ignore enter BMPS\n"));
+ pMac->pmc.remainInPowerActiveThreshold++;
+ if( pMac->pmc.remainInPowerActiveThreshold >= DHCP_REMAIN_POWER_ACTIVE_THRESHOLD)
+ {
+ smsLog(pMac, LOGE, FL("Remain in power active DHCP threshold reached FALLBACK to enable enter BMPS\n"));
+ /*FALLBACK: reset the flag to make BMPS entry possible*/
+ pMac->pmc.remainInPowerActiveTillDHCP = FALSE;
+ pMac->pmc.remainInPowerActiveThreshold = 0;
+ }
+ //Activate the Traffic Timer again for entering into BMPS
+ vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ if ( !VOS_IS_STATUS_SUCCESS(vosStatus) && (VOS_STATUS_E_ALREADY != vosStatus) )
+ {
+ smsLog(pMac, LOGP, FL("Cannot re-start traffic timer\n"));
+ }
+ return;
+ }
+
+ /* Clear remain in power active threshold */
+ pMac->pmc.remainInPowerActiveThreshold = 0;
+
+ /* Check if the timer should be running */
+ if (!pmcShouldBmpsTimerRun(pMac))
+ {
+ smsLog(pMac, LOGE, FL("BMPS timer should not be running"));
+ return;
+ }
+
+ if (pmcPowerSaveCheck(hHal))
+ {
+ smsLog(pMac, LOGW, FL("BMPS entry criteria satisfied. Requesting BMPS state"));
+ (void)pmcEnterRequestBmpsState(hHal);
+ }
+ else
+ {
+ /*Some module voted against Power Save. So timer should be restarted again to retry BMPS */
+ smsLog(pMac, LOGE, FL("Power Save check failed. Retry BMPS again later"));
+ //Since hTrafficTimer is a vos_timer now, we need to restart the timer here
+ vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ if ( !VOS_IS_STATUS_SUCCESS(vosStatus) && (VOS_STATUS_E_ALREADY != vosStatus) )
+ {
+ smsLog(pMac, LOGP, FL("Cannot start traffic timer\n"));
+ return;
+ }
+ }
+}
+
+
+/******************************************************************************
+*
+* Name: pmcExitPowerSaveTimerExpired
+*
+* Description:
+* Called when timer used to schedule a deferred power save mode exit expires.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* nothing
+*
+******************************************************************************/
+void pmcExitPowerSaveTimerExpired (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcExitPowerSaveTimerExpired\n"));
+
+ /* Make sure process of exiting power save mode might hasn't already been started due to another trigger. */
+ if (pMac->pmc.requestFullPowerPending)
+
+ /* Start on the path of going back to full power. */
+ pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
+}
+
+/******************************************************************************
+*
+* Name: pmcDoBmpsCallbacks
+*
+* Description:
+* Call the registered BMPS callback routines because device is unable to
+* enter BMPS state
+*
+* Parameters:
+* hHal - HAL handle for device
+* callbackStatus - Success or Failure.
+*
+* Returns:
+* nothing
+*
+******************************************************************************/
+void pmcDoBmpsCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tListElem *pEntry;
+ tpRequestBmpsEntry pRequestBmpsEntry;
+
+ smsLog(pMac, LOG2, "PMC: entering pmcDoBmpsCallbacks\n");
+
+ /* Call the routines in the request BMPS callback routine list. */
+ pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE);
+ while (pEntry != NULL)
+ {
+ pRequestBmpsEntry = GET_BASE_ADDR(pEntry, tRequestBmpsEntry, link);
+ if (pRequestBmpsEntry->callbackRoutine)
+ pRequestBmpsEntry->callbackRoutine(pRequestBmpsEntry->callbackContext,
+ callbackStatus);
+ palFreeMemory(pMac->hHdd, pRequestBmpsEntry);
+ pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE);
+ }
+}
+
+
+
+
+/******************************************************************************
+*
+* Name: pmcDoStartUapsdCallbacks
+*
+* Description:
+* Call the registered UAPSD callback routines because device is unable to
+* start UAPSD state
+*
+* Parameters:
+* hHal - HAL handle for device
+* callbackStatus - Success or Failure.
+*
+* Returns:
+* nothing
+*
+******************************************************************************/
+void pmcDoStartUapsdCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tListElem *pEntry;
+ tpStartUapsdEntry pStartUapsdEntry;
+
+ smsLog(pMac, LOG2, "PMC: entering pmcDoStartUapsdCallbacks\n");
+
+ /* Call the routines in the request start UAPSD callback routine list. */
+ pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE);
+ while (pEntry != NULL)
+ {
+ pStartUapsdEntry = GET_BASE_ADDR(pEntry, tStartUapsdEntry, link);
+ pStartUapsdEntry->callbackRoutine(pStartUapsdEntry->callbackContext,
+ callbackStatus);
+ palFreeMemory(pMac->hHdd, pStartUapsdEntry);
+ pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE);
+ }
+}
+
+/******************************************************************************
+*
+* Name: pmcEnterRequestStartUapsdState
+*
+* Description:
+* Have the device enter the UAPSD State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterRequestStartUapsdState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ v_BOOL_t fFullPower = VOS_FALSE; //need to get back to full power state
+
+ smsLog(pMac, LOG2, "PMC: entering pmcEnterRequestStartUapsdState\n");
+
+ /* Can enter UAPSD State only from FULL_POWER or BMPS State. */
+ switch (pMac->pmc.pmcState)
+ {
+ case FULL_POWER:
+ /* Check that entry into a power save mode is allowed at this time. */
+ if (!pmcPowerSaveCheck(hHal))
+ {
+ smsLog(pMac, LOGW, "PMC: Power save check failed. UAPSD request "
+ "will be accepted and buffered\n");
+ /* UAPSD mode will be attempted when we enter BMPS later */
+ pMac->pmc.uapsdSessionRequired = TRUE;
+ /* Make sure the BMPS retry timer is running */
+ if(pmcShouldBmpsTimerRun(pMac))
+ (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ break;
+ }
+ else
+ {
+ pMac->pmc.uapsdSessionRequired = TRUE;
+ //Check BTC state
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ if( btcIsReadyForUapsd( pMac ) )
+#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
+ {
+ /* Put device in BMPS mode first. This step should NEVER fail.
+ That is why no need to buffer the UAPSD request*/
+ if(pmcEnterRequestBmpsState(hHal) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: Device in Full Power. Enter Request Bmps failed. "
+ "UAPSD request will be dropped \n");
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ else
+ {
+ (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ }
+#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
+ }
+ break;
+
+ case BMPS:
+ //It is already in BMPS mode, check BTC state
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ if( btcIsReadyForUapsd(pMac) )
+#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
+ {
+ /* Tell MAC to have device enter UAPSD mode. */
+ if (pmcIssueCommand(hHal, eSmeCommandEnterUapsd, NULL, 0, FALSE) !=
+ eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message "
+ "eWNI_PMC_ENTER_BMPS_REQ\n");
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ else
+ {
+ //Not ready for UAPSD at this time, save it first and wake up the chip
+ smsLog(pMac, LOGE, " PMC state = %d\n",pMac->pmc.pmcState);
+ pMac->pmc.uapsdSessionRequired = TRUE;
+ /* While BTC traffic is going on, STA can be in BMPS
+ * and need not go to Full Power */
+ //fFullPower = VOS_TRUE;
+ }
+#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
+ break;
+
+ case REQUEST_START_UAPSD:
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ if( !btcIsReadyForUapsd(pMac) )
+ {
+ //BTC rejects UAPSD, bring it back to full power
+ fFullPower = VOS_TRUE;
+ }
+#endif
+ break;
+
+ case REQUEST_BMPS:
+ /* Buffer request for UAPSD mode. */
+ pMac->pmc.uapsdSessionRequired = TRUE;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ if( !btcIsReadyForUapsd(pMac) )
+ {
+ //BTC rejects UAPSD, bring it back to full power
+ fFullPower = VOS_TRUE;
+ }
+#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
+ break;
+
+ default:
+ smsLog(pMac, LOGE, "PMC: trying to enter UAPSD State from state %d\n",
+ pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if(fFullPower)
+ {
+ if( eHAL_STATUS_PMC_PENDING != pmcRequestFullPower( pMac, NULL, NULL, eSME_REASON_OTHER ) )
+ {
+ //This is an error
+ smsLog(pMac, LOGE, FL(" fail to request full power because BTC\n"));
+ }
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/******************************************************************************
+*
+* Name: pmcEnterUapsdState
+*
+* Description:
+* Have the device enter the UAPSD State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterUapsdState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, "PMC: entering pmcEnterUapsdState\n");
+
+ /* Can enter UAPSD State only from Request UAPSD State. */
+ if (pMac->pmc.pmcState != REQUEST_START_UAPSD )
+ {
+ smsLog(pMac, LOGE, "PMC: trying to enter UAPSD State from state %d\n",
+ pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Change state. */
+ pMac->pmc.pmcState = UAPSD;
+
+ /* Update registerd modules that we are entering UAPSD. This is
+ only way to inform modules if PMC resumed UAPSD power save mode
+ on its own after full power mode */
+ pmcDoDeviceStateUpdateCallbacks(hHal, UAPSD);
+
+ /* If we have a reqeust for full power pending then we have to go
+ directly into full power. */
+ if (pMac->pmc.requestFullPowerPending)
+ {
+ /* Start exit UAPSD sequence now. */
+ return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcEnterRequestStopUapsdState
+*
+* Description:
+* Have the device Stop the UAPSD State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterRequestStopUapsdState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, "PMC: entering pmcEnterRequestStopUapsdState\n");
+
+ /* If already in REQUEST_STOP_UAPSD, simply return */
+ if (pMac->pmc.pmcState == REQUEST_STOP_UAPSD)
+ {
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ /* Can enter Request Stop UAPSD State only from UAPSD */
+ if (pMac->pmc.pmcState != UAPSD)
+ {
+ smsLog(pMac, LOGE, "PMC: trying to enter Request Stop UAPSD State from "
+ "state %d\n", pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Tell MAC to have device exit UAPSD mode. */
+ if (pmcIssueCommand(hHal, eSmeCommandExitUapsd, NULL, 0, FALSE) !=
+ eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message "
+ "eWNI_PMC_EXIT_UAPSD_REQ\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/******************************************************************************
+*
+* Name: pmcEnterRequestStandbyState
+*
+* Description:
+* Have the device enter the Request STANDBY State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterRequestStandbyState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, "PMC: entering pmcEnterRequestStandbyState\n");
+
+ /* Can enter Standby State only from Full Power State. */
+ if (pMac->pmc.pmcState != FULL_POWER)
+ {
+ smsLog(pMac, LOGE, "PMC: trying to enter Standby State from "
+ "state %d\n", pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ // Stop traffic timer. Just making sure timer is not running
+ pmcStopTrafficTimer(hHal);
+
+ /* Tell MAC to have device enter STANDBY mode. We are using the same message
+ as IMPS mode to avoid code changes in layer below (PE/HAL)*/
+ if (pmcIssueCommand(hHal, eSmeCommandEnterStandby, NULL, 0, FALSE) !=
+ eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message "
+ "eWNI_PMC_ENTER_IMPS_REQ\n");
+ pMac->pmc.pmcState = FULL_POWER;
+
+ if(pmcShouldBmpsTimerRun(pMac))
+ (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/******************************************************************************
+*
+* Name: pmcEnterStandbyState
+*
+* Description:
+* Have the device enter the STANDBY State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterStandbyState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ vos_call_status_type callType;
+ VOS_STATUS status;
+
+ smsLog(pMac, LOG2, "PMC: entering pmcEnterStandbyState\n");
+
+ /* Can enter STANDBY State only from REQUEST_STANDBY State. */
+ if (pMac->pmc.pmcState != REQUEST_STANDBY)
+ {
+ smsLog(pMac, LOGE, "PMC: trying to enter STANDBY State from state %d\n",
+ pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Change state. */
+ pMac->pmc.pmcState = STANDBY;
+
+ /* If we have a reqeust for full power pending then we have to go
+ directly into full power. */
+ if (pMac->pmc.requestFullPowerPending)
+ {
+ /* Start exit STANDBY sequence now. */
+ return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
+ }
+
+ //Note that RF supplies are not voted off if there is already a pending request
+ //for full power
+ status = vos_chipVoteOffRFSupply(&callType, NULL, NULL);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
+
+ status = vos_chipVoteOffXOBuffer(&callType, NULL, NULL);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
+
+ pMac->pmc.rfSuppliesVotedOff= TRUE;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/******************************************************************************
+*
+* Name: pmcDoStandbyCallbacks
+*
+* Description:
+* Call the registered Standby callback routines
+*
+* Parameters:
+* hHal - HAL handle for device
+* callbackStatus - Success or Failure.
+*
+* Returns:
+* nothing
+*
+******************************************************************************/
+void pmcDoStandbyCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, "PMC: entering pmcDoStandbyCallbacks\n");
+
+ /* Call Standby callback routine. */
+ if (pMac->pmc.standbyCallbackRoutine != NULL)
+ pMac->pmc.standbyCallbackRoutine(pMac->pmc.standbyCallbackContext, callbackStatus);
+ pMac->pmc.standbyCallbackRoutine = NULL;
+ pMac->pmc.standbyCallbackContext = NULL;
+}
+
+/******************************************************************************
+*
+* Name: pmcGetPmcState
+*
+* Description:
+* Return the PMC state
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* tPmcState (one of IMPS, REQUEST_IMPS, BMPS, REQUEST_BMPS etc)
+*
+******************************************************************************/
+tPmcState pmcGetPmcState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ return pMac->pmc.pmcState;
+}
+
+const char* pmcGetPmcStateStr(tPmcState state)
+{
+ switch(state)
+ {
+ case STOPPED:
+ return "STOPPED";
+ case FULL_POWER:
+ return "FULL_POWER";
+ case LOW_POWER:
+ return "LOW_POWER";
+ case IMPS:
+ return "IMPS";
+ case BMPS:
+ return "BMPS";
+ case UAPSD:
+ return "UAPSD";
+ case STANDBY:
+ return "STANDBY";
+ case REQUEST_IMPS:
+ return "REQUEST_IMPS";
+ case REQUEST_BMPS:
+ return "REQUEST_BMPS";
+ case REQUEST_START_UAPSD:
+ return "REQUEST_START_UAPSD";
+ case REQUEST_STOP_UAPSD:
+ return "REQUEST_STOP_UAPSD";
+ case REQUEST_FULL_POWER:
+ return "REQUEST_FULL_POWER";
+ case REQUEST_STANDBY:
+ return "REQUEST_STANDBY";
+ case REQUEST_ENTER_WOWL:
+ return "REQUEST_ENTER_WOWL";
+ case REQUEST_EXIT_WOWL:
+ return "REQUEST_EXIT_WOWL";
+ case WOWL:
+ return "WOWL";
+ default:
+ break;
+ }
+
+ return "UNKNOWN";
+}
+
+void pmcDoDeviceStateUpdateCallbacks (tHalHandle hHal, tPmcState state)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tListElem *pEntry;
+ tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry;
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState);
+
+ smsLog(pMac, LOG2, FL("PMC - Update registered modules of new device "
+ "state: %s\n"), pmcGetPmcStateStr(state));
+
+ /* Call the routines in the update device state routine list. */
+ pEntry = csrLLPeekHead(&pMac->pmc.deviceStateUpdateIndList, FALSE);
+ while (pEntry != NULL)
+ {
+ pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link);
+ callbackRoutine = pDeviceStateUpdateIndEntry->callbackRoutine;
+ callbackRoutine(pDeviceStateUpdateIndEntry->callbackContext, state);
+ pEntry = csrLLNext(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE);
+ }
+}
+
+/******************************************************************************
+*
+* Name: pmcRequestEnterWowlState
+*
+* Description:
+* Have the device enter the WOWL State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - WOWL mode will be entered
+* eHAL_STATUS_FAILURE - WOWL mode cannot be entered
+*
+******************************************************************************/
+eHalStatus pmcRequestEnterWowlState(tHalHandle hHal, tpSirSmeWowlEnterParams wowlEnterParams)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ smsLog(pMac, LOG2, "PMC: entering pmcRequestEnterWowlState\n");
+
+ switch (pMac->pmc.pmcState)
+ {
+ case FULL_POWER:
+ /* Put device in BMPS mode first. This step should NEVER fail. */
+ if(pmcEnterRequestBmpsState(hHal) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: Device in Full Power. pmcEnterRequestBmpsState failed. "
+ "Cannot enter WOWL\n");
+ return eHAL_STATUS_FAILURE;
+ }
+ break;
+
+ case REQUEST_BMPS:
+ smsLog(pMac, LOGW, "PMC: BMPS transaction going on. WOWL request "
+ "will be buffered\n");
+ break;
+
+ case BMPS:
+ case WOWL:
+ /* Tell MAC to have device enter WOWL mode. Note: We accept WOWL request
+ when we are in WOWL mode. This allows HDD to change WOWL configuration
+ without having to exit WOWL mode */
+ if (pmcIssueCommand(hHal, eSmeCommandEnterWowl, wowlEnterParams, sizeof(tSirSmeWowlEnterParams), FALSE) !=
+ eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ\n");
+ return eHAL_STATUS_FAILURE;
+ }
+ break;
+
+ case REQUEST_ENTER_WOWL:
+ //Multiple enter WOWL requests at the same time are not accepted
+ smsLog(pMac, LOGE, "PMC: Enter WOWL transaction already going on. New WOWL request "
+ "will be rejected\n");
+ return eHAL_STATUS_FAILURE;
+
+ case REQUEST_EXIT_WOWL:
+ smsLog(pMac, LOGW, "PMC: Exit WOWL transaction going on. New WOWL request "
+ "will be buffered\n");
+ break;
+
+ default:
+ smsLog(pMac, LOGE, "PMC: Trying to enter WOWL State from state %s\n",
+ pmcGetPmcStateStr(pMac->pmc.pmcState));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/******************************************************************************
+*
+* Name: pmcEnterWowlState
+*
+* Description:
+* Have the device enter the WOWL State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - changing state successful
+* eHAL_STATUS_FAILURE - changing state not successful
+*
+******************************************************************************/
+eHalStatus pmcEnterWowlState (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, "PMC: entering pmcEnterWowlState\n");
+
+ /* Can enter WOWL State only from Request WOWL State. */
+ if (pMac->pmc.pmcState != REQUEST_ENTER_WOWL )
+ {
+ smsLog(pMac, LOGP, "PMC: trying to enter WOWL State from state %d\n",
+ pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Change state. */
+ pMac->pmc.pmcState = WOWL;
+
+ /* Clear the buffered command for WOWL */
+ pMac->pmc.wowlModeRequired = FALSE;
+
+ /* If we have a reqeust for full power pending then we have to go
+ directly into full power. */
+ if (pMac->pmc.requestFullPowerPending)
+ {
+ /* Start exit Wowl sequence now. */
+ return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/******************************************************************************
+*
+* Name: pmcRequestExitWowlState
+*
+* Description:
+* Have the device exit WOWL State.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - Exit WOWL successful
+* eHAL_STATUS_FAILURE - Exit WOWL unsuccessful
+*
+******************************************************************************/
+eHalStatus pmcRequestExitWowlState(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, "PMC: entering pmcRequestExitWowlState\n");
+
+ switch (pMac->pmc.pmcState)
+ {
+ case WOWL:
+ /* Tell MAC to have device exit WOWL mode. */
+ if (pmcIssueCommand(hHal, eSmeCommandExitWowl, NULL, 0, FALSE) !=
+ eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ\n");
+ return eHAL_STATUS_FAILURE;
+ }
+ break;
+
+ case REQUEST_ENTER_WOWL:
+ smsLog(pMac, LOGP, "PMC: Rcvd exit WOWL even before enter WOWL was completed\n");
+ return eHAL_STATUS_FAILURE;
+
+ default:
+ smsLog(pMac, LOGW, "PMC: Got exit WOWL in state %s. Nothing to do as already out of WOWL\n",
+ pmcGetPmcStateStr(pMac->pmc.pmcState));
+ break;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/******************************************************************************
+*
+* Name: pmcDoEnterWowlCallbacks
+*
+* Description:
+* Invoke Enter WOWL callbacks
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns: None
+*
+******************************************************************************/
+void pmcDoEnterWowlCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, "PMC: entering pmcDoWowlCallbacks\n");
+
+ /* Call Wowl callback routine. */
+ if (pMac->pmc.enterWowlCallbackRoutine != NULL)
+ pMac->pmc.enterWowlCallbackRoutine(pMac->pmc.enterWowlCallbackContext, callbackStatus);
+
+ pMac->pmc.enterWowlCallbackRoutine = NULL;
+ pMac->pmc.enterWowlCallbackContext = NULL;
+}
+
+
+static void pmcProcessDeferredMsg( tpAniSirGlobal pMac )
+{
+ tPmcDeferredMsg *pDeferredMsg;
+ tListElem *pEntry;
+
+ while( NULL != ( pEntry = csrLLRemoveHead( &pMac->pmc.deferredMsgList, eANI_BOOLEAN_TRUE ) ) )
+ {
+ pDeferredMsg = GET_BASE_ADDR( pEntry, tPmcDeferredMsg, link );
+ switch (pDeferredMsg->messageType)
+ {
+ case eWNI_PMC_WOWL_ADD_BCAST_PTRN:
+ VOS_ASSERT( pDeferredMsg->size == sizeof(tSirWowlAddBcastPtrn) );
+ if (pmcSendMessage(pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN,
+ &pDeferredMsg->u.wowlAddPattern, sizeof(tSirWowlAddBcastPtrn))
+ != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed\n"));
+ }
+ break;
+
+ case eWNI_PMC_WOWL_DEL_BCAST_PTRN:
+ VOS_ASSERT( pDeferredMsg->size == sizeof(tSirWowlDelBcastPtrn) );
+ if (pmcSendMessage(pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN,
+ &pDeferredMsg->u.wowlDelPattern, sizeof(tSirWowlDelBcastPtrn))
+ != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed\n"));
+ }
+ break;
+
+ case eWNI_PMC_PWR_SAVE_CFG:
+ VOS_ASSERT( pDeferredMsg->size == sizeof(tSirPowerSaveCfg) );
+ if (pmcSendMessage(pMac, eWNI_PMC_PWR_SAVE_CFG,
+ &pDeferredMsg->u.powerSaveConfig, sizeof(tSirPowerSaveCfg))
+ != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Send of eWNI_PMC_PWR_SAVE_CFG to PE failed\n"));
+ }
+ break;
+
+ default:
+ smsLog(pMac, LOGE, FL("unknown message (%d)\n"), pDeferredMsg->messageType);
+ break;
+ }
+ //Need to free the memory here
+ palFreeMemory( pMac->hHdd, pDeferredMsg );
+ } //while
+}
+
+
+eHalStatus pmcDeferMsg( tpAniSirGlobal pMac, tANI_U16 messageType, void *pData, tANI_U32 size)
+{
+ tPmcDeferredMsg *pDeferredMsg;
+ eHalStatus status;
+
+ if( !HAL_STATUS_SUCCESS( palAllocateMemory( pMac->hHdd, (void **)&pDeferredMsg, sizeof(tPmcDeferredMsg) ) ) )
+ {
+ smsLog(pMac, LOGE, FL("Cannot allocate memory for callback context\n"));
+ return eHAL_STATUS_RESOURCES;
+ }
+ palZeroMemory( pMac->hHdd, pDeferredMsg, sizeof(tPmcDeferredMsg) );
+ pDeferredMsg->messageType = messageType;
+ pDeferredMsg->size = (tANI_U16)size;
+ if( pData )
+ {
+ if( !HAL_STATUS_SUCCESS( palCopyMemory( pMac->hHdd, &pDeferredMsg->u.data,
+ pData, size ) ) )
+ {
+ smsLog(pMac, LOGE, FL("Cannot copy pattern for callback context\n"));
+ palFreeMemory( pMac->hHdd, pDeferredMsg );
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+ csrLLInsertTail( &pMac->pmc.deferredMsgList, &pDeferredMsg->link, eANI_BOOLEAN_TRUE );
+ //No callback is needed. The messages are put into deferred queue and be processed first
+ //when enter full power is complete.
+ status = pmcRequestFullPower( pMac, NULL, NULL, eSME_REASON_OTHER );
+ if( eHAL_STATUS_PMC_PENDING != status )
+ {
+ //either fail or already in full power
+ if( csrLLRemoveEntry( &pMac->pmc.deferredMsgList, &pDeferredMsg->link, eANI_BOOLEAN_TRUE ) )
+ {
+ palFreeMemory( pMac->hHdd, pDeferredMsg );
+ }
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog(pMac, LOGE, FL("failed to request full power status = %d\n"), status);
+ }
+ }
+
+ return (status);
+}
+
+void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ if(!pCommand->u.pmcCmd.fReleaseWhenDone)
+ {
+ //This is a normal command, put it back to the free lsit
+ pCommand->u.pmcCmd.size = 0;
+ smeReleaseCommand( pMac, pCommand );
+ }
+ else
+ {
+ //this is a specially allocated comamnd due to out of command buffer. free it.
+ palFreeMemory(pMac->hHdd, pCommand);
+ }
+}
+
+
+//this function is used to abort a command where the normal processing of the command
+//is terminated without going through the normal path. it is here to take care of callbacks for
+//the command, if applicable.
+void pmcAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping )
+{
+ if( eSmePmcCommandMask & pCommand->command )
+ {
+ if( !fStopping )
+ {
+ switch( pCommand->command )
+ {
+ case eSmeCommandEnterImps:
+ smsLog(pMac, LOGE, FL("aborting request to enter IMPS\n"));
+ pmcEnterFullPowerState(pMac);
+ break;
+
+ case eSmeCommandExitImps:
+ smsLog(pMac, LOGE, FL("aborting request to exit IMPS \n"));
+ pmcEnterFullPowerState(pMac);
+ break;
+
+ case eSmeCommandEnterBmps:
+ smsLog(pMac, LOGE, FL("aborting request to enter BMPS \n"));
+ pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
+ pmcEnterFullPowerState(pMac);
+ pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE);
+ break;
+
+ case eSmeCommandExitBmps:
+ smsLog(pMac, LOGE, FL("aborting request to exit BMPS \n"));
+ pmcEnterFullPowerState(pMac);
+ break;
+
+ case eSmeCommandEnterUapsd:
+ smsLog(pMac, LOGE, FL("aborting request to enter UAPSD \n"));
+ //Since there is no retry for UAPSD, tell the requester here we are done with failure
+ pMac->pmc.uapsdSessionRequired = FALSE;
+ pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE);
+ break;
+
+ case eSmeCommandExitUapsd:
+ smsLog(pMac, LOGE, FL("aborting request to exit UAPSD \n"));
+ break;
+
+ case eSmeCommandEnterWowl:
+ smsLog(pMac, LOGE, FL("aborting request to enter WOWL \n"));
+ pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE);
+ break;
+
+ case eSmeCommandExitWowl:
+ smsLog(pMac, LOGE, FL("aborting request to exit WOWL \n"));
+ break;
+
+ case eSmeCommandEnterStandby:
+ smsLog(pMac, LOGE, FL("aborting request to enter Standby \n"));
+ pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE);
+ break;
+
+ default:
+ smsLog(pMac, LOGE, FL("Request for PMC command (%d) is dropped\n"), pCommand->command);
+ break;
+ }
+ }// !stopping
+ pmcReleaseCommand( pMac, pCommand );
+ }
+}
+
+
+
+//These commands are not supposed to fail due to out of command buffer,
+//otherwise other commands are not executed and no command is released. It will be deadlock.
+#define PMC_IS_COMMAND_CANNOT_FAIL(cmdType)\
+ ( (eSmeCommandEnterStandby == (cmdType )) ||\
+ (eSmeCommandExitImps == (cmdType )) ||\
+ (eSmeCommandExitBmps == (cmdType )) ||\
+ (eSmeCommandExitUapsd == (cmdType )) ||\
+ (eSmeCommandExitWowl == (cmdType )) )
+
+eHalStatus pmcPrepareCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void *pvParam,
+ tANI_U32 size, tSmeCmd **ppCmd )
+{
+ eHalStatus status = eHAL_STATUS_RESOURCES;
+ tSmeCmd *pCommand = NULL;
+
+ VOS_ASSERT( ppCmd );
+ do
+ {
+ pCommand = smeGetCommandBuffer( pMac );
+ if ( pCommand )
+ {
+ //Make sure it will be put back to the list
+ pCommand->u.pmcCmd.fReleaseWhenDone = FALSE;
+ }
+ else
+ {
+ smsLog( pMac, LOGE, FL(" fail to get command buffer for command 0x%X curState = %d"), cmdType, pMac->pmc.pmcState );
+ //For certain PMC command, we cannot fail
+ if( PMC_IS_COMMAND_CANNOT_FAIL(cmdType) )
+ {
+ smsLog( pMac, LOGE, FL(" command 0x%X cannot fail try allocating memory for it"), cmdType );
+ status = palAllocateMemory(pMac->hHdd, (void **)&pCommand, sizeof(tSmeCmd));
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, "%s fail to allocate memory for command (0x%X)",
+ __FUNCTION__, cmdType);
+ pCommand = NULL;
+ break;
+ }
+ palZeroMemory(pMac->hHdd, pCommand, sizeof(tSmeCmd));
+ //Make sure it will be free when it is done
+ pCommand->u.pmcCmd.fReleaseWhenDone = TRUE;
+ }
+ else
+ {
+ break;
+ }
+ }
+ pCommand->command = cmdType;
+ pCommand->u.pmcCmd.size = size;
+ //Initialize the reason code here. It may be overwritten later when
+ //a particular reason is needed.
+ pCommand->u.pmcCmd.fullPowerReason = eSME_REASON_OTHER;
+ switch ( cmdType )
+ {
+ case eSmeCommandEnterImps:
+ case eSmeCommandExitImps:
+ case eSmeCommandEnterBmps:
+ case eSmeCommandEnterUapsd:
+ case eSmeCommandEnterStandby:
+ status = eHAL_STATUS_SUCCESS;
+ break;
+
+ case eSmeCommandExitUapsd:
+ case eSmeCommandExitWowl:
+ status = eHAL_STATUS_SUCCESS;
+ if( pvParam )
+ {
+ pCommand->u.pmcCmd.fullPowerReason = *( (tRequestFullPowerReason *)pvParam );
+ }
+ break;
+
+ case eSmeCommandExitBmps:
+ status = eHAL_STATUS_SUCCESS;
+ if( pvParam )
+ {
+ pCommand->u.pmcCmd.u.exitBmpsInfo = *( (tExitBmpsInfo *)pvParam );
+ pCommand->u.pmcCmd.fullPowerReason = pCommand->u.pmcCmd.u.exitBmpsInfo.exitBmpsReason;
+ }
+ else
+ {
+ smsLog( pMac, LOGE, (" exit BMPS must have a reason code\n") );
+ }
+ break;
+
+ case eSmeCommandEnterWowl:
+ status = eHAL_STATUS_SUCCESS;
+ if( pvParam )
+ {
+ pCommand->u.pmcCmd.u.enterWowlInfo = *( ( tSirSmeWowlEnterParams * )pvParam );
+ }
+ break;
+
+ default:
+ smsLog( pMac, LOGE, FL(" invalid command type %d\n"), cmdType );
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ } while( 0 );
+
+ if( HAL_STATUS_SUCCESS( status ) && pCommand )
+ {
+ *ppCmd = pCommand;
+ }
+ else if( pCommand )
+ {
+ pmcReleaseCommand( pMac, pCommand );
+ }
+
+ return (status);
+}
+
+
+eHalStatus pmcIssueCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void *pvParam,
+ tANI_U32 size, tANI_BOOLEAN fPutToListHead )
+{
+ eHalStatus status = eHAL_STATUS_RESOURCES;
+ tSmeCmd *pCommand = NULL;
+
+ status = pmcPrepareCommand( pMac, cmdType, pvParam, size, &pCommand );
+ if( HAL_STATUS_SUCCESS( status ) && pCommand )
+ {
+ smePushCommand( pMac, pCommand, fPutToListHead );
+ }
+
+ return( status );
+}
+
+
+
+tANI_BOOLEAN pmcProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tANI_BOOLEAN fRemoveCmd = eANI_BOOLEAN_TRUE;
+
+ do
+ {
+ switch ( pCommand->command )
+ {
+ case eSmeCommandEnterImps:
+ if( FULL_POWER == pMac->pmc.pmcState )
+ {
+ status = pmcEnterImpsCheck( pMac );
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ /* Change state. */
+ pMac->pmc.pmcState = REQUEST_IMPS;
+ status = pmcSendMessage(pMac, eWNI_PMC_ENTER_IMPS_REQ, NULL, 0);
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ /* If we already went back Full Power State (meaning that request did not
+ get as far as the device) then we are not successfull. */
+ if ( FULL_POWER != pMac->pmc.pmcState )
+ {
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ }
+ }
+ }
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_IMPS_REQ or pmcEnterImpsCheck failed\n");
+ pmcEnterFullPowerState( pMac );
+ if(pmcShouldBmpsTimerRun(pMac))
+ (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ }
+ }//full_power
+ break;
+
+ case eSmeCommandExitImps:
+ pMac->pmc.requestFullPowerPending = FALSE;
+ if( ( IMPS == pMac->pmc.pmcState ) || ( STANDBY == pMac->pmc.pmcState ) )
+ {
+ //Check state before sending message. The state may change after that
+ if( STANDBY == pMac->pmc.pmcState )
+ {
+ //Enable Idle scan in CSR
+ csrScanResumeIMPS(pMac);
+ }
+
+ status = pmcSendMessage(pMac, eWNI_PMC_EXIT_IMPS_REQ, NULL, 0);
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ pMac->pmc.pmcState = REQUEST_FULL_POWER;
+ smsLog(pMac, LOGW, FL("eWNI_PMC_EXIT_IMPS_REQ sent to PE\n"));
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("eWNI_PMC_EXIT_IMPS_REQ fail to be sent to PE status %d\n"), status);
+ //Callbacks are called with success srarus, do we need to pass in real status??
+ pmcEnterFullPowerState(pMac);
+ }
+ }
+ break;
+
+ case eSmeCommandEnterBmps:
+ if( FULL_POWER == pMac->pmc.pmcState )
+ {
+ //This function will not return success because the pmc state is not BMPS
+ status = pmcEnterBmpsCheck( pMac );
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ /* Change PMC state */
+ pMac->pmc.pmcState = REQUEST_BMPS;
+ smsLog(pMac, LOGW, "PMC: Enter BMPS req done: Force XO Core ON\n");
+ status = vos_chipVoteXOCore(NULL, NULL, NULL, VOS_TRUE);
+ if ( !VOS_IS_STATUS_SUCCESS(status) )
+ {
+ smsLog(pMac, LOGE, "Could not turn XO Core ON. Can't go to BMPS\n");
+ }
+ else /* XO Core turn ON was successful */
+ {
+ /* Tell MAC to have device enter BMPS mode. */
+ status = pmcSendMessage(pMac, eWNI_PMC_ENTER_BMPS_REQ, NULL, 0);
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "Fail to send enter BMPS msg to PE\n");
+ /* Cancel the vote for XO Core */
+ smsLog(pMac, LOGW, "In module init: Cancel the vote for XO CORE ON "
+ "since send enter bmps failed\n");
+ if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "Could not cancel XO Core ON vote."
+ "Not returning failure."
+ "Power consumed will be high\n");
+ }
+
+ }
+ }
+ }
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_BMPS_REQ status %d\n", status);
+ pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
+ pmcEnterFullPowerState(pMac);
+ //Do not call UAPSD callback here since it may be retried
+ pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE);
+ if(pmcShouldBmpsTimerRun(pMac))
+ (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ }
+ }
+ break;
+
+ case eSmeCommandExitBmps:
+ if( BMPS == pMac->pmc.pmcState )
+ {
+ pMac->pmc.requestFullPowerPending = FALSE;
+
+ status = pmcSendMessage( pMac, eWNI_PMC_EXIT_BMPS_REQ,
+ &pCommand->u.pmcCmd.u.exitBmpsInfo, sizeof(tExitBmpsInfo) );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ pMac->pmc.pmcState = REQUEST_FULL_POWER;
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ smsLog(pMac, LOGW, FL("eWNI_PMC_EXIT_BMPS_REQ sent to PE\n"));
+
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("eWNI_PMC_EXIT_BMPS_REQ fail to be sent to PE status %d\n"), status);
+ pmcEnterFullPowerState(pMac);
+ }
+ }
+ break;
+
+ case eSmeCommandEnterUapsd:
+ if( BMPS == pMac->pmc.pmcState )
+ {
+ pMac->pmc.uapsdSessionRequired = TRUE;
+ status = pmcSendMessage(pMac, eWNI_PMC_ENTER_UAPSD_REQ, NULL, 0);
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ pMac->pmc.pmcState = REQUEST_START_UAPSD;
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message "
+ "eWNI_PMC_ENTER_BMPS_REQ\n");
+ //there is no retry for re-entering UAPSD so tell the requester we are done witgh failure.
+ pMac->pmc.uapsdSessionRequired = FALSE;
+ pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE);
+ }
+ }
+ break;
+
+ case eSmeCommandExitUapsd:
+ if( UAPSD == pMac->pmc.pmcState )
+ {
+ pMac->pmc.requestFullPowerPending = FALSE;
+ /* If already in REQUEST_STOP_UAPSD, simply return */
+ if (pMac->pmc.pmcState == REQUEST_STOP_UAPSD)
+ {
+ break;
+ }
+
+ /* Tell MAC to have device exit UAPSD mode. */
+ status = pmcSendMessage(pMac, eWNI_PMC_EXIT_UAPSD_REQ, NULL, 0);
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ /* Change state. Note that device will be put in BMPS state at the
+ end of REQUEST_STOP_UAPSD state even if response is a failure*/
+ pMac->pmc.pmcState = REQUEST_STOP_UAPSD;
+ pMac->pmc.requestFullPowerPending = TRUE;
+ pMac->pmc.requestFullPowerReason = pCommand->u.pmcCmd.fullPowerReason;
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message "
+ "eWNI_PMC_EXIT_UAPSD_REQ\n");
+ pmcEnterBmpsState(pMac);
+ }
+ }
+
+ break;
+
+ case eSmeCommandEnterWowl:
+ if( ( BMPS == pMac->pmc.pmcState ) || ( WOWL == pMac->pmc.pmcState ) )
+ {
+ status = pmcSendMessage(pMac, eWNI_PMC_ENTER_WOWL_REQ,
+ &pCommand->u.pmcCmd.u.enterWowlInfo, sizeof(tSirSmeWowlEnterParams));
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ pMac->pmc.pmcState = REQUEST_ENTER_WOWL;
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ\n");
+ pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE);
+ }
+ }
+ else
+ {
+ fRemoveCmd = eANI_BOOLEAN_TRUE;
+ }
+ break;
+
+ case eSmeCommandExitWowl:
+ if( WOWL == pMac->pmc.pmcState )
+ {
+ pMac->pmc.requestFullPowerPending = FALSE;
+ pMac->pmc.pmcState = REQUEST_EXIT_WOWL;
+ status = pmcSendMessage(pMac, eWNI_PMC_EXIT_WOWL_REQ, NULL, 0);
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ pMac->pmc.requestFullPowerPending = TRUE;
+ pMac->pmc.requestFullPowerReason = pCommand->u.pmcCmd.fullPowerReason;
+ }
+ else
+ {
+ smsLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ\n");
+ pmcEnterBmpsState(pMac);
+ }
+ }
+ break;
+
+ case eSmeCommandEnterStandby:
+ if( FULL_POWER == pMac->pmc.pmcState )
+ {
+ //Disallow standby if concurrent sessions are present. Note that CSR would have
+ //caused the STA to disconnect the Infra session (if not already disconnected) because of
+ //standby request. But we are now failing the standby request because of concurrent session.
+ //So was the tearing of infra session wasteful if we were going to fail the standby request ?
+ //Not really. This is beacuse if and when BT-AMP etc sessions are torn down we will transition
+ //to IMPS/standby and still save power.
+ if (csrIsIBSSStarted(pMac) || csrIsBTAMPStarted(pMac))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "WLAN: IBSS or BT-AMP session present. Cannot honor standby request");
+
+ pmcDoStandbyCallbacks(pMac, eHAL_STATUS_PMC_NOT_NOW);
+ if(pmcShouldBmpsTimerRun(pMac))
+ (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ break;
+ }
+
+ // Stop traffic timer. Just making sure timer is not running
+ pmcStopTrafficTimer(pMac);
+
+ /* Change state. */
+ pMac->pmc.pmcState = REQUEST_STANDBY;
+
+ /* Tell MAC to have device enter STANDBY mode. We are using the same message
+ as IMPS mode to avoid code changes in layer below (PE/HAL)*/
+ status = pmcSendMessage(pMac, eWNI_PMC_ENTER_IMPS_REQ, NULL, 0);
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ //Disable Idle scan in CSR
+ csrScanSuspendIMPS(pMac);
+ fRemoveCmd = eANI_BOOLEAN_FALSE;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "PMC: failure to send message "
+ "eWNI_PMC_ENTER_IMPS_REQ\n");
+ pmcEnterFullPowerState(pMac);
+ pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE);
+ /* Start the timer only if Auto BMPS feature is enabled or an UAPSD session is
+ required */
+ if(pmcShouldBmpsTimerRun(pMac))
+ (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ }
+ }
+ break;
+
+ default:
+ smsLog( pMac, LOGE, FL(" invalid command type %d\n"), pCommand->command );
+ break;
+ }
+
+ } while( 0 );
+
+ return( fRemoveCmd );
+}
+
+eHalStatus pmcEnterImpsCheck( tpAniSirGlobal pMac )
+{
+
+ if( !PMC_IS_READY(pMac) )
+ {
+ smsLog(pMac, LOGE, FL("Requesting IMPS when PMC not ready\n"));
+ smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
+ pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Check if IMPS is enabled. */
+ if (!pMac->pmc.impsEnabled)
+ {
+ smsLog(pMac, LOG2, FL("IMPS is disabled\n"));
+ return eHAL_STATUS_PMC_DISABLED;
+ }
+
+ /* Check if IMPS enabled for current power source. */
+ if ((pMac->pmc.powerSource == AC_POWER) && !pMac->pmc.impsConfig.enterOnAc)
+ {
+ smsLog(pMac, LOG2, FL("IMPS is disabled when operating on AC power\n"));
+ return eHAL_STATUS_PMC_AC_POWER;
+ }
+
+ /* Check that entry into a power save mode is allowed at this time. */
+ if (!pmcPowerSaveCheck(pMac))
+ {
+ smsLog(pMac, LOG2, FL("IMPS cannot be entered now\n"));
+ return eHAL_STATUS_PMC_NOT_NOW;
+ }
+
+ /* Check that entry into a power save mode is allowed at this time if all
+ running sessions agree. */
+ if (!pmcAllowImps(pMac))
+ {
+ smsLog(pMac, LOG2, FL("IMPS cannot be entered now\n"));
+ return eHAL_STATUS_PMC_NOT_NOW;
+ }
+
+ /* Check if already in IMPS. */
+ if ((pMac->pmc.pmcState == REQUEST_IMPS) || (pMac->pmc.pmcState == IMPS) ||
+ (pMac->pmc.pmcState == REQUEST_FULL_POWER))
+ {
+ smsLog(pMac, LOG2, FL("Already in IMPS\n"));
+ return eHAL_STATUS_PMC_ALREADY_IN_IMPS;
+ }
+
+ return ( eHAL_STATUS_SUCCESS );
+}
+
+/* This API detrmines if it is ok to proceed with a Enter BMPS Request or not . Note when
+ device is in BMPS/UAPSD states, this API returns failure because it is not ok to issue
+ a BMPS request */
+eHalStatus pmcEnterBmpsCheck( tpAniSirGlobal pMac )
+{
+
+ /* Check if BMPS is enabled. */
+ if (!pMac->pmc.bmpsEnabled)
+ {
+ smsLog(pMac, LOGE, "PMC: Cannot initiate BMPS. BMPS is disabled\n");
+ return eHAL_STATUS_PMC_DISABLED;
+ }
+
+ if( !PMC_IS_READY(pMac) )
+ {
+ smsLog(pMac, LOGE, FL("Requesting BMPS when PMC not ready\n"));
+ smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
+ pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Check that we are associated with a single active session. */
+ if (!pmcValidateConnectState( pMac ))
+ {
+ smsLog(pMac, LOGE, "PMC: STA not associated with an AP with single active session. BMPS cannot be entered\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* BMPS can only be requested when device is in Full Power */
+ if (pMac->pmc.pmcState != FULL_POWER)
+ {
+ smsLog(pMac, LOGE, "PMC: Device not in full power. Cannot request BMPS. pmcState %d\n", pMac->pmc.pmcState);
+ return eHAL_STATUS_FAILURE;
+ }
+ /* Check that entry into a power save mode is allowed at this time. */
+ if (!pmcPowerSaveCheck(pMac))
+ {
+ smsLog(pMac, LOGE, "PMC: Power save check failed. BMPS cannot be entered now\n");
+ return eHAL_STATUS_PMC_NOT_NOW;
+ }
+
+ smsLog(pMac, LOG1, FL("concurrency enabled %u\n"), pMac->roam.configParam.concurrencyEnabled);
+ if (pMac->roam.configParam.concurrencyEnabled)
+ {
+ pMac->roam.configParam.concurrencyEnabled = 0;
+ smsLog(pMac, LOG1, FL("reset concurrency to disabled %u\n"), pMac->roam.configParam.concurrencyEnabled);
+ csrDisconnectAllActiveSessions(pMac);
+ }
+ return ( eHAL_STATUS_SUCCESS );
+}
+
+tANI_BOOLEAN pmcShouldBmpsTimerRun( tpAniSirGlobal pMac )
+{
+ /* Check if BMPS is enabled and if Auto BMPS Feature is still enabled
+ * or there is a pending Uapsd request or HDD requested BMPS or there
+ * is a pending request for WoWL. In all these cases BMPS is required.
+ * Otherwise just stop the timer and return.
+ */
+ if (!(pMac->pmc.bmpsEnabled && (pMac->pmc.autoBmpsEntryEnabled ||
+ pMac->pmc.uapsdSessionRequired || pMac->pmc.bmpsRequestedByHdd ||
+ pMac->pmc.wowlModeRequired )))
+ {
+ smsLog(pMac, LOG1, FL("BMPS is not enabled or not required"));
+ return eANI_BOOLEAN_FALSE;
+ }
+
+ /* Check if there is an Infra session. BMPS is possible only if there is
+ * an Infra session */
+ if (!csrIsInfraConnected(pMac))
+ {
+ smsLog(pMac, LOG1, FL("No Infra Session or multiple sessions. BMPS should not be started"));
+ return eANI_BOOLEAN_FALSE;
+ }
+ return eANI_BOOLEAN_TRUE;
+}
+
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+
+#define PMC_DIAG_EVT_TIMER_INTERVAL ( 5000 )
+
+void pmcDiagEvtTimerExpired (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_PMC_CURRENT_STATE;
+ psRequest.pmc_current_state = pMac->pmc.pmcState;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+
+ smsLog(pMac, LOGW, FL("DIAG event timer expired\n"));
+
+ /* re-arm timer */
+ if (pmcStartDiagEvtTimer(hHal) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGP, FL("Cannot re-arm DIAG evt timer\n"));
+ }
+}
+
+eHalStatus pmcStartDiagEvtTimer (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcStartDiagEvtTimer\n"));
+
+ if (palTimerStart(pMac->hHdd, pMac->pmc.hDiagEvtTimer, PMC_DIAG_EVT_TIMER_INTERVAL *
+ 1000, TRUE) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGP, FL("Cannot start DIAG evt timer\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+void pmcStopDiagEvtTimer (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ smsLog(pMac, LOG2, FL("Entering pmcStopDiagEvtTimer\n"));
+ (void)palTimerStop(pMac->hHdd, pMac->pmc.hDiagEvtTimer);
+}
+#endif
diff --git a/CORE/SME/src/pmc/pmcApi.c b/CORE/SME/src/pmc/pmcApi.c
new file mode 100644
index 0000000..ac4a73e
--- /dev/null
+++ b/CORE/SME/src/pmc/pmcApi.c
@@ -0,0 +1,3122 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/******************************************************************************
+*
+* Name: pmcApi.c
+*
+* Description: Routines that make up the Power Management Control (PMC) API.
+*
+* Copyright 2008 (c) Qualcomm, Incorporated.
+* All Rights Reserved.
+* Qualcomm Confidential and Proprietary.
+*
+******************************************************************************/
+
+#include "palTypes.h"
+#include "aniGlobal.h"
+#include "palTimer.h"
+#include "csrLinkList.h"
+#include "smsDebug.h"
+#include "pmcApi.h"
+#include "pmc.h"
+#include "cfgApi.h"
+#include "smeInside.h"
+#include "csrInsideApi.h"
+#include "wlan_ps_wow_diag.h"
+#include "wlan_qct_wda.h"
+#include "limSessionUtils.h"
+#include "csrInsideApi.h"
+
+extern void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+
+void pmcCloseDeferredMsgList(tpAniSirGlobal pMac);
+void pmcCloseDeviceStateUpdateList(tpAniSirGlobal pMac);
+void pmcCloseRequestStartUapsdList(tpAniSirGlobal pMac);
+void pmcCloseRequestBmpsList(tpAniSirGlobal pMac);
+void pmcCloseRequestFullPowerList(tpAniSirGlobal pMac);
+void pmcClosePowerSaveCheckList(tpAniSirGlobal pMac);
+
+/******************************************************************************
+*
+* Name: pmcOpen
+*
+* Description:
+* Does a PMC open operation on the device.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - open successful
+* eHAL_STATUS_FAILURE - open not successful
+*
+******************************************************************************/
+eHalStatus pmcOpen (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcOpen\n"));
+
+ /* Initialize basic PMC information about device. */
+ pMac->pmc.powerSource = BATTERY_POWER;
+ pMac->pmc.pmcState = STOPPED;
+ pMac->pmc.pmcReady = FALSE;
+
+ /* Initialize Power Save Modes */
+ pMac->pmc.impsEnabled = FALSE;
+ pMac->pmc.autoBmpsEntryEnabled = FALSE;
+ pMac->pmc.smpsEnabled = FALSE;
+ pMac->pmc.uapsdEnabled = TRUE;
+ pMac->pmc.bmpsEnabled = TRUE;
+ pMac->pmc.standbyEnabled = TRUE;
+ pMac->pmc.wowlEnabled = TRUE;
+ pMac->pmc.rfSuppliesVotedOff= FALSE;
+
+ palZeroMemory(pMac->hHdd, &(pMac->pmc.bmpsConfig), sizeof(tPmcBmpsConfigParams));
+ palZeroMemory(pMac->hHdd, &(pMac->pmc.impsConfig), sizeof(tPmcImpsConfigParams));
+ palZeroMemory(pMac->hHdd, &(pMac->pmc.smpsConfig), sizeof(tPmcSmpsConfigParams));
+
+ /* Allocate a timer to use with IMPS. */
+ if (palTimerAlloc(pMac->hHdd, &pMac->pmc.hImpsTimer, pmcImpsTimerExpired, hHal) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot allocate timer for IMPS\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Allocate a timer used in Full Power State to measure traffic
+ levels and determine when to enter BMPS. */
+ if (!VOS_IS_STATUS_SUCCESS(vos_timer_init(&pMac->pmc.hTrafficTimer,
+ VOS_TIMER_TYPE_SW, pmcTrafficTimerExpired, hHal)))
+ {
+ smsLog(pMac, LOGE, FL("Cannot allocate timer for traffic measurement\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ /* Allocate a timer used to report current PMC state through periodic DIAG event */
+ if (palTimerAlloc(pMac->hHdd, &pMac->pmc.hDiagEvtTimer, pmcDiagEvtTimerExpired, hHal) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot allocate timer for diag event reporting\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+#endif
+
+ //Initialize the default value for Bmps related config.
+ pMac->pmc.bmpsConfig.trafficMeasurePeriod = BMPS_TRAFFIC_TIMER_DEFAULT;
+ pMac->pmc.bmpsConfig.bmpsPeriod = WNI_CFG_LISTEN_INTERVAL_STADEF;
+
+ /* Allocate a timer used to schedule a deferred power save mode exit. */
+ if (palTimerAlloc(pMac->hHdd, &pMac->pmc.hExitPowerSaveTimer,
+ pmcExitPowerSaveTimerExpired, hHal) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot allocate exit power save mode timer\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Initialize lists for power save check routines and request full power callback routines. */
+ if (csrLLOpen(pMac->hHdd, &pMac->pmc.powerSaveCheckList) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot initialize power save check routine list\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+ if (csrLLOpen(pMac->hHdd, &pMac->pmc.requestFullPowerList) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot initialize request full power callback routine list\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Initialize lists for request BMPS callback routines. */
+ if (csrLLOpen(pMac->hHdd, &pMac->pmc.requestBmpsList) !=
+ eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: cannot initialize request BMPS callback routine list\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Initialize lists for request start UAPSD callback routines. */
+ if (csrLLOpen(pMac->hHdd, &pMac->pmc.requestStartUapsdList) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: cannot initialize request start UAPSD callback routine list\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Initialize lists for device state update indication callback routines. */
+ if (csrLLOpen(pMac->hHdd, &pMac->pmc.deviceStateUpdateIndList) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: cannot initialize device state update indication callback list\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if (csrLLOpen(pMac->hHdd, &pMac->pmc.deferredMsgList) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot initialize deferred msg list\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcStart
+*
+* Description:
+* Does a PMC start operation on the device.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - start successful
+* eHAL_STATUS_FAILURE - start not successful
+*
+******************************************************************************/
+eHalStatus pmcStart (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tSirMacHTMIMOPowerSaveState htMimoPowerSaveState;
+
+ smsLog(pMac, LOG2, FL("Entering pmcStart\n"));
+
+ /* Initialize basic PMC information about device. */
+ pMac->pmc.pmcState = FULL_POWER;
+ pMac->pmc.requestFullPowerPending = FALSE;
+ pMac->pmc.uapsdSessionRequired = FALSE;
+ pMac->pmc.wowlModeRequired = FALSE;
+ pMac->pmc.bmpsRequestedByHdd = FALSE;
+ pMac->pmc.remainInPowerActiveTillDHCP = FALSE;
+ pMac->pmc.remainInPowerActiveThreshold = 0;
+
+ /* WLAN Switch initial states. */
+ pMac->pmc.hwWlanSwitchState = ePMC_SWITCH_ON;
+ pMac->pmc.swWlanSwitchState = ePMC_SWITCH_ON;
+
+ /* No IMPS callback routine yet. */
+ pMac->pmc.impsCallbackRoutine = NULL;
+
+ /* No STANDBY callback routine yet. */
+ pMac->pmc.standbyCallbackRoutine = NULL;
+
+ /* No WOWL callback routine yet. */
+ pMac->pmc.enterWowlCallbackRoutine = NULL;
+
+ /* Initialize BMPS traffic counts. */
+ pMac->pmc.cLastTxUnicastFrames = 0;
+ pMac->pmc.cLastRxUnicastFrames = 0;
+
+ /* Configure SMPS. */
+ if (pMac->pmc.smpsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.smpsConfig.enterOnAc))
+ {
+ if (pMac->pmc.smpsConfig.mode == ePMC_DYNAMIC_SMPS)
+ htMimoPowerSaveState = eSIR_HT_MIMO_PS_DYNAMIC;
+ if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS)
+ htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC;
+ }
+ else
+ htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT;
+
+ if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
+ sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ if (pmcStartDiagEvtTimer(hHal) != eHAL_STATUS_SUCCESS)
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+#endif
+
+#if defined(ANI_LOGDUMP)
+ pmcDumpInit(hHal);
+#endif
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcStop
+*
+* Description:
+* Does a PMC stop operation on the device.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - stop successful
+* eHAL_STATUS_FAILURE - stop not successful
+*
+******************************************************************************/
+eHalStatus pmcStop (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tListElem *pEntry;
+ tPmcDeferredMsg *pDeferredMsg;
+
+ smsLog(pMac, LOG2, FL("Entering pmcStop\n"));
+
+ /* Cancel any running timers. */
+ if (palTimerStop(pMac->hHdd, pMac->pmc.hImpsTimer) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot cancel IMPS timer\n"));
+ }
+
+ pmcStopTrafficTimer(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ pmcStopDiagEvtTimer(hHal);
+#endif
+
+ if (palTimerStop(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot cancel exit power save mode timer\n"));
+ }
+
+ /* Do all the callbacks. */
+ pmcDoCallbacks(hHal, eHAL_STATUS_FAILURE);
+ pmcDoBmpsCallbacks(hHal, eHAL_STATUS_FAILURE);
+ pMac->pmc.uapsdSessionRequired = FALSE;
+ pmcDoStartUapsdCallbacks(hHal, eHAL_STATUS_FAILURE);
+ pmcDoStandbyCallbacks(hHal, eHAL_STATUS_FAILURE);
+
+ //purge the deferred msg list
+ csrLLLock( &pMac->pmc.deferredMsgList );
+ while( NULL != ( pEntry = csrLLRemoveHead( &pMac->pmc.deferredMsgList, eANI_BOOLEAN_FALSE ) ) )
+ {
+ pDeferredMsg = GET_BASE_ADDR( pEntry, tPmcDeferredMsg, link );
+ palFreeMemory( pMac->hHdd, pDeferredMsg );
+ }
+ csrLLUnlock( &pMac->pmc.deferredMsgList );
+
+ /* PMC is stopped. */
+ pMac->pmc.pmcState = STOPPED;
+ pMac->pmc.pmcReady = FALSE;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcClose
+*
+* Description:
+* Does a PMC close operation on the device.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - close successful
+* eHAL_STATUS_FAILURE - close not successful
+*
+******************************************************************************/
+eHalStatus pmcClose (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcClose\n"));
+
+ /* Free up allocated resources. */
+ if (palTimerFree(pMac->hHdd, pMac->pmc.hImpsTimer) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot deallocate IMPS timer\n"));
+ }
+ if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(&pMac->pmc.hTrafficTimer)))
+ {
+ smsLog(pMac, LOGE, FL("Cannot deallocate traffic timer\n"));
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ if (palTimerFree(pMac->hHdd, pMac->pmc.hDiagEvtTimer) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot deallocate timer for diag event reporting\n"));
+ }
+#endif
+ if (palTimerFree(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot deallocate exit power save mode timer\n"));
+ }
+
+ /*
+ The following list's entries are dynamically allocated so they need their own
+ cleanup function
+ */
+ pmcClosePowerSaveCheckList(pMac);
+ pmcCloseRequestFullPowerList(pMac);
+ pmcCloseRequestBmpsList(pMac);
+ pmcCloseRequestStartUapsdList(pMac);
+ pmcCloseDeviceStateUpdateList(pMac);
+ pmcCloseDeferredMsgList(pMac);
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcSignalPowerEvent
+*
+* Description:
+* Signals to PMC that a power event has occurred.
+*
+* Parameters:
+* hHal - HAL handle for device
+* event - the event that has occurred
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - signaling successful
+* eHAL_STATUS_FAILURE - signaling not successful
+*
+******************************************************************************/
+eHalStatus pmcSignalPowerEvent (tHalHandle hHal, tPmcPowerEvent event)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+#ifndef GEN6_ONWARDS
+ tSirMacHTMIMOPowerSaveState htMimoPowerSaveState;
+#endif
+
+ smsLog(pMac, LOG2, FL("Entering pmcSignalPowerEvent, event %d\n"), event);
+
+ /* Take action based on the event being signaled. */
+ switch (event)
+ {
+#ifndef GEN6_ONWARDS
+ case ePMC_SYSTEM_HIBERNATE:
+ return pmcEnterLowPowerState(hHal);
+
+ case ePMC_SYSTEM_RESUME:
+ return pmcExitLowPowerState(hHal);
+
+ case ePMC_HW_WLAN_SWITCH_OFF:
+ pMac->pmc.hwWlanSwitchState = ePMC_SWITCH_OFF;
+ return pmcEnterLowPowerState(hHal);
+
+ case ePMC_HW_WLAN_SWITCH_ON:
+ pMac->pmc.hwWlanSwitchState = ePMC_SWITCH_ON;
+ return pmcExitLowPowerState(hHal);
+
+ case ePMC_SW_WLAN_SWITCH_OFF:
+ pMac->pmc.swWlanSwitchState = ePMC_SWITCH_OFF;
+ return pmcEnterLowPowerState(hHal);
+
+ case ePMC_SW_WLAN_SWITCH_ON:
+ pMac->pmc.swWlanSwitchState = ePMC_SWITCH_ON;
+ return pmcExitLowPowerState(hHal);
+
+ case ePMC_BATTERY_OPERATION:
+ pMac->pmc.powerSource = BATTERY_POWER;
+
+ /* Turn on SMPS. */
+ if (pMac->pmc.smpsEnabled)
+ {
+ if (pMac->pmc.smpsConfig.mode == ePMC_DYNAMIC_SMPS)
+ htMimoPowerSaveState = eSIR_HT_MIMO_PS_DYNAMIC;
+ if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS)
+ htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC;
+ if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
+ sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+
+ case ePMC_AC_OPERATION:
+ pMac->pmc.powerSource = AC_POWER;
+
+ /* Turn off SMPS. */
+ if (!pMac->pmc.smpsConfig.enterOnAc)
+ {
+ htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT;
+ if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
+ sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+#endif //GEN6_ONWARDS
+ default:
+ smsLog(pMac, LOGE, FL("Invalid event %d\n"), event);
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+}
+
+
+/******************************************************************************
+*
+* Name: pmcSetConfigPowerSave
+*
+* Description:
+* Configures one of the power saving modes.
+*
+* Parameters:
+* hHal - HAL handle for device
+* psMode - the power saving mode to configure
+* pConfigParams - pointer to configuration parameters specific to the
+* power saving mode
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - configuration successful
+* eHAL_STATUS_FAILURE - configuration not successful
+*
+******************************************************************************/
+eHalStatus pmcSetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+#endif
+
+ smsLog(pMac, LOG2, FL("Entering pmcSetConfigPowerSave, power save mode %d\n"), psMode);
+
+ /* Configure the specified power saving mode. */
+ switch (psMode)
+ {
+
+ case ePMC_IDLE_MODE_POWER_SAVE:
+ pMac->pmc.impsConfig = *(tpPmcImpsConfigParams)pConfigParams;
+ smsLog(pMac, LOG3, FL("IMPS configuration"));
+ smsLog(pMac, LOG3, " enter on AC: %d\n",
+ pMac->pmc.impsConfig.enterOnAc);
+ break;
+
+ case ePMC_BEACON_MODE_POWER_SAVE:
+ pMac->pmc.bmpsConfig = *(tpPmcBmpsConfigParams)pConfigParams;
+ smsLog(pMac, LOG3, FL("BMPS configuration"));
+ smsLog(pMac, LOG3, " enter on AC: %d\n",
+ pMac->pmc.bmpsConfig.enterOnAc);
+ smsLog(pMac, LOG3, " TX threshold: %d\n",
+ pMac->pmc.bmpsConfig.txThreshold);
+ smsLog(pMac, LOG3, " RX threshold: %d\n",
+ pMac->pmc.bmpsConfig.rxThreshold);
+ smsLog(pMac, LOG3, " traffic measurement period (ms): %d\n",
+ pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ smsLog(pMac, LOG3, " BMPS period: %d\n",
+ pMac->pmc.bmpsConfig.bmpsPeriod);
+ smsLog(pMac, LOG3, " beacons to forward code: %d\n",
+ pMac->pmc.bmpsConfig.forwardBeacons);
+ smsLog(pMac, LOG3, " value of N: %d\n",
+ pMac->pmc.bmpsConfig.valueOfN);
+ smsLog(pMac, LOG3, " use PS poll: %d\n",
+ pMac->pmc.bmpsConfig.usePsPoll);
+ smsLog(pMac, LOG3, " set PM on last frame: %d\n",
+ pMac->pmc.bmpsConfig.setPmOnLastFrame);
+ smsLog(pMac, LOG3, " value of enableBeaconEarlyTermination: %d\n",
+ pMac->pmc.bmpsConfig.enableBeaconEarlyTermination);
+ smsLog(pMac, LOG3, " value of bcnEarlyTermWakeInterval: %d\n",
+ pMac->pmc.bmpsConfig.bcnEarlyTermWakeInterval);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_BMPS_SET_CONFIG;
+ /* possible loss of data due to mismatch but expectation is that
+ values can reasonably be expected to fit in target widths */
+ psRequest.bmps_auto_timer_duration = (v_U16_t)pMac->pmc.bmpsConfig.trafficMeasurePeriod;
+ psRequest.bmps_period = (v_U16_t)pMac->pmc.bmpsConfig.bmpsPeriod;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+
+ break;
+
+ case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
+ pMac->pmc.smpsConfig = *(tpPmcSmpsConfigParams)pConfigParams;
+ smsLog(pMac, LOG3, FL("SMPS configuration"));
+ smsLog(pMac, LOG3, " mode: %d\n", pMac->pmc.smpsConfig.mode);
+ smsLog(pMac, LOG3, " enter on AC: %d\n",
+ pMac->pmc.smpsConfig.enterOnAc);
+ break;
+
+ default:
+ smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ //Send the power save config down to PE/HAL/FW if BMPS mode is being configured
+ //and pmcReady has been invoked
+ if(PMC_IS_READY(pMac) && psMode == ePMC_BEACON_MODE_POWER_SAVE)
+ {
+ if (pmcSendPowerSaveConfigMessage(hHal) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/******************************************************************************
+*
+* Name: pmcGetConfigPowerSave
+*
+* Description:
+* Get the config for the specified power save mode
+*
+* Parameters:
+* hHal - HAL handle for device
+* psMode - the power saving mode to configure
+* pConfigParams - pointer to configuration parameters specific to the
+* power saving mode
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - configuration successful
+* eHAL_STATUS_FAILURE - configuration not successful
+*
+******************************************************************************/
+eHalStatus pmcGetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcGetConfigPowerSave, power save mode %d\n"), psMode);
+
+ /* Configure the specified power saving mode. */
+ switch (psMode)
+ {
+
+ case ePMC_IDLE_MODE_POWER_SAVE:
+ *(tpPmcImpsConfigParams)pConfigParams = pMac->pmc.impsConfig;
+ break;
+
+ case ePMC_BEACON_MODE_POWER_SAVE:
+ *(tpPmcBmpsConfigParams)pConfigParams = pMac->pmc.bmpsConfig;
+ break;
+
+ case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
+ *(tpPmcSmpsConfigParams)pConfigParams = pMac->pmc.smpsConfig;
+ break;
+
+ default:
+ smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+/******************************************************************************
+*
+* Name: pmcEnablePowerSave
+*
+* Description:
+* Enables one of the power saving modes.
+*
+* Parameters:
+* hHal - HAL handle for device
+* psMode - the power saving mode to enable
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - successfully enabled
+* eHAL_STATUS_FAILURE - not successfully enabled
+*
+******************************************************************************/
+eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tSirMacHTMIMOPowerSaveState htMimoPowerSaveState;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_PS_MODE_ENABLE_REQ;
+ psRequest.enable_disable_powersave_mode = psMode;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+ smsLog(pMac, LOG2, FL("Entering pmcEnablePowerSave, power save mode %d\n"), psMode);
+
+ /* Enable the specified power saving mode. */
+ switch (psMode)
+ {
+
+ case ePMC_IDLE_MODE_POWER_SAVE:
+ pMac->pmc.impsEnabled = TRUE;
+ break;
+
+ case ePMC_BEACON_MODE_POWER_SAVE:
+ pMac->pmc.bmpsEnabled = TRUE;
+ break;
+
+ case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
+ pMac->pmc.smpsEnabled = TRUE;
+
+ /* If PMC already started, then turn on SMPS. */
+ if (pMac->pmc.pmcState != STOPPED)
+ if (pMac->pmc.powerSource != AC_POWER ||
+ pMac->pmc.smpsConfig.enterOnAc)
+ {
+ if (pMac->pmc.smpsConfig.mode == ePMC_DYNAMIC_SMPS)
+ htMimoPowerSaveState = eSIR_HT_MIMO_PS_DYNAMIC;
+ if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS)
+ htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC;
+ if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
+ sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+ }
+ break;
+
+ case ePMC_UAPSD_MODE_POWER_SAVE:
+ pMac->pmc.uapsdEnabled = TRUE;
+ break;
+
+ case ePMC_STANDBY_MODE_POWER_SAVE:
+ pMac->pmc.standbyEnabled = TRUE;
+ break;
+
+ case ePMC_WOWL_MODE_POWER_SAVE:
+ pMac->pmc.wowlEnabled = TRUE;
+ break;
+
+ default:
+ smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+/* ---------------------------------------------------------------------------
+ \fn pmcStartAutoBmpsTimer
+ \brief Starts a timer that periodically polls all the registered
+ module for entry into Bmps mode. This timer is started only if BMPS is
+ enabled and whenever the device is in full power.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_START_BMPS_AUTO_TIMER_REQ;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+ smsLog(pMac, LOG2, FL("Entering pmcStartAutoBmpsTimer\n"));
+
+ /* Check if BMPS is enabled. */
+ if (!pMac->pmc.bmpsEnabled)
+ {
+ smsLog(pMac, LOGE, "PMC: Cannot enable BMPS timer. BMPS is disabled\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ pMac->pmc.autoBmpsEntryEnabled = TRUE;
+
+ /* Check if there is an Infra session. If there is no Infra session, timer will be started
+ when STA associates to AP */
+
+ if (pmcShouldBmpsTimerRun(pMac))
+ {
+ if (pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+ }
+
+
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcStopAutoBmpsTimer
+ \brief Stops the Auto BMPS Timer that was started using sme_startAutoBmpsTimer
+ Stopping the timer does not cause a device state change. Only the timer
+ is stopped. If "Full Power" is desired, use the pmcRequestFullPower API
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcStopAutoBmpsTimer (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_STOP_BMPS_AUTO_TIMER_REQ;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+ smsLog(pMac, LOG2, FL("Entering pmcStopAutoBmpsTimer\n"));
+
+ pMac->pmc.autoBmpsEntryEnabled = FALSE;
+ /* If uapsd session is not required or HDD has not requested BMPS, stop the auto bmps timer.*/
+ if (!pMac->pmc.uapsdSessionRequired && !pMac->pmc.bmpsRequestedByHdd)
+ pmcStopTrafficTimer(hHal);
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/******************************************************************************
+*
+* Name: pmcDisablePowerSave
+*
+* Description:
+* Disables one of the power saving modes.
+*
+* Parameters:
+* hHal - HAL handle for device
+* psMode - the power saving mode to disable
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - successfully disabled
+* eHAL_STATUS_FAILURE - not successfully disabled
+*
+******************************************************************************/
+eHalStatus pmcDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tSirMacHTMIMOPowerSaveState htMimoPowerSaveState;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_PS_MODE_DISABLE_REQ;
+ psRequest.enable_disable_powersave_mode = psMode;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+ smsLog(pMac, LOG2, FL("Entering pmcDisablePowerSave, power save mode %d\n"), psMode);
+
+ /* Disable the specified power saving mode. */
+ switch (psMode)
+ {
+
+ case ePMC_IDLE_MODE_POWER_SAVE:
+ pMac->pmc.impsEnabled = FALSE;
+ break;
+
+ case ePMC_BEACON_MODE_POWER_SAVE:
+ pMac->pmc.bmpsEnabled = FALSE;
+ break;
+
+ case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
+ pMac->pmc.smpsEnabled = FALSE;
+
+ /* Turn off SMPS. */
+ htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT;
+ if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
+ sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+ break;
+
+ case ePMC_UAPSD_MODE_POWER_SAVE:
+ pMac->pmc.uapsdEnabled = FALSE;
+ break;
+
+ case ePMC_STANDBY_MODE_POWER_SAVE:
+ pMac->pmc.standbyEnabled = FALSE;
+ break;
+
+ case ePMC_WOWL_MODE_POWER_SAVE:
+ pMac->pmc.wowlEnabled = FALSE;
+ break;
+
+ default:
+ smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcQueryPowerState
+*
+* Description:
+* Returns the current power state of the device.
+*
+* Parameters:
+* hHal - HAL handle for device
+* pPowerState - pointer to location to return power state
+* pHwWlanSwitchState - pointer to location to return Hardware WLAN
+* Switch state
+* pSwWlanSwitchState - pointer to location to return Software WLAN
+* Switch state
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - power state successfully returned
+* eHAL_STATUS_FAILURE - power state not successfully returned
+*
+******************************************************************************/
+eHalStatus pmcQueryPowerState (tHalHandle hHal, tPmcPowerState *pPowerState,
+ tPmcSwitchState *pHwWlanSwitchState, tPmcSwitchState *pSwWlanSwitchState)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcQueryPowerState\n"));
+
+ /* Return current power state based on PMC state. */
+ if(pPowerState != NULL)
+ {
+ /* Return current power state based on PMC state. */
+ switch (pMac->pmc.pmcState)
+ {
+
+ case FULL_POWER:
+ *pPowerState = ePMC_FULL_POWER;
+ break;
+
+ default:
+ *pPowerState = ePMC_LOW_POWER;
+ break;
+ }
+ }
+
+ /* Return current switch settings. */
+ if(pHwWlanSwitchState != NULL)
+ *pHwWlanSwitchState = pMac->pmc.hwWlanSwitchState;
+ if(pSwWlanSwitchState != NULL)
+ *pSwWlanSwitchState = pMac->pmc.swWlanSwitchState;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcIsPowerSaveEnabled
+*
+* Description:
+* Checks if the device is able to enter one of the power save modes.
+* "Able to enter" means the power save mode is enabled for the device
+* and the host is using the correct power source for entry into the
+* power save mode. This routine does not indicate whether the device
+* is actually in the power save mode at a particular point in time.
+*
+* Parameters:
+* hHal - HAL handle for device
+* psMode - the power saving mode
+*
+* Returns:
+* TRUE if device is able to enter the power save mode, FALSE otherwise
+*
+******************************************************************************/
+tANI_BOOLEAN pmcIsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcIsPowerSaveEnabled, power save mode %d\n"), psMode);
+
+ /* Check ability to enter based on the specified power saving mode. */
+ switch (psMode)
+ {
+
+ case ePMC_IDLE_MODE_POWER_SAVE:
+ return pMac->pmc.impsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.impsConfig.enterOnAc);
+
+ case ePMC_BEACON_MODE_POWER_SAVE:
+ return pMac->pmc.bmpsEnabled;
+
+ case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
+ return pMac->pmc.smpsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.smpsConfig.enterOnAc);
+
+ case ePMC_UAPSD_MODE_POWER_SAVE:
+ return pMac->pmc.uapsdEnabled;
+
+ case ePMC_STANDBY_MODE_POWER_SAVE:
+ return pMac->pmc.standbyEnabled;
+
+ case ePMC_WOWL_MODE_POWER_SAVE:
+ return pMac->pmc.wowlEnabled;
+ break;
+
+ default:
+ smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
+ PMC_ABORT;
+ return FALSE;
+ }
+}
+
+
+/******************************************************************************
+*
+* Name: pmcRequestFullPower
+*
+* Description:
+* Request that the device be brought to full power state.
+*
+* Parameters:
+* hHal - HAL handle for device
+* callbackRoutine - routine to call when device actually achieves full
+* power state if "eHAL_STATUS_PMC_PENDING" is returned
+* callbackContext - value to be passed as parameter to routine specified
+* above
+* fullPowerReason - Reason for requesting full power mode. This is used
+* by PE to decide whether data null should be sent to
+* AP when exiting BMPS mode. Caller should use the
+* eSME_LINK_DISCONNECTED reason if link is disconnected
+* and there is no need to tell the AP that we are going
+* out of power save.
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - device brought to full power state
+* eHAL_STATUS_FAILURE - device cannot be brought to full power state
+* eHAL_STATUS_PMC_PENDING - device is being brought to full power state,
+* callbackRoutine will be called when completed
+*
+******************************************************************************/
+eHalStatus pmcRequestFullPower (tHalHandle hHal, void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext, tRequestFullPowerReason fullPowerReason)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tpRequestFullPowerEntry pEntry;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_ENTER_FULL_POWER_REQ;
+ psRequest.full_power_request_reason = fullPowerReason;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+ smsLog(pMac, LOG2, FL("Entering pmcRequestFullPower"));
+
+ if( !PMC_IS_READY(pMac) )
+ {
+ smsLog(pMac, LOGE, FL("Requesting Full Power when PMC not ready\n"));
+ smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
+ pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* If HDD is requesting full power, clear any buffered requests for WOWL and BMPS that were
+ requested by HDD previously */
+ if(SIR_IS_FULL_POWER_NEEDED_BY_HDD(fullPowerReason))
+ {
+ pMac->pmc.bmpsRequestedByHdd = FALSE;
+ pMac->pmc.wowlModeRequired = FALSE;
+ }
+
+ /* If already in full power, just return. */
+ if (pMac->pmc.pmcState == FULL_POWER)
+ return eHAL_STATUS_SUCCESS;
+
+ /* If in IMPS State, then cancel the timer. */
+ if (pMac->pmc.pmcState == IMPS)
+ if (palTimerStop(pMac->hHdd, pMac->pmc.hImpsTimer) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot cancel IMPS timer\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Enter Request Full Power State. */
+ if (pmcEnterRequestFullPowerState(hHal, fullPowerReason) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+
+ /* If able to enter Request Full Power State, then request is pending.
+ Allocate entry for request full power callback routine list. */
+ //If caller doesn't need a callback, simply waits up the chip.
+ if( callbackRoutine )
+ {
+ if (palAllocateMemory(pMac->hHdd, (void **)&pEntry, sizeof(tRequestFullPowerEntry)) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot allocate memory for request full power routine list entry\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Store routine and context in entry. */
+ pEntry->callbackRoutine = callbackRoutine;
+ pEntry->callbackContext = callbackContext;
+
+ /* Add entry to list. */
+ csrLLInsertTail(&pMac->pmc.requestFullPowerList, &pEntry->link, TRUE);
+ }
+
+ return eHAL_STATUS_PMC_PENDING;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcRequestImps
+*
+* Description:
+* Request that the device be placed in Idle Mode Power Save (IMPS).
+* The Common Scan/Roam Module makes this request. The device will be
+* placed into IMPS for the specified amount of time, and then returned
+* to full power.
+*
+* Parameters:
+* hHal - HAL handle for device
+* impsPeriod - amount of time to remain in IMPS (milliseconds)
+* callbackRoutine - routine to call when IMPS period has finished and
+* the device has been brought to full power
+* callbackContext - value to be passed as parameter to routine specified
+* above
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - device will enter IMPS
+* eHAL_STATUS_PMC_DISABLED - IMPS is disabled
+* eHAL_STATUS_PMC_NOT_NOW - another module is prohibiting entering IMPS
+* at this time
+* eHAL_STATUS_PMC_AC_POWER - IMPS is disabled when host operating from
+* AC power
+* eHAL_STATUS_PMC_ALREADY_IN_IMPS - device is already in IMPS
+* eHAL_STATUS_PMC_SYS_ERROR - system error that prohibits entering IMPS
+*
+******************************************************************************/
+eHalStatus pmcRequestImps (tHalHandle hHal, tANI_U32 impsPeriod,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ eHalStatus status;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_IMPS_ENTER_REQ;
+ psRequest.imps_period = impsPeriod;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+
+ smsLog(pMac, LOG2, FL("Entering pmcRequestImps"));
+
+ status = pmcEnterImpsCheck( pMac );
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ /* Enter Request IMPS State. */
+ status = pmcEnterRequestImpsState( hHal );
+ if (HAL_STATUS_SUCCESS( status ))
+ {
+ /* Save the period and callback routine for when we need it. */
+ pMac->pmc.impsPeriod = impsPeriod;
+ pMac->pmc.impsCallbackRoutine = callbackRoutine;
+ pMac->pmc.impsCallbackContext = callbackContext;
+
+ }
+ else
+ {
+ status = eHAL_STATUS_PMC_SYS_ERROR;
+ }
+ }
+
+ return status;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcRegisterPowerSaveCheck
+*
+* Description:
+* Allows a routine to be registered so that the routine is called whenever
+* the device is about to enter one of the power save modes. This routine
+* will say whether the device is allowed to enter the power save mode at
+* the time of the call.
+*
+* Parameters:
+* hHal - HAL handle for device
+* checkRoutine - routine to call before entering a power save mode, should
+* return TRUE if the device is allowed to enter the power
+* save mode, FALSE otherwise
+* checkContext - value to be passed as parameter to routine specified above
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - successfully registered
+* eHAL_STATUS_FAILURE - not successfully registered
+*
+******************************************************************************/
+eHalStatus pmcRegisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext),
+ void *checkContext)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tpPowerSaveCheckEntry pEntry;
+
+ smsLog(pMac, LOG2, FL("Entering pmcRegisterPowerSaveCheck"));
+
+ /* Allocate entry for power save check routine list. */
+ if (palAllocateMemory(pMac->hHdd, (void **)&pEntry, sizeof(tPowerSaveCheckEntry)) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot allocate memory for power save check routine list entry\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Store routine and context in entry. */
+ pEntry->checkRoutine = checkRoutine;
+ pEntry->checkContext = checkContext;
+
+ /* Add entry to list. */
+ csrLLInsertTail(&pMac->pmc.powerSaveCheckList, &pEntry->link, FALSE);
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+*
+* Name: pmcDeregisterPowerSaveCheck
+*
+* Description:
+* Reregisters a routine that was previously registered with
+* pmcRegisterPowerSaveCheck.
+*
+* Parameters:
+* hHal - HAL handle for device
+* checkRoutine - routine to deregister
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - successfully deregistered
+* eHAL_STATUS_FAILURE - not successfully deregistered
+*
+******************************************************************************/
+eHalStatus pmcDeregisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext))
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tListElem *pEntry;
+ tpPowerSaveCheckEntry pPowerSaveCheckEntry;
+
+ smsLog(pMac, LOG2, FL("Entering pmcDeregisterPowerSaveCheck"));
+
+ /* Find entry in the power save check routine list that matches
+ the specified routine and remove it. */
+ pEntry = csrLLPeekHead(&pMac->pmc.powerSaveCheckList, FALSE);
+ while (pEntry != NULL)
+ {
+ pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link);
+ if (pPowerSaveCheckEntry->checkRoutine == checkRoutine)
+ {
+ if (csrLLRemoveEntry(&pMac->pmc.powerSaveCheckList, pEntry, FALSE))
+ {
+ if (palFreeMemory(pMac->hHdd, pPowerSaveCheckEntry) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot free memory for power save check routine list entry\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("Cannot remove power save check routine list entry\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+ }
+ pEntry = csrLLNext(&pMac->pmc.powerSaveCheckList, pEntry, FALSE);
+ }
+
+ /* Could not find matching entry. */
+ return eHAL_STATUS_FAILURE;
+}
+
+
+static void pmcProcessResponse( tpAniSirGlobal pMac, tSirSmeRsp *pMsg )
+{
+ tListElem *pEntry = NULL;
+ tSmeCmd *pCommand = NULL;
+ tANI_BOOLEAN fRemoveCommand = eANI_BOOLEAN_TRUE;
+
+ pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
+ if(pEntry)
+ {
+ pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+
+ smsLog(pMac, LOG1, FL("process message = %d\n"), pMsg->messageType);
+
+ /* Process each different type of message. */
+ switch (pMsg->messageType)
+ {
+
+ /* We got a response to our IMPS request. */
+ case eWNI_PMC_ENTER_IMPS_RSP:
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_IMPS_RSP with status = %d\n"), pMsg->statusCode);
+ if( (eSmeCommandEnterImps != pCommand->command) && (eSmeCommandEnterStandby != pCommand->command) )
+ {
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_IMPS_RSP without request\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ if(pMac->pmc.pmcState == REQUEST_IMPS)
+ {
+ /* Enter IMPS State if response indicates success. */
+ if (pMsg->statusCode == eSIR_SME_SUCCESS)
+ {
+ pmcEnterImpsState(pMac);
+ }
+
+ /* If response is failure, then we stay in Full Power State and tell everyone that we aren't going into IMPS. */
+ else {
+ smsLog(pMac, LOGE, FL("Response message to request to enter IMPS indicates failure, status %x\n"),
+ pMsg->statusCode);
+ pmcEnterFullPowerState(pMac);
+ }
+ }
+ else if (pMac->pmc.pmcState == REQUEST_STANDBY)
+ {
+ /* Enter STANDBY State if response indicates success. */
+ if (pMsg->statusCode == eSIR_SME_SUCCESS)
+ {
+ pmcEnterStandbyState(pMac);
+ pmcDoStandbyCallbacks(pMac, eHAL_STATUS_SUCCESS);
+ }
+
+ /* If response is failure, then we stay in Full Power State
+ and tell everyone that we aren't going into STANDBY. */
+ else
+ {
+ smsLog(pMac, LOGE, "PMC: response message to request to enter "
+ "standby indicates failure, status %x\n", pMsg->statusCode);
+ pmcEnterFullPowerState(pMac);
+ pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE);
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "PMC: Enter IMPS rsp rcvd when device is "
+ "in %d state\n", pMac->pmc.pmcState);
+ }
+ break;
+
+ /* We got a response to our wake from IMPS request. */
+ case eWNI_PMC_EXIT_IMPS_RSP:
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_IMPS_RSP with status = %d\n"), pMsg->statusCode);
+ if( eSmeCommandExitImps != pCommand->command )
+ {
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_IMPS_RSP without request\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ /* Check that we are in the correct state for this message. */
+ if (pMac->pmc.pmcState != REQUEST_FULL_POWER)
+ {
+ smsLog(pMac, LOGE, FL("Got Exit IMPS Response Message while in state %d\n"), pMac->pmc.pmcState);
+ break;
+ }
+
+ /* Enter Full Power State. */
+ if (pMsg->statusCode != eSIR_SME_SUCCESS)
+ {
+ smsLog(pMac, LOGP, FL("Response message to request to exit IMPS indicates failure, status %x\n"),
+ pMsg->statusCode);
+ }
+ pmcEnterFullPowerState(pMac);
+ break;
+
+ /* We got a response to our BMPS request. */
+ case eWNI_PMC_ENTER_BMPS_RSP:
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_BMPS_RSP with status = %d\n"), pMsg->statusCode);
+ if( eSmeCommandEnterBmps != pCommand->command )
+ {
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_BMPS_RSP without request\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
+ /* Check that we are in the correct state for this message. */
+ if (pMac->pmc.pmcState != REQUEST_BMPS)
+ {
+ smsLog(pMac, LOGE, FL("Got Enter BMPS Response Message while in state %d\n"), pMac->pmc.pmcState);
+ break;
+ }
+
+ /* Enter BMPS State if response indicates success. */
+ if (pMsg->statusCode == eSIR_SME_SUCCESS)
+ {
+ pmcEnterBmpsState(pMac);
+ /* Note: If BMPS was requested because of start UAPSD,
+ there will no entries for BMPS callback routines and
+ pmcDoBmpsCallbacks will be a No-Op*/
+ pmcDoBmpsCallbacks(pMac, eHAL_STATUS_SUCCESS);
+ }
+ /* If response is failure, then we stay in Full Power State and tell everyone that we aren't going into BMPS. */
+ else
+ {
+ smsLog(pMac, LOGE, FL("Response message to request to enter BMPS indicates failure, status %x\n"),
+ pMsg->statusCode);
+ pmcEnterFullPowerState(pMac);
+ //Do not call UAPSD callback here since it may be re-entered
+ pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE);
+ }
+ break;
+
+ /* We got a response to our wake from BMPS request. */
+ case eWNI_PMC_EXIT_BMPS_RSP:
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_BMPS_RSP with status = %d\n"), pMsg->statusCode);
+ if( eSmeCommandExitBmps != pCommand->command )
+ {
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_BMPS_RSP without request\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ /* Check that we are in the correct state for this message. */
+ if (pMac->pmc.pmcState != REQUEST_FULL_POWER)
+ {
+ smsLog(pMac, LOGE, FL("Got Exit BMPS Response Message while in state %d\n"), pMac->pmc.pmcState);
+ break;
+ }
+
+ /* Enter Full Power State. */
+ if (pMsg->statusCode != eSIR_SME_SUCCESS)
+ {
+ smsLog(pMac, LOGP, FL("Response message to request to exit BMPS indicates failure, status %x\n"),
+ pMsg->statusCode);
+ }
+ pmcEnterFullPowerState(pMac);
+ break;
+
+ /* We got a response to our Start UAPSD request. */
+ case eWNI_PMC_ENTER_UAPSD_RSP:
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_UAPSD_RSP with status = %d\n"), pMsg->statusCode);
+ if( eSmeCommandEnterUapsd != pCommand->command )
+ {
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_UAPSD_RSP without request\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ /* Check that we are in the correct state for this message. */
+ if (pMac->pmc.pmcState != REQUEST_START_UAPSD)
+ {
+ smsLog(pMac, LOGE, FL("Got Enter Uapsd rsp Message while in state %d\n"), pMac->pmc.pmcState);
+ break;
+ }
+
+ /* Enter UAPSD State if response indicates success. */
+ if (pMsg->statusCode == eSIR_SME_SUCCESS)
+ {
+ pmcEnterUapsdState(pMac);
+ pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_SUCCESS);
+ }
+ /* If response is failure, then we try to put the chip back in
+ BMPS mode*/
+ else {
+ smsLog(pMac, LOGE, "PMC: response message to request to enter "
+ "UAPSD indicates failure, status %x\n", pMsg->statusCode);
+ //Need to reset the UAPSD flag so pmcEnterBmpsState won't try to enter UAPSD.
+ pMac->pmc.uapsdSessionRequired = FALSE;
+ pmcEnterBmpsState(pMac);
+ //UAPSD will not be retied in this case so tell requester we are done with failure
+ pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE);
+ }
+ break;
+
+ /* We got a response to our Stop UAPSD request. */
+ case eWNI_PMC_EXIT_UAPSD_RSP:
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_UAPSD_RSP with status = %d\n"), pMsg->statusCode);
+ if( eSmeCommandExitUapsd != pCommand->command )
+ {
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_UAPSD_RSP without request\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ /* Check that we are in the correct state for this message. */
+ if (pMac->pmc.pmcState != REQUEST_STOP_UAPSD)
+ {
+ smsLog(pMac, LOGE, FL("Got Exit Uapsd rsp Message while in state %d\n"), pMac->pmc.pmcState);
+ break;
+ }
+
+ /* Enter BMPS State */
+ if (pMsg->statusCode != eSIR_SME_SUCCESS) {
+ smsLog(pMac, LOGP, "PMC: response message to request to exit "
+ "UAPSD indicates failure, status %x\n", pMsg->statusCode);
+ }
+ pmcEnterBmpsState(pMac);
+ break;
+
+ /* We got a response to our enter WOWL request. */
+ case eWNI_PMC_ENTER_WOWL_RSP:
+
+ if( eSmeCommandEnterWowl != pCommand->command )
+ {
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_WOWL_RSP without request\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ /* Check that we are in the correct state for this message. */
+ if (pMac->pmc.pmcState != REQUEST_ENTER_WOWL)
+ {
+ smsLog(pMac, LOGE, FL("Got eWNI_PMC_ENTER_WOWL_RSP while in state %s\n"),
+ pmcGetPmcStateStr(pMac->pmc.pmcState));
+ break;
+ }
+
+ /* Enter WOWL State if response indicates success. */
+ if (pMsg->statusCode == eSIR_SME_SUCCESS) {
+ pmcEnterWowlState(pMac);
+ pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_SUCCESS);
+ }
+
+ /* If response is failure, then we try to put the chip back in
+ BMPS mode*/
+ else {
+ smsLog(pMac, LOGE, "PMC: response message to request to enter "
+ "WOWL indicates failure, status %x\n", pMsg->statusCode);
+ pmcEnterBmpsState(pMac);
+ pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE);
+ }
+ break;
+
+ /* We got a response to our exit WOWL request. */
+ case eWNI_PMC_EXIT_WOWL_RSP:
+
+ if( eSmeCommandExitWowl != pCommand->command )
+ {
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_WOWL_RSP without request\n"));
+ fRemoveCommand = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ /* Check that we are in the correct state for this message. */
+ if (pMac->pmc.pmcState != REQUEST_EXIT_WOWL)
+ {
+ smsLog(pMac, LOGE, FL("Got Exit WOWL rsp Message while in state %d\n"), pMac->pmc.pmcState);
+ break;
+ }
+
+ /* Enter BMPS State */
+ if (pMsg->statusCode != eSIR_SME_SUCCESS) {
+ smsLog(pMac, LOGP, "PMC: response message to request to exit "
+ "WOWL indicates failure, status %x\n", pMsg->statusCode);
+ }
+ pmcEnterBmpsState(pMac);
+ break;
+
+ default:
+ smsLog(pMac, LOGE, FL("Invalid message type %d received\n"), pMsg->messageType);
+ PMC_ABORT;
+ break;
+ }//switch
+
+ if( fRemoveCommand )
+ {
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
+ {
+ pmcReleaseCommand( pMac, pCommand );
+ smeProcessPendingQueue( pMac );
+ }
+ }
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("message type %d received but no request is found\n"), pMsg->messageType);
+ }
+}
+
+
+/******************************************************************************
+*
+* Name: pmcMessageProcessor
+*
+* Description:
+* Process a message received by PMC.
+*
+* Parameters:
+* hHal - HAL handle for device
+* pMsg - pointer to received message
+*
+* Returns:
+* nothing
+*
+******************************************************************************/
+void pmcMessageProcessor (tHalHandle hHal, tSirSmeRsp *pMsg)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcMessageProcessor, message type %d\n"), pMsg->messageType);
+
+ switch( pMsg->messageType )
+ {
+ case eWNI_PMC_EXIT_BMPS_IND:
+ //When PMC needs to handle more indication from PE, they need to be added here.
+ {
+ /* Device left BMPS on its own. */
+ smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_BMPS_IND with status = %d\n"), pMsg->statusCode);
+ /* Check that we are in the correct state for this message. */
+ switch(pMac->pmc.pmcState)
+ {
+ case BMPS:
+ case REQUEST_START_UAPSD:
+ case UAPSD:
+ case REQUEST_STOP_UAPSD:
+ case REQUEST_ENTER_WOWL:
+ case WOWL:
+ case REQUEST_EXIT_WOWL:
+ case REQUEST_FULL_POWER:
+ smsLog(pMac, LOGW, FL("Got eWNI_PMC_EXIT_BMPS_IND while in state %d\n"), pMac->pmc.pmcState);
+ break;
+ default:
+ smsLog(pMac, LOGE, FL("Got eWNI_PMC_EXIT_BMPS_IND while in state %d\n"), pMac->pmc.pmcState);
+ PMC_ABORT;
+ break;
+ }
+
+ /* Enter Full Power State. */
+ if (pMsg->statusCode != eSIR_SME_SUCCESS)
+ {
+ smsLog(pMac, LOGP, FL("Exit BMPS indication indicates failure, status %x\n"), pMsg->statusCode);
+ }
+ else
+ {
+ tpSirSmeExitBmpsInd pExitBmpsInd = (tpSirSmeExitBmpsInd)pMsg;
+ pmcEnterRequestFullPowerState(hHal, pExitBmpsInd->exitBmpsReason);
+ }
+ break;
+ }
+
+ default:
+ pmcProcessResponse( pMac, pMsg );
+ break;
+ }
+
+}
+
+
+tANI_BOOLEAN pmcValidateConnectState( tHalHandle hHal )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ if ( !csrIsInfraConnected( pMac ) )
+ {
+ smsLog(pMac, LOGW, "PMC: STA not associated. BMPS cannot be entered\n");
+ return eANI_BOOLEAN_FALSE;
+ }
+
+ //Cannot have other session
+ if ( csrIsIBSSStarted( pMac ) )
+ {
+ smsLog(pMac, LOGW, "PMC: IBSS started. BMPS cannot be entered\n");
+ return eANI_BOOLEAN_FALSE;
+ }
+ if ( csrIsBTAMPStarted( pMac ) )
+ {
+ smsLog(pMac, LOGW, "PMC: BT-AMP exists. BMPS cannot be entered\n");
+ return eANI_BOOLEAN_FALSE;
+ }
+ if ((vos_concurrent_sessions_running()) &&
+ csrIsConcurrentInfraConnected( pMac ))
+ {
+ smsLog(pMac, LOGW, "PMC: Multiple active sessions exists. BMPS cannot be entered\n");
+ return eANI_BOOLEAN_FALSE;
+ }
+ return eANI_BOOLEAN_TRUE;
+}
+
+tANI_BOOLEAN pmcAllowImps( tHalHandle hHal )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ //Cannot have other session like IBSS or BT AMP running
+ if ( csrIsIBSSStarted( pMac ) )
+ {
+ smsLog(pMac, LOGW, "PMC: IBSS started. IMPS cannot be entered\n");
+ return eANI_BOOLEAN_FALSE;
+ }
+ if ( csrIsBTAMPStarted( pMac ) )
+ {
+ smsLog(pMac, LOGW, "PMC: BT-AMP exists. IMPS cannot be entered\n");
+ return eANI_BOOLEAN_FALSE;
+ }
+
+ //All sessions must be disconnected to allow IMPS
+ if ( !csrIsAllSessionDisconnected( pMac ) )
+ {
+ smsLog(pMac, LOGW, "PMC: Atleast one connected session. IMPS cannot be entered\n");
+ return eANI_BOOLEAN_FALSE;
+ }
+
+ return eANI_BOOLEAN_TRUE;
+}
+
+/******************************************************************************
+*
+* Name: pmcRequestBmps
+*
+* Description:
+* Request that the device be put in BMPS state.
+*
+* Parameters:
+* hHal - HAL handle for device
+* callbackRoutine - Callback routine invoked in case of success/failure
+* callbackContext - value to be passed as parameter to routine specified
+* above
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - device is in BMPS state
+* eHAL_STATUS_FAILURE - device cannot be brought to BMPS state
+* eHAL_STATUS_PMC_PENDING - device is being brought to BMPS state,
+*
+******************************************************************************/
+eHalStatus pmcRequestBmps (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tpRequestBmpsEntry pEntry;
+ eHalStatus status;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_BMPS_ENTER_REQ;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+ smsLog(pMac, LOG2, "PMC: entering pmcRequestBmps");
+
+ /* If already in BMPS, just return. */
+ if (pMac->pmc.pmcState == BMPS || REQUEST_START_UAPSD == pMac->pmc.pmcState || UAPSD == pMac->pmc.pmcState)
+ {
+ smsLog(pMac, LOG2, "PMC: Device already in BMPS pmcState %d", pMac->pmc.pmcState);
+ pMac->pmc.bmpsRequestedByHdd = TRUE;
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ status = pmcEnterBmpsCheck( pMac );
+ if(HAL_STATUS_SUCCESS( status ))
+ {
+ status = pmcEnterRequestBmpsState(hHal);
+ /* Enter Request BMPS State. */
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ /* Remember that HDD requested BMPS. This flag will be used to put the
+ device back into BMPS if any module other than HDD (e.g. CSR, QoS, or BAP)
+ requests full power for any reason */
+ pMac->pmc.bmpsRequestedByHdd = TRUE;
+
+ /* If able to enter Request BMPS State, then request is pending.
+ Allocate entry for request BMPS callback routine list. */
+ if (palAllocateMemory(
+ pMac->hHdd, (void **)&pEntry,
+ sizeof(tRequestBmpsEntry)) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: cannot allocate memory for request "
+ "BMPS routine list entry\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Store routine and context in entry. */
+ pEntry->callbackRoutine = callbackRoutine;
+ pEntry->callbackContext = callbackContext;
+
+ /* Add entry to list. */
+ csrLLInsertTail(&pMac->pmc.requestBmpsList, &pEntry->link, FALSE);
+
+ status = eHAL_STATUS_PMC_PENDING;
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ }
+
+ return status;
+}
+
+/******************************************************************************
+*
+* Name: pmcStartUapsd
+*
+* Description:
+* Request that the device be put in UAPSD state.
+*
+* Parameters:
+* hHal - HAL handle for device
+* callbackRoutine - Callback routine invoked in case of success/failure
+* callbackContext - value to be passed as parameter to routine specified
+* above
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - device is in UAPSD state
+* eHAL_STATUS_FAILURE - device cannot be brought to UAPSD state
+* eHAL_STATUS_PMC_PENDING - device is being brought to UAPSD state
+* eHAL_STATUS_PMC_DISABLED - UAPSD is disabled or BMPS mode is disabled
+*
+******************************************************************************/
+eHalStatus pmcStartUapsd (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tpStartUapsdEntry pEntry;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_UAPSD_START_REQ;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+ smsLog(pMac, LOG2, "PMC: entering pmcStartUapsd");
+
+ if( !PMC_IS_READY(pMac) )
+ {
+ smsLog(pMac, LOGE, FL("Requesting UAPSD when PMC not ready\n"));
+ smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
+ pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Check if BMPS is enabled. */
+ if (!pMac->pmc.bmpsEnabled)
+ {
+ smsLog(pMac, LOGE, "PMC: Cannot enter UAPSD. BMPS is disabled\n");
+ return eHAL_STATUS_PMC_DISABLED;
+ }
+
+ /* Check if UAPSD is enabled. */
+ if (!pMac->pmc.uapsdEnabled)
+ {
+ smsLog(pMac, LOGE, "PMC: Cannot enter UAPSD. UAPSD is disabled\n");
+ return eHAL_STATUS_PMC_DISABLED;
+ }
+
+ /* If already in UAPSD, just return. */
+ if (pMac->pmc.pmcState == UAPSD)
+ return eHAL_STATUS_SUCCESS;
+
+ /* Check that we are associated. */
+ if (!pmcValidateConnectState( pMac ))
+ {
+ smsLog(pMac, LOGE, "PMC: STA not associated with an AP. UAPSD cannot be entered\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Enter REQUEST_START_UAPSD State. */
+ if (pmcEnterRequestStartUapsdState(hHal) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+
+ if( NULL != callbackRoutine )
+ {
+ /* If success then request is pending. Allocate entry for callback routine list. */
+ if (palAllocateMemory(pMac->hHdd, (void **)&pEntry,
+ sizeof(tStartUapsdEntry)) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, "PMC: cannot allocate memory for request "
+ "start UAPSD routine list entry\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Store routine and context in entry. */
+ pEntry->callbackRoutine = callbackRoutine;
+ pEntry->callbackContext = callbackContext;
+
+ /* Add entry to list. */
+ csrLLInsertTail(&pMac->pmc.requestStartUapsdList, &pEntry->link, FALSE);
+ }
+
+ return eHAL_STATUS_PMC_PENDING;
+}
+
+/******************************************************************************
+*
+* Name: pmcStopUapsd
+*
+* Description:
+* Request that the device be put out of UAPSD state.
+*
+* Parameters:
+* hHal - HAL handle for device
+*
+* Returns:
+* eHAL_STATUS_SUCCESS - device is put out of UAPSD and back in BMPS state
+* eHAL_STATUS_FAILURE - device cannot be brought out of UAPSD state
+*
+******************************************************************************/
+eHalStatus pmcStopUapsd (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_UAPSD_STOP_REQ;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+ smsLog(pMac, LOG2, "PMC: entering pmcStopUapsd");
+
+ /* Clear any buffered command for entering UAPSD */
+ pMac->pmc.uapsdSessionRequired = FALSE;
+
+ /* Nothing to be done if we are already out of UAPSD. This can happen if
+ some other module (HDD, BT-AMP) requested Full Power.*/
+ if (pMac->pmc.pmcState != UAPSD && pMac->pmc.pmcState != REQUEST_STOP_UAPSD)
+ {
+ smsLog(pMac, LOGW, "PMC: Device is already out of UAPSD "
+ "state. Current state is %d\n", pMac->pmc.pmcState);
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ /* Enter REQUEST_STOP_UAPSD State*/
+ if (pmcEnterRequestStopUapsdState(hHal) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcRequestStandby
+ \brief Request that the device be put in standby.
+ \param hHal - The handle returned by macOpen.
+ \param callbackRoutine - Callback routine invoked in case of success/failure
+ \param callbackContext - value to be passed as parameter to callback
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - device is in Standby mode
+ eHAL_STATUS_FAILURE - device cannot be put in standby mode
+ eHAL_STATUS_PMC_PENDING - device is being put in standby mode
+ ---------------------------------------------------------------------------*/
+extern eHalStatus pmcRequestStandby (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
+
+ vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
+ psRequest.event_subtype = WLAN_ENTER_STANDBY_REQ;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
+#endif
+
+ smsLog(pMac, LOG2, "PMC: entering pmcRequestStandby");
+
+ /* Check if standby is enabled. */
+ if (!pMac->pmc.standbyEnabled)
+ {
+ smsLog(pMac, LOGE, "PMC: Cannot enter standby. Standby is disabled\n");
+ return eHAL_STATUS_PMC_DISABLED;
+ }
+
+ if( !PMC_IS_READY(pMac) )
+ {
+ smsLog(pMac, LOGE, FL("Requesting standby when PMC not ready\n"));
+ smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
+ pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* If already in STANDBY, just return. */
+ if (pMac->pmc.pmcState == STANDBY)
+ return eHAL_STATUS_SUCCESS;
+
+
+ if (csrIsIBSSStarted(pMac) || csrIsBTAMPStarted(pMac))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
+ "WLAN: IBSS or BT-AMP session present. Cannot honor standby request");
+ return eHAL_STATUS_PMC_NOT_NOW;
+ }
+
+ /* Enter Request Standby State. */
+ if (pmcEnterRequestStandbyState(hHal) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+
+ /* Save the callback routine for when we need it. */
+ pMac->pmc.standbyCallbackRoutine = callbackRoutine;
+ pMac->pmc.standbyCallbackContext = callbackContext;
+
+ return eHAL_STATUS_PMC_PENDING;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcRegisterDeviceStateUpdateInd
+ \brief Register a callback routine that is called whenever
+ the device enters a new device state (Full Power, BMPS, UAPSD)
+ \param hHal - The handle returned by macOpen.
+ \param callbackRoutine - Callback routine to be registered
+ \param callbackContext - Cookie to be passed back during callback
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully registered
+ eHAL_STATUS_FAILURE - not successfully registered
+ ---------------------------------------------------------------------------*/
+extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState),
+ void *callbackContext)
+{
+
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tpDeviceStateUpdateIndEntry pEntry;
+
+ smsLog(pMac, LOG2, FL("Entering pmcRegisterDeviceStateUpdateInd"));
+
+ /* Allocate entry for device power state update indication. */
+ if (palAllocateMemory(pMac->hHdd, (void **)&pEntry, sizeof(tDeviceStateUpdateIndEntry)) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot allocate memory for device power state update indication\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Store routine in entry. */
+ pEntry->callbackRoutine = callbackRoutine;
+ pEntry->callbackContext = callbackContext;
+
+ /* Add entry to list. */
+ csrLLInsertTail(&pMac->pmc.deviceStateUpdateIndList, &pEntry->link, FALSE);
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcDeregisterDeviceStateUpdateInd
+ \brief Deregister a routine that was registered for device state changes
+ \param hHal - The handle returned by macOpen.
+ \param callbackRoutine - Callback routine to be deregistered
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully deregistered
+ eHAL_STATUS_FAILURE - not successfully deregistered
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState))
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tListElem *pEntry;
+ tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry;
+
+ smsLog(pMac, LOG2, FL("Entering pmcDeregisterDeviceStateUpdateInd"));
+
+ /* Find entry in the power save update routine list that matches
+ the specified routine and remove it. */
+ pEntry = csrLLPeekHead(&pMac->pmc.deviceStateUpdateIndList, FALSE);
+ while (pEntry != NULL)
+ {
+ pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link);
+ if (pDeviceStateUpdateIndEntry->callbackRoutine == callbackRoutine)
+ {
+ if (!csrLLRemoveEntry(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE))
+ {
+ smsLog(pMac, LOGE, FL("Cannot remove device state update ind entry from list\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+ if (palFreeMemory(pMac->hHdd, pDeviceStateUpdateIndEntry) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot free memory for device state update ind routine list entry\n"));
+ PMC_ABORT;
+ return eHAL_STATUS_FAILURE;
+ }
+ return eHAL_STATUS_SUCCESS;
+ }
+ pEntry = csrLLNext(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE);
+ }
+
+ /* Could not find matching entry. */
+ return eHAL_STATUS_FAILURE;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcReady
+ \brief fn to inform PMC that eWNI_SME_SYS_READY_IND has been sent to PE.
+ This acts as a trigger to send a message to PE to update the power
+ save related conig to FW. Note that if HDD configures any power save
+ related stuff before this API is invoked, PMC will buffer all the
+ configutaion.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcReady(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ smsLog(pMac, LOG2, FL("Entering pmcReady"));
+
+ if(pMac->pmc.pmcState == STOPPED)
+ {
+ smsLog(pMac, LOGP, FL("pmcReady is invoked even before pmcStart"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ pMac->pmc.pmcReady = TRUE;
+ if (pmcSendPowerSaveConfigMessage(hHal) != eHAL_STATUS_SUCCESS)
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcWowlAddBcastPattern
+ \brief Add a pattern for Pattern Byte Matching in Wowl mode. Firmware will
+ do a pattern match on these patterns when Wowl is enabled during BMPS
+ mode. Note that Firmware performs the pattern matching only on
+ broadcast frames and while Libra is in BMPS mode.
+ \param hHal - The handle returned by macOpen.
+ \param pattern - Pointer to the pattern to be added
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot add pattern
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcWowlAddBcastPattern (
+ tHalHandle hHal,
+ tpSirWowlAddBcastPtrn pattern)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ vos_log_powersave_wow_add_ptrn_pkt_type *log_ptr = NULL;
+ WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_powersave_wow_add_ptrn_pkt_type, LOG_WLAN_POWERSAVE_WOW_ADD_PTRN_C);
+#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT
+
+ smsLog(pMac, LOG2, "PMC: entering pmcWowlAddBcastPattern");
+
+ if(pattern == NULL)
+ {
+ smsLog(pMac, LOGE, FL("Null broadcast pattern being passed\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ if( log_ptr )
+ {
+ log_ptr->pattern_id = pattern->ucPatternId;
+ log_ptr->pattern_byte_offset = pattern->ucPatternByteOffset;
+ log_ptr->pattern_size = pattern->ucPatternSize;
+ log_ptr->pattern_mask_size = pattern->ucPatternMaskSize;
+
+ vos_mem_copy(log_ptr->pattern, pattern->ucPattern, SIR_WOWL_BCAST_PATTERN_MAX_SIZE);
+ /* 1 bit in the pattern mask denotes 1 byte of pattern hence pattern mask size is 1/8 */
+ vos_mem_copy(log_ptr->pattern_mask, pattern->ucPatternMask, SIR_WOWL_BCAST_PATTERN_MAX_SIZE >> 3);
+ }
+
+ WLAN_VOS_DIAG_LOG_REPORT(log_ptr);
+#endif
+
+
+ if(pattern->ucPatternId >= SIR_WOWL_BCAST_MAX_NUM_PATTERNS )
+ {
+ smsLog(pMac, LOGE, FL("Pattern Id must range from 0 to %d\n"), SIR_WOWL_BCAST_MAX_NUM_PATTERNS-1);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if( pMac->pmc.pmcState == STANDBY || pMac->pmc.pmcState == REQUEST_STANDBY )
+ {
+ smsLog(pMac, LOGE, FL("Cannot add WoWL Pattern as chip is in %s state\n"),
+ pmcGetPmcStateStr(pMac->pmc.pmcState));
+ return eHAL_STATUS_FAILURE;
+ }
+ if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS )
+ {
+ //Wake up the chip first
+ eHalStatus status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN,
+ pattern, sizeof(tSirWowlAddBcastPtrn) );
+
+ if( eHAL_STATUS_PMC_PENDING == status )
+ {
+ return eHAL_STATUS_SUCCESS;
+ }
+ else
+ {
+ //either fail or already in full power
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ return ( status );
+ }
+ //else let it through because it is in full power state
+ }
+ }
+
+ if (pmcSendMessage(hHal, eWNI_PMC_WOWL_ADD_BCAST_PTRN, pattern, sizeof(tSirWowlAddBcastPtrn))
+ != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcWowlDelBcastPattern
+ \brief Delete a pattern that was added for Pattern Byte Matching.
+ \param hHal - The handle returned by macOpen.
+ \param pattern - Pattern to be deleted
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot delete pattern
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcWowlDelBcastPattern (
+ tHalHandle hHal,
+ tpSirWowlDelBcastPtrn pattern)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type);
+
+ vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type));
+ wowRequest.event_subtype = WLAN_WOW_DEL_PTRN_REQ;
+ wowRequest.wow_del_ptrn_id = pattern->ucPatternId;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW);
+#endif
+
+ smsLog(pMac, LOG2, "PMC: entering pmcWowlDelBcastPattern");
+
+ if(pattern->ucPatternId >= SIR_WOWL_BCAST_MAX_NUM_PATTERNS )
+ {
+ smsLog(pMac, LOGE, FL("Pattern Id must range from 0 to %d\n"),
+ SIR_WOWL_BCAST_MAX_NUM_PATTERNS-1);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if(pMac->pmc.pmcState == STANDBY || pMac->pmc.pmcState == REQUEST_STANDBY)
+ {
+ smsLog(pMac, LOGE, FL("Cannot delete WoWL Pattern as chip is in %s state\n"),
+ pmcGetPmcStateStr(pMac->pmc.pmcState));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS )
+ {
+ //Wake up the chip first
+ eHalStatus status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN,
+ pattern, sizeof(tSirWowlDelBcastPtrn) );
+
+ if( eHAL_STATUS_PMC_PENDING == status )
+ {
+ return eHAL_STATUS_SUCCESS;
+ }
+ else
+ {
+ //either fail or already in full power
+ if( !HAL_STATUS_SUCCESS( status ) )
+ {
+ return ( status );
+ }
+ //else let it through because it is in full power state
+ }
+ }
+
+ if (pmcSendMessage(hHal, eWNI_PMC_WOWL_DEL_BCAST_PTRN, pattern, sizeof(tSirWowlDelBcastPtrn))
+ != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_DEL_BCAST_PTRN to PE failed\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcEnterWowl
+ \brief Request that the device be brought to full power state.
+ Note 1: If "fullPowerReason" specificied in this API is set to
+ eSME_FULL_PWR_NEEDED_BY_HDD, PMC will clear any "buffered wowl" requests
+ and also clear any "buffered BMPS requests by HDD". Assumption is that since
+ HDD is requesting full power, we need to undo any previous HDD requests for
+ BMPS (using sme_RequestBmps) or WoWL (using sme_EnterWoWL). If the reason is
+ specified anything other than above, the buffered requests for BMPS and WoWL
+ will not be cleared.
+ Note 2: Requesting full power (no matter what the fullPowerReason is) doesn't
+ disable the "auto bmps timer" (if it is enabled) or clear any "buffered uapsd
+ request".
+ Note 3: When the device finally enters Full Power PMC will start a timer
+ if any of the following holds true:
+ - Auto BMPS mode is enabled
+ - Uapsd request is pending
+ - HDD's request for BMPS is pending
+ - HDD's request for WoWL is pending
+ On timer expiry PMC will attempt to put the device in BMPS mode if following
+ (in addition to those listed above) holds true:
+ - Polling of all modules through the Power Save Check routine passes
+ - STA is associated to an access point
+ \param hHal - The handle returned by macOpen.
+ \param - enterWowlCallbackRoutine Callback routine invoked in case of success/failure
+ \param - enterWowlCallbackContext - Cookie to be passed back during callback
+ \param - wakeReasonIndCB Callback routine invoked for Wake Reason Indication
+ \param - wakeReasonIndCBContext - Cookie to be passed back during callback
+ \param - fullPowerReason - Reason why this API is being invoked. SME needs to
+ distinguish between BAP and HDD requests
+ \return eHalStatus - status
+ eHAL_STATUS_SUCCESS - device brought to full power state
+ eHAL_STATUS_FAILURE - device cannot be brought to full power state
+ eHAL_STATUS_PMC_PENDING - device is being brought to full power state,
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcEnterWowl (
+ tHalHandle hHal,
+ void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status),
+ void *enterWowlCallbackContext,
+#ifdef WLAN_WAKEUP_EVENTS
+ void (*wakeReasonIndCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd),
+ void *wakeReasonIndCBContext,
+#endif // WLAN_WAKEUP_EVENTS
+ tpSirSmeWowlEnterParams wowlEnterParams)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type);
+
+ vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type));
+ wowRequest.event_subtype = WLAN_WOW_ENTER_REQ;
+ wowRequest.wow_type = 0;
+
+ if(wowlEnterParams->ucMagicPktEnable)
+ {
+ wowRequest.wow_type |= 1;
+ vos_mem_copy(wowRequest.wow_magic_pattern, (tANI_U8 *)wowlEnterParams->magicPtrn, 6);
+ }
+
+ if(wowlEnterParams->ucPatternFilteringEnable)
+ {
+ wowRequest.wow_type |= 2;
+ }
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW);
+#endif
+
+ smsLog(pMac, LOG2, "PMC: entering pmcEnterWowl\n");
+
+ if( !PMC_IS_READY(pMac) )
+ {
+ smsLog(pMac, LOGE, FL("Requesting WoWL when PMC not ready\n"));
+ smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
+ pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Check if BMPS is enabled. */
+ if (!pMac->pmc.bmpsEnabled)
+ {
+ smsLog(pMac, LOGE, "PMC: Cannot enter WoWL. BMPS is disabled\n");
+ return eHAL_STATUS_PMC_DISABLED;
+ }
+
+ /* Check if WoWL is enabled. */
+ if (!pMac->pmc.wowlEnabled)
+ {
+ smsLog(pMac, LOGE, "PMC: Cannot enter WoWL. WoWL is disabled\n");
+ return eHAL_STATUS_PMC_DISABLED;
+ }
+
+ /* Check that we are associated with single Session. */
+ if (!pmcValidateConnectState( pMac ))
+ {
+ smsLog(pMac, LOGE, "PMC: Cannot enable WOWL. STA not associated "
+ "with an Access Point in Infra Mode with single active session\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Is there a pending UAPSD request? HDD should have triggered QoS
+ module to do the necessary cleanup before triggring WOWL*/
+ if(pMac->pmc.uapsdSessionRequired)
+ {
+ smsLog(pMac, LOGE, "PMC: Cannot request WOWL. Pending UAPSD request\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Check that entry into a power save mode is allowed at this time. */
+ if (pMac->pmc.pmcState == FULL_POWER && !pmcPowerSaveCheck(hHal))
+ {
+ smsLog(pMac, LOGE, "PMC: Power save check failed. WOWL request "
+ "will not be accepted\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ // To avoid race condition, set callback routines before sending message.
+ /* cache the WOWL information */
+ pMac->pmc.wowlEnterParams = *wowlEnterParams;
+ pMac->pmc.enterWowlCallbackRoutine = enterWowlCallbackRoutine;
+ pMac->pmc.enterWowlCallbackContext = enterWowlCallbackContext;
+#ifdef WLAN_WAKEUP_EVENTS
+ /* Cache the Wake Reason Indication callback information */
+ pMac->pmc.wakeReasonIndCB = wakeReasonIndCB;
+ pMac->pmc.wakeReasonIndCBContext = wakeReasonIndCBContext;
+#endif // WLAN_WAKEUP_EVENTS
+
+ /* Enter Request WOWL State. */
+ if (pmcRequestEnterWowlState(hHal, wowlEnterParams) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+
+ pMac->pmc.wowlModeRequired = TRUE;
+
+ return eHAL_STATUS_PMC_PENDING;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcExitWowl
+ \brief This is the SME API exposed to HDD to request exit from WoWLAN mode.
+ SME will initiate exit from WoWLAN mode and device will be put in BMPS
+ mode.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Device cannot exit WoWLAN mode.
+ eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode.
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcExitWowl (tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type);
+
+ vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type));
+ wowRequest.event_subtype = WLAN_WOW_EXIT_REQ;
+
+ WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW);
+#endif
+
+ smsLog(pMac, LOG2, "PMC: entering pmcExitWowl");
+
+ /* Clear any buffered command for entering WOWL */
+ pMac->pmc.wowlModeRequired = FALSE;
+
+ /* Enter REQUEST_EXIT_WOWL State*/
+ if (pmcRequestExitWowlState(hHal) != eHAL_STATUS_SUCCESS)
+ return eHAL_STATUS_FAILURE;
+
+ /* Clear the callback routines */
+ pMac->pmc.enterWowlCallbackRoutine = NULL;
+ pMac->pmc.enterWowlCallbackContext = NULL;
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+ \fn pmcSetHostOffload
+ \brief Set the host offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the offload request.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot set the offload.
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest)
+{
+ tpSirHostOffloadReq pRequestBuf;
+ vos_msg_t msg;
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: IP address = %d.%d.%d.%d", __FUNCTION__,
+ pRequest->params.hostIpv4Addr[0], pRequest->params.hostIpv4Addr[1],
+ pRequest->params.hostIpv4Addr[2], pRequest->params.hostIpv4Addr[3]);
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirHostOffloadReq));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for host offload request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirHostOffloadReq));
+
+ msg.type = WDA_SET_HOST_OFFLOAD;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ if(VOS_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_SET_HOST_OFFLOAD message to WDA", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcSetKeepAlive
+ \brief Set the Keep Alive feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the Keep Alive.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot set the keepalive.
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcSetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest)
+{
+ tpSirKeepAliveReq pRequestBuf;
+ vos_msg_t msg;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_LOW, "%s: "
+ "WDA_SET_KEEP_ALIVE message", __FUNCTION__);
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirKeepAliveReq));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "Not able to allocate memory for keep alive request",
+ __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirKeepAliveReq));
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_LOW, "buff TP %d "
+ "input TP %d ", pRequestBuf->timePeriod, pRequest->timePeriod);
+
+ msg.type = WDA_SET_KEEP_ALIVE;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ if(VOS_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_SET_KEEP_ALIVE message to WDA",
+ __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+#ifdef WLAN_NS_OFFLOAD
+
+/* ---------------------------------------------------------------------------
+ \fn pmcSetNSOffload
+ \brief Set the host offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the offload request.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot set the offload.
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest)
+{
+ tpSirHostOffloadReq pRequestBuf;
+ vos_msg_t msg;
+ int i;
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirHostOffloadReq));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for NS offload request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirHostOffloadReq));
+
+ msg.type = WDA_SET_NS_OFFLOAD;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ if(VOS_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 SIR_HAL_SET_HOST_OFFLOAD message to HAL", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+#endif //WLAN_NS_OFFLOAD
+
+
+void pmcClosePowerSaveCheckList(tpAniSirGlobal pMac)
+{
+ tListElem *pEntry;
+ tpPowerSaveCheckEntry pPowerSaveCheckEntry;
+
+ csrLLLock(&pMac->pmc.powerSaveCheckList);
+ while ( (pEntry = csrLLRemoveHead(&pMac->pmc.powerSaveCheckList, FALSE)) )
+ {
+ pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link);
+ if (palFreeMemory(pMac->hHdd, pPowerSaveCheckEntry) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot free memory \n"));
+ PMC_ABORT;
+ break;
+ }
+ }
+ csrLLUnlock(&pMac->pmc.powerSaveCheckList);
+ csrLLClose(&pMac->pmc.powerSaveCheckList);
+}
+
+
+void pmcCloseRequestFullPowerList(tpAniSirGlobal pMac)
+{
+ tListElem *pEntry;
+ tpRequestFullPowerEntry pRequestFullPowerEntry;
+
+ csrLLLock(&pMac->pmc.requestFullPowerList);
+ while ( (pEntry = csrLLRemoveHead(&pMac->pmc.requestFullPowerList, FALSE)) )
+ {
+ pRequestFullPowerEntry = GET_BASE_ADDR(pEntry, tRequestFullPowerEntry, link);
+ if (palFreeMemory(pMac->hHdd, pRequestFullPowerEntry) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot free memory \n"));
+ PMC_ABORT;
+ break;
+ }
+ }
+ csrLLUnlock(&pMac->pmc.requestFullPowerList);
+ csrLLClose(&pMac->pmc.requestFullPowerList);
+}
+
+
+void pmcCloseRequestBmpsList(tpAniSirGlobal pMac)
+{
+ tListElem *pEntry;
+ tpRequestBmpsEntry pRequestBmpsEntry;
+
+ csrLLLock(&pMac->pmc.requestBmpsList);
+ while ( (pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE)) )
+ {
+ pRequestBmpsEntry = GET_BASE_ADDR(pEntry, tRequestBmpsEntry, link);
+ if (palFreeMemory(pMac->hHdd, pRequestBmpsEntry) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot free memory \n"));
+ PMC_ABORT;
+ break;
+ }
+ }
+ csrLLUnlock(&pMac->pmc.requestBmpsList);
+ csrLLClose(&pMac->pmc.requestBmpsList);
+}
+
+
+void pmcCloseRequestStartUapsdList(tpAniSirGlobal pMac)
+{
+ tListElem *pEntry;
+ tpStartUapsdEntry pStartUapsdEntry;
+
+ csrLLLock(&pMac->pmc.requestStartUapsdList);
+ while ( (pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE)) )
+ {
+ pStartUapsdEntry = GET_BASE_ADDR(pEntry, tStartUapsdEntry, link);
+ if (palFreeMemory(pMac->hHdd, pStartUapsdEntry) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot free memory \n"));
+ PMC_ABORT;
+ break;
+ }
+ }
+ csrLLUnlock(&pMac->pmc.requestStartUapsdList);
+ csrLLClose(&pMac->pmc.requestStartUapsdList);
+}
+
+
+void pmcCloseDeviceStateUpdateList(tpAniSirGlobal pMac)
+{
+ tListElem *pEntry;
+ tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry;
+
+ csrLLLock(&pMac->pmc.deviceStateUpdateIndList);
+ while ( (pEntry = csrLLRemoveHead(&pMac->pmc.deviceStateUpdateIndList, FALSE)) )
+ {
+ pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link);
+ if (palFreeMemory(pMac->hHdd, pDeviceStateUpdateIndEntry) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot free memory \n"));
+ PMC_ABORT;
+ break;
+ }
+ }
+ csrLLUnlock(&pMac->pmc.deviceStateUpdateIndList);
+ csrLLClose(&pMac->pmc.deviceStateUpdateIndList);
+}
+
+
+void pmcCloseDeferredMsgList(tpAniSirGlobal pMac)
+{
+ tListElem *pEntry;
+ tPmcDeferredMsg *pDeferredMsg;
+
+ csrLLLock(&pMac->pmc.deferredMsgList);
+ while ( (pEntry = csrLLRemoveHead(&pMac->pmc.deferredMsgList, FALSE)) )
+ {
+ pDeferredMsg = GET_BASE_ADDR(pEntry, tPmcDeferredMsg, link);
+ if (palFreeMemory(pMac->hHdd, pDeferredMsg) != eHAL_STATUS_SUCCESS)
+ {
+ smsLog(pMac, LOGE, FL("Cannot free memory \n"));
+ PMC_ABORT;
+ break;
+ }
+ }
+ csrLLUnlock(&pMac->pmc.deferredMsgList);
+ csrLLClose(&pMac->pmc.deferredMsgList);
+}
+
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+
+static tSirRetStatus
+pmcPopulateMacHeader( 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
+ palCopyMemory( pMac->hHdd,
+ (tANI_U8 *) pMacHdr->da,
+ (tANI_U8 *) peerAddr,
+ sizeof( tSirMacAddr ));
+
+ sirCopyMacAddr(pMacHdr->sa,selfMacAddr);
+
+ // Prepare Address 3
+ palCopyMemory( pMac->hHdd,
+ (tANI_U8 *) pMacHdr->bssId,
+ (tANI_U8 *) peerAddr,
+ sizeof( tSirMacAddr ));
+ return statusCode;
+} /*** pmcPopulateMacHeader() ***/
+
+
+static tSirRetStatus
+pmcPrepareProbeReqTemplate(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};
+ /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+ // The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ // and then hand it off to 'dot11fPackProbeRequest' (for
+ // serialization). We start by zero-initializing the structure:
+ palZeroMemory( pMac->hHdd, ( tANI_U8* )&pr, sizeof( pr ) );
+
+ 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, &pr.HTCaps );
+ }
+
+ // That's it-- now we pack it. First, how much space are we going to
+ // need?
+ 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 );
+
+ // We'll fall back on the worst case scenario:
+ 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*/
+ palZeroMemory( pMac->hHdd, pFrame, nBytes );
+
+ // Next, we fill out the buffer descriptor:
+ nSirStatus = pmcPopulateMacHeader( 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; // allocated!
+ }
+
+ // That done, pack the Probe Request:
+ 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; // allocated!
+ }
+ 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" );
+ }
+
+ *pusLen = nPayload + sizeof(tSirMacMgmtHdr);
+ return eSIR_SUCCESS;
+} // End pmcPrepareProbeReqTemplate.
+
+
+eHalStatus pmcSetPreferredNetworkList
+(
+ tHalHandle hHal,
+ tpSirPNOScanReq pRequest,
+ tANI_U8 sessionId,
+ preferredNetworkFoundIndCallback callbackRoutine,
+ void *callbackContext
+)
+{
+ tpSirPNOScanReq pRequestBuf;
+ vos_msg_t msg;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+ tANI_U8 ucDot11Mode;
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: SSID = %s, %s", __FUNCTION__,
+ pRequest->aNetworks[0].ssId.ssId, pRequest->aNetworks[1].ssId.ssId);
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirPNOScanReq));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for PNO request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+
+ vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirPNOScanReq));
+
+ /*Must translate the mode first*/
+ ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac,
+ csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode ));
+
+ /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/
+ pmcPrepareProbeReqTemplate(pMac,SIR_PNO_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr,
+ pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen);
+
+ pmcPrepareProbeReqTemplate(pMac,SIR_PNO_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr,
+ pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen);
+
+
+ msg.type = WDA_SET_PNO_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ 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_SET_PNO_REQ message to WDA", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* Cache the Preferred Network Found Indication callback information */
+ pMac->pmc.prefNetwFoundCB = callbackRoutine;
+ pMac->pmc.preferredNetworkFoundIndCallbackContext = callbackContext;
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "-%s", __FUNCTION__);
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+eHalStatus pmcSetRssiFilter(tHalHandle hHal, v_U8_t rssiThreshold)
+{
+ tpSirSetRSSIFilterReq pRequestBuf;
+ vos_msg_t msg;
+
+
+ pRequestBuf = vos_mem_malloc(sizeof(tpSirSetRSSIFilterReq));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for PNO request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+
+
+ pRequestBuf->rssiThreshold = rssiThreshold;
+
+ msg.type = WDA_SET_RSSI_FILTER_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ 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_SET_PNO_REQ message to WDA", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+
+eHalStatus pmcUpdateScanParams(tHalHandle hHal, tCsrConfig *pRequest, tCsrChannel *pChannelList, tANI_U8 b11dResolved)
+{
+ tpSirUpdateScanParams pRequestBuf;
+ vos_msg_t msg;
+ int i;
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s started", __FUNCTION__);
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirUpdateScanParams));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for UpdateScanParams request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+
+ //
+ // Fill pRequestBuf structure from pRequest
+ //
+ pRequestBuf->b11dEnabled = pRequest->Is11eSupportEnabled;
+ pRequestBuf->b11dResolved = b11dResolved;
+ pRequestBuf->ucChannelCount =
+ ( pChannelList->numChannels < SIR_PNO_MAX_NETW_CHANNELS )?
+ pChannelList->numChannels:SIR_PNO_MAX_NETW_CHANNELS;
+
+ for (i=0; i < pChannelList->numChannels; i++)
+ {
+ pRequestBuf->aChannels[i] = pChannelList->channelList[i];
+ }
+ pRequestBuf->usPassiveMinChTime = pRequest->nPassiveMinChnTime;
+ pRequestBuf->usPassiveMaxChTime = pRequest->nPassiveMaxChnTime;
+ pRequestBuf->usActiveMinChTime = pRequest->nActiveMinChnTime;
+ pRequestBuf->usActiveMaxChTime = pRequest->nActiveMaxChnTime;
+ pRequestBuf->ucCBState = PHY_SINGLE_CHANNEL_CENTERED;
+
+ msg.type = WDA_UPDATE_SCAN_PARAMS_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ 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_UPDATE_SCAN_PARAMS message to WDA", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+#endif // FEATURE_WLAN_SCAN_PNO
+
+eHalStatus pmcSetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams)
+{
+ tSirSetPowerParamsReq* pRequestBuf;
+ vos_msg_t msg;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tpPESession psessionEntry;
+
+ if((psessionEntry = peGetValidPowerSaveSession(pMac))== NULL)
+ {
+ return eHAL_STATUS_NOT_INITIALIZED;
+ }
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirSetPowerParamsReq));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for Power Paramrequest", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+
+
+ vos_mem_copy(pRequestBuf, pwParams, sizeof(*pRequestBuf));
+
+
+ msg.type = WDA_SET_POWER_PARAMS_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+
+ if(VOS_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_SET_POWER_PARAMS_REQ message to WDA", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+eHalStatus pmcGetFilterMatchCount
+(
+ tHalHandle hHal,
+ FilterMatchCountCallback callbackRoutine,
+ void *callbackContext
+)
+{
+ tpSirRcvFltPktMatchRsp pRequestBuf;
+ vos_msg_t msg;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "%s: filterId = %d", __FUNCTION__);
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirRcvFltPktMatchRsp));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: Not able to allocate "
+ "memory for Get PC Filter Match Count request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+
+ msg.type = WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+
+ /* Cache the Packet Coalescing Filter Match Count callback information */
+ if (NULL != pMac->pmc.FilterMatchCountCB)
+ {
+ // Do we need to check if the callback is in use?
+ // Because we are not sending the same message again when it is pending,
+ // the only case when the callback is not NULL is that the previous message
+ //was timed out or failed.
+ // So, it will be safe to set the callback in this case.
+ }
+
+ pMac->pmc.FilterMatchCountCB = callbackRoutine;
+ pMac->pmc.FilterMatchCountCBContext = callbackContext;
+
+ if(VOS_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_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ "
+ "message to WDA", __FUNCTION__);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+#endif // WLAN_FEATURE_PACKET_FILTERING
+
+#ifdef WLAN_FEATURE_GTK_OFFLOAD
+/* ---------------------------------------------------------------------------
+ \fn pmcSetGTKOffload
+ \brief Set GTK offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pGtkOffload - Pointer to the GTK offload request.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot set the offload.
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload)
+{
+ tpSirGtkOffloadParams pRequestBuf;
+ vos_msg_t msg;
+ int i;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: KeyReplayCounter: %d",
+ __FUNCTION__, pGtkOffload->ullKeyReplayCounter);
+
+ pRequestBuf = (tpSirGtkOffloadParams)vos_mem_malloc(sizeof(tSirGtkOffloadParams));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate "
+ "memory for GTK offload request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+
+ vos_mem_copy(pRequestBuf, pGtkOffload, sizeof(tSirGtkOffloadParams));
+
+ msg.type = WDA_GTK_OFFLOAD_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ 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 "
+ "SIR_HAL_SET_GTK_OFFLOAD message to HAL", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn pmcGetGTKOffload
+ \brief Get GTK offload information.
+ \param hHal - The handle returned by macOpen.
+ \param callbackRoutine - Pointer to the GTK Offload Get Info response callback routine.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot set the offload.
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, void *callbackContext)
+{
+ tpSirGtkOffloadGetInfoRspParams pRequestBuf;
+ vos_msg_t msg;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterId = %d",
+ __FUNCTION__);
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirGtkOffloadGetInfoRspParams));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate "
+ "memory for Get GTK Offload request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+
+ msg.type = WDA_GTK_OFFLOAD_GETINFO_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+
+ /* Cache the Get GTK Offload callback information */
+ if (NULL != pMac->pmc.GtkOffloadGetInfoCB)
+ {
+ // Do we need to check if the callback is in use?
+ // Because we are not sending the same message again when it is pending,
+ // the only case when the callback is not NULL is that the previous message was timed out or failed.
+ // So, it will be safe to set the callback in this case.
+ }
+
+ pMac->pmc.GtkOffloadGetInfoCB = callbackRoutine;
+ pMac->pmc.GtkOffloadGetInfoCBContext = callbackContext;
+
+ 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_GTK_OFFLOAD_GETINFO_REQ message to WDA",
+ __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+#endif // WLAN_FEATURE_GTK_OFFLOAD
diff --git a/CORE/SME/src/pmc/pmcLogDump.c b/CORE/SME/src/pmc/pmcLogDump.c
new file mode 100644
index 0000000..463ea21
--- /dev/null
+++ b/CORE/SME/src/pmc/pmcLogDump.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/******************************************************************************
+*
+* Name: pmcLogDump.c
+*
+* Description: Implements the dump commands specific to PMC module
+*
+* Copyright 2008 (c) Qualcomm, Incorporated.
+* All Rights Reserved.
+* Qualcomm Confidential and Proprietary.
+*
+******************************************************************************/
+
+#include "palTypes.h"
+#include "aniGlobal.h"
+#include "pmcApi.h"
+#include "pmc.h"
+#include "logDump.h"
+#include "smsDebug.h"
+#include "sme_Api.h"
+#include "cfgApi.h"
+
+#if defined(ANI_LOGDUMP)
+
+void dump_pmc_callbackRoutine (void *callbackContext, eHalStatus status)
+{
+ tpAniSirGlobal pMac = (tpAniSirGlobal)callbackContext;
+ smsLog(pMac, LOGW, "*********Received callback from PMC with status = %d\n*********",status);
+}
+
+#ifdef WLAN_WAKEUP_EVENTS
+void dump_pmc_callbackRoutine2 (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd)
+{
+ tpAniSirGlobal pMac = (tpAniSirGlobal)callbackContext;
+ smsLog(pMac, LOGW, "*********Received callback from PMC with reason = %d\n*********",pWakeReasonInd->ulReason);
+}
+#endif // WLAN_WAKEUP_EVENTS
+
+void dump_pmc_deviceUpdateRoutine (void *callbackContext, tPmcState pmcState)
+{
+ tpAniSirGlobal pMac = (tpAniSirGlobal)callbackContext;
+ smsLog(pMac, LOGW, "*********Received msg from PMC: Device is in %s state\n*********", pmcGetPmcStateStr(pmcState));
+}
+
+static char *
+dump_pmc_state( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ char *ptr = p;
+
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+
+ p += log_sprintf( pMac,p, "******** PMC State & Configuration ******** \n");
+ p += log_sprintf( pMac,p, " PMC: IMPS Enabled? %d\n", pMac->pmc.impsEnabled);
+ p += log_sprintf( pMac,p, " PMC: Auto BMPS Timer Enabled? %d\n", pMac->pmc.autoBmpsEntryEnabled);
+ p += log_sprintf( pMac,p, " PMC: BMPS Enabled? %d\n", pMac->pmc.bmpsEnabled);
+ p += log_sprintf( pMac,p, " PMC: UAPSD Enabled? %d\n", pMac->pmc.uapsdEnabled);
+ p += log_sprintf( pMac,p, " PMC: WoWL Enabled? %d\n", pMac->pmc.wowlEnabled);
+ p += log_sprintf( pMac,p, " PMC: Standby Enabled? %d\n", pMac->pmc.standbyEnabled);
+ p += log_sprintf( pMac,p, " PMC: Auto BMPS timer period (ms): %d\n", pMac->pmc.bmpsConfig.trafficMeasurePeriod);
+ p += log_sprintf( pMac,p, " PMC: BMPS Listen Interval (Beacon intervals): %d\n", pMac->pmc.bmpsConfig.bmpsPeriod);
+ p += log_sprintf( pMac,p, " PMC: Device State = %s\n", pmcGetPmcStateStr(pMac->pmc.pmcState));
+ p += log_sprintf( pMac,p, " PMC: RequestFullPowerPending = %d\n", pMac->pmc.requestFullPowerPending);
+ p += log_sprintf( pMac,p, " PMC: UapsdSessionRequired = %d\n", pMac->pmc.uapsdSessionRequired);
+ p += log_sprintf( pMac,p, " PMC: wowlModeRequired = %d\n\n", pMac->pmc.wowlModeRequired);
+
+ smsLog(pMac, LOGW, "\n%s", ptr);
+
+ return p;
+}
+
+static char *
+dump_pmc_enable_imps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)pmcEnablePowerSave(pMac, ePMC_IDLE_MODE_POWER_SAVE);
+ return p;
+}
+
+static char *
+dump_pmc_disable_imps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)pmcDisablePowerSave(pMac, ePMC_IDLE_MODE_POWER_SAVE);
+ return p;
+}
+
+static char *
+dump_pmc_request_imps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg2; (void) arg3; (void) arg4;
+ pMac->pmc.impsEnabled = TRUE;
+ (void)pmcRequestImps(pMac, arg1, dump_pmc_callbackRoutine, pMac);
+ return p;
+}
+
+static char *
+dump_pmc_start_auto_bmps_timer( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ pMac->pmc.bmpsEnabled = TRUE;
+ (void)pmcStartAutoBmpsTimer(pMac);
+ return p;
+}
+
+static char *
+dump_pmc_stop_auto_bmps_timer( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)pmcStopAutoBmpsTimer(pMac);
+ return p;
+}
+
+static char *
+dump_pmc_enable_bmps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)pmcEnablePowerSave(pMac, ePMC_BEACON_MODE_POWER_SAVE);
+ return p;
+}
+
+static char *
+dump_pmc_disable_bmps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)pmcDisablePowerSave(pMac, ePMC_BEACON_MODE_POWER_SAVE);
+ return p;
+}
+
+static char *
+dump_pmc_request_bmps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ pMac->pmc.bmpsEnabled = TRUE;
+ (void)sme_RequestBmps(pMac, dump_pmc_callbackRoutine, pMac);
+ return p;
+}
+
+static char *
+dump_pmc_enable_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)pmcEnablePowerSave(pMac, ePMC_UAPSD_MODE_POWER_SAVE);
+ return p;
+}
+
+static char *
+dump_pmc_disable_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)pmcDisablePowerSave(pMac, ePMC_UAPSD_MODE_POWER_SAVE);
+ return p;
+}
+
+static char *
+dump_pmc_start_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ pMac->pmc.bmpsEnabled = TRUE;
+ pMac->pmc.uapsdEnabled = TRUE;
+ (void)pmcStartUapsd(pMac, dump_pmc_callbackRoutine, pMac);
+ return p;
+}
+
+static char *
+dump_pmc_stop_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)pmcStopUapsd(pMac);
+ return p;
+}
+
+static char *
+dump_pmc_request_standby( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ pMac->pmc.standbyEnabled = TRUE;
+ (void)pmcRequestStandby(pMac, dump_pmc_callbackRoutine, pMac);
+ return p;
+}
+
+static char *
+dump_pmc_request_full_power( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)sme_RequestFullPower(pMac, dump_pmc_callbackRoutine, pMac, eSME_FULL_PWR_NEEDED_BY_HDD);
+ return p;
+}
+
+static char *
+dump_pmc_enter_wowl( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ tSirSmeWowlEnterParams wowlEnterParams;
+ tSirRetStatus status;
+ tANI_U32 length;
+ (void) arg3; (void) arg4;
+
+ palZeroMemory(pMac->hHdd, &wowlEnterParams, sizeof(tSirSmeWowlEnterParams));
+
+ if (arg1 == 0 && arg2 == 0)
+ {
+ smsLog(pMac, LOGE, "Requesting WoWL but neither magic pkt and ptrn byte matching is being enabled\n");
+ return p;
+ }
+ if(arg1 == 1)
+ {
+ wowlEnterParams.ucMagicPktEnable = 1;
+ /* magic packet */
+ length = SIR_MAC_ADDR_LENGTH;
+ status = wlan_cfgGetStr(pMac, WNI_CFG_STA_ID, (tANI_U8 *)wowlEnterParams.magicPtrn, &length);
+ if (eSIR_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, "Reading of WNI_CFG_STA_ID from CFG failed. Using hardcoded STA MAC Addr\n");
+ wowlEnterParams.magicPtrn[0] = 0x00;
+ wowlEnterParams.magicPtrn[1] = 0x0a;
+ wowlEnterParams.magicPtrn[2] = 0xf5;
+ wowlEnterParams.magicPtrn[3] = 0x04;
+ wowlEnterParams.magicPtrn[4] = 0x05;
+ wowlEnterParams.magicPtrn[5] = 0x06;
+ }
+ }
+ if(arg2 == 1)
+ {
+ wowlEnterParams.ucPatternFilteringEnable = 1;
+ }
+
+ pMac->pmc.bmpsEnabled = TRUE;
+ pMac->pmc.wowlEnabled = TRUE;
+#ifdef WLAN_WAKEUP_EVENTS
+ (void)sme_EnterWowl(pMac, dump_pmc_callbackRoutine, pMac, dump_pmc_callbackRoutine2, pMac, &wowlEnterParams);
+#else // WLAN_WAKEUP_EVENTS
+ (void)sme_EnterWowl(pMac, dump_pmc_callbackRoutine, pMac, &wowlEnterParams);
+#endif // WLAN_WAKEUP_EVENTS
+ return p;
+}
+
+static char *
+dump_pmc_exit_wowl( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+ (void)sme_ExitWowl(pMac);
+ return p;
+}
+
+static char *
+dump_pmc_remove_ptrn( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ tSirWowlDelBcastPtrn delPattern;
+ (void) arg2; (void) arg3; (void) arg4;
+
+ palZeroMemory(pMac->hHdd, &delPattern, sizeof(tSirWowlDelBcastPtrn));
+
+ if(arg1 <= 7)
+ {
+ delPattern.ucPatternId = (tANI_U8)arg1;
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "dump_pmc_remove_ptrn: Invalid pattern Id %d\n",arg1);
+ return p;
+ }
+
+ (void)pmcWowlDelBcastPattern(pMac, &delPattern);
+ return p;
+}
+
+static char *
+dump_pmc_test_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ tSirSmeRsp smeRsp;
+ smeRsp.statusCode = eSIR_SME_SUCCESS;
+
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+
+ pMac->pmc.uapsdEnabled = TRUE;
+ pMac->pmc.pmcState = BMPS;
+
+ pmcRegisterDeviceStateUpdateInd(pMac, dump_pmc_deviceUpdateRoutine, pMac);
+
+ pmcStartUapsd(pMac, dump_pmc_callbackRoutine, pMac);
+ smeRsp.messageType = eWNI_PMC_ENTER_UAPSD_RSP;
+ pmcMessageProcessor(pMac, &smeRsp);
+ pmcStopUapsd(pMac);
+ smeRsp.messageType = eWNI_PMC_EXIT_UAPSD_RSP;
+ pmcMessageProcessor(pMac, &smeRsp);
+ pmcDeregisterDeviceStateUpdateInd(pMac, dump_pmc_deviceUpdateRoutine);
+ return p;
+}
+
+static char *
+dump_pmc_test_Wowl( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ tSirSmeRsp smeRsp;
+ tSirWowlAddBcastPtrn addPattern;
+ tSirWowlDelBcastPtrn delPattern;
+ tSirSmeWowlEnterParams wowlEnterParams;
+
+ smeRsp.statusCode = eSIR_SME_SUCCESS;
+ palZeroMemory(pMac->hHdd, &addPattern, sizeof(tSirWowlAddBcastPtrn));
+ palZeroMemory(pMac->hHdd, &delPattern, sizeof(tSirWowlDelBcastPtrn));
+ palZeroMemory(pMac->hHdd, &wowlEnterParams, sizeof(tSirSmeWowlEnterParams));
+
+ (void) arg1; (void) arg2; (void) arg3; (void) arg4;
+
+ //Add pattern
+ sme_WowlAddBcastPattern(pMac, &addPattern);
+
+ //Delete pattern
+ sme_WowlDelBcastPattern(pMac, &delPattern);
+
+ //Force the device into BMPS
+ pMac->pmc.pmcState = BMPS;
+
+ //Enter Wowl
+#ifdef WLAN_WAKEUP_EVENTS
+ sme_EnterWowl(pMac, dump_pmc_callbackRoutine, pMac, dump_pmc_callbackRoutine2, pMac, &wowlEnterParams);
+#else // WLAN_WAKEUP_EVENTS
+ sme_EnterWowl(pMac, dump_pmc_callbackRoutine, pMac, &wowlEnterParams);
+#endif // WLAN_WAKEUP_EVENTS
+ smeRsp.messageType = eWNI_PMC_ENTER_WOWL_RSP;
+ pmcMessageProcessor(pMac, &smeRsp);
+
+ //Exit Wowl
+ sme_ExitWowl(pMac);
+ smeRsp.messageType = eWNI_PMC_EXIT_WOWL_RSP;
+ pmcMessageProcessor(pMac, &smeRsp);
+ return p;
+}
+
+static tDumpFuncEntry pmcMenuDumpTable[] = {
+ {0, "PMC (900-925)", NULL},
+ // General
+ {900, "PMC: Dump State + config", dump_pmc_state},
+ // IMPS Related
+ {901, "PMC: Enable IMPS", dump_pmc_enable_imps},
+ {902, "PMC: Disable IMPS", dump_pmc_disable_imps},
+ {903, "PMC: Request IMPS: Syntax: dump 903 <imps_period_ms>", dump_pmc_request_imps},
+ // BMPS Related
+ {904, "PMC: Start Auto BMPS Timer", dump_pmc_start_auto_bmps_timer},
+ {905, "PMC: Stop Auto BMPS Timer", dump_pmc_stop_auto_bmps_timer},
+ {906, "PMC: Request BMPS", dump_pmc_request_bmps},
+ // UAPSD Related
+ {907, "PMC: Enable UAPSD", dump_pmc_enable_uapsd},
+ {908, "PMC: Disable UAPSD", dump_pmc_disable_uapsd},
+ {909, "PMC: Start UAPSD", dump_pmc_start_uapsd},
+ {910, "PMC: Stop UAPSD", dump_pmc_stop_uapsd},
+ // Standby Related
+ {911, "PMC: Request Standby", dump_pmc_request_standby},
+ // Full Power Related
+ {912, "PMC: Request Full Power", dump_pmc_request_full_power},
+ //Unit Test Related
+ {913, "PMC: Test UAPSD", dump_pmc_test_uapsd},
+ {914, "PMC: Test WOWL", dump_pmc_test_Wowl},
+ // WoWL Related
+ {915, "PMC: Enter WoWL: Syntax: dump 915 <enable_magic_pkt> <enable_ptrn_match>", dump_pmc_enter_wowl},
+ {916, "PMC: Exit WoWL", dump_pmc_exit_wowl},
+ {917, "PMC: Remove a pattern: Syntax: dump 917 <pattern_id(0-7)>", dump_pmc_remove_ptrn},
+ {918, "PMC: Enable BMPS", dump_pmc_enable_bmps},
+ {919, "PMC: Disable BMPS", dump_pmc_disable_bmps}
+};
+
+void pmcDumpInit(tHalHandle hHal)
+{
+ logDumpRegisterTable( (tpAniSirGlobal)hHal, &pmcMenuDumpTable[0],
+ sizeof(pmcMenuDumpTable)/sizeof(pmcMenuDumpTable[0]) );
+}
+
+#endif //#if defined(ANI_LOGDUMP)
diff --git a/CORE/SME/src/rrm/sme_rrm.c b/CORE/SME/src/rrm/sme_rrm.c
new file mode 100644
index 0000000..3ce9c0f
--- /dev/null
+++ b/CORE/SME/src/rrm/sme_rrm.c
@@ -0,0 +1,1296 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/*
+ * */
+/**=========================================================================
+
+ \file sme_Rrm.c
+
+ \brief implementation for SME RRM APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/* $Header$ */
+
+#if defined WLAN_FEATURE_VOWIFI
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include "halInternal.h"
+#endif
+#include "aniGlobal.h"
+#include "smeInside.h"
+#include "sme_Api.h"
+#include "smsDebug.h"
+#include "cfgApi.h"
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+#include "vos_diag_core_event.h"
+#include "vos_diag_core_log.h"
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+#include "csrInsideApi.h"
+
+#include "rrmGlobal.h"
+
+#ifdef FEATURE_WLAN_CCX
+#include "csrCcx.h"
+#endif
+
+/* Roam score for a neighbor AP will be calculated based on the below definitions.
+ The calculated roam score will be used to select the roamable candidate from neighbor AP list */
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY 0 /* When we support 11r over the DS, this should have a non-zero value */
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY 10
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE 20
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT 0 /* Not used */
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS 5
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD 3
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM 8
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA 0 /* We dont support delayed BA */
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA 3
+#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN 30
+
+#ifdef FEATURE_WLAN_CCX
+#define RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST 30
+#endif
+/**---------------------------------------------------------------------------
+
+ \brief rrmLLPurgeNeighborCache() -
+ This function purges all the entries in the neighbor cache and frees up all the internal nodes
+
+ \param - pMac - Pointer to the Hal Handle.
+ - pList - Pointer the List that should be purged.
+ \return - void
+
+ --------------------------------------------------------------------------*/
+static void rrmLLPurgeNeighborCache(tpAniSirGlobal pMac, tDblLinkList *pList)
+{
+ tListElem *pEntry;
+ tRrmNeighborReportDesc *pNeighborReportDesc;
+
+ csrLLLock(pList);
+
+ while((pEntry = csrLLRemoveHead(pList, LL_ACCESS_NOLOCK)) != NULL)
+ {
+ pNeighborReportDesc = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List );
+ vos_mem_free(pNeighborReportDesc->pNeighborBssDescription);
+ vos_mem_free(pNeighborReportDesc);
+ }
+
+ csrLLUnlock(pList);
+
+ return;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief rrmIndicateNeighborReportResult() -
+ This function calls the callback register by the caller while requesting for
+ neighbor report. This function gets invoked if a neighbor report is received from an AP
+ or neighbor response wait timer expires.
+
+ \param - pMac - Pointer to the Hal Handle.
+ - vosStatus - VOS_STATUS_SUCCESS/VOS_STATUS_FAILURE based on whether a valid report is
+ received or neighbor timer expired
+ \return - void
+
+ --------------------------------------------------------------------------*/
+void rrmIndicateNeighborReportResult(tpAniSirGlobal pMac, VOS_STATUS vosStatus)
+{
+ NeighborReportRspCallback callback;
+ void *callbackContext;
+
+ /* Reset the neighbor response pending status */
+ pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = eANI_BOOLEAN_FALSE;
+
+ /* Stop the timer if it is already running. The timer should be running only in the SUCCESS case. */
+ if (VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer))
+ {
+ VOS_ASSERT(VOS_STATUS_SUCCESS == vosStatus);
+ vos_timer_stop(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer);
+ }
+ callback = pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback;
+ callbackContext = pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallbackContext;
+
+ /* Reset the callback and the callback context before calling the callback. It is very likely that there may be a registration in
+ callback itself. */
+ pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback = NULL;
+ pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallbackContext = NULL;
+
+ /* Call the callback with the status received from caller */
+ if (callback)
+ callback(callbackContext, vosStatus);
+#ifdef FEATURE_WLAN_CCX
+ // We came here with IAPP AP List
+ // Make sure we inform CSR of the neighbor list
+ // for CCX Associations. First clear the cache.
+ else
+ if (csrNeighborRoamIsCCXAssoc(pMac))
+ {
+ ProcessIAPPNeighborAPList(pMac);
+ }
+#endif
+
+ return;
+
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief sme_RrmBeaconReportXmitInd() -
+
+ Create and send the beacon report Xmit ind message to PE.
+
+ \param - pMac - Pointer to the Hal Handle.
+ - pResult - scan result.
+ - measurementDone - flag to indicate that the measurement is done.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+static eHalStatus sme_RrmSendBeaconReportXmitInd( tpAniSirGlobal pMac, tCsrScanResultInfo **pResultArr, tANI_U8 measurementDone )
+{
+ tpSirBssDescription pBssDesc = NULL;
+ tpSirBeaconReportXmitInd pBeaconRep;
+ tANI_U16 length, ie_len;
+ tANI_U8 bssCounter=0, msgCounter=0;
+ tCsrScanResultInfo *pCurResult=NULL;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+
+
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Beacon report xmit Ind to PE\n");
+#endif
+
+ if( NULL == pResultArr && !measurementDone )
+ {
+ smsLog( pMac, LOGE, "Beacon report xmit Ind to PE Failed\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if (pResultArr)
+ pCurResult=pResultArr[bssCounter];
+
+ do
+ {
+ length = sizeof(tSirBeaconReportXmitInd);
+ pBeaconRep = vos_mem_malloc ( length );
+ if ( NULL == pBeaconRep )
+ {
+ smsLog( pMac, LOGP, "Unable to allocate memory for beacon report");
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ vos_mem_zero( pBeaconRep, length );
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Allocated memory for pBeaconRep\n"));
+#endif
+ pBeaconRep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND;
+ pBeaconRep->length = length;
+ pBeaconRep->uDialogToken = pSmeRrmContext->token;
+ pBeaconRep->duration = pSmeRrmContext->duration;
+ pBeaconRep->regClass = pSmeRrmContext->regClass;
+ vos_mem_copy( pBeaconRep->bssId, pSmeRrmContext->sessionBssId, sizeof(tSirMacAddr) );
+
+ msgCounter=0;
+ while (pCurResult)
+ {
+ pBssDesc = &pCurResult->BssDescriptor;
+ ie_len = GET_IE_LEN_IN_BSS( pBssDesc->length );
+ pBeaconRep->pBssDescription[msgCounter] = vos_mem_malloc ( ie_len+sizeof(tSirBssDescription) );
+ vos_mem_copy( pBeaconRep->pBssDescription[msgCounter], pBssDesc, sizeof(tSirBssDescription) );
+ vos_mem_copy( &pBeaconRep->pBssDescription[msgCounter]->ieFields[0], pBssDesc->ieFields, ie_len );
+
+ pBeaconRep->numBssDesc++;
+
+ if (++msgCounter >= SIR_BCN_REPORT_MAX_BSS_DESC)
+ break;
+
+ if (csrRoamIs11rAssoc(pMac)) {
+ break;
+ }
+
+ pCurResult = pResultArr[msgCounter];
+ }
+
+ bssCounter+=msgCounter;
+ if (!pResultArr || !pCurResult || (bssCounter>=SIR_BCN_REPORT_MAX_BSS_DESC))
+ pCurResult = NULL;
+ else
+ pCurResult = pResultArr[bssCounter];
+
+ pBeaconRep->fMeasureDone = (pCurResult)?false:measurementDone;
+
+ status = palSendMBMessage(pMac->hHdd, pBeaconRep);
+
+ smsLog( pMac, LOGW, "SME Sent BcnRepXmit to PE numBss %d\n", pBeaconRep->numBssDesc);
+
+ } while (pCurResult);
+
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief sme_RrmSendScanRequest() -
+
+ This function is called to get the scan result from CSR and send the beacon report
+ xmit ind message to PE.
+
+ \param - pMac - Pointer to the Hal Handle.
+ - num_chan - number of channels.
+ - channel list - list of channels to fetch the result from.
+ - measurementDone - flag to indicate that the measurement is done.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+static eHalStatus sme_RrmSendScanResult( tpAniSirGlobal pMac, tANI_U8 num_chan, tANI_U8* chanList, tANI_U8 measurementDone )
+{
+ tCsrScanResultFilter filter;
+ tScanResultHandle pResult;
+ tCsrScanResultInfo *pScanResult, *pNextResult;
+ tCsrScanResultInfo *pScanResultsArr[SIR_BCN_REPORT_MAX_BSS_DESC];
+ eHalStatus status;
+ tANI_U8 counter=0;
+ tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+ tANI_U32 sessionId;
+
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Send scan result to PE \n");
+#endif
+
+ vos_mem_zero( &filter, sizeof(filter) );
+ vos_mem_zero( pScanResultsArr, sizeof(pNextResult)*SIR_BCN_REPORT_MAX_BSS_DESC );
+
+ filter.BSSIDs.numOfBSSIDs = 1;
+ filter.BSSIDs.bssid = &pSmeRrmContext->bssId;
+
+ if( pSmeRrmContext->ssId.length )
+ {
+ filter.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
+ if( filter.SSIDs.SSIDList == NULL )
+ {
+ smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") );
+ return eHAL_STATUS_FAILURE;
+ }
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Allocated memory for SSIDList\n"));
+#endif
+ vos_mem_zero( filter.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) );
+
+ filter.SSIDs.SSIDList->SSID.length = pSmeRrmContext->ssId.length;
+ vos_mem_copy(filter.SSIDs.SSIDList->SSID.ssId, pSmeRrmContext->ssId.ssId, pSmeRrmContext->ssId.length);
+ filter.SSIDs.numOfSSIDs = 1;
+ }
+ else
+ {
+ filter.SSIDs.numOfSSIDs = 0;
+ }
+
+ filter.ChannelInfo.numOfChannels = num_chan;
+ filter.ChannelInfo.ChannelList = chanList;
+
+ filter.fMeasurement = TRUE;
+
+ csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid*)pSmeRrmContext->sessionBssId, &sessionId );
+ status = sme_ScanGetResult(pMac, (tANI_U8)sessionId, &filter, &pResult);
+
+ if( filter.SSIDs.SSIDList )
+ {
+ //Free the memory allocated for SSIDList.
+ vos_mem_free( filter.SSIDs.SSIDList );
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Free memory for SSIDList\n") );
+#endif
+ }
+
+ if (NULL == pResult)
+ {
+ // no scan results
+ //
+ // Spec. doesnt say anything about such condition.
+ // Since section 7.4.6.2 (IEEE802.11k-2008) says-rrm report frame should contain
+ // one or more report IEs. It probably means dont send any respose if no matching
+ // BSS found. Moreover, there is no flag or field in measurement report IE(7.3.2.22)
+ // OR beacon report IE(7.3.2.22.6) that can be set to indicate no BSS found on a given channel.
+ //
+ // If we finished measurement on all the channels, we still need to
+ // send a xmit indication with moreToFollow set to MEASURMENT_DONE
+ // so that PE can clean any context allocated.
+ if( measurementDone )
+ status = sme_RrmSendBeaconReportXmitInd( pMac, NULL, measurementDone );
+ return status;
+ }
+
+ pScanResult = sme_ScanResultGetFirst(pMac, pResult);
+
+ if( NULL == pScanResult && measurementDone )
+ status = sme_RrmSendBeaconReportXmitInd( pMac, NULL, measurementDone );
+
+ counter=0;
+ while (pScanResult)
+ {
+ pNextResult = sme_ScanResultGetNext(pMac, pResult);
+ pScanResultsArr[counter++] = pScanResult;
+ pScanResult = pNextResult; //sme_ScanResultGetNext(hHal, pResult);
+ if (counter >= SIR_BCN_REPORT_MAX_BSS_DESC)
+ break;
+ }
+
+ if (counter)
+ status = sme_RrmSendBeaconReportXmitInd( pMac, pScanResultsArr, measurementDone);
+
+ sme_ScanResultPurge(pMac, pResult);
+
+ return status;
+}
+/**---------------------------------------------------------------------------
+
+ \brief sme_RrmScanRequestCallback() -
+
+ The sme module calls this callback function once it finish the scan request
+ and this function send the beacon report xmit to PE and starts a timer of
+ random interval to issue next request.
+
+ \param - halHandle - Pointer to the Hal Handle.
+ - pContext - Pointer to the data context.
+ - scanId - Scan ID.
+ - status - CSR Status.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static eHalStatus sme_RrmScanRequestCallback(tHalHandle halHandle, void *pContext,
+ tANI_U32 scanId, eCsrScanStatus status)
+{
+
+ tANI_U16 interval;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle;
+ tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+ tANI_U32 time_tick;
+
+
+
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Scan Request callback \n");
+#endif
+ //if any more channels are pending, start a timer of a random value within randomization interval.
+ //
+ //
+ if( (pSmeRrmContext->currentIndex + 1) < pSmeRrmContext->channelList.numOfChannels )
+ {
+ sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], false );
+
+ pSmeRrmContext->currentIndex++; //Advance the current index.
+ //start the timer to issue next request.
+ //From timer tick get a random number within 10ms and max randmization interval.
+ time_tick = vos_timer_get_system_ticks();
+ interval = time_tick % (pSmeRrmContext->randnIntvl - 10 + 1) + 10;
+
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Set timer for interval %d \n", interval);
+#endif
+ vos_timer_start( &pSmeRrmContext->IterMeasTimer, interval );
+
+ }
+ else
+ {
+ //Done with the measurement. Clean up all context and send a message to PE with measurement done flag set.
+ sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], true );
+ vos_mem_free( pSmeRrmContext->channelList.ChannelList );
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Free memory for ChannelList\n") );
+#endif
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_RrmIssueScanReq() - This is called to send a scan request as part
+ of beacon report request .
+
+ \param
+
+ \return eHAL_STATUS_SUCCESS - Validation is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_RrmIssueScanReq( tpAniSirGlobal pMac )
+{
+ //Issue scan request.
+ tCsrScanRequest scanRequest;
+ v_U32_t scanId = 0;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+ tANI_U32 sessionId;
+
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Issue scan request \n" );
+#endif
+
+ vos_mem_zero( &scanRequest, sizeof(scanRequest));
+
+ /* set scanType, active or passive */
+
+ scanRequest.scanType = pSmeRrmContext->measMode;
+
+ vos_mem_copy(scanRequest.bssid,
+ pSmeRrmContext->bssId, sizeof(scanRequest.bssid) );
+
+ if( pSmeRrmContext->ssId.length )
+ {
+ scanRequest.SSIDs.numOfSSIDs = 1;
+ scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
+ if( scanRequest.SSIDs.SSIDList == NULL )
+ {
+ smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") );
+ return eHAL_STATUS_FAILURE;
+ }
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Allocated memory for pSSIDList\n"));
+#endif
+ vos_mem_zero( scanRequest.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) );
+ scanRequest.SSIDs.SSIDList->SSID.length = pSmeRrmContext->ssId.length;
+ vos_mem_copy(scanRequest.SSIDs.SSIDList->SSID.ssId, pSmeRrmContext->ssId.ssId, pSmeRrmContext->ssId.length);
+ }
+
+ /* set min and max channel time */
+ scanRequest.minChnTime = 0; //pSmeRrmContext->duration; Dont use min timeout.
+ scanRequest.maxChnTime = pSmeRrmContext->duration;
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "For Duration %d \n", pSmeRrmContext->duration );
+#endif
+
+ /* set BSSType to default type */
+ scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
+
+ /*Scan all the channels */
+ scanRequest.ChannelInfo.numOfChannels = 1;
+
+ scanRequest.ChannelInfo.ChannelList = &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex];
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "On channel %d \n", pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex] );
+#endif
+
+ /* set requestType to full scan */
+ scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
+
+ csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid*)pSmeRrmContext->sessionBssId, &sessionId );
+ status = sme_ScanRequest( pMac, (tANI_U8)sessionId, &scanRequest, &scanId, &sme_RrmScanRequestCallback, NULL );
+
+ if ( pSmeRrmContext->ssId.length )
+ {
+ vos_mem_free(scanRequest.SSIDs.SSIDList);
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Free memory for SSIDList\n"));
+#endif
+ }
+
+ return status;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_RrmProcessBeaconReportReqInd() - This is called to process the Beacon
+ report request from peer AP forwarded through PE .
+
+ \param pMsgBuf - a pointer to a buffer that maps to various structures base
+ on the message type.
+ The beginning of the buffer can always map to tSirSmeRsp.
+
+ \return eHAL_STATUS_SUCCESS - Validation is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+void sme_RrmProcessBeaconReportReqInd(tpAniSirGlobal pMac, void *pMsgBuf)
+{
+ tpSirBeaconReportReqInd pBeaconReq = (tpSirBeaconReportReqInd) pMsgBuf;
+ tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+ tANI_U32 len,i;
+
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Received Beacon report request ind Channel = %d\n", pBeaconReq->channelInfo.channelNum );
+#endif
+ //section 11.10.8.1 (IEEE Std 802.11k-2008)
+ //channel 0 and 255 has special meaning.
+ if( (pBeaconReq->channelInfo.channelNum == 0) ||
+ ((pBeaconReq->channelInfo.channelNum == 255) && (pBeaconReq->channelList.numChannels == 0) ) )
+ {
+ //Add all the channel in the regulatory domain.
+ wlan_cfgGetStrLen( pMac, WNI_CFG_VALID_CHANNEL_LIST, &len );
+ pSmeRrmContext->channelList.ChannelList = vos_mem_malloc( len );
+ if( pSmeRrmContext->channelList.ChannelList == NULL )
+ {
+ smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") );
+ return;
+ }
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Allocated memory for ChannelList\n") );
+#endif
+ csrGetCfgValidChannels( pMac, pSmeRrmContext->channelList.ChannelList, &len );
+ pSmeRrmContext->channelList.numOfChannels = (tANI_U8)len;
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "channel == 0 perfoming on all channels \n");
+#endif
+ }
+ else
+ {
+ len = 0;
+ pSmeRrmContext->channelList.numOfChannels = 0;
+
+ //If valid channel is present. We firt Measure on the given channel. and
+ //if there are additional channels present in APchannelreport, measure on these also.
+ if ( pBeaconReq->channelInfo.channelNum != 255 )
+ len = 1;
+#if defined WLAN_VOWIFI_DEBUG
+ else
+ smsLog( pMac, LOGE, "channel == 255 \n");
+#endif
+
+ len += pBeaconReq->channelList.numChannels;
+
+ pSmeRrmContext->channelList.ChannelList = vos_mem_malloc( len );
+ if( pSmeRrmContext->channelList.ChannelList == NULL )
+ {
+ smsLog( pMac, LOGP, FL("vos_mem_malloc failed") );
+ return;
+ }
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Allocated memory for ChannelList\n") );
+#endif
+
+ if ( pBeaconReq->channelInfo.channelNum != 255 )
+ {
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "channel == %d \n", pBeaconReq->channelInfo.channelNum );
+#endif
+ if(csrRoamIsChannelValid( pMac, pBeaconReq->channelInfo.channelNum ))
+ pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->channelList.numOfChannels++] = pBeaconReq->channelInfo.channelNum;
+#if defined WLAN_VOWIFI_DEBUG
+ else
+ smsLog( pMac, LOGE, "is Invalid channel, Ignoring this channel\n" );
+#endif
+ }
+
+ for ( i = 0 ; i < pBeaconReq->channelList.numChannels; i++ )
+ {
+ if(csrRoamIsChannelValid( pMac, pBeaconReq->channelList.channelNumber[i] ))
+ {
+ pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->channelList.numOfChannels] = pBeaconReq->channelList.channelNumber[i];
+ pSmeRrmContext->channelList.numOfChannels++;
+ }
+ }
+ }
+
+ //Copy session bssid
+ vos_mem_copy( pSmeRrmContext->sessionBssId, pBeaconReq->bssId, sizeof(tSirMacAddr) );
+
+ //copy measurement bssid
+ vos_mem_copy( pSmeRrmContext->bssId, pBeaconReq->macaddrBssid, sizeof(tSirMacAddr) );
+
+ //Copy ssid
+ vos_mem_copy( &pSmeRrmContext->ssId, &pBeaconReq->ssId, sizeof(tAniSSID) );
+
+ pSmeRrmContext->token = pBeaconReq->uDialogToken;
+ pSmeRrmContext->regClass = pBeaconReq->channelInfo.regulatoryClass;
+
+ switch( pBeaconReq->fMeasurementtype )
+ {
+ case 0: //Passive
+ case 1: //Active
+ pSmeRrmContext->measMode = pBeaconReq->fMeasurementtype? eSIR_ACTIVE_SCAN : eSIR_PASSIVE_SCAN ;
+ pSmeRrmContext->duration = pBeaconReq->measurementDuration;
+ pSmeRrmContext->randnIntvl = VOS_MAX( pBeaconReq->randomizationInterval, pSmeRrmContext->rrmConfig.maxRandnInterval );
+ pSmeRrmContext->currentIndex = 0;
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Send beacon report after scan \n" );
+#endif
+ sme_RrmIssueScanReq( pMac );
+ break;
+ case 2: //Table
+ //Get the current scan results for the given channel and send it.
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Send beacon report from table \n" );
+#endif
+ sme_RrmSendScanResult( pMac, pSmeRrmContext->channelList.numOfChannels, pSmeRrmContext->channelList.ChannelList, true );
+ vos_mem_free( pSmeRrmContext->channelList.ChannelList );
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Free memory for ChannelList\n") );
+#endif
+ break;
+ default:
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Unknown beacon report request mode\n");
+#endif
+ /* Indicate measurement completion to PE */
+ /* If this is not done, pCurrentReq pointer will not be freed and
+ PE will not handle subsequent Beacon requests */
+ sme_RrmSendBeaconReportXmitInd(pMac, NULL, true);
+ break;
+
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_RrmNeighborReportRequest() - This is API can be used to trigger a
+ Neighbor report from the peer.
+
+ \param sessionId - session identifier on which the request should be made.
+ \param pNeighborReq - a pointer to a neighbor report request.
+
+ \return eHAL_STATUS_SUCCESS - Validation is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+VOS_STATUS sme_RrmNeighborReportRequest(tpAniSirGlobal pMac, tANI_U8 sessionId,
+ tpRrmNeighborReq pNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpSirNeighborReportReqInd pMsg;
+ tCsrRoamSession *pSession;
+
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Request to send Neighbor report request received \n"));
+#endif
+ if( !CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ smsLog( pMac, LOGE, FL("Invalid session %d\n"), sessionId );
+ return VOS_STATUS_E_INVAL;
+ }
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ /* If already a report is pending, return failure */
+ if (eANI_BOOLEAN_TRUE == pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending)
+ {
+ smsLog( pMac, LOGE, FL("Neighbor request already pending.. Not allowed"));
+ return VOS_STATUS_E_AGAIN;
+ }
+
+ pMsg = vos_mem_malloc ( sizeof(tSirNeighborReportReqInd) );
+ if ( NULL == pMsg )
+ {
+ smsLog( pMac, LOGE, "Unable to allocate memory for Neighbor request");
+ return VOS_STATUS_E_NOMEM;
+ }
+
+
+ vos_mem_zero( pMsg, sizeof(tSirNeighborReportReqInd) );
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL(" Allocated memory for Neighbor request\n") );
+#endif
+
+ rrmLLPurgeNeighborCache(pMac, &pMac->rrm.rrmSmeContext.neighborReportCache);
+
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, FL("Purged the neighbor cache before sending Neighbor request: Status = %d\n"), status );
+#endif
+
+ pMsg->messageType = eWNI_SME_NEIGHBOR_REPORT_REQ_IND;
+ pMsg->length = sizeof( tSirNeighborReportReqInd );
+ vos_mem_copy( &pMsg->bssId, &pSession->connectedProfile.bssid, sizeof(tSirMacAddr) );
+ pMsg->noSSID = pNeighborReq->no_ssid;
+ vos_mem_copy( &pMsg->ucSSID, &pNeighborReq->ssid, sizeof(tSirMacSSid));
+
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ if( status != eHAL_STATUS_SUCCESS )
+ return VOS_STATUS_E_FAILURE;
+
+ /* Neighbor report request message sent successfully to PE. Now register the callbacks */
+ pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback =
+ callbackInfo->neighborRspCallback;
+ pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallbackContext =
+ callbackInfo->neighborRspCallbackContext;
+ pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = eANI_BOOLEAN_TRUE;
+
+ /* Start neighbor response wait timer now */
+ vos_timer_start(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer, callbackInfo->timeout);
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------
+ \brief rrmCalculateNeighborAPRoamScore() - This API is called while handling
+ individual neighbor reports from the APs neighbor AP report to
+ calculate the cumulative roam score before storing it in neighbor
+ cache.
+
+ \param pNeighborReportDesc - Neighbor BSS Descriptor node for which roam score
+ should be calculated
+
+ \return void.
+--------------------------------------------------------------------------*/
+static void rrmCalculateNeighborAPRoamScore(tpAniSirGlobal pMac, tpRrmNeighborReportDesc pNeighborReportDesc)
+{
+ tpSirNeighborBssDescripton pNeighborBssDesc;
+ tANI_U32 roamScore = 0;
+
+ VOS_ASSERT(pNeighborReportDesc != NULL);
+ VOS_ASSERT(pNeighborReportDesc->pNeighborBssDescription != NULL);
+
+ pNeighborBssDesc = pNeighborReportDesc->pNeighborBssDescription;
+
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fMobilityDomain)
+ {
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN;
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fSameSecurityMode)
+ {
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY;
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fSameAuthenticator)
+ {
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE;
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapRadioMeasurement)
+ {
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM;
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapSpectrumMeasurement)
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT;
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapQos)
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS;
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapApsd)
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD;
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapDelayedBlockAck)
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA;
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapImmediateBlockAck)
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA;
+ if (pNeighborBssDesc->bssidInfo.rrmInfo.fApPreauthReachable)
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY;
+ }
+ }
+ }
+ }
+#ifdef FEATURE_WLAN_CCX
+ // It has come in the report so its the best score
+ if (csrNeighborRoamIs11rAssoc(pMac) == FALSE)
+ {
+ // IAPP Route so lets make use of this info
+ // save all AP, as the list does not come all the time
+ // Save and reuse till the next AP List comes to us.
+ // Even save our own MAC address. Will be useful next time around.
+ roamScore += RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST;
+ }
+#endif
+ pNeighborReportDesc->roamScore = roamScore;
+
+ return;
+}
+
+/*--------------------------------------------------------------------------
+ \brief rrmStoreNeighborRptByRoamScore() - This API is called to store a given
+ Neighbor BSS descriptor to the neighbor cache. This function
+ stores the neighbor BSS descriptors in such a way that descriptors
+ are sorted by roamScore in descending order
+
+ \param pNeighborReportDesc - Neighbor BSS Descriptor node to be stored in cache
+
+ \return void.
+--------------------------------------------------------------------------*/
+void rrmStoreNeighborRptByRoamScore(tpAniSirGlobal pMac, tpRrmNeighborReportDesc pNeighborReportDesc)
+{
+ tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+ tListElem *pEntry;
+ tRrmNeighborReportDesc *pTempNeighborReportDesc;
+
+ VOS_ASSERT(pNeighborReportDesc != NULL);
+ VOS_ASSERT(pNeighborReportDesc->pNeighborBssDescription != NULL);
+
+ if (csrLLIsListEmpty(&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK))
+ {
+ smsLog(pMac, LOGE, FL("Neighbor report cache is empty.. Adding a entry now\n"));
+ /* Neighbor list cache is empty. Insert this entry in the tail */
+ csrLLInsertTail(&pSmeRrmContext->neighborReportCache, &pNeighborReportDesc->List, LL_ACCESS_LOCK);
+ return;
+ }
+ else
+ {
+ /* Should store the neighbor BSS description in the order sorted by roamScore in descending
+ order. APs with highest roamScore should be the 1st entry in the list */
+ pEntry = csrLLPeekHead(&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK);
+ while (pEntry != NULL)
+ {
+ pTempNeighborReportDesc = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List );
+ if (pTempNeighborReportDesc->roamScore < pNeighborReportDesc->roamScore)
+ break;
+ pEntry = csrLLNext(&pSmeRrmContext->neighborReportCache, pEntry, LL_ACCESS_LOCK);
+ }
+
+ if (pEntry)
+ /* This BSS roamscore is better than something in the list. Insert this before that one */
+ csrLLInsertEntry(&pSmeRrmContext->neighborReportCache, pEntry, &pNeighborReportDesc->List, LL_ACCESS_LOCK);
+ else
+ /* All the entries in the list has a better roam Score than this one. Insert this at the last */
+ csrLLInsertTail(&pSmeRrmContext->neighborReportCache, &pNeighborReportDesc->List, LL_ACCESS_LOCK);
+ }
+ return;
+}
+
+/*--------------------------------------------------------------------------
+ \brief sme_RrmProcessNeighborReport() - This is called to process the Neighbor
+ report received from PE.
+
+ \param pMsgBuf - a pointer to a buffer that maps to various structures base
+ on the message type.
+ The beginning of the buffer can always map to tSirSmeRsp.
+
+ \return eHAL_STATUS_SUCCESS - Validation is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_RrmProcessNeighborReport(tpAniSirGlobal pMac, void *pMsgBuf)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpSirNeighborReportInd pNeighborRpt = (tpSirNeighborReportInd) pMsgBuf;
+ tpRrmNeighborReportDesc pNeighborReportDesc;
+ tANI_U8 i = 0;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+
+#ifdef FEATURE_WLAN_CCX
+ // Clear the cache for CCX.
+ if (csrNeighborRoamIsCCXAssoc(pMac))
+ {
+ rrmLLPurgeNeighborCache(pMac,
+ &pMac->rrm.rrmSmeContext.neighborReportCache);
+ }
+#endif
+
+ for (i = 0; i < pNeighborRpt->numNeighborReports; i++)
+ {
+ pNeighborReportDesc = vos_mem_malloc(sizeof(tRrmNeighborReportDesc));
+ if (NULL == pNeighborReportDesc)
+ {
+ smsLog( pMac, LOGE, "Failed to allocate memory for RRM Neighbor report desc\n");
+ status = eHAL_STATUS_FAILED_ALLOC;
+ goto end;
+
+ }
+
+ vos_mem_zero(pNeighborReportDesc, sizeof(tRrmNeighborReportDesc));
+ pNeighborReportDesc->pNeighborBssDescription = vos_mem_malloc(sizeof(tSirNeighborBssDescription));
+ if (NULL == pNeighborReportDesc->pNeighborBssDescription)
+ {
+ smsLog( pMac, LOGE, "Failed to allocate memory for RRM Neighbor report BSS Description\n");
+ status = eHAL_STATUS_FAILED_ALLOC;
+ goto end;
+ }
+ vos_mem_zero(pNeighborReportDesc->pNeighborBssDescription, sizeof(tSirNeighborBssDescription));
+ vos_mem_copy(pNeighborReportDesc->pNeighborBssDescription, &pNeighborRpt->sNeighborBssDescription[i],
+ sizeof(tSirNeighborBssDescription));
+
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Received neighbor report with Neighbor BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
+ pNeighborRpt->sNeighborBssDescription[i].bssId[0],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[1],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[2],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[3],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[4],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[5]);
+#endif
+
+ /* Calculate the roam score based on the BSS Capability in the BSSID Information and store it in Neighbor report Desc */
+ rrmCalculateNeighborAPRoamScore(pMac, pNeighborReportDesc);
+
+ /* Store the Neighbor report Desc in the cache based on the roam score */
+ if ( pNeighborReportDesc->roamScore > 0)
+ {
+ rrmStoreNeighborRptByRoamScore(pMac, pNeighborReportDesc);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, FL("Roam score of BSSID %02x:%02x:%02x:%02x:%02x:%02x is 0, Ignoring.."),
+ pNeighborRpt->sNeighborBssDescription[i].bssId[0],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[1],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[2],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[3],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[4],
+ pNeighborRpt->sNeighborBssDescription[i].bssId[5]);
+
+ vos_mem_free(pNeighborReportDesc->pNeighborBssDescription);
+ vos_mem_free(pNeighborReportDesc);
+ }
+ }
+end:
+
+ if (!csrLLCount(&pMac->rrm.rrmSmeContext.neighborReportCache))
+ vosStatus = VOS_STATUS_E_FAILURE;
+
+ /* Received a report from AP. Indicate SUCCESS to the caller if there are some valid reports */
+ rrmIndicateNeighborReportResult(pMac, vosStatus);
+
+ return status;
+}
+/*--------------------------------------------------------------------------
+ \brief sme_RrmMsgProcessor() - sme_ProcessMsg() calls this function for the
+ messages that are handled by SME RRM module.
+
+ \param pMac - Pointer to the global MAC parameter structure.
+ \param msg_type - the type of msg passed by PE as defined in wniApi.h
+ \param pMsgBuf - a pointer to a buffer that maps to various structures base
+ on the message type.
+ The beginning of the buffer can always map to tSirSmeRsp.
+
+ \return eHAL_STATUS_SUCCESS - Validation is successful.
+
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_RrmMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type,
+ void *pMsgBuf)
+{
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+ FL(" Msg = %d for RRM measurement\n") , msg_type );
+
+ //switch on the msg type & make the state transition accordingly
+ switch(msg_type)
+ {
+ case eWNI_SME_NEIGHBOR_REPORT_IND:
+ sme_RrmProcessNeighborReport( pMac, pMsgBuf );
+ break;
+
+ case eWNI_SME_BEACON_REPORT_REQ_IND:
+ sme_RrmProcessBeaconReportReqInd( pMac, pMsgBuf );
+ break;
+
+ default:
+ //err msg
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("sme_RrmMsgProcessor:unknown msg type = %d\n"), msg_type);
+
+ break;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn rrmIterMeasTimerHandle
+
+ \brief Timer handler to handlet the timeout condition when a specific BT
+
+ stop event does not come back, in which case to restore back the
+
+ heartbeat timer.
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+ ---------------------------------------------------------------------------*/
+
+void rrmIterMeasTimerHandle( v_PVOID_t userData )
+{
+ tpAniSirGlobal pMac = (tpAniSirGlobal) userData;
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Randomization timer expired...send on next channel \n");
+#endif
+ //Issue a scan req for next channel.
+ sme_RrmIssueScanReq( pMac );
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn rrmNeighborRspTimeoutHandler
+
+ \brief Timer handler to handle the timeout condition when a neighbor request is sent
+ and no neighbor response is received from the AP
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+
+void rrmNeighborRspTimeoutHandler
+( v_PVOID_t userData )
+{
+ tpAniSirGlobal pMac = (tpAniSirGlobal) userData;
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Neighbor Response timed out \n");
+#endif
+ rrmIndicateNeighborReportResult(pMac, VOS_STATUS_E_FAILURE);
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn rrmOpen
+
+ \brief
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOS_STATUS
+
+ VOS_STATUS_E_FAILURE success
+
+ VOS_STATUS_SUCCESS failure
+
+ ---------------------------------------------------------------------------*/
+
+VOS_STATUS rrmOpen (tpAniSirGlobal pMac)
+
+{
+
+ VOS_STATUS vosStatus;
+ tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+ eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+
+ pSmeRrmContext->rrmConfig.maxRandnInterval = 50; //ms
+
+ vosStatus = vos_timer_init( &pSmeRrmContext->IterMeasTimer,
+
+ VOS_TIMER_TYPE_SW,
+
+ rrmIterMeasTimerHandle,
+
+ (void*) pMac);
+
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "rrmOpen: Fail to init timer");
+
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ vosStatus = vos_timer_init( &pSmeRrmContext->neighborReqControlInfo.neighborRspWaitTimer,
+
+ VOS_TIMER_TYPE_SW,
+
+ rrmNeighborRspTimeoutHandler,
+
+ (void*) pMac);
+
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "rrmOpen: Fail to init timer");
+
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending = eANI_BOOLEAN_FALSE;
+
+ halStatus = csrLLOpen(pMac->hHdd, &pSmeRrmContext->neighborReportCache);
+ if (eHAL_STATUS_SUCCESS != halStatus)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "rrmOpen: Fail to open neighbor cache result");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn rrmClose
+
+ \brief
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOS_STATUS
+
+ VOS_STATUS_E_FAILURE success
+
+ VOS_STATUS_SUCCESS failure
+
+ ---------------------------------------------------------------------------*/
+
+VOS_STATUS rrmClose (tpAniSirGlobal pMac)
+
+{
+
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+
+ if( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState( &pSmeRrmContext->IterMeasTimer ) )
+ {
+ vosStatus = vos_timer_stop( &pSmeRrmContext->IterMeasTimer );
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("Timer stop fail") );
+ }
+ }
+
+ vosStatus = vos_timer_destroy( &pSmeRrmContext->IterMeasTimer );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("Fail to destroy timer") );
+
+ }
+
+ rrmLLPurgeNeighborCache(pMac, &pSmeRrmContext->neighborReportCache);
+
+ csrLLClose(&pSmeRrmContext->neighborReportCache);
+
+ return vosStatus;
+
+}
+
+
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn rrmReady
+
+ \brief fn
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOS_STATUS
+
+ ---------------------------------------------------------------------------*/
+
+VOS_STATUS rrmReady (tpAniSirGlobal pMac)
+
+{
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn rrmChangeDefaultConfigParam
+ \brief fn
+
+ \param pMac - The handle returned by macOpen.
+ \param pRrmConfig - pointer to new rrm configs.
+
+ \return VOS_STATUS
+
+ ---------------------------------------------------------------------------*/
+VOS_STATUS rrmChangeDefaultConfigParam(tpAniSirGlobal pMac, tpRrmConfigParam pRrmConfig)
+{
+ vos_mem_copy( &pMac->rrm.rrmSmeContext.rrmConfig, pRrmConfig, sizeof( tRrmConfigParam ) );
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn smeRrmGetFirstBssEntryFromNeighborCache()
+
+ \brief This function returns the first entry from the neighbor cache to the caller
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+tRrmNeighborReportDesc* smeRrmGetFirstBssEntryFromNeighborCache( tpAniSirGlobal pMac)
+{
+ tListElem *pEntry;
+ tRrmNeighborReportDesc *pTempBssEntry = NULL;
+ tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+
+
+ pEntry = csrLLPeekHead( &pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK );
+
+ if(!pEntry || !csrLLCount(&pSmeRrmContext->neighborReportCache))
+ {
+ //list empty
+ smsLog(pMac, LOGW, FL("List empty\n"));
+ return NULL;
+ }
+
+ pTempBssEntry = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List );
+
+ return pTempBssEntry;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn smeRrmGetNextBssEntryFromNeighborCache()
+
+ \brief This function returns the entry next to the given entry from the
+ neighbor cache to the caller
+
+ \param pMac - The handle returned by macOpen.
+
+ \return VOID
+
+---------------------------------------------------------------------------*/
+tRrmNeighborReportDesc* smeRrmGetNextBssEntryFromNeighborCache( tpAniSirGlobal pMac,
+ tpRrmNeighborReportDesc pBssEntry)
+{
+ tListElem *pEntry;
+ tRrmNeighborReportDesc *pTempBssEntry = NULL;
+
+ pEntry = csrLLNext(&pMac->rrm.rrmSmeContext.neighborReportCache, &pBssEntry->List, LL_ACCESS_LOCK);
+
+ if(!pEntry)
+ {
+ //list empty
+ smsLog(pMac, LOGW, FL("List empty\n"));
+ return NULL;
+ }
+
+ pTempBssEntry = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List );
+
+ return pTempBssEntry;
+}
+
+#ifdef FEATURE_WLAN_CCX
+void csrCcxSendAdjacentApRepMsg(tpAniSirGlobal pMac, tCsrRoamSession *pSession)
+{
+ tpSirAdjacentApRepInd pAdjRep;
+ tANI_U16 length;
+ tANI_U32 roamTS2;
+
+ smsLog( pMac, LOG1, "Adjacent AP Report Msg to PE\n");
+
+ length = sizeof(tSirAdjacentApRepInd );
+ pAdjRep = vos_mem_malloc ( length );
+
+ if ( NULL == pAdjRep )
+ {
+ smsLog( pMac, LOGP, "Unable to allocate memory for Adjacent AP report");
+ return;
+ }
+
+ vos_mem_zero( pAdjRep, length );
+ pAdjRep->messageType = eWNI_SME_CCX_ADJACENT_AP_REPORT;
+ pAdjRep->length = length;
+ pAdjRep->channelNum = pSession->prevOpChannel;
+ vos_mem_copy( pAdjRep->bssid, &pSession->connectedProfile.bssid, sizeof(tSirMacAddr) );
+ vos_mem_copy( pAdjRep->prevApMacAddr, &pSession->prevApBssid, sizeof(tSirMacAddr) );
+ vos_mem_copy( &pAdjRep->prevApSSID, &pSession->prevApSSID, sizeof(tSirMacSSid) );
+ roamTS2 = vos_timer_get_system_time();
+ pAdjRep->tsmRoamdelay = roamTS2 - pSession->roamTS1;
+ pAdjRep->roamReason =SIR_CCX_ASSOC_REASON_UNSPECIFIED;
+ pAdjRep->clientDissSecs =(pAdjRep->tsmRoamdelay/1000);
+
+ palSendMBMessage(pMac->hHdd, pAdjRep);
+
+ return;
+}
+#endif /* FEATURE_WLAN_CCX */
+#endif
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
new file mode 100644
index 0000000..642e8f0
--- /dev/null
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -0,0 +1,6353 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/**=========================================================================
+
+ \file smeApi.c
+
+ \brief Definitions for SME APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/*===========================================================================
+
+ 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 Files
+ ------------------------------------------------------------------------*/
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include "halInternal.h"
+#endif
+
+#include "smsDebug.h"
+#include "sme_Api.h"
+#include "csrInsideApi.h"
+#include "smeInside.h"
+#include "csrInternal.h"
+#include "wlan_qct_wda.h"
+#include "halMsgApi.h"
+
+#ifdef WLAN_SOFTAP_FEATURE
+#include "sapApi.h"
+#endif
+
+
+
+#if !defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+extern tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb);
+
+#include <wlan_qct_pal_api.h>
+#endif
+
+// TxMB Functions
+extern eHalStatus pmcPrepareCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void *pvParam,
+ tANI_U32 size, tSmeCmd **ppCmd );
+extern void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+extern void qosReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
+#if defined WLAN_FEATURE_P2P
+extern eHalStatus p2pProcessRemainOnChannelCmd(tpAniSirGlobal pMac, tSmeCmd *p2pRemainonChn);
+extern eHalStatus sme_remainOnChnRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg);
+extern eHalStatus sme_mgmtFrmInd( tHalHandle hHal, tpSirSmeMgmtFrameInd pSmeMgmtFrm);
+extern eHalStatus sme_remainOnChnReady( tHalHandle hHal, tANI_U8* pMsg);
+extern eHalStatus sme_sendActionCnf( tHalHandle hHal, tANI_U8* pMsg);
+extern eHalStatus p2pProcessNoAReq(tpAniSirGlobal pMac, tSmeCmd *pNoACmd);
+#endif
+
+static eHalStatus initSmeCmdList(tpAniSirGlobal pMac);
+static void smeAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping );
+
+eCsrPhyMode sme_GetPhyMode(tHalHandle hHal);
+
+eHalStatus sme_HandleChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf);
+
+eHalStatus sme_HandlePreChannelSwitchInd(tHalHandle hHal);
+
+eHalStatus sme_HandlePostChannelSwitchInd(tHalHandle hHal);
+
+//Internal SME APIs
+eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+
+ if(psSme)
+ {
+ if( VOS_IS_STATUS_SUCCESS( vos_lock_acquire( &psSme->lkSmeGlobalLock) ) )
+ {
+ status = eHAL_STATUS_SUCCESS;
+ }
+ }
+
+ return (status);
+}
+
+
+eHalStatus sme_ReleaseGlobalLock( tSmeStruct *psSme)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+
+ if(psSme)
+ {
+ if( VOS_IS_STATUS_SUCCESS( vos_lock_release( &psSme->lkSmeGlobalLock) ) )
+ {
+ status = eHAL_STATUS_SUCCESS;
+ }
+ }
+
+ return (status);
+}
+
+
+
+static eHalStatus initSmeCmdList(tpAniSirGlobal pMac)
+{
+ eHalStatus status;
+ tSmeCmd *pCmd;
+
+ pMac->sme.totalSmeCmd = SME_TOTAL_COMMAND;
+ if(HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd, &pMac->sme.smeCmdActiveList)))
+ {
+ if(HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd, &pMac->sme.smeCmdPendingList)))
+ {
+ if(HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd, &pMac->sme.smeCmdFreeList)))
+ {
+ status = palAllocateMemory(pMac->hHdd, (void **)&pCmd, sizeof(tSmeCmd) * pMac->sme.totalSmeCmd);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ tANI_U32 c;
+
+ palZeroMemory(pMac->hHdd, pCmd, sizeof(tSmeCmd) * pMac->sme.totalSmeCmd);
+ pMac->sme.pSmeCmdBufAddr = pCmd;
+ for(c = 0; c < pMac->sme.totalSmeCmd; c++)
+ {
+ csrLLInsertTail(&pMac->sme.smeCmdFreeList, &pCmd[c].Link, LL_ACCESS_LOCK);
+ }
+ }
+ }
+ }
+ }
+
+ return (status);
+}
+
+
+void smeReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCmd)
+{
+ pCmd->command = eSmeNoCommand;
+ csrLLInsertTail(&pMac->sme.smeCmdFreeList, &pCmd->Link, LL_ACCESS_LOCK);
+}
+
+
+
+static void smeReleaseCmdList(tpAniSirGlobal pMac, tDblLinkList *pList)
+{
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+
+ while((pEntry = csrLLRemoveHead(pList, LL_ACCESS_LOCK)) != NULL)
+ {
+ //TODO: base on command type to call release functions
+ //reinitialize different command types so they can be reused
+ pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ smeAbortCommand(pMac, pCommand, eANI_BOOLEAN_TRUE);
+ }
+}
+
+static void purgeSmeCmdList(tpAniSirGlobal pMac)
+{
+ //release any out standing commands back to free command list
+ smeReleaseCmdList(pMac, &pMac->sme.smeCmdPendingList);
+ smeReleaseCmdList(pMac, &pMac->sme.smeCmdActiveList);
+}
+
+void purgeSmeSessionCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+ //release any out standing commands back to free command list
+ tListElem *pEntry, *pNext;
+ tSmeCmd *pCommand;
+ tDblLinkList *pList = &pMac->sme.smeCmdPendingList;
+ 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(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 );
+ smeAbortCommand(pMac, pCommand, eANI_BOOLEAN_TRUE);
+ }
+ csrLLClose(&localList);
+
+}
+
+
+static eHalStatus freeSmeCmdList(tpAniSirGlobal pMac)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ purgeSmeCmdList(pMac);
+ csrLLClose(&pMac->sme.smeCmdPendingList);
+ csrLLClose(&pMac->sme.smeCmdActiveList);
+ csrLLClose(&pMac->sme.smeCmdFreeList);
+
+ if(NULL != pMac->sme.pSmeCmdBufAddr)
+ {
+ status = palFreeMemory(pMac->hHdd, pMac->sme.pSmeCmdBufAddr);
+ pMac->sme.pSmeCmdBufAddr = NULL;
+ }
+
+ return (status);
+}
+
+
+void dumpCsrCommandInfo(tpAniSirGlobal pMac, tSmeCmd *pCmd)
+{
+#ifdef WLAN_DEBUG
+ switch( pCmd->command )
+ {
+ case eSmeCommandScan:
+ smsLog( pMac, LOGE, " scan command reason is %d", pCmd->u.scanCmd.reason );
+ break;
+
+ case eSmeCommandRoam:
+ smsLog( pMac, LOGE, " roam command reason is %d", pCmd->u.roamCmd.roamReason );
+ break;
+
+ case eSmeCommandWmStatusChange:
+ smsLog( pMac, LOGE, " WMStatusChange command type is %d", pCmd->u.wmStatusChangeCmd.Type );
+ break;
+
+ case eSmeCommandSetKey:
+ smsLog( pMac, LOGE, " setKey command auth(%d) enc(%d)",
+ pCmd->u.setKeyCmd.authType, pCmd->u.setKeyCmd.encType );
+ break;
+
+ case eSmeCommandRemoveKey:
+ smsLog( pMac, LOGE, " removeKey command auth(%d) enc(%d)",
+ pCmd->u.removeKeyCmd.authType, pCmd->u.removeKeyCmd.encType );
+ break;
+
+ default:
+ break;
+ }
+#endif //#ifdef WLAN_DEBUG
+}
+
+tSmeCmd *smeGetCommandBuffer( tpAniSirGlobal pMac )
+{
+ tSmeCmd *pRetCmd = NULL, *pTempCmd = NULL;
+ tListElem *pEntry;
+
+ pEntry = csrLLRemoveHead( &pMac->sme.smeCmdFreeList, LL_ACCESS_LOCK );
+
+ // If we can get another MS Msg buffer, then we are ok. Just link
+ // the entry onto the linked list. (We are using the linked list
+ // to keep track of tfhe message buffers).
+ if ( pEntry )
+ {
+ pRetCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ }
+ else {
+ int idx = 1;
+
+ //Cannot change pRetCmd here since it needs to return later.
+ pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
+ if( pEntry )
+ {
+ pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ }
+ smsLog( pMac, LOGE, "Out of command buffer.... command (0x%X) stuck\n",
+ (pTempCmd) ? pTempCmd->command : eSmeNoCommand );
+ if(pTempCmd)
+ {
+ if( eSmeCsrCommandMask & pTempCmd->command )
+ {
+ //CSR command is stuck. See what the reason code is for that command
+ dumpCsrCommandInfo(pMac, pTempCmd);
+ }
+ } //if(pTempCmd)
+
+ //dump what is in the pending queue
+ csrLLLock(&pMac->sme.smeCmdPendingList);
+ pEntry = csrLLPeekHead( &pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK );
+ while(pEntry)
+ {
+ pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ smsLog( pMac, LOGE, "Out of command buffer.... SME pending command #%d (0x%X)\n",
+ idx++, pTempCmd->command );
+ if( eSmeCsrCommandMask & pTempCmd->command )
+ {
+ //CSR command is stuck. See what the reason code is for that command
+ dumpCsrCommandInfo(pMac, pTempCmd);
+ }
+ pEntry = csrLLNext( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK );
+ }
+ csrLLUnlock(&pMac->sme.smeCmdPendingList);
+
+ //There may be some more command in CSR's own pending queue
+ csrLLLock(&pMac->roam.roamCmdPendingList);
+ pEntry = csrLLPeekHead( &pMac->roam.roamCmdPendingList, LL_ACCESS_NOLOCK );
+ while(pEntry)
+ {
+ pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ smsLog( pMac, LOGE, "Out of command buffer.... CSR pending command #%d (0x%X)\n",
+ idx++, pTempCmd->command );
+ dumpCsrCommandInfo(pMac, pTempCmd);
+ pEntry = csrLLNext( &pMac->roam.roamCmdPendingList, pEntry, LL_ACCESS_NOLOCK );
+ }
+ csrLLUnlock(&pMac->roam.roamCmdPendingList);
+ }
+
+ return( pRetCmd );
+}
+
+
+void smePushCommand( tpAniSirGlobal pMac, tSmeCmd *pCmd, tANI_BOOLEAN fHighPriority )
+{
+ if ( fHighPriority )
+ {
+ csrLLInsertHead( &pMac->sme.smeCmdPendingList, &pCmd->Link, LL_ACCESS_LOCK );
+ }
+ else
+ {
+ csrLLInsertTail( &pMac->sme.smeCmdPendingList, &pCmd->Link, LL_ACCESS_LOCK );
+ }
+
+ // process the command queue...
+ smeProcessPendingQueue( pMac );
+
+ return;
+}
+
+
+static eSmeCommandType smeIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand )
+{
+ eSmeCommandType pmcCommand = eSmeNoCommand;
+ tANI_BOOLEAN fFullPowerNeeded = eANI_BOOLEAN_FALSE;
+ tPmcState pmcState;
+ eHalStatus status;
+
+ do
+ {
+ pmcState = pmcGetPmcState(pMac);
+
+ status = csrIsFullPowerNeeded( pMac, pCommand, NULL, &fFullPowerNeeded );
+ if( !HAL_STATUS_SUCCESS(status) )
+ {
+ //PMC state is not right for the command, drop it
+ return ( eSmeDropCommand );
+ }
+ if( fFullPowerNeeded ) break;
+ fFullPowerNeeded = ( ( eSmeCommandAddTs == pCommand->command ) ||
+ ( eSmeCommandDelTs == pCommand->command ) );
+ if( fFullPowerNeeded ) break;
+#ifdef WLAN_FEATURE_P2P
+ fFullPowerNeeded = (pmcState == IMPS &&
+ eSmeCommandRemainOnChannel == pCommand->command);
+ if(fFullPowerNeeded) break;
+#endif
+ } while(0);
+
+ if( fFullPowerNeeded )
+ {
+ switch( pmcState )
+ {
+ case IMPS:
+ case STANDBY:
+ pmcCommand = eSmeCommandExitImps;
+ break;
+
+ case BMPS:
+ pmcCommand = eSmeCommandExitBmps;
+ break;
+
+ case UAPSD:
+ pmcCommand = eSmeCommandExitUapsd;
+ break;
+
+ case WOWL:
+ pmcCommand = eSmeCommandExitWowl;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return ( pmcCommand );
+}
+
+
+//For commands that need to do extra cleanup.
+static void smeAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping )
+{
+ if( eSmePmcCommandMask & pCommand->command )
+ {
+ pmcAbortCommand( pMac, pCommand, fStopping );
+ }
+ else if ( eSmeCsrCommandMask & pCommand->command )
+ {
+ csrAbortCommand( pMac, pCommand, fStopping );
+ }
+ else
+ {
+ switch( pCommand->command )
+ {
+#ifdef WLAN_FEATURE_P2P
+ case eSmeCommandRemainOnChannel:
+ if (NULL != pCommand->u.remainChlCmd.callback)
+ {
+ remainOnChanCallback callback =
+ pCommand->u.remainChlCmd.callback;
+ /* process the msg */
+ if( callback )
+ {
+ callback(pMac, pCommand->u.remainChlCmd.callbackCtx,
+ eCSR_SCAN_ABORT );
+ }
+ }
+ smeReleaseCommand( pMac, pCommand );
+ break;
+#endif
+ default:
+ smeReleaseCommand( pMac, pCommand );
+ break;
+ }
+ }
+}
+
+
+
+tANI_BOOLEAN smeProcessCommand( tpAniSirGlobal pMac )
+{
+ tANI_BOOLEAN fContinue = eANI_BOOLEAN_FALSE;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tListElem *pEntry;
+ tSmeCmd *pCommand;
+ eSmeCommandType pmcCommand = eSmeNoCommand;
+
+ // if the ActiveList is empty, then nothing is active so we can process a
+ // pending command...
+ //alwasy lock active list before locking pending list
+ csrLLLock( &pMac->sme.smeCmdActiveList );
+ if ( csrLLIsListEmpty( &pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK ) )
+ {
+ if(!csrLLIsListEmpty(&pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK))
+ {
+ //Peek the command
+ pEntry = csrLLPeekHead( &pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK );
+ if( pEntry )
+ {
+ pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ //We cannot execute any command in wait-for-key state until setKey is through.
+ if( CSR_IS_WAIT_FOR_KEY( pMac, pCommand->sessionId ) )
+ {
+ if( !CSR_IS_SET_KEY_COMMAND( pCommand ) )
+ {
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ smsLog(pMac, LOGE, " Cannot process command(%d) while waiting for key\n", pCommand->command);
+ return ( eANI_BOOLEAN_FALSE );
+ }
+ }
+ pmcCommand = smeIsFullPowerNeeded( pMac, pCommand );
+ if( eSmeDropCommand == pmcCommand )
+ {
+ //This command is not ok for current PMC state
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_LOCK ) )
+ {
+ smeAbortCommand( pMac, pCommand, eANI_BOOLEAN_FALSE );
+ }
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ //tell caller to continue
+ return (eANI_BOOLEAN_TRUE);
+ }
+ else if( eSmeNoCommand != pmcCommand )
+ {
+ tExitBmpsInfo exitBmpsInfo;
+ void *pv = NULL;
+ tANI_U32 size = 0;
+ tSmeCmd *pPmcCmd = NULL;
+
+ if( eSmeCommandExitBmps == pmcCommand )
+ {
+ exitBmpsInfo.exitBmpsReason = eSME_REASON_OTHER;
+ pv = (void *)&exitBmpsInfo;
+ size = sizeof(tExitBmpsInfo);
+ }
+ //pmcCommand has to be one of the exit power save command
+ status = pmcPrepareCommand( pMac, pmcCommand, pv, size, &pPmcCmd );
+ if( HAL_STATUS_SUCCESS( status ) && pPmcCmd )
+ {
+ //Force this command to wake up the chip
+ csrLLInsertHead( &pMac->sme.smeCmdActiveList, &pPmcCmd->Link, LL_ACCESS_NOLOCK );
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ fContinue = pmcProcessCommand( pMac, pPmcCmd );
+ if( fContinue )
+ {
+ //The command failed, remove it
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, &pPmcCmd->Link, LL_ACCESS_NOLOCK ) )
+ {
+ pmcReleaseCommand( pMac, pPmcCmd );
+ }
+ }
+ }
+ else
+ {
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ smsLog( pMac, LOGE, FL( "Cannot issue command(0x%X) to wake up the chip. Status = %d\n"), pmcCommand, status );
+ //Let it retry
+ fContinue = eANI_BOOLEAN_TRUE;
+ }
+ return fContinue;
+ }
+ if ( csrLLRemoveEntry( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_LOCK ) )
+ {
+ // we can reuse the pCommand
+
+ // Insert the command onto the ActiveList...
+ csrLLInsertHead( &pMac->sme.smeCmdActiveList, &pCommand->Link, LL_ACCESS_NOLOCK );
+
+ // .... and process the command.
+
+ switch ( pCommand->command )
+ {
+
+ case eSmeCommandScan:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ status = csrProcessScanCommand( pMac, pCommand );
+ break;
+
+ case eSmeCommandRoam:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ status = csrRoamProcessCommand( pMac, pCommand );
+ break;
+
+ case eSmeCommandWmStatusChange:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ csrRoamProcessWmStatusChangeCommand(pMac, pCommand);
+ break;
+
+ case eSmeCommandSetKey:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ status = csrRoamProcessSetKeyCommand( pMac, pCommand );
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
+ &pCommand->Link, LL_ACCESS_LOCK ) )
+ {
+ csrReleaseCommandSetKey( pMac, pCommand );
+ }
+ }
+ break;
+
+ case eSmeCommandRemoveKey:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ status = csrRoamProcessRemoveKeyCommand( pMac, pCommand );
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
+ &pCommand->Link, LL_ACCESS_LOCK ) )
+ {
+ csrReleaseCommandRemoveKey( pMac, pCommand );
+ }
+ }
+ break;
+
+ case eSmeCommandAddStaSession:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ csrProcessAddStaSessionCommand( pMac, pCommand );
+ break;
+ case eSmeCommandDelStaSession:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ csrProcessDelStaSessionCommand( pMac, pCommand );
+ break;
+
+#if defined WLAN_FEATURE_P2P
+ case eSmeCommandRemainOnChannel:
+ csrLLUnlock(&pMac->sme.smeCmdActiveList);
+ p2pProcessRemainOnChannelCmd(pMac, pCommand);
+ break;
+ case eSmeCommandNoAUpdate:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ p2pProcessNoAReq(pMac,pCommand);
+#endif
+ case eSmeCommandEnterImps:
+ case eSmeCommandExitImps:
+ case eSmeCommandEnterBmps:
+ case eSmeCommandExitBmps:
+ case eSmeCommandEnterUapsd:
+ case eSmeCommandExitUapsd:
+ case eSmeCommandEnterWowl:
+ case eSmeCommandExitWowl:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ fContinue = pmcProcessCommand( pMac, pCommand );
+ if( fContinue )
+ {
+ //The command failed, remove it
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
+ &pCommand->Link, LL_ACCESS_LOCK ) )
+ {
+ pmcReleaseCommand( pMac, pCommand );
+ }
+ }
+ break;
+
+ //Treat standby differently here because caller may not be able to handle
+ //the failure so we do our best here
+ case eSmeCommandEnterStandby:
+ if( csrIsConnStateDisconnected( pMac, pCommand->sessionId ) )
+ {
+ //It can continue
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ fContinue = pmcProcessCommand( pMac, pCommand );
+ if( fContinue )
+ {
+ //The command failed, remove it
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
+ &pCommand->Link, LL_ACCESS_LOCK ) )
+ {
+ pmcReleaseCommand( pMac, pCommand );
+ }
+ }
+ }
+ else
+ {
+ //Need to issue a disconnect first before processing this command
+ tSmeCmd *pNewCmd;
+
+ //We need to re-run the command
+ fContinue = eANI_BOOLEAN_TRUE;
+ //Pull off the standby command first
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
+ &pCommand->Link, LL_ACCESS_NOLOCK ) )
+ {
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ //Need to call CSR function here because the disconnect command
+ //is handled by CSR
+ pNewCmd = csrGetCommandBuffer( pMac );
+ if( NULL != pNewCmd )
+ {
+ //Put the standby command to the head of the pending list first
+ csrLLInsertHead( &pMac->sme.smeCmdPendingList, &pCommand->Link,
+ LL_ACCESS_LOCK );
+ pNewCmd->command = eSmeCommandRoam;
+ pNewCmd->u.roamCmd.roamReason = eCsrForcedDisassoc;
+ //Put the disassoc command before the standby command
+ csrLLInsertHead( &pMac->sme.smeCmdPendingList, &pNewCmd->Link,
+ LL_ACCESS_LOCK );
+ }
+ else
+ {
+ //Continue the command here
+ fContinue = pmcProcessCommand( pMac, pCommand );
+ if( fContinue )
+ {
+ //The command failed, remove it
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
+ &pCommand->Link, LL_ACCESS_LOCK ) )
+ {
+ pmcReleaseCommand( pMac, pCommand );
+ }
+ }
+ }
+ }
+ else
+ {
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ smsLog( pMac, LOGE, FL(" failed to remove standby command\n") );
+ VOS_ASSERT(0);
+ }
+ }
+ break;
+
+ case eSmeCommandAddTs:
+ case eSmeCommandDelTs:
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ fContinue = qosProcessCommand( pMac, pCommand );
+ if( fContinue )
+ {
+ //The command failed, remove it
+ if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
+ &pCommand->Link, LL_ACCESS_NOLOCK ) )
+ {
+//#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ qosReleaseCommand( pMac, pCommand );
+//#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
+ }
+ }
+#endif
+ break;
+
+ default:
+ //something is wrong
+ //remove it from the active list
+ smsLog(pMac, LOGE, " csrProcessCommand processes an unknown command %d\n", pCommand->command);
+ pEntry = csrLLRemoveHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK );
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
+ smeReleaseCommand( pMac, pCommand );
+ status = eHAL_STATUS_FAILURE;
+ break;
+ }
+ if(!HAL_STATUS_SUCCESS(status))
+ {
+ fContinue = eANI_BOOLEAN_TRUE;
+ }
+ }//if(pEntry)
+ else
+ {
+ //This is odd. Some one else pull off the command.
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ }
+ }
+ else
+ {
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ }
+ }
+ else
+ {
+ //No command waiting
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ //This is only used to restart an idle mode scan, it means at least one other idle scan has finished.
+ if(pMac->scan.fRestartIdleScan && eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan)
+ {
+ tANI_U32 nTime = 0;
+
+ pMac->scan.fRestartIdleScan = eANI_BOOLEAN_FALSE;
+ if(!HAL_STATUS_SUCCESS(csrScanTriggerIdleScan(pMac, &nTime)))
+ {
+ csrScanStartIdleScanTimer(pMac, nTime);
+ }
+ }
+ }
+ }
+ else {
+ csrLLUnlock( &pMac->sme.smeCmdActiveList );
+ }
+
+ return ( fContinue );
+}
+
+void smeProcessPendingQueue( tpAniSirGlobal pMac )
+{
+ while( smeProcessCommand( pMac ) );
+}
+
+
+tANI_BOOLEAN smeCommandPending(tpAniSirGlobal pMac)
+{
+ return ( !csrLLIsListEmpty( &pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK ) ||
+ !csrLLIsListEmpty(&pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK) );
+}
+
+
+
+//Global APIs
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_Open() - Initialze all SME modules and put them at idle state
+
+ The function initializes each module inside SME, PMC, CCM, CSR, etc. . Upon
+ successfully return, all modules are at idle state ready to start.
+
+ smeOpen must be called before any other SME APIs can be involved.
+ smeOpen must be called after macOpen.
+ This is a synchronuous call
+ \param hHal - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS - SME is successfully initialized.
+
+ Other status means SME is failed to be initialized
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_Open(tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ do {
+ pMac->sme.state = SME_STATE_STOP;
+ if( !VOS_IS_STATUS_SUCCESS( vos_lock_init( &pMac->sme.lkSmeGlobalLock ) ) )
+ {
+ smsLog( pMac, LOGE, "sme_Open failed init lock\n" );
+ status = eHAL_STATUS_FAILURE;
+ break;
+ }
+
+ status = ccmOpen(hHal);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE,
+ "ccmOpen failed during initialization with status=%d", status );
+ break;
+ }
+
+ status = csrOpen(pMac);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE,
+ "csrOpen failed during initialization with status=%d", status );
+ break;
+ }
+
+ status = pmcOpen(hHal);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE,
+ "pmcOpen failed during initialization with status=%d", status );
+ break;
+ }
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ status = sme_QosOpen(pMac);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE,
+ "Qos open failed during initialization with status=%d", status );
+ break;
+ }
+
+ status = btcOpen(pMac);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE,
+ "btcOpen open failed during initialization with status=%d", status );
+ break;
+ }
+#endif
+
+ if(!HAL_STATUS_SUCCESS((status = initSmeCmdList(pMac))))
+ break;
+
+#ifdef WLAN_SOFTAP_FEATURE
+ {
+ v_PVOID_t pvosGCtx = vos_get_global_context(VOS_MODULE_ID_SAP, NULL);
+ if ( NULL == pvosGCtx ){
+ smsLog( pMac, LOGE, "WLANSAP_Open open failed during initialization");
+ status = eHAL_STATUS_FAILURE;
+ break;
+ }
+
+ status = WLANSAP_Open( pvosGCtx );
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE,
+ "WLANSAP_Open open failed during initialization with status=%d", status );
+ break;
+ }
+ }
+#endif
+#if defined WLAN_FEATURE_VOWIFI
+ status = rrmOpen(pMac);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE,
+ "rrmOpen open failed during initialization with status=%d", status );
+ break;
+ }
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ sme_FTOpen(pMac);
+#endif
+#if defined WLAN_FEATURE_P2P
+ sme_p2pOpen(pMac);
+#endif
+
+ }while (0);
+
+ return status;
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+/*--------------------------------------------------------------------------
+
+ \brief sme_set11dinfo() - Set the 11d information about valid channels
+ and there power using information from nvRAM
+ This function is called only for AP.
+
+ This is a synchronuous call
+
+ \param hHal - The handle returned by macOpen.
+ \Param pSmeConfigParams - a pointer to a caller allocated object of
+ typedef struct _smeConfigParams.
+
+ \return eHAL_STATUS_SUCCESS - SME update the config parameters successfully.
+
+ Other status means SME is failed to update the config parameters.
+ \sa
+--------------------------------------------------------------------------*/
+
+eHalStatus sme_set11dinfo(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if (NULL == pSmeConfigParams ) {
+ smsLog( pMac, LOGE,
+ "Empty config param structure for SME, nothing to update");
+ return status;
+ }
+
+ status = csrSetChannels(hHal, &pSmeConfigParams->csrConfig );
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "csrChangeDefaultConfigParam failed with status=%d\n",
+ status );
+ }
+ return status;
+}
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_getSoftApDomain() - Get the current regulatory domain of softAp.
+
+ This is a synchronuous call
+
+ \param hHal - The handle returned by HostapdAdapter.
+ \Param v_REGDOMAIN_t - The current Regulatory Domain requested for SoftAp.
+
+ \return eHAL_STATUS_SUCCESS - SME successfully completed the request.
+
+ Other status means, failed to get the current regulatory domain.
+ \sa
+--------------------------------------------------------------------------*/
+
+eHalStatus sme_getSoftApDomain(tHalHandle hHal, v_REGDOMAIN_t *domainIdSoftAp)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if (NULL == domainIdSoftAp ) {
+ smsLog( pMac, LOGE, "Uninitialized domain Id");
+ return status;
+ }
+
+ *domainIdSoftAp = pMac->scan.domainIdCurrent;
+ status = eHAL_STATUS_SUCCESS;
+
+ return status;
+}
+
+
+eHalStatus sme_setRegInfo(tHalHandle hHal, tANI_U8 *apCntryCode)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if (NULL == apCntryCode ) {
+ smsLog( pMac, LOGE, "Empty Country Code, nothing to update");
+ return status;
+ }
+
+ status = csrSetRegInfo(hHal, apCntryCode );
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "csrSetRegInfo failed with status=%d\n",
+ status );
+ }
+ return status;
+}
+
+#endif
+#ifdef FEATURE_WLAN_SCAN_PNO
+/*--------------------------------------------------------------------------
+
+ \brief sme_UpdateChannelConfig() - Update channel configuration in RIVA.
+
+ It is used at driver start up to inform RIVA of the default channel
+ configuration.
+
+ This is a synchronuous call
+
+ \param hHal - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS - SME update the channel config successfully.
+
+ Other status means SME is failed to update the channel config.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_UpdateChannelConfig(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ pmcUpdateScanParams( pMac, &(pMac->roam.configParam),
+ &pMac->scan.base20MHzChannels, FALSE);
+ return eHAL_STATUS_SUCCESS;
+}
+#endif // FEATURE_WLAN_SCAN_PNLO
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_UpdateConfig() - Change configurations for all SME moduels
+
+ The function updates some configuration for modules in SME, CCM, CSR, etc
+ during SMEs close open sequence.
+
+ Modules inside SME apply the new configuration at the next transaction.
+
+ This is a synchronuous call
+
+ \param hHal - The handle returned by macOpen.
+ \Param pSmeConfigParams - a pointer to a caller allocated object of
+ typedef struct _smeConfigParams.
+
+ \return eHAL_STATUS_SUCCESS - SME update the config parameters successfully.
+
+ Other status means SME is failed to update the config parameters.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_UpdateConfig(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if (NULL == pSmeConfigParams ) {
+ smsLog( pMac, LOGE,
+ "Empty config param structure for SME, nothing to update");
+ return status;
+ }
+
+ status = csrChangeDefaultConfigParam(pMac, &pSmeConfigParams->csrConfig);
+
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "csrChangeDefaultConfigParam failed with status=%d\n",
+ status );
+ }
+#if defined WLAN_FEATURE_P2P_INTERNAL
+ status = p2pChangeDefaultConfigParam(pMac, &pSmeConfigParams->p2pConfig);
+
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "p2pChangeDefaultConfigParam failed with status=%d\n",
+ status );
+ }
+#endif
+#if defined WLAN_FEATURE_VOWIFI
+ status = rrmChangeDefaultConfigParam(hHal, &pSmeConfigParams->rrmConfig);
+
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "rrmChangeDefaultConfigParam failed with status=%d\n",
+ status );
+ }
+#endif
+ //For SOC, CFG is set before start
+ //We don't want to apply global CFG in connect state because that may cause some side affect
+ if(
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ //For the new init sequence, CFGs need to apply before vos_start is call
+ //No need to wait for ready state.
+ SME_IS_READY(pMac) &&
+#endif
+ csrIsAllSessionDisconnected( pMac) )
+ {
+ csrSetGlobalCfgs(pMac);
+ }
+
+ return status;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ChangeConfigParams
+ \brief The SME API exposed for HDD to provide config params to SME during
+ SMEs stop -> start sequence.
+
+ If HDD changed the domain that will cause a reset. This function will
+ provide the new set of 11d information for the new domain. Currrently this
+ API provides info regarding 11d only at reset but we can extend this for
+ other params (PMC, QoS) which needs to be initialized again at reset.
+
+ This is a synchronuous call
+
+ \param hHal - The handle returned by macOpen.
+
+ \Param
+ pUpdateConfigParam - a pointer to a structure (tCsrUpdateConfigParam) that
+ currently provides 11d related information like Country code,
+ Regulatory domain, valid channel list, Tx power per channel, a
+ list with active/passive scan allowed per valid channel.
+
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ChangeConfigParams(tHalHandle hHal,
+ tCsrUpdateConfigParam *pUpdateConfigParam)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if (NULL == pUpdateConfigParam ) {
+ smsLog( pMac, LOGE,
+ "Empty config param structure for SME, nothing to reset\n");
+ return status;
+ }
+
+ status = csrChangeConfigParams(pMac, pUpdateConfigParam);
+
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "csrUpdateConfigParam failed with status=%d\n",
+ status );
+ }
+
+ return status;
+
+}
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_HDDReadyInd() - SME sends eWNI_SME_SYS_READY_IND to PE to inform
+ that the NIC is ready tio run.
+
+ The function is called by HDD at the end of initialization stage so PE/HAL can
+ enable the NIC to running state.
+
+ This is a synchronuous call
+ \param hHal - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS - eWNI_SME_SYS_READY_IND is sent to PE
+ successfully.
+
+ Other status means SME failed to send the message to PE.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_HDDReadyInd(tHalHandle hHal)
+{
+ tSirSmeReadyReq Msg;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tPmcPowerState powerState;
+ tPmcSwitchState hwWlanSwitchState;
+ tPmcSwitchState swWlanSwitchState;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ do
+ {
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ csrSetGlobalCfgs( pMac );
+#endif
+
+ Msg.messageType = eWNI_SME_SYS_READY_IND;
+ Msg.length = sizeof( tSirSmeReadyReq );
+
+ if (eSIR_FAILURE != uMacPostCtrlMsg( hHal, (tSirMbMsg*)&Msg ))
+ {
+ status = eHAL_STATUS_SUCCESS;
+ }
+ else
+ {
+ smsLog( pMac, LOGE,
+ "uMacPostCtrlMsg failed to send eWNI_SME_SYS_READY_IND");
+ break;
+ }
+
+ status = pmcQueryPowerState( hHal, &powerState,
+ &hwWlanSwitchState, &swWlanSwitchState );
+ if ( ! HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, "pmcQueryPowerState failed with status=%d\n",
+ status );
+ break;
+ }
+
+ if ( (ePMC_SWITCH_OFF != hwWlanSwitchState) &&
+ (ePMC_SWITCH_OFF != swWlanSwitchState) )
+ {
+ status = csrReady(pMac);
+ if ( ! HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, "csrReady failed with status=%d\n", status );
+ break;
+ }
+ status = pmcReady(hHal);
+ if ( ! HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog( pMac, LOGE, "pmcReady failed with status=%d\n", status );
+ break;
+ }
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ if(VOS_STATUS_SUCCESS != btcReady(hHal))
+ {
+ status = eHAL_STATUS_FAILURE;
+ smsLog( pMac, LOGE, "btcReady failed\n");
+ break;
+ }
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI
+ if(VOS_STATUS_SUCCESS != rrmReady(hHal))
+ {
+ status = eHAL_STATUS_FAILURE;
+ smsLog( pMac, LOGE, "rrmReady failed\n");
+ break;
+ }
+#endif
+ }
+ pMac->sme.state = SME_STATE_READY;
+ } while( 0 );
+
+ return status;
+}
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_Start() - Put all SME modules at ready state.
+
+ The function starts each module in SME, PMC, CCM, CSR, etc. . Upon
+ successfully return, all modules are ready to run.
+ This is a synchronuous call
+ \param hHal - The handle returned by macOpen.
+
+ \return eHAL_STATUS_SUCCESS - SME is ready.
+
+ Other status means SME is failed to start
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_Start(tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ do
+ {
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ ccmStart(hHal);
+#endif
+ status = csrStart(pMac);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "csrStart failed during smeStart with status=%d\n",
+ status );
+ break;
+ }
+
+ status = pmcStart(hHal);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "pmcStart failed during smeStart with status=%d\n",
+ status );
+ break;
+ }
+
+#ifdef WLAN_SOFTAP_FEATURE
+ status = WLANSAP_Start(vos_get_global_context(VOS_MODULE_ID_SAP, NULL));
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "WLANSAP_Start failed during smeStart with status=%d\n",
+ status );
+ break;
+ }
+#endif
+ pMac->sme.state = SME_STATE_START;
+ }while (0);
+
+ return status;
+}
+
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+/******************************************************************************
+*
+* Name: sme_PCFilterMatchCountResponseHandler
+*
+* Description:
+* Invoke Packet Coalescing Filter Match Count callback routine
+*
+* Parameters:
+* hHal - HAL handle for device
+* pMsg - Pointer to tRcvFltPktMatchRsp structure
+*
+* Returns: eHalStatus
+*
+******************************************************************************/
+eHalStatus sme_PCFilterMatchCountResponseHandler(tHalHandle hHal, void* pMsg)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpSirRcvFltPktMatchRsp pRcvFltPktMatchRsp = (tpSirRcvFltPktMatchRsp)pMsg;
+
+ if (NULL == pMsg)
+ {
+ smsLog(pMac, LOGE, "in %s msg ptr is NULL\n", __FUNCTION__);
+ status = eHAL_STATUS_FAILURE;
+ }
+ else
+ {
+ smsLog(pMac, LOG2, "SME: entering "
+ "sme_FilterMatchCountResponseHandler\n");
+
+ /* Call Packet Coalescing Filter Match Count callback routine. */
+ if (pMac->pmc.FilterMatchCountCB != NULL)
+ pMac->pmc.FilterMatchCountCB(pMac->pmc.FilterMatchCountCBContext,
+ pRcvFltPktMatchRsp);
+
+ smsLog(pMac, LOG1, "%s: status=0x%x", __FUNCTION__,
+ pRcvFltPktMatchRsp->status);
+
+ pMac->pmc.FilterMatchCountCB = NULL;
+ pMac->pmc.FilterMatchCountCBContext = NULL;
+ }
+
+ return(status);
+}
+#endif // WLAN_FEATURE_PACKET_FILTERING
+
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_ProcessMsg() - The main message processor for SME.
+
+ The function is called by a message dispatcher when to process a message
+ targeted for SME.
+
+ This is a synchronuous call
+ \param hHal - The handle returned by macOpen.
+ \param pMsg - A pointer to a caller allocated object of tSirMsgQ.
+
+ \return eHAL_STATUS_SUCCESS - SME successfully process the message.
+
+ Other status means SME failed to process the message to HAL.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if (pMsg == NULL) {
+ smsLog( pMac, LOGE, "Empty message for SME, nothing to process\n");
+ return status;
+ }
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( SME_IS_START(pMac) )
+ {
+ switch (pMsg->type) { // TODO: Will be modified to do a range check for msgs instead of having cases for each msgs
+ case eWNI_PMC_ENTER_BMPS_RSP:
+ case eWNI_PMC_EXIT_BMPS_RSP:
+ case eWNI_PMC_EXIT_BMPS_IND:
+ case eWNI_PMC_ENTER_IMPS_RSP:
+ case eWNI_PMC_EXIT_IMPS_RSP:
+ case eWNI_PMC_SMPS_STATE_IND:
+ case eWNI_PMC_ENTER_UAPSD_RSP:
+ case eWNI_PMC_EXIT_UAPSD_RSP:
+ case eWNI_PMC_ENTER_WOWL_RSP:
+ case eWNI_PMC_EXIT_WOWL_RSP:
+ //PMC
+ if (pMsg->bodyptr)
+ {
+ pmcMessageProcessor(hHal, pMsg->bodyptr);
+ status = eHAL_STATUS_SUCCESS;
+ vos_mem_free( pMsg->bodyptr );
+ } else {
+ smsLog( pMac, LOGE, "Empty rsp message for PMC, nothing to process\n");
+ }
+ break;
+
+ case WNI_CFG_SET_CNF:
+ case WNI_CFG_DNLD_CNF:
+ case WNI_CFG_GET_RSP:
+ case WNI_CFG_ADD_GRP_ADDR_CNF:
+ case WNI_CFG_DEL_GRP_ADDR_CNF:
+ //CCM
+ if (pMsg->bodyptr)
+ {
+ ccmCfgCnfMsgHandler(hHal, pMsg->bodyptr);
+ status = eHAL_STATUS_SUCCESS;
+ vos_mem_free( pMsg->bodyptr );
+ } else {
+ smsLog( pMac, LOGE, "Empty rsp message for CCM, nothing to process\n");
+ }
+ break;
+
+ case eWNI_SME_ADDTS_RSP:
+ case eWNI_SME_DELTS_RSP:
+ case eWNI_SME_DELTS_IND:
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eWNI_SME_FT_AGGR_QOS_RSP:
+#endif
+ //QoS
+ if (pMsg->bodyptr)
+ {
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ status = sme_QosMsgProcessor(pMac, pMsg->type, pMsg->bodyptr);
+ vos_mem_free( pMsg->bodyptr );
+#endif
+ } else {
+ smsLog( pMac, LOGE, "Empty rsp message for QoS, nothing to process\n");
+ }
+ break;
+#if defined WLAN_FEATURE_VOWIFI
+ case eWNI_SME_NEIGHBOR_REPORT_IND:
+ case eWNI_SME_BEACON_REPORT_REQ_IND:
+#if defined WLAN_VOWIFI_DEBUG
+ smsLog( pMac, LOGE, "Received RRM message. Message Id = %d\n", pMsg->type );
+#endif
+ if ( pMsg->bodyptr )
+ {
+ status = sme_RrmMsgProcessor( pMac, pMsg->type, pMsg->bodyptr );
+ vos_mem_free( pMsg->bodyptr );
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "Empty message for RRM, nothing to process\n");
+ }
+ break;
+#endif
+
+
+ case eWNI_SME_ADD_STA_SELF_RSP:
+ if(pMsg->bodyptr)
+ {
+ status = csrProcessAddStaSessionRsp(pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_ADD_STA_SELF_RSP), nothing to process\n");
+ }
+ break;
+ case eWNI_SME_DEL_STA_SELF_RSP:
+ if(pMsg->bodyptr)
+ {
+ status = csrProcessDelStaSessionRsp(pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_DEL_STA_SELF_RSP), nothing to process\n");
+ }
+ break;
+#ifdef WLAN_FEATURE_P2P
+ //Handle the eWNI_SME_INNAV_MEAS_RSP:
+ case eWNI_SME_REMAIN_ON_CHN_RSP:
+ if(pMsg->bodyptr)
+ {
+ status = sme_remainOnChnRsp(pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_REMAIN_ON_CHN_RSP), nothing to process\n");
+ }
+ break;
+ case eWNI_SME_REMAIN_ON_CHN_RDY_IND:
+ if(pMsg->bodyptr)
+ {
+ status = sme_remainOnChnReady(pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_REMAIN_ON_CHN_RDY_IND), nothing to process\n");
+ }
+ break;
+ case eWNI_SME_MGMT_FRM_IND:
+ if(pMsg->bodyptr)
+ {
+ sme_mgmtFrmInd(pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_MGMT_FRM_IND), nothing to process\n");
+ }
+ break;
+ case eWNI_SME_ACTION_FRAME_SEND_CNF:
+ if(pMsg->bodyptr)
+ {
+ status = sme_sendActionCnf(pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_ACTION_FRAME_SEND_CNF), nothing to process\n");
+ }
+ break;
+#endif
+ case eWNI_SME_COEX_IND:
+ if(pMsg->bodyptr)
+ {
+ status = btcHandleCoexInd((void *)pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_COEX_IND), nothing to process\n");
+ }
+ break;
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+ case eWNI_SME_PREF_NETWORK_FOUND_IND:
+ if(pMsg->bodyptr)
+ {
+ status = sme_PreferredNetworkFoundInd((void *)pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_PREF_NETWORK_FOUND_IND), nothing to process\n");
+ }
+ break;
+#endif // FEATURE_WLAN_SCAN_PNO
+
+ case eWNI_SME_TX_PER_HIT_IND:
+ if (pMac->sme.pTxPerHitCallback)
+ {
+ pMac->sme.pTxPerHitCallback(pMac->sme.pTxPerHitCbContext);
+ }
+ break;
+
+ case eWNI_SME_CHANGE_COUNTRY_CODE:
+ if(pMsg->bodyptr)
+ {
+ status = sme_HandleChangeCountryCode((void *)pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_COEX_IND), nothing to process\n");
+ }
+ break;
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ case eWNI_PMC_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP:
+ if(pMsg->bodyptr)
+ {
+ status = sme_PCFilterMatchCountResponseHandler((void *)pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "Empty rsp message for meas "
+ "(PACKET_COALESCING_FILTER_MATCH_COUNT_RSP), nothing to process\n");
+ }
+ break;
+#endif // WLAN_FEATURE_PACKET_FILTERING
+ case eWNI_SME_PRE_SWITCH_CHL_IND:
+ {
+ status = sme_HandlePreChannelSwitchInd(pMac);
+ break;
+ }
+
+ case eWNI_SME_POST_SWITCH_CHL_IND:
+ {
+ status = sme_HandlePostChannelSwitchInd(pMac);
+ break;
+ }
+
+#ifdef WLAN_WAKEUP_EVENTS
+ case eWNI_SME_WAKE_REASON_IND:
+ if(pMsg->bodyptr)
+ {
+ status = sme_WakeReasonIndCallback((void *)pMac, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_WAKE_REASON_IND), nothing to process\n");
+ }
+ break;
+#endif // WLAN_WAKEUP_EVENTS
+
+ default:
+
+ if ( ( pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN )
+ && ( pMsg->type <= eWNI_SME_MSG_TYPES_END ) )
+ {
+ //CSR
+ if (pMsg->bodyptr)
+ {
+ status = csrMsgProcessor(hHal, pMsg->bodyptr);
+ vos_mem_free( pMsg->bodyptr );
+ }
+ else
+ {
+ smsLog( pMac, LOGE, "Empty rsp message for CSR, nothing to process\n");
+ }
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "Unknown message type %d, nothing to process\n",
+ pMsg->type);
+ if (pMsg->bodyptr)
+ {
+ vos_mem_free( pMsg->bodyptr );
+ }
+ }
+ }//switch
+ } //SME_IS_START
+ else
+ {
+ smsLog( pMac, LOGW, "message type %d in stop state ignored\n", pMsg->type);
+ if (pMsg->bodyptr)
+ {
+ vos_mem_free( pMsg->bodyptr );
+ }
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ else
+ {
+ smsLog( pMac, LOGW, "Locking failed, bailing out\n");
+ if (pMsg->bodyptr)
+ {
+ vos_mem_free( pMsg->bodyptr );
+ }
+ }
+
+ return status;
+}
+
+
+//No need to hold the global lock here because this function can only be called
+//after sme_Stop.
+v_VOID_t sme_FreeMsg( tHalHandle hHal, vos_msg_t* pMsg )
+{
+ if( pMsg )
+ {
+ if (pMsg->bodyptr)
+ {
+ vos_mem_free( pMsg->bodyptr );
+ }
+ }
+
+}
+
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_Stop() - Stop all SME modules and put them at idle state
+
+ The function stops each module in SME, PMC, CCM, CSR, etc. . Upon
+ return, all modules are at idle state ready to start.
+
+ This is a synchronuous call
+ \param hHal - The handle returned by macOpen
+
+ \return eHAL_STATUS_SUCCESS - SME is stopped.
+
+ Other status means SME is failed to stop but caller should still
+ consider SME is stopped.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_Stop(tHalHandle hHal, tANI_BOOLEAN pmcFlag)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ eHalStatus fail_status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+#ifdef WLAN_SOFTAP_FEATURE
+ status = WLANSAP_Stop(vos_get_global_context(VOS_MODULE_ID_SAP, NULL));
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "WLANSAP_Stop failed during smeStop with status=%d\n",
+ status );
+ fail_status = status;
+ }
+#endif
+
+ p2pStop(hHal);
+
+ if(pmcFlag)
+ {
+ status = pmcStop(hHal);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "pmcStop failed during smeStop with status=%d\n",
+ status );
+ fail_status = status;
+ }
+ }
+
+ status = csrStop(pMac);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "csrStop failed during smeStop with status=%d\n",
+ status );
+ fail_status = status;
+ }
+
+ ccmStop(hHal);
+
+ purgeSmeCmdList(pMac);
+
+ if (!HAL_STATUS_SUCCESS( fail_status )) {
+ status = fail_status;
+ }
+
+ pMac->sme.state = SME_STATE_STOP;
+
+ return status;
+}
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_Close() - Release all SME modules and their resources.
+
+ The function release each module in SME, PMC, CCM, CSR, etc. . Upon
+ return, all modules are at closed state.
+
+ No SME APIs can be involved after smeClose except smeOpen.
+ smeClose must be called before macClose.
+ This is a synchronuous call
+ \param hHal - The handle returned by macOpen
+
+ \return eHAL_STATUS_SUCCESS - SME is successfully close.
+
+ Other status means SME is failed to be closed but caller still cannot
+ call any other SME functions except smeOpen.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_Close(tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ eHalStatus fail_status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = csrClose(pMac);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "csrClose failed during sme close with status=%d\n",
+ status );
+ fail_status = status;
+ }
+
+#ifdef WLAN_SOFTAP_FEATURE
+ status = WLANSAP_Close(vos_get_global_context(VOS_MODULE_ID_SAP, NULL));
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "WLANSAP_close failed during sme close with status=%d\n",
+ status );
+ fail_status = status;
+ }
+#endif
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ status = btcClose(hHal);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "BTC close failed during sme close with status=%d\n",
+ status );
+ fail_status = status;
+ }
+
+ status = sme_QosClose(pMac);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "Qos close failed during sme close with status=%d\n",
+ status );
+ fail_status = status;
+ }
+#endif
+
+ status = ccmClose(hHal);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "ccmClose failed during sme close with status=%d\n",
+ status );
+ fail_status = status;
+ }
+
+ status = pmcClose(hHal);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "pmcClose failed during sme close with status=%d\n",
+ status );
+ fail_status = status;
+ }
+#if defined WLAN_FEATURE_VOWIFI
+ status = rrmClose(hHal);
+ if ( ! HAL_STATUS_SUCCESS( status ) ) {
+ smsLog( pMac, LOGE, "RRM close failed during sme close with status=%d\n",
+ status );
+ fail_status = status;
+ }
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ sme_FTClose(hHal);
+#endif
+#if defined WLAN_FEATURE_P2P
+ sme_p2pClose(hHal);
+#endif
+
+ freeSmeCmdList(pMac);
+
+ if( !VOS_IS_STATUS_SUCCESS( vos_lock_destroy( &pMac->sme.lkSmeGlobalLock ) ) )
+ {
+ fail_status = eHAL_STATUS_FAILURE;
+ }
+
+ if (!HAL_STATUS_SUCCESS( fail_status )) {
+ status = fail_status;
+ }
+
+ pMac->sme.state = SME_STATE_STOP;
+
+ return status;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanRequest
+ \brief a wrapper function to Request a 11d or full scan from CSR.
+ This is an asynchronuous call
+ \param pScanRequestID - pointer to an object to get back the request ID
+ \param callback - a callback function that scan calls upon finish, will not
+ be called if csrScanRequest returns error
+ \param pContext - a pointer passed in for the callback
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanRequest(tHalHandle hHal, tANI_U8 sessionId, tCsrScanRequest *pscanReq,
+ tANI_U32 *pScanRequestID,
+ csrScanCompleteCallback callback, void *pContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ smsLog(pMac, LOG2, FL("enter"));
+ do
+ {
+ if(pMac->scan.fScanEnable)
+ {
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ {
+ status = csrScanRequest( hHal, sessionId, pscanReq,
+ pScanRequestID, callback, pContext );
+ }
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ } //sme_AcquireGlobalLock success
+ } //if(pMac->scan.fScanEnable)
+ } while( 0 );
+
+ return (status);
+
+
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanGetResult
+ \brief a wrapper function to request scan results from CSR.
+ This is a synchronuous call
+ \param pFilter - If pFilter is NULL, all cached results are returned
+ \param phResult - an object for the result.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanGetResult(tHalHandle hHal, tANI_U8 sessionId, tCsrScanResultFilter *pFilter,
+ tScanResultHandle *phResult)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ smsLog(pMac, LOG2, FL("enter"));
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrScanGetResult( hHal, pFilter, phResult );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ smsLog(pMac, LOG2, FL("exit status %d"), status);
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanFlushResult
+ \brief a wrapper function to request CSR to clear scan results.
+ This is a synchronuous call
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanFlushResult(tHalHandle hHal, tANI_U8 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrScanFlushResult( hHal );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanResultGetFirst
+ \brief a wrapper function to request CSR to returns the first element of
+ scan result.
+ This is a synchronuous call
+ \param hScanResult - returned from csrScanGetResult
+ \return tCsrScanResultInfo * - NULL if no result
+ ---------------------------------------------------------------------------*/
+tCsrScanResultInfo *sme_ScanResultGetFirst(tHalHandle hHal,
+ tScanResultHandle hScanResult)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tCsrScanResultInfo *pRet = NULL;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ pRet = csrScanResultGetFirst( pMac, hScanResult );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (pRet);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanResultGetNext
+ \brief a wrapper function to request CSR to returns the next element of
+ scan result. It can be called without calling csrScanResultGetFirst
+ first
+ This is a synchronuous call
+ \param hScanResult - returned from csrScanGetResult
+ \return Null if no result or reach the end
+ ---------------------------------------------------------------------------*/
+tCsrScanResultInfo *sme_ScanResultGetNext(tHalHandle hHal,
+ tScanResultHandle hScanResult)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tCsrScanResultInfo *pRet = NULL;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ pRet = csrScanResultGetNext( pMac, hScanResult );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (pRet);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanSetBGScanparams
+ \brief a wrapper function to request CSR to set BG scan params in PE
+ This is a synchronuous call
+ \param pScanReq - BG scan request structure
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanSetBGScanparams(tHalHandle hHal, tANI_U8 sessionId, tCsrBGScanRequest *pScanReq)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if( NULL != pScanReq )
+ {
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrScanSetBGScanparams( hHal, pScanReq );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ }
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanResultPurge
+ \brief a wrapper function to request CSR to remove all items(tCsrScanResult)
+ in the list and free memory for each item
+ This is a synchronuous call
+ \param hScanResult - returned from csrScanGetResult. hScanResult is
+ considered gone by
+ calling this function and even before this function reutrns.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanResultPurge(tHalHandle hHal, tScanResultHandle hScanResult)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrScanResultPurge( hHal, hScanResult );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanGetPMKIDCandidateList
+ \brief a wrapper function to return the PMKID candidate list
+ This is a synchronuous call
+ \param pPmkidList - caller allocated buffer point to an array of
+ tPmkidCandidateInfo
+ \param pNumItems - pointer to a variable that has the number of
+ tPmkidCandidateInfo allocated when retruning, this is
+ either the number needed or number of items put into
+ pPmkidList
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough and pNumItems
+ has the number of tPmkidCandidateInfo.
+ \Note: pNumItems is a number of tPmkidCandidateInfo,
+ not sizeof(tPmkidCandidateInfo) * something
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanGetPMKIDCandidateList(tHalHandle hHal, tANI_U8 sessionId,
+ tPmkidCandidateInfo *pPmkidList,
+ tANI_U32 *pNumItems )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrScanGetPMKIDCandidateList( pMac, sessionId, pPmkidList, pNumItems );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/*----------------------------------------------------------------------------
+ \fn sme_RoamRegisterLinkQualityIndCallback
+
+ \brief
+ a wrapper function to allow HDD to register a callback handler with CSR for
+ link quality indications.
+
+ Only one callback may be registered at any time.
+ In order to deregister the callback, a NULL cback may be provided.
+
+ Registration happens in the task context of the caller.
+
+ \param callback - Call back being registered
+ \param pContext - user data
+
+ DEPENDENCIES: After CSR open
+
+ \return eHalStatus
+-----------------------------------------------------------------------------*/
+eHalStatus sme_RoamRegisterLinkQualityIndCallback(tHalHandle hHal, tANI_U8 sessionId,
+ csrRoamLinkQualityIndCallback callback,
+ void *pContext)
+{
+ return(csrRoamRegisterLinkQualityIndCallback((tpAniSirGlobal)hHal, callback, pContext));
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamRegisterCallback
+ \brief a wrapper function to allow HDD to register a callback with CSR.
+ Unlike scan, roam has one callback for all the roam requests
+ \param callback - a callback function that roam calls upon when state changes
+ \param pContext - a pointer passed in for the callback
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamRegisterCallback(tHalHandle hHal,
+ csrRoamCompleteCallback callback,
+ void *pContext)
+{
+ return(csrRoamRegisterCallback((tpAniSirGlobal)hHal, callback, pContext));
+}
+
+eCsrPhyMode sme_GetPhyMode(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ return pMac->roam.configParam.phyMode;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamConnect
+ \brief a wrapper function to request CSR to inititiate an association
+ This is an asynchronuous call.
+ \param sessionId - the sessionId returned by sme_OpenSession.
+ \param pProfile - description of the network to which to connect
+ \param hBssListIn - a list of BSS descriptor to roam to. It is returned
+ from csrScanGetResult
+ \param pRoamId - to get back the request ID
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamConnect(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile *pProfile,
+ tANI_U32 *pRoamId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ smsLog(pMac, LOG2, FL("enter"));
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamConnect( pMac, sessionId, pProfile, NULL, pRoamId );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamReassoc
+ \brief a wrapper function to request CSR to inititiate a re-association
+ \param pProfile - can be NULL to join the currently connected AP. In that
+ case modProfileFields should carry the modified field(s) which could trigger
+ reassoc
+ \param modProfileFields - fields which are part of tCsrRoamConnectedProfile
+ that might need modification dynamically once STA is up & running and this
+ could trigger a reassoc
+ \param pRoamId - to get back the request ID
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamReassoc(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile *pProfile,
+ tCsrRoamModifyProfileFields modProfileFields,
+ tANI_U32 *pRoamId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ smsLog(pMac, LOG2, FL("enter"));
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamReassoc( pMac, sessionId, pProfile, modProfileFields, pRoamId );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamConnectToLastProfile
+ \brief a wrapper function to request CSR to disconnect and reconnect with
+ the same profile
+ This is an asynchronuous call.
+ \return eHalStatus. It returns fail if currently connected
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamConnectToLastProfile(tHalHandle hHal, tANI_U8 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamConnectToLastProfile( pMac, sessionId );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamDisconnect
+ \brief a wrapper function to request CSR to disconnect from a network
+ This is an asynchronuous call.
+ \param reason -- To indicate the reason for disconnecting. Currently, only
+ eCSR_DISCONNECT_REASON_MIC_ERROR is meanful.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamDisconnect(tHalHandle hHal, tANI_U8 sessionId, eCsrRoamDisconnectReason reason)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ smsLog(pMac, LOG2, FL("enter"));
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamDisconnect( pMac, sessionId, reason );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamStopBss
+ \brief To stop BSS for Soft AP. This is an asynchronous API.
+ \param hHal - Global structure
+ \param sessionId - sessionId of SoftAP
+ \return eHalStatus SUCCESS Roam callback will be called to indicate actual results
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamStopBss(tHalHandle hHal, tANI_U8 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ smsLog(pMac, LOG2, FL("enter"));
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamIssueStopBssCmd( pMac, sessionId, eANI_BOOLEAN_TRUE );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamDisconnectSta
+ \brief To disassociate a station. This is an asynchronous API.
+ \param hHal - Global structure
+ \param sessionId - sessionId of SoftAP
+ \param pPeerMacAddr - Caller allocated memory filled with peer MAC address (6 bytes)
+ \return eHalStatus SUCCESS Roam callback will be called to indicate actual results
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamDisconnectSta(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U8 *pPeerMacAddr)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( NULL == pMac )
+ {
+ VOS_ASSERT(0);
+ return status;
+ }
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamIssueDisassociateStaCmd( pMac, sessionId, pPeerMacAddr,
+ eSIR_MAC_UNSPEC_FAILURE_REASON);
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamDeauthSta
+ \brief To disassociate a station. This is an asynchronous API.
+ \param hHal - Global structure
+ \param sessionId - sessionId of SoftAP
+ \param pPeerMacAddr - Caller allocated memory filled with peer MAC address (6 bytes)
+ \return eHalStatus SUCCESS Roam callback will be called to indicate actual results
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamDeauthSta(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U8 *pPeerMacAddr)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( NULL == pMac )
+ {
+ VOS_ASSERT(0);
+ return status;
+ }
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamIssueDeauthStaCmd( pMac, sessionId, pPeerMacAddr,
+ eSIR_MAC_UNSPEC_FAILURE_REASON);
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamTKIPCounterMeasures
+ \brief To start or stop TKIP counter measures. This is an asynchronous API.
+ \param sessionId - sessionId of SoftAP
+ \param pPeerMacAddr - Caller allocated memory filled with peer MAC address (6 bytes)
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamTKIPCounterMeasures(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_BOOLEAN bEnable)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( NULL == pMac )
+ {
+ VOS_ASSERT(0);
+ return status;
+ }
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamIssueTkipCounterMeasures( pMac, sessionId, bEnable);
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetAssociatedStas
+ \brief To probe the list of associated stations from various modules of CORE stack.
+ \This is an asynchronous API.
+ \param sessionId - sessionId of SoftAP
+ \param modId - Module from whom list of associtated stations is to be probed.
+ If an invalid module is passed then by default VOS_MODULE_ID_PE will be probed
+ \param pUsrContext - Opaque HDD context
+ \param pfnSapEventCallback - Sap event callback in HDD
+ \param pAssocBuf - Caller allocated memory to be filled with associatd stations info
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetAssociatedStas(tHalHandle hHal, tANI_U8 sessionId,
+ VOS_MODULE_ID modId, void *pUsrContext,
+ void *pfnSapEventCallback, tANI_U8 *pAssocStasBuf)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( NULL == pMac )
+ {
+ VOS_ASSERT(0);
+ return status;
+ }
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamGetAssociatedStas( pMac, sessionId, modId, pUsrContext, pfnSapEventCallback, pAssocStasBuf );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetWpsSessionOverlap
+ \brief To get the WPS PBC session overlap information.
+ \This is an asynchronous API.
+ \param sessionId - sessionId of SoftAP
+ \param pUsrContext - Opaque HDD context
+ \param pfnSapEventCallback - Sap event callback in HDD
+ \pRemoveMac - pointer to Mac address which needs to be removed from session
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetWpsSessionOverlap(tHalHandle hHal, tANI_U8 sessionId,
+ void *pUsrContext, void
+ *pfnSapEventCallback, v_MACADDR_t pRemoveMac)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( NULL == pMac )
+ {
+ VOS_ASSERT(0);
+ return status;
+ }
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamGetWpsSessionOverlap( pMac, sessionId, pUsrContext, pfnSapEventCallback, pRemoveMac);
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+#endif
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetConnectState
+ \brief a wrapper function to request CSR to return the current connect state
+ of Roaming
+ This is a synchronuous call.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetConnectState(tHalHandle hHal, tANI_U8 sessionId, eCsrConnectState *pState)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamGetConnectState( pMac, sessionId, pState );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetConnectProfile
+ \brief a wrapper function to request CSR to return the current connect
+ profile. Caller must call csrRoamFreeConnectProfile after it is done
+ and before reuse for another csrRoamGetConnectProfile call.
+ This is a synchronuous call.
+ \param pProfile - pointer to a caller allocated structure
+ tCsrRoamConnectedProfile
+ \return eHalStatus. Failure if not connected
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetConnectProfile(tHalHandle hHal, tANI_U8 sessionId,
+ tCsrRoamConnectedProfile *pProfile)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamGetConnectProfile( pMac, sessionId, pProfile );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamFreeConnectProfile
+ \brief a wrapper function to request CSR to free and reinitialize the
+ profile returned previously by csrRoamGetConnectProfile.
+ This is a synchronuous call.
+ \param pProfile - pointer to a caller allocated structure
+ tCsrRoamConnectedProfile
+ \return eHalStatus.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamFreeConnectProfile(tHalHandle hHal,
+ tCsrRoamConnectedProfile *pProfile)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrRoamFreeConnectProfile( pMac, pProfile );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamSetPMKIDCache
+ \brief a wrapper function to request CSR to return the PMKID candidate list
+ This is a synchronuous call.
+ \param pPMKIDCache - caller allocated buffer point to an array of
+ tPmkidCacheInfo
+ \param numItems - a variable that has the number of tPmkidCacheInfo
+ allocated when retruning, this is either the number needed
+ or number of items put into pPMKIDCache
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough and pNumItems has the number of
+ tPmkidCacheInfo.
+ \Note: pNumItems is a number of tPmkidCacheInfo,
+ not sizeof(tPmkidCacheInfo) * something
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamSetPMKIDCache( tHalHandle hHal, tANI_U8 sessionId, tPmkidCacheInfo *pPMKIDCache,
+ tANI_U32 numItems )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamSetPMKIDCache( pMac, sessionId, pPMKIDCache, numItems );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetSecurityReqIE
+ \brief a wrapper function to request CSR to return the WPA or RSN or WAPI IE CSR
+ passes to PE to JOIN request or START_BSS request
+ This is a synchronuous call.
+ \param pLen - caller allocated memory that has the length of pBuf as input.
+ Upon returned, *pLen has the needed or IE length in pBuf.
+ \param pBuf - Caller allocated memory that contain the IE field, if any,
+ upon return
+ \param secType - Specifies whether looking for WPA/WPA2/WAPI IE
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetSecurityReqIE(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pLen,
+ tANI_U8 *pBuf, eCsrSecurityType secType)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamGetWpaRsnReqIE( hHal, sessionId, pLen, pBuf );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetSecurityRspIE
+ \brief a wrapper function to request CSR to return the WPA or RSN or WAPI IE from
+ the beacon or probe rsp if connected
+ This is a synchronuous call.
+ \param pLen - caller allocated memory that has the length of pBuf as input.
+ Upon returned, *pLen has the needed or IE length in pBuf.
+ \param pBuf - Caller allocated memory that contain the IE field, if any,
+ upon return
+ \param secType - Specifies whether looking for WPA/WPA2/WAPI IE
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetSecurityRspIE(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pLen,
+ tANI_U8 *pBuf, eCsrSecurityType secType)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamGetWpaRsnRspIE( pMac, sessionId, pLen, pBuf );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetNumPMKIDCache
+ \brief a wrapper function to request CSR to return number of PMKID cache
+ entries
+ This is a synchronuous call.
+ \return tANI_U32 - the number of PMKID cache entries
+ ---------------------------------------------------------------------------*/
+tANI_U32 sme_RoamGetNumPMKIDCache(tHalHandle hHal, tANI_U8 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U32 numPmkidCache = 0;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ numPmkidCache = csrRoamGetNumPMKIDCache( pMac, sessionId );
+ status = eHAL_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (numPmkidCache);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetPMKIDCache
+ \brief a wrapper function to request CSR to return PMKID cache from CSR
+ This is a synchronuous call.
+ \param pNum - caller allocated memory that has the space of the number of
+ pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the
+ needed or actually number in tPmkidCacheInfo.
+ \param pPmkidCache - Caller allocated memory that contains PMKID cache, if
+ any, upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetPMKIDCache(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pNum,
+ tPmkidCacheInfo *pPmkidCache)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrRoamGetPMKIDCache( pMac, sessionId, pNum, pPmkidCache );
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetConfigParam
+ \brief a wrapper function that HDD calls to get the global settings
+ currently maintained by CSR.
+ This is a synchronuous call.
+ \param pParam - caller allocated memory
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_GetConfigParam(tHalHandle hHal, tSmeConfigParams *pParam)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrGetConfigParam(pMac, &pParam->csrConfig);
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog( pMac, LOGE, "%s csrGetConfigParam failed\n", __FUNCTION__);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return status;
+ }
+#if defined WLAN_FEATURE_P2P_INTERNAL
+ status = p2pGetConfigParam(pMac, &pParam->p2pConfig);
+ if (status != eHAL_STATUS_SUCCESS)
+ {
+ smsLog( pMac, LOGE, "%s p2pGetConfigParam failed\n", __FUNCTION__);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return status;
+ }
+#endif
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_CfgSetInt
+ \brief a wrapper function that HDD calls to set parameters in CFG.
+ This is a synchronuous call.
+ \param cfgId - Configuration Parameter ID (type) for STA.
+ \param ccmValue - The information related to Configuration Parameter ID
+ which needs to be saved in CFG
+ \param callback - To be registered by CSR with CCM. Once the CFG done with
+ saving the information in the database, it notifies CCM &
+ then the callback will be invoked to notify.
+ \param toBeSaved - To save the request for future reference
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_CfgSetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 ccmValue,
+ tCcmCfgSetCallback callback, eAniBoolean toBeSaved)
+{
+ return(ccmCfgSetInt(hHal, cfgId, ccmValue, callback, toBeSaved));
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_CfgSetStr
+ \brief a wrapper function that HDD calls to set parameters in CFG.
+ This is a synchronuous call.
+ \param cfgId - Configuration Parameter ID (type) for STA.
+ \param pStr - Pointer to the byte array which carries the information needs
+ to be saved in CFG
+ \param length - Length of the data to be saved
+ \param callback - To be registered by CSR with CCM. Once the CFG done with
+ saving the information in the database, it notifies CCM &
+ then the callback will be invoked to notify.
+ \param toBeSaved - To save the request for future reference
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_CfgSetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pStr,
+ tANI_U32 length, tCcmCfgSetCallback callback,
+ eAniBoolean toBeSaved)
+{
+ return(ccmCfgSetStr(hHal, cfgId, pStr, length, callback, toBeSaved));
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetModifyProfileFields
+ \brief HDD or SME - QOS calls this function to get the current values of
+ connected profile fields, changing which can cause reassoc.
+ This function must be called after CFG is downloaded and STA is in connected
+ state. Also, make sure to call this function to get the current profile
+ fields before calling the reassoc. So that pModifyProfileFields will have
+ all the latest values plus the one(s) has been updated as part of reassoc
+ request.
+ \param pModifyProfileFields - pointer to the connected profile fields
+ changing which can cause reassoc
+
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetModifyProfileFields(tHalHandle hHal, tANI_U8 sessionId,
+ tCsrRoamModifyProfileFields * pModifyProfileFields)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
+ {
+ status = csrGetModifyProfileFields(pMac, sessionId, pModifyProfileFields);
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/*--------------------------------------------------------------------------
+ \fn sme_SetConfigPowerSave
+ \brief Wrapper fn to change power save configuration in SME (PMC) module.
+ For BMPS related configuration, this function also updates the CFG
+ and sends a message to FW to pick up the new values. Note: Calling
+ this function only updates the configuration and does not enable
+ the specified power save mode.
+ \param hHal - The handle returned by macOpen.
+ \param psMode - Power Saving mode being modified
+ \param pConfigParams - a pointer to a caller allocated object of type
+ tPmcSmpsConfigParams or tPmcBmpsConfigParams or tPmcImpsConfigParams
+ \return eHalStatus
+ --------------------------------------------------------------------------*/
+eHalStatus sme_SetConfigPowerSave(tHalHandle hHal, tPmcPowerSavingMode psMode,
+ void *pConfigParams)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if (NULL == pConfigParams ) {
+ smsLog( pMac, LOGE, "Empty config param structure for PMC, "
+ "nothing to update");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcSetConfigPowerSave(hHal, psMode, pConfigParams);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/*--------------------------------------------------------------------------
+ \fn sme_GetConfigPowerSave
+ \brief Wrapper fn to retrieve power save configuration in SME (PMC) module
+ \param hHal - The handle returned by macOpen.
+ \param psMode - Power Saving mode
+ \param pConfigParams - a pointer to a caller allocated object of type
+ tPmcSmpsConfigParams or tPmcBmpsConfigParams or tPmcImpsConfigParams
+ \return eHalStatus
+ --------------------------------------------------------------------------*/
+eHalStatus sme_GetConfigPowerSave(tHalHandle hHal, tPmcPowerSavingMode psMode,
+ void *pConfigParams)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if (NULL == pConfigParams ) {
+ smsLog( pMac, LOGE, "Empty config param structure for PMC, "
+ "nothing to update");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcGetConfigPowerSave(hHal, psMode, pConfigParams);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SignalPowerEvent
+ \brief Signals to PMC that a power event has occurred. Used for putting
+ the chip into deep sleep mode.
+ \param hHal - The handle returned by macOpen.
+ \param event - the event that has occurred
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SignalPowerEvent (tHalHandle hHal, tPmcPowerEvent event)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcSignalPowerEvent(hHal, event);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_EnablePowerSave
+ \brief Enables one of the power saving modes.
+ \param hHal - The handle returned by macOpen.
+ \param psMode - The power saving mode to enable. If BMPS mode is enabled
+ while the chip is operating in Full Power, PMC will start
+ a timer that will try to put the chip in BMPS mode after
+ expiry.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_EnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcEnablePowerSave(hHal, psMode);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_DisablePowerSave
+ \brief Disables one of the power saving modes.
+ \param hHal - The handle returned by macOpen.
+ \param psMode - The power saving mode to disable. Disabling does not imply
+ that device will be brought out of the current PS mode. This
+ is purely a configuration API.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_DisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcDisablePowerSave(hHal, psMode);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+ }
+
+/* ---------------------------------------------------------------------------
+ \fn sme_StartAutoBmpsTimer
+ \brief Starts a timer that periodically polls all the registered
+ module for entry into Bmps mode. This timer is started only if BMPS is
+ enabled and whenever the device is in full power.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_StartAutoBmpsTimer ( tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcStartAutoBmpsTimer(hHal);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+/* ---------------------------------------------------------------------------
+ \fn sme_StopAutoBmpsTimer
+ \brief Stops the Auto BMPS Timer that was started using sme_startAutoBmpsTimer
+ Stopping the timer does not cause a device state change. Only the timer
+ is stopped. If "Full Power" is desired, use the sme_RequestFullPower API
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_StopAutoBmpsTimer ( tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcStopAutoBmpsTimer(hHal);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+/* ---------------------------------------------------------------------------
+ \fn sme_QueryPowerState
+ \brief Returns the current power state of the device.
+ \param hHal - The handle returned by macOpen.
+ \param pPowerState - pointer to location to return power state (LOW or HIGH)
+ \param pSwWlanSwitchState - ptr to location to return SW WLAN Switch state
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_QueryPowerState (
+ tHalHandle hHal,
+ tPmcPowerState *pPowerState,
+ tPmcSwitchState *pSwWlanSwitchState)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcQueryPowerState (hHal, pPowerState, NULL, pSwWlanSwitchState);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_IsPowerSaveEnabled
+ \brief Checks if the device is able to enter a particular power save mode
+ This does not imply that the device is in a particular PS mode
+ \param hHal - The handle returned by macOpen.
+ \param psMode - the power saving mode
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+tANI_BOOLEAN sme_IsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_BOOLEAN result = false;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ result = pmcIsPowerSaveEnabled(hHal, psMode);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return result;
+ }
+
+ return false;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RequestFullPower
+ \brief Request that the device be brought to full power state. When the
+ device enters Full Power PMC will start a BMPS timer if BMPS PS mode
+ is enabled. On timer expiry PMC will attempt to put the device in
+ BMPS mode if following holds true:
+ - BMPS mode is enabled
+ - Polling of all modules through the Power Save Check routine passes
+ - STA is associated to an access point
+ \param hHal - The handle returned by macOpen.
+ \param - callbackRoutine Callback routine invoked in case of success/failure
+ \return eHalStatus - status
+ eHAL_STATUS_SUCCESS - device brought to full power state
+ eHAL_STATUS_FAILURE - device cannot be brought to full power state
+ eHAL_STATUS_PMC_PENDING - device is being brought to full power state,
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RequestFullPower (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext,
+ tRequestFullPowerReason fullPowerReason)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcRequestFullPower(hHal, callbackRoutine, callbackContext, fullPowerReason);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RequestBmps
+ \brief Request that the device be put in BMPS state. Request will be
+ accepted only if BMPS mode is enabled and power save check routine
+ passes.
+ \param hHal - The handle returned by macOpen.
+ \param - callbackRoutine Callback routine invoked in case of success/failure
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - device is in BMPS state
+ eHAL_STATUS_FAILURE - device cannot be brought to BMPS state
+ eHAL_STATUS_PMC_PENDING - device is being brought to BMPS state
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RequestBmps (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcRequestBmps(hHal, callbackRoutine, callbackContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetDHCPTillPowerActiveFlag
+ \brief Sets/Clears DHCP related flag in PMC to disable/enable auto BMPS
+ entry by PMC
+ \param hHal - The handle returned by macOpen.
+ ---------------------------------------------------------------------------*/
+void sme_SetDHCPTillPowerActiveFlag(tHalHandle hHal, tANI_U8 flag)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ // Set/Clear the DHCP flag which will disable/enable auto BMPS entery by PMC
+ pMac->pmc.remainInPowerActiveTillDHCP = flag;
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_StartUapsd
+ \brief Request that the device be put in UAPSD state. If the device is in
+ Full Power it will be put in BMPS mode first and then into UAPSD
+ mode.
+ \param hHal - The handle returned by macOpen.
+ \param - callbackRoutine Callback routine invoked in case of success/failure
+ eHAL_STATUS_SUCCESS - device is in UAPSD state
+ eHAL_STATUS_FAILURE - device cannot be brought to UAPSD state
+ eHAL_STATUS_PMC_PENDING - device is being brought to UAPSD state
+ eHAL_STATUS_PMC_DISABLED - UAPSD is disabled or BMPS mode is disabled
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_StartUapsd (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcStartUapsd(hHal, callbackRoutine, callbackContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+ }
+
+/* ---------------------------------------------------------------------------
+ \fn sme_StopUapsd
+ \brief Request that the device be put out of UAPSD state. Device will be
+ put in in BMPS state after stop UAPSD completes.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - device is put out of UAPSD and back in BMPS state
+ eHAL_STATUS_FAILURE - device cannot be brought out of UAPSD state
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_StopUapsd (tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcStopUapsd(hHal);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RequestStandby
+ \brief Request that the device be put in standby. It is HDD's responsibility
+ to bring the chip to full power and do a disassoc before calling
+ this API.
+ \param hHal - The handle returned by macOpen.
+ \param - callbackRoutine Callback routine invoked in case of success/failure
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - device is in Standby mode
+ eHAL_STATUS_FAILURE - device cannot be put in standby mode
+ eHAL_STATUS_PMC_PENDING - device is being put in standby mode
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RequestStandby (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, eHalStatus status),
+ void *callbackContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ smsLog( pMac, LOG1, FL("") );
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcRequestStandby(hHal, callbackRoutine, callbackContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RegisterPowerSaveCheck
+ \brief Register a power save check routine that is called whenever
+ the device is about to enter one of the power save modes.
+ \param hHal - The handle returned by macOpen.
+ \param checkRoutine - Power save check routine to be registered
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully registered
+ eHAL_STATUS_FAILURE - not successfully registered
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RegisterPowerSaveCheck (
+ tHalHandle hHal,
+ tANI_BOOLEAN (*checkRoutine) (void *checkContext), void *checkContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcRegisterPowerSaveCheck (hHal, checkRoutine, checkContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_DeregisterPowerSaveCheck
+ \brief Deregister a power save check routine
+ \param hHal - The handle returned by macOpen.
+ \param checkRoutine - Power save check routine to be deregistered
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully deregistered
+ eHAL_STATUS_FAILURE - not successfully deregistered
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_DeregisterPowerSaveCheck (
+ tHalHandle hHal,
+ tANI_BOOLEAN (*checkRoutine) (void *checkContext))
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcDeregisterPowerSaveCheck (hHal, checkRoutine);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RegisterDeviceStateUpdateInd
+ \brief Register a callback routine that is called whenever
+ the device enters a new device state (Full Power, BMPS, UAPSD)
+ \param hHal - The handle returned by macOpen.
+ \param callbackRoutine - Callback routine to be registered
+ \param callbackContext - Cookie to be passed back during callback
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully registered
+ eHAL_STATUS_FAILURE - not successfully registered
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RegisterDeviceStateUpdateInd (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState),
+ void *callbackContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcRegisterDeviceStateUpdateInd (hHal, callbackRoutine, callbackContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_DeregisterDeviceStateUpdateInd
+ \brief Deregister a routine that was registered for device state changes
+ \param hHal - The handle returned by macOpen.
+ \param callbackRoutine - Callback routine to be deregistered
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS - successfully deregistered
+ eHAL_STATUS_FAILURE - not successfully deregistered
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_DeregisterDeviceStateUpdateInd (
+ tHalHandle hHal,
+ void (*callbackRoutine) (void *callbackContext, tPmcState pmcState))
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcDeregisterDeviceStateUpdateInd (hHal, callbackRoutine);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_WowlAddBcastPattern
+ \brief Add a pattern for Pattern Byte Matching in Wowl mode. Firmware will
+ do a pattern match on these patterns when Wowl is enabled during BMPS
+ mode. Note that Firmware performs the pattern matching only on
+ broadcast frames and while Libra is in BMPS mode.
+ \param hHal - The handle returned by macOpen.
+ \param pattern - Pattern to be added
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot add pattern
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_WowlAddBcastPattern (
+ tHalHandle hHal,
+ tpSirWowlAddBcastPtrn pattern)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcWowlAddBcastPattern (hHal, pattern);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_WowlDelBcastPattern
+ \brief Delete a pattern that was added for Pattern Byte Matching.
+ \param hHal - The handle returned by macOpen.
+ \param pattern - Pattern to be deleted
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Cannot delete pattern
+ eHAL_STATUS_SUCCESS Request accepted.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_WowlDelBcastPattern (
+ tHalHandle hHal,
+ tpSirWowlDelBcastPtrn pattern)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcWowlDelBcastPattern (hHal, pattern);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_EnterWowl
+ \brief This is the SME API exposed to HDD to request enabling of WOWL mode.
+ WoWLAN works on top of BMPS mode. If the device is not in BMPS mode,
+ SME will will cache the information that WOWL has been enabled and
+ attempt to put the device in BMPS. On entry into BMPS, SME will
+ enable the WOWL mode.
+ Note 1: If we exit BMPS mode (someone requests full power), we
+ will NOT resume WOWL when we go back to BMPS again. Request for full
+ power (while in WOWL mode) means disable WOWL and go to full power.
+ Note 2: Both UAPSD and WOWL work on top of BMPS. On entry into BMPS, SME
+ will give priority to UAPSD and enable only UAPSD if both UAPSD and WOWL
+ are required. Currently there is no requirement or use case to support
+ UAPSD and WOWL at the same time.
+
+ \param hHal - The handle returned by macOpen.
+ \param enterWowlCallbackRoutine - Callback routine provided by HDD.
+ Used for success/failure notification by SME
+ \param enterWowlCallbackContext - A cookie passed by HDD, that is passed back to HDD
+ at the time of callback.
+ \param wakeReasonIndCB - Callback routine provided by HDD.
+ Used for Wake Reason Indication by SME
+ \param wakeReasonIndCBContext - A cookie passed by HDD, that is passed back to HDD
+ at the time of callback.
+ \return eHalStatus
+ eHAL_STATUS_SUCCESS Device is already in WoWLAN mode
+ eHAL_STATUS_FAILURE Device cannot enter WoWLAN mode.
+ eHAL_STATUS_PMC_PENDING Request accepted. SME will enable WOWL after
+ BMPS mode is entered.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_EnterWowl (
+ tHalHandle hHal,
+ void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status),
+ void *enterWowlCallbackContext,
+#ifdef WLAN_WAKEUP_EVENTS
+ void (*wakeIndicationCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd),
+ void *wakeIndicationCBContext,
+#endif // WLAN_WAKEUP_EVENTS
+ tpSirSmeWowlEnterParams wowlEnterParams)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcEnterWowl (hHal, enterWowlCallbackRoutine, enterWowlCallbackContext,
+#ifdef WLAN_WAKEUP_EVENTS
+ wakeIndicationCB, wakeIndicationCBContext,
+#endif // WLAN_WAKEUP_EVENTS
+ wowlEnterParams);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+/* ---------------------------------------------------------------------------
+ \fn sme_ExitWowl
+ \brief This is the SME API exposed to HDD to request exit from WoWLAN mode.
+ SME will initiate exit from WoWLAN mode and device will be put in BMPS
+ mode.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ eHAL_STATUS_FAILURE Device cannot exit WoWLAN mode.
+ eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ExitWowl (tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcExitWowl (hHal);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RoamSetKey
+
+ \brief To set encryption key. This function should be called only when connected
+ This is an asynchronous API.
+
+ \param pSetKeyInfo - pointer to a caller allocated object of tCsrSetContextInfo
+
+ \param pRoamId Upon success return, this is the id caller can use to identify the request in roamcallback
+
+ \return eHalStatus SUCCESS Roam callback will be called indicate actually results
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamSetKey(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 *pRoamId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U32 roamId;
+#ifdef WLAN_SOFTAP_FEATURE
+ tANI_U32 i;
+ tCsrRoamSession *pSession = NULL;
+#endif
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ roamId = GET_NEXT_ROAM_ID(&pMac->roam);
+ if(pRoamId)
+ {
+ *pRoamId = roamId;
+ }
+
+#ifdef WLAN_SOFTAP_FEATURE
+ smsLog(pMac, LOG2, FL("keyLength\n"), pSetKey->keyLength);
+
+ for(i=0; i<pSetKey->keyLength; i++)
+ smsLog(pMac, LOG2, FL("%02x"), pSetKey->Key[i]);
+
+ smsLog(pMac, LOG2, "\n sessionId=%d roamId=%d\n", sessionId, roamId);
+
+ pSession = CSR_GET_SESSION(pMac, sessionId);
+
+ if(CSR_IS_INFRA_AP(&pSession->connectedProfile))
+ {
+ if(pSetKey->keyDirection == eSIR_TX_DEFAULT)
+ {
+ if ( ( eCSR_ENCRYPT_TYPE_WEP40 == pSetKey->encType ) ||
+ ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pSetKey->encType ))
+ {
+ pSession->pCurRoamProfile->negotiatedUCEncryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ }
+ if ( ( eCSR_ENCRYPT_TYPE_WEP104 == pSetKey->encType ) ||
+ ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pSetKey->encType ))
+ {
+ pSession->pCurRoamProfile->negotiatedUCEncryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
+ }
+ }
+ }
+#endif
+
+ status = csrRoamSetKey ( pMac, sessionId, pSetKey, roamId );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RoamRemoveKey
+
+ \brief To set encryption key. This is an asynchronous API.
+
+ \param pRemoveKey - pointer to a caller allocated object of tCsrRoamRemoveKey
+
+ \param pRoamId Upon success return, this is the id caller can use to identify the request in roamcallback
+
+ \return eHalStatus SUCCESS Roam callback will be called indicate actually results
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamRemoveKey(tHalHandle hHal, tANI_U8 sessionId,
+ tCsrRoamRemoveKey *pRemoveKey, tANI_U32 *pRoamId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U32 roamId;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ roamId = GET_NEXT_ROAM_ID(&pMac->roam);
+ if(pRoamId)
+ {
+ *pRoamId = roamId;
+ }
+ status = csrRoamIssueRemoveKeyCommand( pMac, sessionId, pRemoveKey, roamId );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetRssi
+ \brief a wrapper function that client calls to register a callback to get RSSI
+
+ \param callback - SME sends back the requested stats using the callback
+ \param staId - The station ID for which the stats is requested for
+ \param pContext - user context to be passed back along with the callback
+ \param pVosContext - vos context
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_GetRssi(tHalHandle hHal,
+ tCsrRssiCallback callback,
+ tANI_U8 staId, tCsrBssid bssId,
+ void *pContext, void* pVosContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrGetRssi( pMac, callback,
+ staId, bssId, pContext, pVosContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetStatistics
+ \brief a wrapper function that client calls to register a callback to get
+ different PHY level statistics from CSR.
+
+ \param requesterId - different client requesting for statistics, HDD, UMA/GAN etc
+ \param statsMask - The different category/categories of stats requester is looking for
+ \param callback - SME sends back the requested stats using the callback
+ \param periodicity - If requester needs periodic update in millisec, 0 means
+ it's an one time request
+ \param cache - If requester is happy with cached stats
+ \param staId - The station ID for which the stats is requested for
+ \param pContext - user context to be passed back along with the callback
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_GetStatistics(tHalHandle hHal, eCsrStatsRequesterType requesterId,
+ tANI_U32 statsMask,
+ tCsrStatsCallback callback,
+ tANI_U32 periodicity, tANI_BOOLEAN cache,
+ tANI_U8 staId, void *pContext)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrGetStatistics( pMac, requesterId , statsMask, callback,
+ periodicity, cache, staId, pContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetCountryCode
+
+ \brief To return the current country code. If no country code is applied, default country code is
+ used to fill the buffer.
+ If 11d supported is turned off, an error is return and the last applied/default country code is used.
+ This is a synchronous API.
+
+ \param pBuf - pointer to a caller allocated buffer for returned country code.
+
+ \param pbLen For input, this parameter indicates how big is the buffer.
+ Upon return, this parameter has the number of bytes for country. If pBuf
+ doesn't have enough space, this function returns
+ fail status and this parameter contains the number that is needed.
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetCountryCode(tHalHandle hHal, tANI_U8 *pBuf, tANI_U8 *pbLen)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return ( csrGetCountryCode( pMac, pBuf, pbLen ) );
+}
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_SetCountryCode
+
+ \brief To change the current/default country code.
+ If 11d supported is turned off, an error is return.
+ This is a synchronous API.
+
+ \param pCountry - pointer to a caller allocated buffer for the country code.
+
+ \param pfRestartNeeded A pointer to caller allocated memory, upon successful return, it indicates
+ whether a reset is required.
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_SetCountryCode(tHalHandle hHal, tANI_U8 *pCountry, tANI_BOOLEAN *pfRestartNeeded)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return ( csrSetCountryCode( pMac, pCountry, pfRestartNeeded ) );
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ResetCountryCodeInformation
+ \brief this function is to reset the country code current being used back to EEPROM default
+ this includes channel list and power setting. This is a synchronous API.
+ \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether
+ a restart is needed to apply the change
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_ResetCountryCodeInformation(tHalHandle hHal, tANI_BOOLEAN *pfRestartNeeded)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return ( csrResetCountryCodeInformation( pMac, pfRestartNeeded ) );
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetSupportedCountryCode
+ \brief this function is to get a list of the country code current being supported
+ \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return,
+ this has the country code list. 3 bytes for each country code. This may be NULL if
+ caller wants to know the needed byte count.
+ \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return,
+ this contains the length of the data in pBuf. If pbuf is NULL, as input, *pbLen should be 0.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetSupportedCountryCode(tHalHandle hHal, tANI_U8 *pBuf, tANI_U32 *pbLen)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return ( csrGetSupportedCountryCode( pMac, pBuf, pbLen ) );
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetCurrentRegulatoryDomain
+ \brief this function is to get the current regulatory domain. This is a synchronous API.
+ This function must be called after CFG is downloaded and all the band/mode setting already passed into
+ SME. The function fails if 11d support is turned off.
+ \param pDomain - Caller allocated buffer to return the current domain.
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetCurrentRegulatoryDomain(tHalHandle hHal, v_REGDOMAIN_t *pDomain)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+
+ if( pDomain )
+ {
+ if( csrIs11dSupported( pMac ) )
+ {
+ *pDomain = csrGetCurrentRegulatoryDomain( pMac );
+ status = eHAL_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ }
+
+ return ( status );
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetRegulatoryDomain
+ \brief this function is to set the current regulatory domain.
+ This function must be called after CFG is downloaded and all the band/mode setting already passed into
+ SME. This is a synchronous API.
+ \param domainId - indicate the domain (defined in the driver) needs to set to.
+ See v_REGDOMAIN_t for definition
+ \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether
+ a restart is needed to apply the change
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_SetRegulatoryDomain(tHalHandle hHal, v_REGDOMAIN_t domainId, tANI_BOOLEAN *pfRestartNeeded)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return ( csrSetRegulatoryDomain( pMac, domainId, pfRestartNeeded ) );
+}
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetRegulatoryDomainForCountry
+
+ \brief To return a regulatory domain base on a country code. This is a synchronous API.
+
+ \param pCountry - pointer to a caller allocated buffer for input country code.
+
+ \param pDomainId Upon successful return, it is the domain that country belongs to.
+ If it is NULL, returning success means that the country code is known.
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetRegulatoryDomainForCountry(tHalHandle hHal, tANI_U8 *pCountry, v_REGDOMAIN_t *pDomainId)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return ( csrGetRegulatoryDomainForCountry( pMac, pCountry, pDomainId ) );
+}
+
+
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetSupportedRegulatoryDomains
+
+ \brief To return a list of supported regulatory domains. This is a synchronous API.
+
+ \param pDomains - pointer to a caller allocated buffer for returned regulatory domains.
+
+ \param pNumDomains For input, this parameter indicates howm many domains pDomains can hold.
+ Upon return, this parameter has the number for supported domains. If pDomains
+ doesn't have enough space for all the supported domains, this function returns
+ fail status and this parameter contains the number that is needed.
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_GetSupportedRegulatoryDomains(tHalHandle hHal, v_REGDOMAIN_t *pDomains, tANI_U32 *pNumDomains)
+{
+ eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
+
+ //We support all domains for now
+ if( pNumDomains )
+ {
+ if( NUM_REG_DOMAINS <= *pNumDomains )
+ {
+ status = eHAL_STATUS_SUCCESS;
+ }
+ *pNumDomains = NUM_REG_DOMAINS;
+ }
+ if( HAL_STATUS_SUCCESS( status ) )
+ {
+ if( pDomains )
+ {
+ pDomains[0] = REGDOMAIN_FCC;
+ pDomains[1] = REGDOMAIN_ETSI;
+ pDomains[2] = REGDOMAIN_JAPAN;
+ pDomains[3] = REGDOMAIN_WORLD;
+ pDomains[4] = REGDOMAIN_N_AMER_EXC_FCC;
+ pDomains[5] = REGDOMAIN_APAC;
+ pDomains[6] = REGDOMAIN_KOREA;
+ pDomains[7] = REGDOMAIN_HI_5GHZ;
+ pDomains[8] = REGDOMAIN_NO_5GHZ;
+ }
+ else
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ return ( status );
+}
+
+
+//some support functions
+tANI_BOOLEAN sme_Is11dSupported(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return ( csrIs11dSupported( pMac ) );
+}
+
+
+tANI_BOOLEAN sme_Is11hSupported(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return ( csrIs11hSupported( pMac ) );
+}
+
+
+tANI_BOOLEAN sme_IsWmmSupported(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return ( csrIsWmmSupported( pMac ) );
+}
+
+//Upper layer to get the list of the base channels to scan for passively 11d info from csr
+eHalStatus sme_ScanGetBaseChannels( tHalHandle hHal, tCsrChannelInfo * pChannelInfo )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ return(csrScanGetBaseChannels(pMac,pChannelInfo) );
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_ChangeCountryCode
+
+ \brief Change Country code from upperlayer during WLAN driver operation.
+ This is a synchronous API.
+
+ \param hHal - The handle returned by macOpen.
+
+ \param pCountry New Country Code String
+
+ \return eHalStatus SUCCESS.
+
+ FAILURE or RESOURCES The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_ChangeCountryCode( tHalHandle hHal,
+ tSmeChangeCountryCallback callback,
+ tANI_U8 *pCountry,
+ void *pContext,
+ void* pVosContext )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ vos_msg_t msg;
+ tAniChangeCountryCodeReq *pMsg;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog(pMac, LOG1, FL(" called\n"));
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, sizeof(tAniChangeCountryCodeReq));
+ if ( !HAL_STATUS_SUCCESS(status) )
+ {
+ smsLog(pMac, LOGE, " csrChangeCountryCode: failed to allocate mem for req \n");
+ return status;
+ }
+
+ pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_CHANGE_COUNTRY_CODE);
+ pMsg->msgLen = (tANI_U16)sizeof(tAniChangeCountryCodeReq);
+ palCopyMemory(pMac->hHdd, pMsg->countryCode, pCountry, 3);
+ pMsg->changeCCCallback = callback;
+ pMsg->pDevContext = pContext;
+ pMsg->pVosContext = pVosContext;
+
+ msg.type = eWNI_SME_CHANGE_COUNTRY_CODE;
+ msg.bodyptr = pMsg;
+ msg.reserved = 0;
+
+ if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, &msg))
+ {
+ smsLog(pMac, LOGE, " sme_ChangeCountryCode failed to post msg to self \n");
+ palFreeMemory(pMac->hHdd, (void *)pMsg);
+ status = eHAL_STATUS_FAILURE;
+ }
+ smsLog(pMac, LOG1, FL(" returned\n"));
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_BtcSignalBtEvent
+ \brief API to signal Bluetooth (BT) event to the WLAN driver. Based on the
+ BT event type and the current operating mode of Libra (full power,
+ BMPS, UAPSD etc), appropriate Bluetooth Coexistence (BTC) strategy
+ would be employed.
+ \param hHal - The handle returned by macOpen.
+ \param pBtEvent - Pointer to a caller allocated object of type tSmeBtEvent
+ Caller owns the memory and is responsible for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE BT Event not passed to HAL. This can happen
+ if BTC execution mode is set to BTC_WLAN_ONLY
+ or BTC_PTA_ONLY.
+ VOS_STATUS_SUCCESS BT Event passed to HAL
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_BtcSignalBtEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ status = btcSignalBTEvent (hHal, pBtEvent);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+#endif
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_BtcSetConfig
+ \brief API to change the current Bluetooth Coexistence (BTC) configuration
+ This function should be invoked only after CFG download has completed.
+ Calling it after sme_HDDReadyInd is recommended.
+ \param hHal - The handle returned by macOpen.
+ \param pSmeBtcConfig - Pointer to a caller allocated object of type tSmeBtcConfig.
+ Caller owns the memory and is responsible for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE Config not passed to HAL.
+ VOS_STATUS_SUCCESS Config passed to HAL
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_BtcSetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ status = btcSetConfig (hHal, pSmeBtcConfig);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+#endif
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_BtcGetConfig
+ \brief API to retrieve the current Bluetooth Coexistence (BTC) configuration
+ \param hHal - The handle returned by macOpen.
+ \param pSmeBtcConfig - Pointer to a caller allocated object of type
+ tSmeBtcConfig. Caller owns the memory and is responsible
+ for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_BtcGetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ status = btcGetConfig (hHal, pSmeBtcConfig);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+#endif
+ return (status);
+}
+/* ---------------------------------------------------------------------------
+ \fn sme_SetCfgPrivacy
+ \brief API to set configure privacy parameters
+ \param hHal - The handle returned by macOpen.
+ \param pProfile - Pointer CSR Roam profile.
+ \param fPrivacy - This parameter indicates status of privacy
+
+ \return void
+ ---------------------------------------------------------------------------*/
+void sme_SetCfgPrivacy( tHalHandle hHal,
+ tCsrRoamProfile *pProfile,
+ tANI_BOOLEAN fPrivacy
+ )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ csrSetCfgPrivacy(pMac, pProfile, fPrivacy);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+}
+
+#if defined WLAN_FEATURE_VOWIFI
+/* ---------------------------------------------------------------------------
+ \fn sme_NeighborReportRequest
+ \brief API to request neighbor report.
+ \param hHal - The handle returned by macOpen.
+ \param pRrmNeighborReq - Pointer to a caller allocated object of type
+ tRrmNeighborReq. Caller owns the memory and is responsible
+ for freeing it.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_NeighborReportRequest (tHalHandle hHal, tANI_U8 sessionId,
+ tpRrmNeighborReq pRrmNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ status = sme_RrmNeighborReportRequest (hHal, sessionId, pRrmNeighborReq, callbackInfo);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+#endif
+
+//The following are debug APIs to support direct read/write register/memory
+//They are placed in SME because HW cannot be access when in LOW_POWER state
+//AND not connected. The knowledge and synchronization is done in SME
+
+//sme_DbgReadRegister
+//Caller needs to validate the input values
+VOS_STATUS sme_DbgReadRegister(tHalHandle hHal, v_U32_t regAddr, v_U32_t *pRegValue)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ tHddHandle hHdd = pMac->hHdd;
+#endif
+ tPmcPowerState PowerState;
+ tANI_U32 sessionId = 0;
+
+ /* 1) To make Quarky work in FTM mode **************************************/
+
+ if(eDRIVER_TYPE_MFG == pMac->gDriverType)
+ {
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ if (HAL_STATUS_SUCCESS(palReadRegister(hHdd, regAddr, pRegValue)))
+#elif defined(FEATURE_WLAN_INTEGRATED_SOC)
+ if (eWLAN_PAL_STATUS_SUCCESS == wpalDbgReadRegister(regAddr, pRegValue))
+#endif
+ {
+ return VOS_STATUS_SUCCESS;
+ }
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* 2) NON FTM mode driver *************************************************/
+
+ /* Acquire SME global lock */
+ if (eHAL_STATUS_SUCCESS != sme_AcquireGlobalLock(&pMac->sme))
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if(HAL_STATUS_SUCCESS(pmcQueryPowerState(pMac, &PowerState, NULL, NULL)))
+ {
+ /* Are we not in IMPS mode? Or are we in connected? Then we're safe*/
+ if(!csrIsConnStateDisconnected(pMac, sessionId) || (ePMC_LOW_POWER != PowerState))
+ {
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ if (HAL_STATUS_SUCCESS(palReadRegister(hHdd, regAddr, pRegValue )))
+#elif defined(FEATURE_WLAN_INTEGRATED_SOC)
+ if (eWLAN_PAL_STATUS_SUCCESS == wpalDbgReadRegister(regAddr, pRegValue))
+#endif
+ {
+ status = VOS_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+ else
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+
+ /* This is a hack for Qualky/pttWniSocket
+ Current implementation doesn't allow pttWniSocket to inform Qualky an error */
+ if ( VOS_STATUS_SUCCESS != status )
+ {
+ *pRegValue = 0xDEADBEEF;
+ status = VOS_STATUS_SUCCESS;
+ }
+
+ /* Release SME global lock */
+ sme_ReleaseGlobalLock(&pMac->sme);
+
+ return (status);
+}
+
+
+//sme_DbgWriteRegister
+//Caller needs to validate the input values
+VOS_STATUS sme_DbgWriteRegister(tHalHandle hHal, v_U32_t regAddr, v_U32_t regValue)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ tHddHandle hHdd = pMac->hHdd;
+#endif
+ tPmcPowerState PowerState;
+ tANI_U32 sessionId = 0;
+
+ /* 1) To make Quarky work in FTM mode **************************************/
+
+ if(eDRIVER_TYPE_MFG == pMac->gDriverType)
+ {
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ if (HAL_STATUS_SUCCESS(palWriteRegister(hHdd, regAddr, regValue)))
+#elif defined(FEATURE_WLAN_INTEGRATED_SOC)
+ if (eWLAN_PAL_STATUS_SUCCESS == wpalDbgWriteRegister(regAddr, regValue))
+#endif
+ {
+ return VOS_STATUS_SUCCESS;
+ }
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* 2) NON FTM mode driver *************************************************/
+
+ /* Acquire SME global lock */
+ if (eHAL_STATUS_SUCCESS != sme_AcquireGlobalLock(&pMac->sme))
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if(HAL_STATUS_SUCCESS(pmcQueryPowerState(pMac, &PowerState, NULL, NULL)))
+ {
+ /* Are we not in IMPS mode? Or are we in connected? Then we're safe*/
+ if(!csrIsConnStateDisconnected(pMac, sessionId) || (ePMC_LOW_POWER != PowerState))
+ {
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ if (HAL_STATUS_SUCCESS(palWriteRegister(hHdd, regAddr, regValue)))
+#elif defined(FEATURE_WLAN_INTEGRATED_SOC)
+ if (eWLAN_PAL_STATUS_SUCCESS == wpalDbgWriteRegister(regAddr, regValue))
+#endif
+ {
+ status = VOS_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+ else
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+
+ /* Release SME global lock */
+ sme_ReleaseGlobalLock(&pMac->sme);
+
+ return (status);
+}
+
+
+
+//sme_DbgReadMemory
+//Caller needs to validate the input values
+//pBuf caller allocated buffer has the length of nLen
+VOS_STATUS sme_DbgReadMemory(tHalHandle hHal, v_U32_t memAddr, v_U8_t *pBuf, v_U32_t nLen)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ v_PVOID_t pvosGCTx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *)hHal);
+ tHddHandle hHdd = pMac->hHdd;
+#endif
+ tPmcPowerState PowerState;
+ tANI_U32 sessionId = 0;
+
+ /* 1) To make Quarky work in FTM mode **************************************/
+
+ if(eDRIVER_TYPE_MFG == pMac->gDriverType)
+ {
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ if (HAL_STATUS_SUCCESS(palReadDeviceMemory(hHdd, memAddr, (void *)pBuf, nLen)))
+#elif defined(FEATURE_WLAN_INTEGRATED_SOC)
+ if (eWLAN_PAL_STATUS_SUCCESS == wpalDbgReadMemory(memAddr, (void *)pBuf, nLen))
+#endif
+ {
+ return VOS_STATUS_SUCCESS;
+ }
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* 2) NON FTM mode driver *************************************************/
+
+ /* Acquire SME global lock */
+ if (eHAL_STATUS_SUCCESS != sme_AcquireGlobalLock(&pMac->sme))
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if(HAL_STATUS_SUCCESS(pmcQueryPowerState(pMac, &PowerState, NULL, NULL)))
+ {
+ /* Are we not in IMPS mode? Or are we in connected? Then we're safe*/
+ if(!csrIsConnStateDisconnected(pMac, sessionId) || (ePMC_LOW_POWER != PowerState))
+ {
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ if (HAL_STATUS_SUCCESS(palReadDeviceMemory(pvosGCTx, memAddr, (void *)pBuf, nLen)))
+#elif defined(FEATURE_WLAN_INTEGRATED_SOC)
+ if (eWLAN_PAL_STATUS_SUCCESS == wpalDbgReadMemory(memAddr, (void *)pBuf, nLen))
+#endif
+ {
+ status = VOS_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+ else
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+
+ /* This is a hack for Qualky/pttWniSocket
+ Current implementation doesn't allow pttWniSocket to inform Qualky an error */
+ if (VOS_STATUS_SUCCESS != status)
+ {
+ vos_mem_set(pBuf, nLen, 0xCD);
+ status = VOS_STATUS_SUCCESS;
+ smsLog(pMac, LOGE, FL(" filled with 0xCD because it cannot access the hardware\n"));
+ }
+
+ /* Release SME lock */
+ sme_ReleaseGlobalLock(&pMac->sme);
+
+ return (status);
+}
+
+
+//sme_DbgWriteMemory
+//Caller needs to validate the input values
+VOS_STATUS sme_DbgWriteMemory(tHalHandle hHal, v_U32_t memAddr, v_U8_t *pBuf, v_U32_t nLen)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ tHddHandle hHdd = pMac->hHdd;
+#endif
+ tPmcPowerState PowerState;
+ tANI_U32 sessionId = 0;
+
+ /* 1) To make Quarky work in FTM mode **************************************/
+
+ if(eDRIVER_TYPE_MFG == pMac->gDriverType)
+ {
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ if (HAL_STATUS_SUCCESS(palWriteDeviceMemory(hHdd, memAddr, (void *)pBuf, nLen)))
+#elif defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ if (eWLAN_PAL_STATUS_SUCCESS == wpalDbgWriteMemory( memAddr, (void *)pBuf, nLen))
+#endif
+ {
+ return VOS_STATUS_SUCCESS;
+ }
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* 2) NON FTM mode driver *************************************************/
+
+ /* Acquire SME global lock */
+ if (eHAL_STATUS_SUCCESS != sme_AcquireGlobalLock(&pMac->sme))
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if(HAL_STATUS_SUCCESS(pmcQueryPowerState(pMac, &PowerState, NULL, NULL)))
+ {
+ /* Are we not in IMPS mode? Or are we in connected? Then we're safe*/
+ if(!csrIsConnStateDisconnected(pMac, sessionId) || (ePMC_LOW_POWER != PowerState))
+ {
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ if (HAL_STATUS_SUCCESS(palWriteDeviceMemory(hHdd, memAddr, (void *)pBuf, nLen)))
+#elif defined(FEATURE_WLAN_INTEGRATED_SOC)
+ if (eWLAN_PAL_STATUS_SUCCESS == wpalDbgWriteMemory(memAddr, (void *)pBuf, nLen))
+#endif
+ {
+ status = VOS_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+ else
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+ }
+
+ /* Release Global lock */
+ sme_ReleaseGlobalLock(&pMac->sme);
+
+ return (status);
+}
+
+
+void smsLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...)
+{
+#ifdef WLAN_DEBUG
+ // Verify against current log level
+ if ( loglevel > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( SIR_SMS_MODULE_ID )] )
+ return;
+ else
+ {
+ va_list marker;
+
+ va_start( marker, pString ); /* Initialize variable arguments. */
+
+ logDebug(pMac, SIR_SMS_MODULE_ID, loglevel, pString, marker);
+
+ va_end( marker ); /* Reset variable arguments. */
+ }
+#endif
+}
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+/* ---------------------------------------------------------------------------
+ \fn sme_GetFwVersion
+ \brief This API returns the firmware version.
+ \param hHal - The handle returned by macOpen.
+ \param version - Points to the FwVersionInfo structure.
+ \return VOS_STATUS
+ VOS_STATUS_E_INVAL - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_GetFwVersion (tHalHandle hHal,FwVersionInfo *pVersion)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ if( pVersion != NULL ) {
+ vos_mem_copy((v_VOID_t*)pVersion,(v_VOID_t*)&pMac->hal.FwParam.fwVersion, sizeof(FwVersionInfo));
+ }
+ else {
+ status = VOS_STATUS_E_INVAL;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+/* ---------------------------------------------------------------------------
+ \fn sme_GetWcnssWlanCompiledVersion
+ \brief This API returns the version of the WCNSS WLAN API with
+ which the HOST driver was built
+ \param hHal - The handle returned by macOpen.
+ \param pVersion - Points to the Version structure to be filled
+ \return VOS_STATUS
+ VOS_STATUS_E_INVAL - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_GetWcnssWlanCompiledVersion(tHalHandle hHal,
+ tSirVersionType *pVersion)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL);
+
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ if( pVersion != NULL )
+ {
+ status = WDA_GetWcnssWlanCompiledVersion(vosContext, pVersion);
+ }
+ else
+ {
+ status = VOS_STATUS_E_INVAL;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetWcnssWlanReportedVersion
+ \brief This API returns the version of the WCNSS WLAN API with
+ which the WCNSS driver reports it was built
+ \param hHal - The handle returned by macOpen.
+ \param pVersion - Points to the Version structure to be filled
+ \return VOS_STATUS
+ VOS_STATUS_E_INVAL - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_GetWcnssWlanReportedVersion(tHalHandle hHal,
+ tSirVersionType *pVersion)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL);
+
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ if( pVersion != NULL )
+ {
+ status = WDA_GetWcnssWlanReportedVersion(vosContext, pVersion);
+ }
+ else
+ {
+ status = VOS_STATUS_E_INVAL;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetWcnssSoftwareVersion
+ \brief This API returns the version string of the WCNSS driver
+ \param hHal - The handle returned by macOpen.
+ \param pVersion - Points to the Version string buffer to be filled
+ \param versionBufferSize - THe size of the Version string buffer
+ \return VOS_STATUS
+ VOS_STATUS_E_INVAL - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_GetWcnssSoftwareVersion(tHalHandle hHal,
+ tANI_U8 *pVersion,
+ tANI_U32 versionBufferSize)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL);
+
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ if( pVersion != NULL )
+ {
+ status = WDA_GetWcnssSoftwareVersion(vosContext, pVersion,
+ versionBufferSize);
+ }
+ else
+ {
+ status = VOS_STATUS_E_INVAL;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetWcnssHardwareVersion
+ \brief This API returns the version string of the WCNSS hardware
+ \param hHal - The handle returned by macOpen.
+ \param pVersion - Points to the Version string buffer to be filled
+ \param versionBufferSize - THe size of the Version string buffer
+ \return VOS_STATUS
+ VOS_STATUS_E_INVAL - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+VOS_STATUS sme_GetWcnssHardwareVersion(tHalHandle hHal,
+ tANI_U8 *pVersion,
+ tANI_U32 versionBufferSize)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL);
+
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ if( pVersion != NULL )
+ {
+ status = WDA_GetWcnssHardwareVersion(vosContext, pVersion,
+ versionBufferSize);
+ }
+ else
+ {
+ status = VOS_STATUS_E_INVAL;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+#endif
+
+#ifdef FEATURE_WLAN_WAPI
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamSetBKIDCache
+ \brief The SME API exposed to HDD to allow HDD to provde SME the BKID
+ candidate list.
+ \param hHal - Handle to the HAL. The HAL handle is returned by the HAL after
+ it is opened (by calling halOpen).
+ \param pBKIDCache - caller allocated buffer point to an array of tBkidCacheInfo
+ \param numItems - a variable that has the number of tBkidCacheInfo allocated
+ when retruning, this is the number of items put into pBKIDCache
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough and pNumItems has the number of tBkidCacheInfo.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamSetBKIDCache( tHalHandle hHal, tANI_U32 sessionId, tBkidCacheInfo *pBKIDCache,
+ tANI_U32 numItems )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrRoamSetBKIDCache( pMac, sessionId, pBKIDCache, numItems );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetBKIDCache
+ \brief The SME API exposed to HDD to allow HDD to request SME to return its
+ BKID cache.
+ \param hHal - Handle to the HAL. The HAL handle is returned by the HAL after
+ it is opened (by calling halOpen).
+ \param pNum - caller allocated memory that has the space of the number of
+ tBkidCacheInfo as input. Upon returned, *pNum has the needed number of entries
+ in SME cache.
+ \param pBkidCache - Caller allocated memory that contains BKID cache, if any,
+ upon return
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough.
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_RoamGetBKIDCache(tHalHandle hHal, tANI_U32 *pNum,
+ tBkidCacheInfo *pBkidCache)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ smsLog(pMac, LOGE, FL(" !!!!!!!!!!!!!!!!!!SessionId is hardcoded\n"));
+ status = csrRoamGetBKIDCache( pMac, 0, pNum, pBkidCache );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RoamGetNumBKIDCache
+ \brief The SME API exposed to HDD to allow HDD to request SME to return the
+ number of BKID cache entries.
+ \param hHal - Handle to the HAL. The HAL handle is returned by the HAL after
+ it is opened (by calling halOpen).
+ \return tANI_U32 - the number of BKID cache entries.
+ ---------------------------------------------------------------------------*/
+tANI_U32 sme_RoamGetNumBKIDCache(tHalHandle hHal, tANI_U32 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U32 numBkidCache = 0;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ numBkidCache = csrRoamGetNumBKIDCache( pMac, sessionId );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (numBkidCache);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ScanGetBKIDCandidateList
+ \brief a wrapper function to return the BKID candidate list
+ \param pBkidList - caller allocated buffer point to an array of
+ tBkidCandidateInfo
+ \param pNumItems - pointer to a variable that has the number of
+ tBkidCandidateInfo allocated when retruning, this is
+ either the number needed or number of items put into
+ pPmkidList
+ \return eHalStatus - when fail, it usually means the buffer allocated is not
+ big enough and pNumItems
+ has the number of tBkidCandidateInfo.
+ \Note: pNumItems is a number of tBkidCandidateInfo,
+ not sizeof(tBkidCandidateInfo) * something
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_ScanGetBKIDCandidateList(tHalHandle hHal, tANI_U32 sessionId,
+ tBkidCandidateInfo *pBkidList,
+ tANI_U32 *pNumItems )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrScanGetBKIDCandidateList( pMac, sessionId, pBkidList, pNumItems );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_OpenSession() - Open a session for scan/roam operation.
+
+ This is a synchronous API.
+
+
+ \param hHal - The handle returned by macOpen.
+ \param callback - A pointer to the function caller specifies for roam/connect status indication
+ \param pContext - The context passed with callback
+ \param pSelfMacAddr - Caller allocated memory filled with self MAC address (6 bytes)
+ \param pbSessionId - pointer to a caller allocated buffer for returned session ID
+
+ \return eHAL_STATUS_SUCCESS - session is opened. sessionId returned.
+
+ Other status means SME is failed to open the session.
+ eHAL_STATUS_RESOURCES - no more session available.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, void *pContext,
+ tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId)
+{
+ eHalStatus status;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if( NULL == pbSessionId )
+ {
+ status = eHAL_STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrRoamOpenSession( pMac, callback, pContext, pSelfMacAddr, pbSessionId );
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ }
+
+ return ( status );
+}
+
+
+/*--------------------------------------------------------------------------
+
+ \brief sme_CloseSession() - Open a session for scan/roam operation.
+
+ This is a synchronous API.
+
+
+ \param hHal - The handle returned by macOpen.
+
+ \param sessionId - A previous opened session's ID.
+
+ \return eHAL_STATUS_SUCCESS - session is closed.
+
+ Other status means SME is failed to open the session.
+ eHAL_STATUS_INVALID_PARAMETER - session is not opened.
+ \sa
+
+ --------------------------------------------------------------------------*/
+eHalStatus sme_CloseSession(tHalHandle hHal, tANI_U8 sessionId,
+ csrRoamSessionCloseCallback callback, void *pContext)
+{
+ eHalStatus status;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrRoamCloseSession( pMac, sessionId, FALSE,
+ callback, pContext );
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return ( status );
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RoamUpdateAPWPSIE
+
+ \brief To update AP's WPS IE. This function should be called after SME AP session is created
+ This is an asynchronous API.
+
+ \param pAPWPSIES - pointer to a caller allocated object of tSirAPWPSIEs
+
+ \return eHalStatus – SUCCESS –
+
+ FAILURE or RESOURCES – The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamUpdateAPWPSIE(tHalHandle hHal, tANI_U8 sessionId, tSirAPWPSIEs *pAPWPSIES)
+{
+
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+
+ status = csrRoamUpdateAPWPSIE( pMac, sessionId, pAPWPSIES );
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RoamUpdateAPWPARSNIEs
+
+ \brief To update AP's WPA/RSN IEs. This function should be called after SME AP session is created
+ This is an asynchronous API.
+
+ \param pAPSirRSNie - pointer to a caller allocated object of tSirRSNie with WPS/RSN IEs
+
+ \return eHalStatus – SUCCESS –
+
+ FAILURE or RESOURCES – The API finished and failed.
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RoamUpdateAPWPARSNIEs(tHalHandle hHal, tANI_U8 sessionId, tSirRSNie * pAPSirRSNie)
+{
+
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+
+ status = csrRoamUpdateWPARSNIEs( pMac, sessionId, pAPSirRSNie);
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+#endif
+
+
+/*-------------------------------------------------------------------------------*
+
+ \fn sme_sendBTAmpEvent
+
+ \brief to receive the coex priorty request from BT-AMP PAL
+ and send the BT_AMP link state to HAL
+
+ \param btAmpEvent - btAmpEvent
+
+ \return eHalStatus: SUCESS : BTAmp event successfully sent to HAL
+
+ FAILURE: API failed
+
+-------------------------------------------------------------------------------*/
+
+eHalStatus sme_sendBTAmpEvent(tHalHandle hHal, tSmeBtAmpEvent btAmpEvent)
+{
+ vos_msg_t msg;
+ tpSmeBtAmpEvent ptrSmeBtAmpEvent = NULL;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+
+ ptrSmeBtAmpEvent = vos_mem_malloc(sizeof(tpSmeBtAmpEvent));
+ if (NULL == ptrSmeBtAmpEvent)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "Not able to allocate memory for BTAmp event", __FUNCTION__);
+ return status;
+ }
+
+ vos_mem_copy(ptrSmeBtAmpEvent, (void*)&btAmpEvent, sizeof(tSmeBtAmpEvent));
+ msg.type = WDA_SIGNAL_BTAMP_EVENT;
+ msg.reserved = 0;
+ msg.bodyptr = ptrSmeBtAmpEvent;
+
+ //status = halFW_SendBTAmpEventMesg(pMac, event);
+
+ if(VOS_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 SIR_HAL_SIGNAL_BTAMP_EVENT message to HAL", __FUNCTION__);
+ vos_mem_free(ptrSmeBtAmpEvent);
+ return status;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetHostOffload
+ \brief API to set the host offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the offload request.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+#ifdef WLAN_NS_OFFLOAD
+ if(SIR_IPV6_NS_OFFLOAD == pRequest->offloadType)
+ {
+ status = pmcSetNSOffload( hHal, pRequest );
+ }
+ else
+#endif //WLAN_NS_OFFLOAD
+ {
+ status = pmcSetHostOffload (hHal, pRequest);
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+#ifdef WLAN_FEATURE_GTK_OFFLOAD
+/* ---------------------------------------------------------------------------
+ \fn sme_SetGTKOffload
+ \brief API to set GTK offload information.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the GTK offload request.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pRequest)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ status = pmcSetGTKOffload( hHal, pRequest );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetGTKOffload
+ \brief API to get GTK offload information.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the GTK offload response.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_GetGTKOffload (tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, void *callbackContext )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ pmcGetGTKOffload(hHal, callbackRoutine, callbackContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+#endif // WLAN_FEATURE_GTK_OFFLOAD
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetKeepAlive
+ \brief API to set the Keep Alive feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the Keep Alive request.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
+ "setting Keep alive in SME TP %d", __FUNCTION__,pRequest->timePeriod);
+
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ status = pmcSetKeepAlive (hHal, pRequest);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+/* ---------------------------------------------------------------------------
+ \fn sme_SetPreferredNetworkList
+ \brief API to set the Preferred Network List Offload feature.
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - Pointer to the offload request.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetPreferredNetworkList (tHalHandle hHal, tpSirPNOScanReq pRequest, tANI_U8 sessionId, void (*callbackRoutine) (void *callbackContext, tSirPrefNetworkFoundInd *pPrefNetworkFoundInd), void *callbackContext )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ pmcSetPreferredNetworkList(hHal, pRequest, sessionId, callbackRoutine, callbackContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+eHalStatus sme_SetRSSIFilter(tHalHandle hHal, v_U8_t rssiThreshold)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ pmcSetRssiFilter(hHal, rssiThreshold);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+#endif // FEATURE_WLAN_SCAN_PNO
+
+eHalStatus sme_SetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ pmcSetPowerParams(hHal, pwParams);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_AbortMacScan
+ \brief API to cancel MAC scan.
+ \param hHal - The handle returned by macOpen.
+ \return VOS_STATUS
+ VOS_STATUS_E_FAILURE - failure
+ VOS_STATUS_SUCCESS success
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_AbortMacScan(tHalHandle hHal)
+{
+ eHalStatus status;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrScanAbortMacScan(pMac);
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return ( status );
+}
+
+/* ----------------------------------------------------------------------------
+ \fn sme_GetOperationChannel
+ \brief API to get current channel on which STA is parked
+ this function gives channel information only of infra station or IBSS station
+ \param hHal and poiter to memory location
+ \returns eHAL_STATUS_SUCCESS
+ eHAL_STATUS_FAILURE
+-------------------------------------------------------------------------------*/
+eHalStatus sme_GetOperationChannel(tHalHandle hHal, tANI_U32 *pChannel)
+{
+ tANI_U32 sessionId;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tCsrRoamSession *pSession;
+
+ for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX ; sessionId++)
+ {
+ if (CSR_IS_SESSION_VALID( pMac, sessionId ))
+ {
+ pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ if(( pSession->connectedProfile.BSSType == eCSR_BSS_TYPE_INFRASTRUCTURE ) ||
+ ( pSession->connectedProfile.BSSType == eCSR_BSS_TYPE_IBSS ) ||
+ ( pSession->connectedProfile.BSSType == eCSR_BSS_TYPE_START_IBSS ))
+ {
+ *pChannel =pSession->connectedProfile.operationChannel;
+ return eHAL_STATUS_SUCCESS;
+ }
+ }
+ }
+ return eHAL_STATUS_FAILURE;
+}// sme_GetOperationChannel ends here
+
+#ifdef WLAN_FEATURE_P2P
+/* ---------------------------------------------------------------------------
+
+ \fn sme_RegisterMgtFrame
+
+ \brief To register managment frame of specified type and subtype.
+ \param frameType - type of the frame that needs to be passed to HDD.
+ \param matchData - data which needs to be matched before passing frame
+ to HDD.
+ \param matchDataLen - Length of matched data.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_RegisterMgmtFrame(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U16 frameType, tANI_U8* matchData, tANI_U16 matchLen)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ tSirRegisterMgmtFrame *pMsg;
+ tANI_U16 len;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ if( !pSession->sessionActive )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s Invalid Sessionid", __FUNCTION__);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return eHAL_STATUS_FAILURE;
+ }
+
+ len = sizeof(tSirRegisterMgmtFrame) + matchLen;
+
+ status = palAllocateMemory(pMac->hHdd, (void**)&pMsg, len );
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pMsg, len);
+ pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ;
+ pMsg->length = len;
+ pMsg->sessionId = sessionId;
+ pMsg->registerFrame = VOS_TRUE;
+ pMsg->frameType = frameType;
+ pMsg->matchLen = matchLen;
+ palCopyMemory( pMac, pMsg->matchData, matchData, matchLen);
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return status;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_DeregisterMgtFrame
+
+ \brief To De-register managment frame of specified type and subtype.
+ \param frameType - type of the frame that needs to be passed to HDD.
+ \param matchData - data which needs to be matched before passing frame
+ to HDD.
+ \param matchDataLen - Length of matched data.
+ \return eHalStatus
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_DeregisterMgmtFrame(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U16 frameType, tANI_U8* matchData, tANI_U16 matchLen)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ tSirRegisterMgmtFrame *pMsg;
+ tANI_U16 len;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ if( !pSession->sessionActive )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s Invalid Sessionid", __FUNCTION__);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return eHAL_STATUS_FAILURE;
+ }
+
+ len = sizeof(tSirRegisterMgmtFrame) + matchLen;
+
+ status = palAllocateMemory(pMac->hHdd, (void**)&pMsg, len );
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pMsg, len);
+ pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ;
+ pMsg->length = len;
+ pMsg->registerFrame = VOS_FALSE;
+ pMsg->frameType = frameType;
+ pMsg->matchLen = matchLen;
+ palCopyMemory( pMac, pMsg->matchData, matchData, matchLen);
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return status;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_RemainOnChannel
+ \brief API to request remain on channel for 'x' duration. used in p2p in listen state
+ \param hHal - The handle returned by macOpen.
+ \param pRequest - channel
+ \param duration - duration in ms
+ \param callback - HDD registered callback to process reaminOnChannelRsp
+ \param context - HDD Callback param
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+
+eHalStatus sme_RemainOnChannel(tHalHandle hHal, tANI_U8 sessionId,
+ tANI_U8 channel, tANI_U32 duration,
+ remainOnChanCallback callback,
+ void *pContext)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ status = p2pRemainOnChannel (hHal, sessionId, channel, duration, callback, pContext
+#ifdef WLAN_FEATURE_P2P_INTERNAL
+ , eP2PRemainOnChnReasonUnknown
+#endif
+ );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return(status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_ReportProbeReq
+ \brief API to enable/disable forwarding of probeReq to apps in p2p.
+ \param hHal - The handle returned by macOpen.
+ \param falg: to set the Probe request forarding to wpa_supplicant in listen state in p2p
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+
+#ifndef WLAN_FEATURE_CONCURRENT_P2P
+eHalStatus sme_ReportProbeReq(tHalHandle hHal, tANI_U8 flag)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ do
+ {
+ //acquire the lock for the sme object
+ status = sme_AcquireGlobalLock(&pMac->sme);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ /* call set in context */
+ pMac->p2pContext.probeReqForwarding = flag;
+ //release the lock for the sme object
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ } while(0);
+
+ smsLog(pMac, LOGW, "exiting function %s\n", __FUNCTION__);
+
+ return(status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_updateP2pIe
+ \brief API to set the P2p Ie in p2p context
+ \param hHal - The handle returned by macOpen.
+ \param p2pIe - Ptr to p2pIe from HDD.
+ \param p2pIeLength: length of p2pIe
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+
+eHalStatus sme_updateP2pIe(tHalHandle hHal, void *p2pIe, tANI_U32 p2pIeLength)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ //acquire the lock for the sme object
+ status = sme_AcquireGlobalLock(&pMac->sme);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ if(NULL != pMac->p2pContext.probeRspIe){
+ vos_mem_free(pMac->p2pContext.probeRspIe);
+ pMac->p2pContext.probeRspIeLength = 0;
+ }
+
+ pMac->p2pContext.probeRspIe = vos_mem_malloc(p2pIeLength);
+ if (NULL == pMac->p2pContext.probeRspIe)
+ {
+ smsLog(pMac, LOGE, "%s: Unable to allocate P2P IE", __FUNCTION__);
+ pMac->p2pContext.probeRspIeLength = 0;
+ status = eHAL_STATUS_FAILURE;
+ }
+ else
+ {
+ pMac->p2pContext.probeRspIeLength = p2pIeLength;
+
+ sirDumpBuf( pMac, SIR_LIM_MODULE_ID, LOG2,
+ pMac->p2pContext.probeRspIe,
+ pMac->p2pContext.probeRspIeLength );
+ vos_mem_copy((tANI_U8 *)pMac->p2pContext.probeRspIe, p2pIe,
+ p2pIeLength);
+ }
+
+ //release the lock for the sme object
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ smsLog(pMac, LOG2, "exiting function %s\n", __FUNCTION__);
+
+ return(status);
+}
+#endif
+
+/* ---------------------------------------------------------------------------
+ \fn sme_sendAction
+ \brief API to send action frame from supplicant.
+ \param hHal - The handle returned by macOpen.
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+
+eHalStatus sme_sendAction(tHalHandle hHal, tANI_U8 sessionId,
+ const tANI_U8 *pBuf, tANI_U32 len)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ //acquire the lock for the sme object
+ status = sme_AcquireGlobalLock(&pMac->sme);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ p2pSendAction(hHal, sessionId, pBuf, len);
+ //release the lock for the sme object
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ smsLog(pMac, LOGW, "exiting function %s\n", __FUNCTION__);
+
+ return(status);
+}
+
+eHalStatus sme_CancelRemainOnChannel(tHalHandle hHal, tANI_U8 sessionId )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ status = p2pCancelRemainOnChannel (hHal, sessionId);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return(status);
+}
+
+//Power Save Related
+eHalStatus sme_p2pSetPs(tHalHandle hHal, tP2pPsConfig * data)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ status = p2pSetPs (hHal, data);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return(status);
+}
+
+#endif
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_ConfigureRxpFilter
+
+ \brief
+ SME will pass this request to lower mac to set/reset the filter on RXP for
+ multicast & broadcast traffic.
+
+ \param
+
+ hHal - The handle returned by macOpen.
+
+ filterMask- Currently the API takes a 1 or 0 (set or reset) as filter.
+ Basically to enable/disable the filter (to filter "all" mcbc traffic) based
+ on this param. In future we can use this as a mask to set various types of
+ filters as suggested below:
+ FILTER_ALL_MULTICAST:
+ FILTER_ALL_BROADCAST:
+ FILTER_ALL_MULTICAST_BROADCAST:
+
+
+ \return eHalStatus
+
+
+--------------------------------------------------------------------------- */
+eHalStatus sme_ConfigureRxpFilter( tHalHandle hHal,
+ tpSirWlanSetRxpFilters wlanRxpFilterParam)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ vos_msg_t vosMessage;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ /* serialize the req through MC thread */
+ vosMessage.bodyptr = wlanRxpFilterParam;
+ vosMessage.type = WDA_CFG_RXP_FILTER_REQ;
+ vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage );
+ if ( !VOS_IS_STATUS_SUCCESS(vosStatus) )
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return(status);
+}
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+/* ---------------------------------------------------------------------------
+
+ \fn sme_ConfigureSuspendInd
+
+ \brief
+ SME will pass this request to lower mac to Indicate that the wlan needs to
+ be suspended
+
+ \param
+
+ hHal - The handle returned by macOpen.
+
+ wlanSuspendParam- Depicts the wlan suspend params
+
+
+ \return eHalStatus
+
+
+--------------------------------------------------------------------------- */
+eHalStatus sme_ConfigureSuspendInd( tHalHandle hHal,
+ tpSirWlanSuspendParam wlanSuspendParam)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ vos_msg_t vosMessage;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ /* serialize the req through MC thread */
+ vosMessage.bodyptr = wlanSuspendParam;
+ vosMessage.type = WDA_WLAN_SUSPEND_IND;
+ vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage );
+ if ( !VOS_IS_STATUS_SUCCESS(vosStatus) )
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return(status);
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_ConfigureResumeReq
+
+ \brief
+ SME will pass this request to lower mac to Indicate that the wlan needs to
+ be Resumed
+
+ \param
+
+ hHal - The handle returned by macOpen.
+
+ wlanResumeParam- Depicts the wlan resume params
+
+
+ \return eHalStatus
+
+
+--------------------------------------------------------------------------- */
+eHalStatus sme_ConfigureResumeReq( tHalHandle hHal,
+ tpSirWlanResumeParam wlanResumeParam)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ vos_msg_t vosMessage;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ /* serialize the req through MC thread */
+ vosMessage.bodyptr = wlanResumeParam;
+ vosMessage.type = WDA_WLAN_RESUME_REQ;
+ vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage );
+ if ( !VOS_IS_STATUS_SUCCESS(vosStatus) )
+ {
+ status = eHAL_STATUS_FAILURE;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return(status);
+}
+
+#endif
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetInfraSessionId
+
+ \brief To get the session ID for infra session, if connected
+ This is a synchronous API.
+
+ \param hHal - The handle returned by macOpen.
+
+ \return sessionid, -1 if infra session is not connected
+
+ -------------------------------------------------------------------------------*/
+tANI_S8 sme_GetInfraSessionId(tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tANI_S8 sessionid = -1;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+
+ sessionid = csrGetInfraSessionId( pMac);
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (sessionid);
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_GetInfraOperationChannel
+
+ \brief To get the operating channel for infra session, if connected
+ This is a synchronous API.
+
+ \param hHal - The handle returned by macOpen.
+ \param sessionId - the sessionId returned by sme_OpenSession.
+
+ \return operating channel, 0 if infra session is not connected
+
+ -------------------------------------------------------------------------------*/
+tANI_U8 sme_GetInfraOperationChannel( tHalHandle hHal, tANI_U8 sessionId)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U8 channel = 0;
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+
+ channel = csrGetInfraOperationChannel( pMac, sessionId);
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (channel);
+}
+
+//This routine will return poerating channel on which other BSS is operating to be used for concurrency mode.
+//If other BSS is not up or not connected it will return 0
+tANI_U8 sme_GetConcurrentOperationChannel( tHalHandle hHal )
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ tANI_U8 channel = 0;
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+
+ channel = csrGetConcurrentOperationChannel( pMac );
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, "%s: "
+ " Other Concurrent Channel = %d", __FUNCTION__,channel);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (channel);
+}
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+/******************************************************************************
+*
+* Name: sme_PreferredNetworkFoundInd
+*
+* Description:
+* Invoke Preferred Network Found Indication
+*
+* Parameters:
+* hHal - HAL handle for device
+* pMsg - found network description
+*
+* Returns: eHalStatus
+*
+******************************************************************************/
+eHalStatus sme_PreferredNetworkFoundInd (tHalHandle hHal, void* pMsg)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirPrefNetworkFoundInd *pPrefNetworkFoundInd = (tSirPrefNetworkFoundInd *)pMsg;
+
+ if (NULL == pMsg)
+ {
+ smsLog(pMac, LOGE, "in %s msg ptr is NULL\n", __FUNCTION__);
+ status = eHAL_STATUS_FAILURE;
+ }
+ else
+ {
+ if (pPrefNetworkFoundInd->ssId.length > 0)
+ {
+ smsLog(pMac, LOG1, "Preferred Network Found Indication in %s(), SSID=%s",
+ __FUNCTION__, pPrefNetworkFoundInd->ssId.ssId);
+
+
+ /* Call Preferred Netowrk Found Indication callback routine. */
+ if (pMac->pmc.prefNetwFoundCB != NULL)
+ {
+ pMac->pmc.prefNetwFoundCB(pMac->pmc.preferredNetworkFoundIndCallbackContext, pPrefNetworkFoundInd);
+ }
+
+ }
+ else
+ {
+ smsLog(pMac, LOGE, "%s: callback failed - SSID is NULL\n", __FUNCTION__);
+ status = eHAL_STATUS_FAILURE;
+ }
+ }
+
+
+ return(status);
+}
+
+#endif // FEATURE_WLAN_SCAN_PNO
+
+
+eHalStatus sme_GetCfgValidChannels(tHalHandle hHal, tANI_U8 *aValidChannels, tANI_U32 *len)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrGetCfgValidChannels(pMac, aValidChannels, len);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_SetTxPerTracking
+
+ \brief Set Tx PER tracking configuration parameters
+
+ \param hHal - The handle returned by macOpen.
+ \param pTxPerTrackingConf - Tx PER configuration parameters
+
+ \return eHalStatus
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_SetTxPerTracking(tHalHandle hHal,
+ void (*pCallbackfn) (void *pCallbackContext),
+ void *pCallbackContext,
+ tpSirTxPerTrackingParam pTxPerTrackingParam)
+{
+ vos_msg_t msg;
+ tpSirTxPerTrackingParam pTxPerTrackingParamReq = NULL;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) )
+ {
+ pMac->sme.pTxPerHitCallback = pCallbackfn;
+ pMac->sme.pTxPerHitCbContext = pCallbackContext;
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ // free this memory in failure case or WDA request callback function
+ pTxPerTrackingParamReq = vos_mem_malloc(sizeof(tSirTxPerTrackingParam));
+ if (NULL == pTxPerTrackingParamReq)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for tSirTxPerTrackingParam", __FUNCTION__);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ vos_mem_copy(pTxPerTrackingParamReq, (void*)pTxPerTrackingParam, sizeof(tSirTxPerTrackingParam));
+ msg.type = WDA_SET_TX_PER_TRACKING_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pTxPerTrackingParamReq;
+
+ if(VOS_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_SET_TX_PER_TRACKING_REQ message to WDA", __FUNCTION__);
+ vos_mem_free(pTxPerTrackingParamReq);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_HandleChangeCountryCode
+
+ \brief Change Country code, Reg Domain and channel list
+
+ \details Country Code Priority
+ 0 = 11D > Configured Country > NV
+ 1 = Configured Country > 11D > NV
+ If Supplicant country code is priority than 11d is disabled.
+ If 11D is enabled, we update the country code after every scan.
+ Hence when Supplicant country code is priority, we don't need 11D info.
+ Country code from Supplicant is set as current courtry code.
+ User can send reset command XX (instead of country code) to reset the
+ country code to default values which is read from NV.
+ In case of reset, 11D is enabled and default NV code is Set as current country code
+ If 11D is priority,
+ Than Supplicant country code code is set to default code. But 11D code is set as current country code
+
+ \param pMac - The handle returned by macOpen.
+ \param pMsgBuf - MSG Buffer
+
+ \return eHalStatus
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_HandleChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tAniChangeCountryCodeReq *pMsg;
+ v_REGDOMAIN_t domainIdIoctl;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ static uNvTables nvTables;
+ pMsg = (tAniChangeCountryCodeReq *)pMsgBuf;
+
+
+ /* if the reset Supplicant country code command is triggered, enable 11D, reset the NV country code and return */
+ if( VOS_TRUE == vos_mem_compare(pMsg->countryCode, SME_INVALID_COUNTRY_CODE, 2) )
+ {
+ pMac->roam.configParam.Is11dSupportEnabled = pMac->roam.configParam.Is11dSupportEnabledOriginal;
+
+ vosStatus = vos_nv_readDefaultCountryTable( &nvTables );
+
+ /* read the country code from NV and use it */
+ if ( VOS_IS_STATUS_SUCCESS(vosStatus) )
+ {
+ palCopyMemory( pMac->hHdd, pMsg->countryCode , nvTables.defaultCountryTable.countryCode, WNI_CFG_COUNTRY_CODE_LEN );
+ }
+ else
+ {
+ status = eHAL_STATUS_FAILURE;
+ return status;
+ }
+ }
+ else
+ {
+ /* if Supplicant country code has priority, disable 11d */
+ if(pMac->roam.configParam.fSupplicantCountryCodeHasPriority)
+ {
+ pMac->roam.configParam.Is11dSupportEnabled = eANI_BOOLEAN_FALSE;
+ }
+ }
+
+ /* WEXT set country code means
+ * 11D should be supported?
+ * 11D Channel should be enforced?
+ * 11D Country code should be matched?
+ * 11D Reg Domian should be matched?
+ * Country string changed */
+ if(pMac->roam.configParam.Is11dSupportEnabled &&
+ pMac->roam.configParam.fEnforce11dChannels &&
+ pMac->roam.configParam.fEnforceCountryCodeMatch &&
+ pMac->roam.configParam.fEnforceDefaultDomain &&
+ !csrSave11dCountryString(pMac, pMsg->countryCode, eANI_BOOLEAN_TRUE))
+ {
+ /* All 11D related options are already enabled
+ * Country string is not changed
+ * Do not need do anything for country code change request */
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ /* Set Current Country code and Current Regulatory domain */
+ status = csrSetCountryCode(pMac, pMsg->countryCode, NULL);
+ if(eHAL_STATUS_SUCCESS != status)
+ {
+ /* Supplicant country code failed. So give 11D priority */
+ pMac->roam.configParam.Is11dSupportEnabled = pMac->roam.configParam.Is11dSupportEnabledOriginal;
+ smsLog(pMac, LOGE, "Set Country Code Fail %d", status);
+ return status;
+ }
+
+ /* purge current scan results
+ if i don't do this than I still get old ap's (of different country code) as available (even if they are powered off).
+ Looks like a bug in current scan sequence.
+ */
+ csrScanFlushResult(pMac);
+
+ /* overwrite the defualt country code */
+ palCopyMemory(pMac->hHdd, pMac->scan.countryCodeDefault, pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
+
+ /* Get Domain ID from country code */
+ status = csrGetRegulatoryDomainForCountry( pMac, pMac->scan.countryCodeCurrent,(v_REGDOMAIN_t *) &domainIdIoctl );
+ if ( status != eHAL_STATUS_SUCCESS )
+ {
+ smsLog( pMac, LOGE, FL(" fail to get regId %d\n"), domainIdIoctl );
+ return status;
+ }
+
+ status = WDA_SetRegDomain(pMac, domainIdIoctl);
+
+ if ( status != eHAL_STATUS_SUCCESS )
+ {
+ smsLog( pMac, LOGE, FL(" fail to set regId %d\n"), domainIdIoctl );
+ return status;
+ }
+
+ /* set to default domain ID */
+ pMac->scan.domainIdDefault = pMac->scan.domainIdCurrent;
+
+ /* get the channels based on new cc */
+ status = csrInitGetChannels( pMac );
+
+ if ( status != eHAL_STATUS_SUCCESS )
+ {
+ smsLog( pMac, LOGE, FL(" fail to get Channels \n"));
+ return status;
+ }
+
+ /* reset info based on new cc, and we are done */
+ csrResetCountryInformation(pMac, eANI_BOOLEAN_TRUE);
+ if( pMsg->changeCCCallback )
+ {
+ ((tSmeChangeCountryCallback)(pMsg->changeCCCallback))((void *)pMsg->pDevContext);
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+eHalStatus sme_8023MulticastList (tHalHandle hHal, tpSirRcvFltMcAddrList pMulticastAddrs)
+{
+ tpSirRcvFltMcAddrList pRequestBuf;
+ vos_msg_t msg;
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: "
+ "ulMulticastAddrCnt=%d, multicastAddr[0]=%d", __FUNCTION__,
+ pMulticastAddrs->ulMulticastAddrCnt,
+ pMulticastAddrs->multicastAddr[0]);
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to "
+ "allocate memory for 8023 Multicast List request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ vos_mem_copy(pRequestBuf, pMulticastAddrs, sizeof(tSirRcvFltMcAddrList));
+
+ msg.type = WDA_8023_MULTICAST_LIST_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ if(VOS_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_8023_MULTICAST_LIST message to WDA", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+eHalStatus sme_ReceiveFilterSetFilter(tHalHandle hHal, tpSirRcvPktFilterCfgType pRcvPktFilterCfg)
+{
+ tpSirRcvPktFilterCfgType pRequestBuf;
+ v_SINT_t allocSize;
+ vos_msg_t msg;
+ /*tpAniSirGlobal pMac = PMAC_STRUCT(hHal);*/
+ v_U8_t idx=0;
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterType=%d, "
+ "filterId = %d", __FUNCTION__,
+ pRcvPktFilterCfg->filterType, pRcvPktFilterCfg->filterId);
+
+ allocSize = sizeof(tSirRcvPktFilterCfgType) +
+ ((pRcvPktFilterCfg->numFieldParams - 1) *
+ sizeof(tSirRcvPktFilterFieldParams));
+ pRequestBuf = vos_mem_malloc(allocSize);
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to "
+ "allocate memory for Receive Filter Set Filter request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ vos_mem_copy(pRequestBuf, pRcvPktFilterCfg, allocSize);
+
+ msg.type = WDA_RECEIVE_FILTER_SET_FILTER_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Pkt Flt Req : "
+ "FT %d FID %d ",
+ pRequestBuf->filterType, pRequestBuf->filterId);
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Pkt Flt Req : "
+ "params %d CT %d",
+ pRequestBuf->numFieldParams, pRequestBuf->coalesceTime);
+
+ for (idx=0; idx<pRequestBuf->numFieldParams; idx++)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "Proto %d Comp Flag %d \n",
+ pRequestBuf->paramsData[idx].protocolLayer,
+ pRequestBuf->paramsData[idx].cmpFlag);
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "Data Offset %d Data Len %d\n",
+ pRequestBuf->paramsData[idx].dataOffset,
+ pRequestBuf->paramsData[idx].dataLength);
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "CData: %d:%d:%d:%d:%d:%d\n",
+ pRequestBuf->paramsData[idx].compareData[0],
+ pRequestBuf->paramsData[idx].compareData[1],
+ pRequestBuf->paramsData[idx].compareData[2],
+ pRequestBuf->paramsData[idx].compareData[3],
+ pRequestBuf->paramsData[idx].compareData[4],
+ pRequestBuf->paramsData[idx].compareData[5]);
+
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ "MData: %d:%d:%d:%d:%d:%d\n",
+ pRequestBuf->paramsData[idx].dataMask[0],
+ pRequestBuf->paramsData[idx].dataMask[1],
+ pRequestBuf->paramsData[idx].dataMask[2],
+ pRequestBuf->paramsData[idx].dataMask[3],
+ pRequestBuf->paramsData[idx].dataMask[4],
+ pRequestBuf->paramsData[idx].dataMask[5]);
+
+ }
+
+ if(VOS_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_RECEIVE_FILTER_SET_FILTER message to WDA", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+eHalStatus sme_GetFilterMatchCount(tHalHandle hHal,
+ FilterMatchCountCallback callbackRoutine,
+ void *callbackContext )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status;
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "+%s", __FUNCTION__);
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme)))
+ {
+ pmcGetFilterMatchCount(hHal, callbackRoutine, callbackContext);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "-%s", __FUNCTION__);
+
+ return (status);
+}
+
+eHalStatus sme_ReceiveFilterClearFilter(tHalHandle hHal, tpSirRcvFltPktClearParam pRcvFltPktClearParam)
+{
+ tpSirRcvFltPktClearParam pRequestBuf;
+ vos_msg_t msg;
+
+ VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterId = %d", __FUNCTION__,
+ pRcvFltPktClearParam->filterId);
+
+ pRequestBuf = vos_mem_malloc(sizeof(tSirRcvFltPktClearParam));
+ if (NULL == pRequestBuf)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: Not able to allocate memory for Receive Filter "
+ "Clear Filter request", __FUNCTION__);
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ vos_mem_copy(pRequestBuf, pRcvFltPktClearParam, sizeof(tSirRcvFltPktClearParam));
+
+ msg.type = WDA_RECEIVE_FILTER_CLEAR_FILTER_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pRequestBuf;
+ if(VOS_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_RECEIVE_FILTER_CLEAR_FILTER message to WDA", __FUNCTION__);
+ vos_mem_free(pRequestBuf);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+#endif // WLAN_FEATURE_PACKET_FILTERING
+
+/* ---------------------------------------------------------------------------
+ \fn sme_PreChannelSwitchIndFullPowerCB
+ \brief call back function for the PMC full power request because of pre
+ channel switch.
+ \param callbackContext
+ \param status
+ ---------------------------------------------------------------------------*/
+void sme_PreChannelSwitchIndFullPowerCB(void *callbackContext,
+ eHalStatus status)
+{
+ tpAniSirGlobal pMac = (tpAniSirGlobal)callbackContext;
+ tSirMbMsg *pMsg;
+ tANI_U16 msgLen;
+
+ msgLen = (tANI_U16)(sizeof( tSirMbMsg ));
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, (void *)pMsg, msgLen);
+ pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_PRE_CHANNEL_SWITCH_FULL_POWER);
+ pMsg->msgLen = pal_cpu_to_be16(msgLen);
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+
+ return;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_HandlePreChannelSwitchInd
+ \brief Processes the indcation from PE for pre-channel switch.
+ \param hHal
+ \- The handle returned by macOpen. return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_HandlePreChannelSwitchInd(tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcRequestFullPower(hHal, sme_PreChannelSwitchIndFullPowerCB,
+ pMac, eSME_FULL_PWR_NEEDED_BY_CHANNEL_SWITCH);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_HandlePostChannelSwitchInd
+ \brief Processes the indcation from PE for post-channel switch.
+ \param hHal
+ \- The handle returned by macOpen. return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_HandlePostChannelSwitchInd(tHalHandle hHal)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = pmcRequestBmps(hHal, NULL, NULL);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (status);
+}
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_IsChannelValid
+
+ \brief To check if the channel is valid for currently established domain
+ This is a synchronous API.
+
+ \param hHal - The handle returned by macOpen.
+ \param channel - channel to verify
+
+ \return TRUE/FALSE, TRUE if channel is valid
+
+ -------------------------------------------------------------------------------*/
+tANI_BOOLEAN sme_IsChannelValid(tHalHandle hHal, tANI_U8 channel)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tANI_BOOLEAN valid = FALSE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+
+ valid = csrRoamIsChannelValid( pMac, channel);
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+
+ return (valid);
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_SetFreqBand
+ \brief Used to set frequency band.
+ \param hHal
+ \eBand band value to be configured
+ \- return eHalStatus
+ -------------------------------------------------------------------------*/
+eHalStatus sme_SetFreqBand(tHalHandle hHal, eCsrBand eBand)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ status = csrSetBand(hHal, eBand);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return status;
+}
+
+/* ---------------------------------------------------------------------------
+ \fn sme_GetFreqBand
+ \brief Used to get the current band settings.
+ \param hHal
+ \pBand pointer to hold band value
+ \- return eHalStatus
+ -------------------------------------------------------------------------*/
+eHalStatus sme_GetFreqBand(tHalHandle hHal, eCsrBand *pBand)
+{
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if ( HAL_STATUS_SUCCESS( status ) )
+ {
+ *pBand = csrGetCurrentBand( hHal );
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return status;
+}
+
+#ifdef WLAN_WAKEUP_EVENTS
+/******************************************************************************
+ \fn sme_WakeReasonIndCallback
+
+ \brief
+ a callback function called when SME received eWNI_SME_WAKE_REASON_IND event from WDA
+
+ \param hHal - HAL handle for device
+ \param pMsg - Message body passed from WDA; includes Wake Reason Indication parameter
+
+ \return eHalStatus
+******************************************************************************/
+eHalStatus sme_WakeReasonIndCallback (tHalHandle hHal, void* pMsg)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tSirWakeReasonInd *pWakeReasonInd = (tSirWakeReasonInd *)pMsg;
+
+ if (NULL == pMsg)
+ {
+ smsLog(pMac, LOGE, "in %s msg ptr is NULL\n", __FUNCTION__);
+ status = eHAL_STATUS_FAILURE;
+ }
+ else
+ {
+ smsLog(pMac, LOG2, "SME: entering sme_WakeReasonIndCallback\n");
+
+ /* Call Wake Reason Indication callback routine. */
+ if (pMac->pmc.wakeReasonIndCB != NULL)
+ pMac->pmc.wakeReasonIndCB(pMac->pmc.wakeReasonIndCBContext, pWakeReasonInd);
+
+ pMac->pmc.wakeReasonIndCB = NULL;
+ pMac->pmc.wakeReasonIndCBContext = NULL;
+
+ smsLog(pMac, LOG1, "Wake Reason Indication in %s(), reason=%d", __FUNCTION__, pWakeReasonInd->ulReason);
+ }
+
+ return(status);
+}
+#endif // WLAN_WAKEUP_EVENTS
+
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_SetMaxTxPower
+
+ \brief Set the Maximum Transmit Power dynamically. Note: this setting will
+ not persist over reboots.
+
+ \param hHal
+ \param pBssid BSSID to set the power cap for
+ \param pBssid pSelfMacAddress self MAC Address
+ \param pBssid power to set in dB
+ \- return eHalStatus
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_SetMaxTxPower(tHalHandle hHal, tSirMacAddr pBssid,
+ tSirMacAddr pSelfMacAddress, v_S7_t dB)
+{
+ vos_msg_t msg;
+ tpMaxTxPowerParams pMaxTxParams = NULL;
+
+ pMaxTxParams = vos_mem_malloc(sizeof(tMaxTxPowerParams));
+ if (NULL == pMaxTxParams)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for pMaxTxParams", __FUNCTION__);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ vos_mem_copy(pMaxTxParams->bssId, pBssid, SIR_MAC_ADDR_LENGTH);
+ vos_mem_copy(pMaxTxParams->selfStaMacAddr , pSelfMacAddress,
+ SIR_MAC_ADDR_LENGTH);
+ pMaxTxParams->power = dB;
+
+ msg.type = WDA_SET_MAX_TX_POWER_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pMaxTxParams;
+
+ if(VOS_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_SET_MAX_TX_POWER_REQ message to WDA", __FUNCTION__);
+ vos_mem_free(pMaxTxParams);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+#ifdef WLAN_SOFTAP_FEATURE
+/* ---------------------------------------------------------------------------
+
+ \fn sme_HideSSID
+
+ \brief hide/show SSID dynamically. Note: this setting will
+ not persist over reboots.
+
+ \param hHal
+ \param sessionId
+ \param ssidHidden 0 - Broadcast SSID, 1 - Disable broadcast SSID
+ \- return eHalStatus
+
+ -------------------------------------------------------------------------------*/
+eHalStatus sme_HideSSID(tHalHandle hHal, v_U8_t sessionId, v_U8_t ssidHidden)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ tANI_U16 len;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ tpSirUpdateParams pMsg;
+ tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
+
+ if( !pSession->sessionActive )
+ VOS_ASSERT(0);
+
+ /* Create the message and send to lim */
+ len = sizeof(tSirUpdateParams);
+ status = palAllocateMemory( pMac->hHdd, (void **)&pMsg, len );
+ if(HAL_STATUS_SUCCESS(status))
+ {
+ palZeroMemory(pMac->hHdd, pMsg, sizeof(tSirUpdateParams) );
+ pMsg->messageType = eWNI_SME_HIDE_SSID_REQ;
+ pMsg->length = len;
+ /* Data starts from here */
+ pMsg->sessionId = sessionId;
+ pMsg->ssidHidden = ssidHidden;
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return status;
+}
+#endif
+
+/* ---------------------------------------------------------------------------
+
+ \fn sme_SetTmLevel
+ \brief Set Thermal Mitigation Level to RIVA
+ \param hHal - The handle returned by macOpen.
+ \param newTMLevel - new Thermal Mitigation Level
+ \param tmMode - Thermal Mitigation handle mode, default 0
+ \return eHalStatus
+ ---------------------------------------------------------------------------*/
+eHalStatus sme_SetTmLevel(tHalHandle hHal, v_U16_t newTMLevel, v_U16_t tmMode)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ vos_msg_t vosMessage;
+ tAniSetTmLevelReq *setTmLevelReq = NULL;
+
+ if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) )
+ {
+ setTmLevelReq = (tAniSetTmLevelReq *)vos_mem_malloc(sizeof(tAniSetTmLevelReq));
+ if(NULL == setTmLevelReq)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: Not able to allocate memory for sme_SetTmLevel", __FUNCTION__);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ setTmLevelReq->tmMode = tmMode;
+ setTmLevelReq->newTmLevel = newTMLevel;
+
+ /* serialize the req through MC thread */
+ vosMessage.bodyptr = setTmLevelReq;
+ vosMessage.type = WDA_SET_TM_LEVEL_REQ;
+ vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage );
+ if ( !VOS_IS_STATUS_SUCCESS(vosStatus) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: Post Set TM Level MSG fail", __FUNCTION__);
+ vos_mem_free(setTmLevelReq);
+ status = eHAL_STATUS_FAILURE;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+ }
+ return(status);
+}
+
+/*---------------------------------------------------------------------------
+
+ \brief sme_featureCapsExchange() - SME interface to exchange capabilities between
+ Host and FW.
+
+ \param hHal - HAL handle for device
+
+ \return NONE
+
+---------------------------------------------------------------------------*/
+void sme_featureCapsExchange( tHalHandle hHal)
+{
+ v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL);
+ WDA_featureCapsExchange(vosContext);
+}
diff --git a/CORE/SME/src/sme_common/sme_FTApi.c b/CORE/SME/src/sme_common/sme_FTApi.c
new file mode 100644
index 0000000..ce76b7e
--- /dev/null
+++ b/CORE/SME/src/sme_common/sme_FTApi.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/**=========================================================================
+
+ \brief Definitions for SME FT APIs
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include <smsDebug.h>
+#include <csrInsideApi.h>
+#include <csrNeighborRoam.h>
+
+/*--------------------------------------------------------------------------
+ Initialize the FT context.
+ ------------------------------------------------------------------------*/
+void sme_FTOpen(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ pMac->ft.ftSmeContext.auth_ft_ies = NULL;
+ pMac->ft.ftSmeContext.auth_ft_ies_length = 0;
+
+ pMac->ft.ftSmeContext.reassoc_ft_ies = NULL;
+ pMac->ft.ftSmeContext.reassoc_ft_ies_length = 0;
+
+ status = palTimerAlloc(pMac->hHdd, &pMac->ft.ftSmeContext.preAuthReassocIntvlTimer,
+ sme_PreauthReassocIntvlTimerCallback, (void *)pMac);
+
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ smsLog(pMac, LOGE, FL("Preauth Reassoc interval Timer allocation failed"));
+ return;
+ }
+
+ pMac->ft.ftSmeContext.psavedFTPreAuthRsp = NULL;
+
+ pMac->ft.ftSmeContext.FTState = eFT_START_READY;
+}
+
+/*--------------------------------------------------------------------------
+ Cleanup the SME FT Global context.
+ ------------------------------------------------------------------------*/
+void sme_FTClose(tHalHandle hHal)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+
+ if (pMac->ft.ftSmeContext.auth_ft_ies != NULL)
+ {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, FL(" Freeing %p and setting to NULL\n"),
+ pMac->ft.ftSmeContext.auth_ft_ies);
+#endif
+ vos_mem_free(pMac->ft.ftSmeContext.auth_ft_ies);
+ pMac->ft.ftSmeContext.auth_ft_ies = NULL;
+ }
+ pMac->ft.ftSmeContext.auth_ft_ies_length = 0;
+
+ if (pMac->ft.ftSmeContext.reassoc_ft_ies != NULL)
+ {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, FL(" Freeing %p and setting to NULL\n"),
+ pMac->ft.ftSmeContext.reassoc_ft_ies);
+#endif
+ vos_mem_free(pMac->ft.ftSmeContext.reassoc_ft_ies);
+ pMac->ft.ftSmeContext.reassoc_ft_ies = NULL;
+ }
+ pMac->ft.ftSmeContext.reassoc_ft_ies_length = 0;
+
+ pMac->ft.ftSmeContext.FTState = eFT_START_READY;
+ vos_mem_zero(pMac->ft.ftSmeContext.preAuthbssId, ANI_MAC_ADDR_SIZE);
+
+ if (pMac->ft.ftSmeContext.psavedFTPreAuthRsp != NULL)
+ {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, FL("%s: Freeing %p and setting to NULL\n"),
+ pMac->ft.ftSmeContext.psavedFTPreAuthRsp);
+#endif
+ vos_mem_free(pMac->ft.ftSmeContext.psavedFTPreAuthRsp);
+ pMac->ft.ftSmeContext.psavedFTPreAuthRsp = NULL;
+ }
+
+ palTimerFree(pMac->hHdd, pMac->ft.ftSmeContext.preAuthReassocIntvlTimer);
+}
+
+
+/*--------------------------------------------------------------------------
+ Each time the supplicant sends down the FT IEs to the driver.
+ This function is called in SME. This fucntion packages and sends
+ the FT IEs to PE.
+ ------------------------------------------------------------------------*/
+void sme_SetFTIEs( tHalHandle hHal, tANI_U8 sessionId, tANI_U8 *ft_ies,
+ tANI_U16 ft_ies_length )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_FAILURE;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if (!( HAL_STATUS_SUCCESS( status ))) return;
+
+ if (ft_ies == NULL)
+ {
+ smsLog( pMac, LOGE, FL(" ft ies is NULL\n"));
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return;
+ }
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, "FT IEs Req is received in state %d\n",
+ pMac->ft.ftSmeContext.FTState);
+#endif
+
+ // Global Station FT State
+ switch(pMac->ft.ftSmeContext.FTState)
+ {
+ case eFT_START_READY:
+ case eFT_AUTH_REQ_READY:
+ if ((pMac->ft.ftSmeContext.auth_ft_ies) &&
+ (pMac->ft.ftSmeContext.auth_ft_ies_length))
+ {
+ // Free the one we received last from the supplicant
+ vos_mem_free(pMac->ft.ftSmeContext.auth_ft_ies);
+ pMac->ft.ftSmeContext.auth_ft_ies_length = 0;
+ }
+
+ // Save the FT IEs
+ pMac->ft.ftSmeContext.auth_ft_ies = vos_mem_malloc(ft_ies_length);
+ if(pMac->ft.ftSmeContext.auth_ft_ies == NULL)
+ {
+ smsLog( pMac, LOGE, FL("Memory allocation failed for "
+ "auth_ft_ies\n"));
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return;
+ }
+ pMac->ft.ftSmeContext.auth_ft_ies_length = ft_ies_length;
+ vos_mem_copy((tANI_U8 *)pMac->ft.ftSmeContext.auth_ft_ies, ft_ies,
+ ft_ies_length);
+
+ pMac->ft.ftSmeContext.FTState = eFT_AUTH_REQ_READY;
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, "ft_ies_length=%d\n", ft_ies_length);
+ /*
+ smsLog( pMac, LOGE, "%d: New Auth ft_ies_length=%02x%02x%02x\n",
+ current->pid, pMac->ft.ftSmeContext.auth_ft_ies[0],
+ pMac->ft.ftSmeContext.auth_ft_ies[1],
+ pMac->ft.ftSmeContext.auth_ft_ies[2]);
+ */
+#endif
+ break;
+
+ case eFT_AUTH_COMPLETE:
+ // We will need to re-start preauth. If we received FT IEs in
+ // eFT_PRE_AUTH_DONE state, it implies there was a rekey in
+ // our pre-auth state. Hence this implies we need Pre-auth again.
+
+ // OK now inform SME we have no pre-auth list.
+ // Delete the pre-auth node locally. Set your self back to restart pre-auth
+ // TBD
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE,
+ "Pre-auth done and now receiving---> AUTH REQ <---- in state %d\n",
+ pMac->ft.ftSmeContext.FTState);
+ smsLog( pMac, LOGE, "Unhandled reception of FT IES in state %d\n",
+ pMac->ft.ftSmeContext.FTState);
+#endif
+ break;
+
+ case eFT_REASSOC_REQ_WAIT:
+ // We are done with pre-auth, hence now waiting for
+ // reassoc req. This is the new FT Roaming in place
+
+ // At this juncture we are ready to start sending Re-Assoc Req.
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, "New Reassoc Req=%p in state %d\n",
+ ft_ies, pMac->ft.ftSmeContext.FTState);
+#endif
+ if ((pMac->ft.ftSmeContext.reassoc_ft_ies) &&
+ (pMac->ft.ftSmeContext.reassoc_ft_ies_length))
+ {
+ // Free the one we received last from the supplicant
+ vos_mem_free(pMac->ft.ftSmeContext.reassoc_ft_ies);
+ pMac->ft.ftSmeContext.reassoc_ft_ies_length = 0;
+ }
+
+ // Save the FT IEs
+ pMac->ft.ftSmeContext.reassoc_ft_ies = vos_mem_malloc(ft_ies_length);
+ if(pMac->ft.ftSmeContext.reassoc_ft_ies == NULL)
+ {
+ smsLog( pMac, LOGE, FL("Memory allocation failed for "
+ "reassoc_ft_ies\n"));
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return;
+ }
+ pMac->ft.ftSmeContext.reassoc_ft_ies_length = ft_ies_length;
+ vos_mem_copy((tANI_U8 *)pMac->ft.ftSmeContext.reassoc_ft_ies, ft_ies,
+ ft_ies_length);
+
+ pMac->ft.ftSmeContext.FTState = eFT_SET_KEY_WAIT;
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, "ft_ies_length=%d state=%d\n", ft_ies_length,
+ pMac->ft.ftSmeContext.FTState);
+ /*
+ smsLog( pMac, LOGE, "%d: New Auth ft_ies_length=%02x%02x%02x\n",
+ current->pid, pMac->ft.ftSmeContext.reassoc_ft_ies[0],
+ pMac->ft.ftSmeContext.reassoc_ft_ies[1],
+ pMac->ft.ftSmeContext.reassoc_ft_ies[2]);
+ */
+#endif
+
+ break;
+
+ default:
+ smsLog( pMac, LOGE, FL(" Unhandled state=%d\n"),
+ pMac->ft.ftSmeContext.FTState);
+ break;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+}
+
+eHalStatus sme_FTSendUpdateKeyInd(tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo)
+{
+ tSirFTUpdateKeyInfo *pMsg;
+ tANI_U16 msgLen;
+ eHalStatus status = eHAL_STATUS_FAILURE;
+ tAniEdType tmpEdType;
+ tAniKeyDirection tmpDirection;
+ //tANI_U8 *pBuf;
+ tANI_U8 *p = NULL;
+ tAniEdType edType;
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ int i = 0;
+
+ smsLog(pMac, LOGE, FL("keyLength %d\n"), pFTKeyInfo->keyLength);
+
+ for(i=0; i<pFTKeyInfo->keyLength; i++)
+ smsLog(pMac, LOGE, FL("%02x"), pFTKeyInfo->Key[i]);
+
+ msgLen = sizeof( tANI_U16) + sizeof( tANI_U16 ) +
+ sizeof( pMsg->keyMaterial.length ) + sizeof( pMsg->keyMaterial.edType ) +
+ sizeof( pMsg->keyMaterial.numKeys ) + sizeof( pMsg->keyMaterial.key );
+
+ status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen);
+ if ( !HAL_STATUS_SUCCESS(status) )
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+
+ palZeroMemory(pMac->hHdd, pMsg, msgLen);
+ pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_FT_UPDATE_KEY);
+ pMsg->length = pal_cpu_to_be16(msgLen);
+
+ p = (tANI_U8 *)&pMsg->keyMaterial;
+
+ // 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 ) +
+ ( pMsg->keyMaterial.numKeys * sizeof( pMsg->keyMaterial.key ) ) )) );
+
+ // set pMsg->keyMaterial.edType
+ edType = csrTranslateEncryptTypeToEdType( pFTKeyInfo->encType );
+ tmpEdType = pal_cpu_to_be32(edType);
+ palCopyMemory( pMac->hHdd, p, (tANI_U8 *)&tmpEdType, sizeof(tAniEdType) );
+ p += sizeof( pMsg->keyMaterial.edType );
+
+ // set the pMsg->keyMaterial.numKeys field
+ *p = pMsg->keyMaterial.numKeys;
+ p += sizeof( pMsg->keyMaterial.numKeys );
+
+ // set pSirKey->keyId = keyId;
+ *p = pMsg->keyMaterial.key[ 0 ].keyId;
+ p += sizeof( pMsg->keyMaterial.key[ 0 ].keyId );
+
+ // set pSirKey->unicast = (tANI_U8)fUnicast;
+ *p = (tANI_U8)eANI_BOOLEAN_TRUE;
+ p += sizeof( pMsg->keyMaterial.key[ 0 ].unicast );
+
+ // set pSirKey->keyDirection = aniKeyDirection;
+ tmpDirection = pal_cpu_to_be32(pFTKeyInfo->keyDirection);
+ palCopyMemory( pMac->hHdd, p, (tANI_U8 *)&tmpDirection, sizeof(tAniKeyDirection) );
+ p += sizeof(tAniKeyDirection);
+ // pSirKey->keyRsc = ;;
+ palCopyMemory( pMac->hHdd, p, pFTKeyInfo->keyRsc, CSR_MAX_RSC_LEN );
+ p += sizeof( pMsg->keyMaterial.key[ 0 ].keyRsc );
+
+ // set pSirKey->paeRole
+ *p = pFTKeyInfo->paeRole; // 0 is Supplicant
+ p++;
+
+ // set pSirKey->keyLength = keyLength;
+ p = pal_set_U16( p, pal_cpu_to_be16(pFTKeyInfo->keyLength) );
+
+ if ( pFTKeyInfo->keyLength && pFTKeyInfo->Key )
+ {
+ palCopyMemory( pMac->hHdd, p, pFTKeyInfo->Key, pFTKeyInfo->keyLength );
+ if(pFTKeyInfo->keyLength == 16)
+ {
+ smsLog(pMac, LOGE, " SME Set keyIdx (%d) encType(%d) key = %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
+ pFTKeyInfo->keyId, edType, pFTKeyInfo->Key[0], pFTKeyInfo->Key[1], pFTKeyInfo->Key[2], pFTKeyInfo->Key[3], pFTKeyInfo->Key[4],
+ pFTKeyInfo->Key[5], pFTKeyInfo->Key[6], pFTKeyInfo->Key[7], pFTKeyInfo->Key[8],
+ pFTKeyInfo->Key[9], pFTKeyInfo->Key[10], pFTKeyInfo->Key[11], pFTKeyInfo->Key[12], pFTKeyInfo->Key[13], pFTKeyInfo->Key[14], pFTKeyInfo->Key[15]);
+ }
+ }
+
+ status = palSendMBMessage(pMac->hHdd, pMsg);
+
+ return( status );
+}
+
+eHalStatus sme_FTUpdateKey( tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_FAILURE;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if (!( HAL_STATUS_SUCCESS( status )))
+ {
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if (pFTKeyInfo == NULL)
+ {
+ smsLog( pMac, LOGE, "%s: pFTKeyInfo is NULL\n", __FUNCTION__);
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return eHAL_STATUS_FAILURE;
+ }
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, "sme_FTUpdateKey is received in state %d\n",
+ pMac->ft.ftSmeContext.FTState);
+#endif
+
+ // Global Station FT State
+ switch(pMac->ft.ftSmeContext.FTState)
+ {
+ case eFT_SET_KEY_WAIT:
+ status = sme_FTSendUpdateKeyInd( hHal, pFTKeyInfo );
+ pMac->ft.ftSmeContext.FTState = eFT_START_READY;
+ break;
+
+ default:
+ smsLog( pMac, LOGE, "%s: Unhandled state=%d\n", __FUNCTION__,
+ pMac->ft.ftSmeContext.FTState);
+ status = eHAL_STATUS_FAILURE;
+ break;
+ }
+ sme_ReleaseGlobalLock( &pMac->sme );
+
+ return status;
+}
+/*--------------------------------------------------------------------------
+ *
+ * HDD Interface to SME. SME now sends the Auth 2 and RIC IEs up to the supplicant.
+ * The supplicant will then proceed to send down the
+ * Reassoc Req.
+ *
+ *------------------------------------------------------------------------*/
+void sme_GetFTPreAuthResponse( tHalHandle hHal, tANI_U8 *ft_ies,
+ tANI_U32 ft_ies_ip_len, tANI_U16 *ft_ies_length )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_FAILURE;
+
+ *ft_ies_length = 0;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if (!( HAL_STATUS_SUCCESS( status )))
+ return;
+
+ /* All or nothing - proceed only if both BSSID and FT IE fit */
+ if((ANI_MAC_ADDR_SIZE +
+ pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ft_ies_length) > ft_ies_ip_len)
+ {
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return;
+ }
+
+ // hdd needs to pack the bssid also along with the
+ // auth response to supplicant
+ vos_mem_copy(ft_ies, pMac->ft.ftSmeContext.preAuthbssId, ANI_MAC_ADDR_SIZE);
+
+ // Copy the auth resp FTIEs
+ vos_mem_copy(&(ft_ies[ANI_MAC_ADDR_SIZE]),
+ pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ft_ies,
+ pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ft_ies_length);
+
+ *ft_ies_length = ANI_MAC_ADDR_SIZE +
+ pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ft_ies_length;
+
+ pMac->ft.ftSmeContext.FTState = eFT_REASSOC_REQ_WAIT;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, FL(" Filled auth resp = %d\n"), *ft_ies_length);
+#endif
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return;
+}
+
+/*--------------------------------------------------------------------------
+ *
+ * SME now sends the RIC IEs up to the supplicant.
+ * The supplicant will then proceed to send down the
+ * Reassoc Req.
+ *
+ *------------------------------------------------------------------------*/
+void sme_GetRICIEs( tHalHandle hHal, tANI_U8 *ric_ies, tANI_U32 ric_ies_ip_len,
+ tANI_U32 *ric_ies_length )
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+ eHalStatus status = eHAL_STATUS_FAILURE;
+
+ *ric_ies_length = 0;
+
+ status = sme_AcquireGlobalLock( &pMac->sme );
+ if (!( HAL_STATUS_SUCCESS( status )))
+ return;
+
+ /* All or nothing */
+ if (pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies_length >
+ ric_ies_ip_len)
+ {
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return;
+ }
+
+ vos_mem_copy(ric_ies, pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies,
+ pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies_length);
+
+ *ric_ies_length = pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies_length;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ smsLog( pMac, LOGE, FL(" Filled ric ies = %d\n"), *ric_ies_length);
+#endif
+
+ sme_ReleaseGlobalLock( &pMac->sme );
+ return;
+}
+
+/*--------------------------------------------------------------------------
+ *
+ * Timer callback for the timer that is started between the preauth completion and
+ * reassoc request to the PE. In this interval, it is expected that the pre-auth response
+ * and RIC IEs are passed up to the WPA supplicant and received back the necessary FTIEs
+ * required to be sent in the reassoc request
+ *
+ *------------------------------------------------------------------------*/
+void sme_PreauthReassocIntvlTimerCallback(void *context)
+{
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ tpAniSirGlobal pMac = (tpAniSirGlobal )context;
+ csrNeighborRoamRequestHandoff(pMac);
+#endif
+ return;
+}
+/* End of File */
+#endif /* WLAN_FEATURE_VOWIFI_11R */