prima: WLAN Driver Release 3.1.7.9
This is the initial release of the Prima WLAN Driver
diff --git a/CORE/HDD/src/bap_hdd_main.c b/CORE/HDD/src/bap_hdd_main.c
new file mode 100644
index 0000000..60a42aa
--- /dev/null
+++ b/CORE/HDD/src/bap_hdd_main.c
@@ -0,0 +1,4545 @@
+/*
+ * 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 bap_hdd_main.c
+
+ \brief 802.11 BT-AMP PAL Host Device Driver implementation
+
+ 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.
+
+
+ $Header: /prj/qct/asw/engbuilds/scl/users02/jzmuda/gb-bluez/vendor/qcom/proprietary/wlan/libra/CORE/HDD/src/bap_hdd_main.c,v 1.63 2011/04/01 15:24:20 jzmuda Exp jzmuda $ $DateTime: $ $Author: jzmuda $
+
+
+ when who what, where, why
+ -------- --- --------------------------------------------------------
+ 12/1/09 JZmuda Created module.
+
+ ==========================================================================*/
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#ifdef WLAN_BTAMP_FEATURE
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/spinlock.h>
+//#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+//#include <wlan_qct_driver.h>
+#include <wlan_hdd_includes.h>
+#include <wlan_hdd_dp_utils.h>
+/* -------------------------------------------------------------------------*/
+#include <bap_hdd_main.h>
+#include <vos_api.h>
+#include <bapApi.h>
+#include <btampHCI.h>
+/* -------------------------------------------------------------------------*/
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#ifdef WLAN_SOFTAP_FEATURE
+#include <wlan_hdd_misc.h>
+#endif
+/*----------------------------------------------------------------------------
+ * Preprocessor Definitions and Constants
+ * -------------------------------------------------------------------------*/
+
+// the difference between the next two is that the first is the max
+// number we support in our current implementation while the second is
+// the max allowed by the spec
+#define BSL_MAX_PHY_LINKS ( BSL_MAX_CLIENTS * BSL_MAX_PHY_LINK_PER_CLIENT )
+#define BSL_MAX_ALLOWED_PHY_LINKS 255
+
+// these likely will need tuning based on experiments
+#define BSL_MAX_RX_PKT_DESCRIPTOR 100
+#define BSL_MAX_TX_PKT_DESCRIPTOR 100
+
+// these caps are in place to not have run-away queues, again needs empirical tuning
+#define BSL_MAX_SIZE_TX_ACL_QUEUE 50
+#define BSL_MAX_SIZE_RX_ACL_QUEUE 50
+#define BSL_MAX_SIZE_RX_EVT_QUEUE 50
+
+#if 0
+What are the maximum sizes of a command packet, an event packet and an ACL
+data packet?
+
+[JimZ]: Sizes:
+1. Cmd Maximum size is slightly greater than 672 btyes. But I am pretty sure
+right now that I will never have more than 240 bytes to send down at a time. And
+that is good. Because some rather unpleasant things happen at the HCI interface
+if I exceed that. ( Think 8-bit CPUs. And the limitations of an 8-bit length
+ field. )
+
+2. Event - Ditto.
+
+3. Data 1492 bytes
+#endif
+
+// jimz
+// TLV related defines
+
+#define USE_FINAL_FRAMESC
+//#undef USE_FINAL_FRAMESC
+// jimz
+// TLV related defines
+
+#ifndef USE_FINAL_FRAMESC //USE_FINAL_FRAMESC
+// AMP ASSOC TLV related defines
+#define AMP_ASSOC_TLV_TYPE_SIZE 2
+#define AMP_ASSOC_TLV_LEN_SIZE 2
+#define AMP_ASSOC_TLV_TYPE_AND_LEN_SIZE (AMP_ASSOC_TLV_TYPE_SIZE + AMP_ASSOC_TLV_LEN_SIZE)
+
+// FLOW SPEC TLV related defines
+#define FLOWSPEC_TYPE_SIZE 2
+#define FLOWSPEC_LEN_SIZE 2
+#define FLOWSPEC_TYPE_AND_LEN_SIZE (FLOWSPEC_TYPE_SIZE + FLOWSPEC_LEN_SIZE)
+
+// CMD TLV related defines
+#define CMD_TLV_TYPE_SIZE 2
+#define CMD_TLV_LEN_SIZE 2
+#define CMD_TLV_TYPE_AND_LEN_SIZE (CMD_TLV_TYPE_SIZE + CMD_TLV_LEN_SIZE)
+
+// Event TLV related defines
+#define EVENT_TLV_TYPE_SIZE 2
+#define EVENT_TLV_LEN_SIZE 2
+#define EVENT_TLV_TYPE_AND_LEN_SIZE (EVENT_TLV_TYPE_SIZE + EVENT_TLV_LEN_SIZE)
+
+// Data header size related defines
+#define DATA_HEADER_SIZE 4
+
+#else //USE_FINAL_FRAMESC
+
+// AMP ASSOC TLV related defines
+#define AMP_ASSOC_TLV_TYPE_SIZE 1
+#define AMP_ASSOC_TLV_LEN_SIZE 2
+#define AMP_ASSOC_TLV_TYPE_AND_LEN_SIZE (AMP_ASSOC_TLV_TYPE_SIZE + AMP_ASSOC_TLV_LEN_SIZE)
+
+// FLOW SPEC TLV related defines
+#define FLOWSPEC_TYPE_SIZE 1
+#define FLOWSPEC_LEN_SIZE 1
+#define FLOWSPEC_TYPE_AND_LEN_SIZE (FLOWSPEC_TYPE_SIZE + FLOWSPEC_LEN_SIZE)
+
+// CMD TLV related defines
+#define CMD_TLV_TYPE_SIZE 2
+#define CMD_TLV_LEN_SIZE 1
+#define CMD_TLV_TYPE_AND_LEN_SIZE (CMD_TLV_TYPE_SIZE + CMD_TLV_LEN_SIZE)
+
+// Event TLV related defines
+#define EVENT_TLV_TYPE_SIZE 1
+#define EVENT_TLV_LEN_SIZE 1
+#define EVENT_TLV_TYPE_AND_LEN_SIZE (EVENT_TLV_TYPE_SIZE + EVENT_TLV_LEN_SIZE)
+
+// Data header size related defines
+#define DATA_HEADER_SIZE 4
+
+#endif // USE_FINAL_FRAMESC
+// jimz
+
+#define BSL_MAX_EVENT_SIZE 700
+
+#define BSL_DEV_HANDLE 0x1234
+
+// Debug related defines
+#define DBGLOG printf
+//#define DUMPLOG
+#if defined DUMPLOG
+#define DUMPLOG(n, name1, name2, aStr, size) \
+ if (1) \
+{\
+ int i;\
+ DBGLOG("%d. %s: %s = \n", n, name1, name2); \
+ for (i = 0; i < size; i++) \
+ DBGLOG("%2.2x%s", ((unsigned char *)aStr)[i], i % 16 == 15 ? "\n" : " "); \
+ DBGLOG("\n"); \
+}
+#else
+#define DUMPLOG(n, name1, name2, aStr, size)
+#endif
+
+// These are required to replace some Microsoft specific specifiers
+//#define UNALIGNED __align
+#define UNALIGNED
+#define INFINITE 0
+
+#define BT_AMP_HCI_CTX_MAGIC 0x48434949 // "HCII"
+
+/*----------------------------------------------------------------------------
+ * Type Declarations
+ * -------------------------------------------------------------------------*/
+
+// Temporary Windows types
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef void * HANDLE;
+typedef char TCHAR;
+typedef void *LPVOID;
+typedef const void *LPCVOID;
+
+typedef struct
+{
+ BOOL used; // is this a valid context?
+ vos_event_t ReadableEvt; // the event a ReadFile can block on
+ ptBtampHandle bapHdl; // our handle in BAP
+ vos_list_t PhyLinks; // a list of all associations setup by this client
+// Newly added for BlueZ
+ struct hci_dev *hdev; // the BlueZ HCI device structure
+
+ /* I don't know how many of these Tx fields we need */
+ spinlock_t lock; /* For serializing operations */
+
+ struct sk_buff_head txq; /* We need the ACL Data Tx queue */
+
+ /* We definitely need some of these rx_skb fields */
+ unsigned long rx_state;
+ unsigned long rx_count;
+ struct sk_buff *rx_skb;
+
+ struct net_device *p_dev; // Our parent wlan network device
+
+} BslClientCtxType;
+
+typedef struct
+{
+ BslClientCtxType* pctx;
+ /* Tx skb queue and the workstructure for handling Tx as deferred work. */
+ struct sk_buff *tx_skb;
+
+ struct work_struct hciInterfaceProcessing;
+ v_U32_t magic;
+
+} BslHciWorkStructure;
+
+typedef struct
+{
+ TCHAR* ValueName; // name of the value
+ DWORD Type; // type of value
+ DWORD DwordValue; // DWORD value
+ TCHAR* StringValue; // string value
+
+} BslRegEntry;
+
+typedef struct
+{
+ BOOL used; // is this a valid context?
+ hdd_list_t ACLTxQueue[WLANTL_MAX_AC]; // the TX ACL queues
+ BslClientCtxType* pClientCtx; // ptr to application context that spawned
+ // this association
+ v_U8_t PhyLinkHdl; // BAP handle for this association
+ void* pPhyLinkDescNode; // ptr to node in list of assoc in client ctx
+ // real type BslPhyLinksNodeType*
+
+} BslPhyLinkCtxType;
+
+typedef struct
+{
+ vos_list_node_t node; // MUST be first element
+ BslPhyLinkCtxType* pPhy; // ptr to an association context
+
+} BslPhyLinksNodeType;
+
+typedef struct
+{
+ vos_list_node_t node; // MUST be first element
+ vos_pkt_t* pVosPkt; // ptr to a RX VoS pkt which can hold an HCI event or ACL data
+
+} BslRxListNodeType;
+
+// Borrowed from wlan_hdd_dp_utils.h
+typedef struct
+{
+ hdd_list_node_t node; // MUST be first element
+ struct sk_buff * skb; // ptr to the ACL data
+
+} BslTxListNodeType;
+
+typedef struct
+{
+ BslPhyLinkCtxType* ptr; // ptr to the association context for this phy_link_handle
+
+} BslPhyLinkMapEntryType;
+
+/*----------------------------------------------------------------------------
+ * Global Data Definitions
+ * -------------------------------------------------------------------------*/
+BslClientCtxType* gpBslctx;
+
+/*----------------------------------------------------------------------------
+ * Static Variable Definitions
+ * -------------------------------------------------------------------------*/
+// Temporary (until multi-phy link) pointer to BT-AMP context
+static void *gpCtx;
+
+// an efficient lookup from phy_link_handle to phy link context
+static BslPhyLinkMapEntryType BslPhyLinkMap[BSL_MAX_ALLOWED_PHY_LINKS];
+
+//static HANDLE hBsl = NULL; //INVALID_HANDLE_VALUE;
+static BOOL bBslInited = FALSE;
+
+static BslClientCtxType BslClientCtx[BSL_MAX_CLIENTS];
+//static vos_lock_t BslClientLock;
+
+static BslPhyLinkCtxType BslPhyLinkCtx[BSL_MAX_PHY_LINKS];
+//static vos_lock_t BslPhyLock;
+
+// the pool for association contexts
+static vos_list_t BslPhyLinksDescPool;
+static BslPhyLinksNodeType BslPhyLinksDesc[BSL_MAX_PHY_LINKS];
+
+//static v_U32_t Eventlen = 0;
+
+/*---------------------------------------------------------------------------
+ * Forward declarations
+ *-------------------------------------------------------------------------*/
+static void bslWriteFinish(struct work_struct *work);
+
+/*---------------------------------------------------------------------------
+ * Driver Entry points and Structure definitions
+ *-------------------------------------------------------------------------*/
+static int BSL_Open (struct hci_dev *hdev);
+static int BSL_Close (struct hci_dev *hdev);
+static int BSL_Flush(struct hci_dev *hdev);
+static int BSL_IOControl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
+static int BSL_Write(struct sk_buff *skb);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+static void BSL_Destruct(struct hci_dev *hdev);
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * Static Function Declarations and Definitions
+ * -------------------------------------------------------------------------*/
+static v_BOOL_t WLANBAP_AmpConnectionAllowed(void)
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
+ hdd_context_t *pHddCtx;
+ v_BOOL_t retVal = VOS_FALSE;
+
+ if (NULL != pVosContext)
+ {
+ pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
+ if (NULL != pHddCtx)
+ {
+ return pHddCtx->isAmpAllowed;
+ }
+ else
+ {
+ return retVal;
+ }
+ }
+ return retVal;
+}
+
+/**
+ @brief WLANBAP_STAFetchPktCB() - The fetch packet callback registered
+ with BAP by HDD.
+
+ It is called by the BAP immediately upon the underlying
+ WLANTL_STAFetchPktCBType routine being called. Which is called by
+ TL when the scheduling algorithms allows for transmission of another
+ packet to the module.
+
+ This function is here to "wrap" or abstract WLANTL_STAFetchPktCBType.
+ Because the BAP-specific HDD "shim" layer (BSL) doesn't know anything
+ about STAIds, or other parameters required by TL.
+
+ @param pHddHdl: [in] The HDD(BSL) specific context for this association.
+ Use the STAId passed to me by TL in WLANTL_STAFetchCBType to retreive
+ this value.
+ @param pucAC: [inout] access category requested by TL, if HDD does not
+ have packets on this AC it can choose to service another AC queue in
+ the order of priority
+ @param vosDataBuff: [out] pointer to the VOSS data buffer that was
+ transmitted
+ @param tlMetaInfo: [out] meta info related to the data frame
+
+ @return
+ The result code associated with performing the operation
+*/
+static VOS_STATUS WLANBAP_STAFetchPktCB
+(
+ v_PVOID_t pHddHdl,
+ WLANTL_ACEnumType ucAC,
+ vos_pkt_t** vosDataBuff,
+ WLANTL_MetaInfoType* tlMetaInfo
+)
+{
+ BslPhyLinkCtxType* pPhyCtx;
+ VOS_STATUS VosStatus;
+ v_U8_t AcIdxStart;
+ v_U8_t AcIdx;
+ hdd_list_node_t *pLink;
+ BslTxListNodeType *pNode;
+ struct sk_buff * skb;
+ BslClientCtxType* pctx;
+ WLANTL_ACEnumType Ac;
+ vos_pkt_t* pVosPkt;
+ WLANTL_MetaInfoType TlMetaInfo;
+ pctx = &BslClientCtx[0];
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "WLANBAP_STAFetchPktCB\n" );
+
+ // sanity checking
+ if( pHddHdl == NULL || vosDataBuff == NULL ||
+ tlMetaInfo == NULL || ucAC >= WLANTL_MAX_AC || ucAC < 0 )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STAFetchPktCB bad input\n" );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ // Initialize the VOSS packet returned to NULL - in case of error
+ *vosDataBuff = NULL;
+
+ pPhyCtx = (BslPhyLinkCtxType *)pHddHdl;
+ AcIdx = AcIdxStart = ucAC;
+
+ spin_lock_bh(&pPhyCtx->ACLTxQueue[AcIdx].lock);
+ VosStatus = hdd_list_remove_front( &pPhyCtx->ACLTxQueue[AcIdx], &pLink );
+ spin_unlock_bh(&pPhyCtx->ACLTxQueue[AcIdx].lock);
+
+ if ( VOS_STATUS_E_EMPTY == VosStatus )
+ {
+ do
+ {
+ AcIdx = (AcIdx + 1) % WLANTL_MAX_AC;
+
+ spin_lock_bh(&pPhyCtx->ACLTxQueue[AcIdx].lock);
+ VosStatus = hdd_list_remove_front( &pPhyCtx->ACLTxQueue[AcIdx], &pLink );
+ spin_unlock_bh(&pPhyCtx->ACLTxQueue[AcIdx].lock);
+
+ }
+ while ( VosStatus == VOS_STATUS_E_EMPTY && AcIdx != AcIdxStart );
+
+ if ( VosStatus == VOS_STATUS_E_EMPTY )
+ {
+ // Queue is empty. This can happen. Just return NULL back to TL...
+ return(VOS_STATUS_E_EMPTY);
+ }
+ else if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_ASSERT( 0 );
+ }
+ }
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_ASSERT( 0 );
+ }
+
+ pNode = (BslTxListNodeType *)pLink;
+ skb = pNode->skb;
+
+ // I will access the skb in a VOSS packet
+ // Wrap the OS provided skb in a VOSS packet
+ // Attach skb to VOS packet.
+ VosStatus = vos_pkt_wrap_data_packet( &pVosPkt,
+ VOS_PKT_TYPE_TX_802_3_DATA,
+ skb,
+ NULL,
+ NULL);
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STAFetchPktCB vos_pkt_wrap_data_packet "
+ "failed status =%d\n", VosStatus );
+ kfree_skb(skb);
+ return VosStatus;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, "%s: pVosPkt(vos_pkt_t *)=%p\n", __FUNCTION__,
+ pVosPkt );
+
+ VosStatus = WLANBAP_XlateTxDataPkt( pctx->bapHdl, pPhyCtx->PhyLinkHdl,
+ &Ac, &TlMetaInfo, pVosPkt);
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STAFetchPktCB WLANBAP_XlateTxDataPkt "
+ "failed status =%d\n", VosStatus );
+
+ // return the packet
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+ kfree_skb(skb);
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return VosStatus;
+ }
+ // give TL the VoS pkt
+ *vosDataBuff = pVosPkt;
+
+ // provide the meta-info BAP provided previously
+ *tlMetaInfo = TlMetaInfo;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: *vosDataBuff(vos_pkt_t *)=%p\n", __FUNCTION__, *vosDataBuff );
+
+ return(VOS_STATUS_SUCCESS);
+} // WLANBAP_STAFetchPktCB()
+
+/**
+ @brief WLANBAP_STARxCB() - The receive callback registered with BAP by HDD.
+
+ It is called by the BAP immediately upon the underlying
+ WLANTL_STARxCBType routine being called. Which is called by
+ TL to notify when a packet was received for a registered STA.
+
+ @param pHddHdl: [in] The HDD(BSL) specific context for this association.
+ Use the STAId passed to me by TL in WLANTL_STARxCBType to retrieve this value.
+ @param vosDataBuff: [in] pointer to the VOSS data buffer that was received
+ (it may be a linked list)
+ @param pRxMetaInfo: [in] Rx meta info related to the data frame
+
+ @return
+ The result code associated with performing the operation
+*/
+static VOS_STATUS WLANBAP_STARxCB
+(
+ v_PVOID_t pHddHdl,
+ vos_pkt_t* vosDataBuff,
+ WLANTL_RxMetaInfoType* pRxMetaInfo
+)
+{
+ BslPhyLinkCtxType* pctx;
+ BslClientCtxType* ppctx;
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ WLANTL_ACEnumType Ac; // this is not needed really
+ struct sk_buff *skb = NULL;
+ vos_pkt_t* pVosPacket;
+ vos_pkt_t* pNextVosPacket;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "WLANBAP_STARxCB\n" );
+
+ // sanity checking
+ if ( pHddHdl == NULL || vosDataBuff == NULL || pRxMetaInfo == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STARxCB bad input\n" );
+ if(NULL != vosDataBuff)
+ {
+ VosStatus = vos_pkt_return_packet( vosDataBuff );
+ }
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pctx = (BslPhyLinkCtxType *)pHddHdl;
+ ppctx = pctx->pClientCtx;
+
+ if( NULL == ppctx )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STARxCB ClientCtx is NULL\n" );
+ VosStatus = vos_pkt_return_packet( vosDataBuff );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ // walk the chain until all are processed
+ pVosPacket = vosDataBuff;
+ do
+ {
+ // get the pointer to the next packet in the chain
+ // (but don't unlink the packet since we free the entire chain later)
+ VosStatus = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
+
+ // both "success" and "empty" are acceptable results
+ if (!((VosStatus == VOS_STATUS_SUCCESS) || (VosStatus == VOS_STATUS_E_EMPTY)))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,"%s: Failure walking packet chain", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ // process the packet
+ VosStatus = WLANBAP_XlateRxDataPkt( ppctx->bapHdl, pctx->PhyLinkHdl,
+ &Ac, pVosPacket );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_FATAL, "WLANBAP_STARxCB WLANBAP_XlateRxDataPkt "
+ "failed status = %d\n", VosStatus );
+
+ VosStatus = VOS_STATUS_E_FAILURE;
+
+ break;
+ }
+
+ // Extract the OS packet (skb).
+ // Tell VOS to detach the OS packet from the VOS packet
+ VosStatus = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
+ if(!VOS_IS_STATUS_SUCCESS( VosStatus ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: Failure extracting skb from vos pkt. "
+ "VosStatus = %d\n", __FUNCTION__, VosStatus );
+
+ VosStatus = VOS_STATUS_E_FAILURE;
+
+ break;
+ }
+
+ //JEZ100809: While an skb is being handled by the kernel, is "skb->dev" de-ref'd?
+ skb->dev = (struct net_device *) gpBslctx->hdev;
+ bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
+ //skb->protocol = eth_type_trans(skb, skb->dev);
+ //skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ // This is my receive skb pointer
+ gpBslctx->rx_skb = skb;
+
+ // This is how data and events are passed up to BlueZ
+ hci_recv_frame(gpBslctx->rx_skb);
+
+ // now process the next packet in the chain
+ pVosPacket = pNextVosPacket;
+
+ } while (pVosPacket);
+
+
+ //JEZ100922: We are free to return the enclosing VOSS packet.
+ VosStatus = vos_pkt_return_packet( vosDataBuff );
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+
+ return(VOS_STATUS_SUCCESS);
+} // WLANBAP_STARxCB()
+
+/**
+ @brief WLANBAP_TxCompCB() - The Tx complete callback registered with BAP by HDD.
+
+ It is called by the BAP immediately upon the underlying
+ WLANTL_TxCompCBType routine being called. Which is called by
+ TL to notify when a transmission for a packet has ended.
+
+ @param pHddHdl: [in] The HDD(BSL) specific context for this association
+ @param vosDataBuff: [in] pointer to the VOSS data buffer that was transmitted
+ @param wTxSTAtus: [in] status of the transmission
+
+ @return
+ The result code associated with performing the operation
+*/
+extern v_VOID_t WLANBAP_TxPacketMonitorHandler ( v_PVOID_t ); // our handle in BAP
+
+static VOS_STATUS WLANBAP_TxCompCB
+(
+ v_PVOID_t pHddHdl,
+ vos_pkt_t* vosDataBuff,
+ VOS_STATUS wTxSTAtus
+)
+{
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ //BslTxListNodeType* pTxNode;
+ void* pOsPkt = NULL;
+ BslPhyLinkCtxType* pctx;
+ BslClientCtxType* ppctx;
+ static int num_packets = 0;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, "WLANBAP_TxCompCB. vosDataBuff(vos_pkt_t *)=%p\n", vosDataBuff );
+
+ // be aware that pHddHdl can be NULL or can point to the per association
+ // BSL context from the register data plane. In either case it does not
+ // matter since we will simply free the VoS pkt and reclaim the TX
+ // descriptor
+
+ // sanity checking
+ if ( vosDataBuff == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_TxCompCB bad input\n" );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Return the skb to the OS
+ VosStatus = vos_pkt_get_os_packet( vosDataBuff, &pOsPkt, VOS_TRUE );
+ if(!VOS_IS_STATUS_SUCCESS( VosStatus ))
+ {
+ //This is bad but still try to free the VOSS resources if we can
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __FUNCTION__);
+ vos_pkt_return_packet( vosDataBuff );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ kfree_skb((struct sk_buff *)pOsPkt);
+
+ //Return the VOS packet resources.
+ VosStatus = vos_pkt_return_packet( vosDataBuff );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_ASSERT(0);
+ }
+
+ // JEZ110330: Now signal the layer above me...that I have released some packets.
+ pctx = (BslPhyLinkCtxType *)pHddHdl;
+ ppctx = pctx->pClientCtx;
+ num_packets = (num_packets + 1) % 4;
+ if (num_packets == 0 )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, "%s: Sending up number of completed packets. num_packets = %d.\n", __FUNCTION__, num_packets );
+ WLANBAP_TxPacketMonitorHandler ( (v_PVOID_t) ppctx->bapHdl ); // our handle in BAP
+ }
+
+ return(VOS_STATUS_SUCCESS);
+} // WLANBAP_TxCompCB()
+
+/**
+ @brief BslFlushTxQueues() - flush the Tx queues
+
+ @param pPhyCtx : [in] ptr to the phy context whose queues need to be flushed
+
+ @return
+ VOS_STATUS
+
+*/
+static VOS_STATUS BslFlushTxQueues
+(
+ BslPhyLinkCtxType* pPhyCtx
+)
+{
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ v_SINT_t i = -1;
+ hdd_list_node_t* pLink;
+ BslTxListNodeType *pNode;
+
+
+ if(TRUE == pPhyCtx->used)
+ {
+ while (++i != WLANTL_MAX_AC)
+ {
+ //Free up any packets in the Tx queue
+ spin_lock_bh(&pPhyCtx->ACLTxQueue[i].lock);
+ while (true)
+ {
+ VosStatus = hdd_list_remove_front(&pPhyCtx->ACLTxQueue[i], &pLink );
+ if(VOS_STATUS_E_EMPTY != VosStatus)
+ {
+ pNode = (BslTxListNodeType *)pLink;
+ kfree_skb(pNode->skb);
+ continue;
+ }
+ break;
+ }
+ spin_unlock_bh(&pPhyCtx->ACLTxQueue[i].lock);
+ }
+ }
+ return(VOS_STATUS_SUCCESS);
+} // BslFlushTxQueues
+
+
+/**
+ @brief BslReleasePhyCtx() - this function will free up an association context
+
+ @param pPhyCtx : [in] ptr to the phy context to release
+
+ @return
+ None
+
+*/
+static void BslReleasePhyCtx
+(
+ BslPhyLinkCtxType* pPhyCtx
+)
+{
+ v_U32_t OldMapVal;
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslReleasePhyCtx\n" );
+
+ pPhyCtx->used = FALSE;
+
+
+ if (BslPhyLinkMap[pPhyCtx->PhyLinkHdl].ptr == NULL) return;
+
+
+ // update the phy link handle based map so TX data is stopped from flowing through
+ OldMapVal = vos_atomic_set_U32( (v_U32_t *) (BslPhyLinkMap[pPhyCtx->PhyLinkHdl].ptr),
+ (v_U32_t) 0 );
+
+ // clear out the Tx Queues
+ VosStatus = BslFlushTxQueues(pPhyCtx);
+
+ // clear out the parent ptr
+ // pPhyCtx->pClientCtx = NULL;//commented to debug exception
+
+ // we also need to remove this assocation from the list of active
+ // associations maintained in the application context
+ if( pPhyCtx->pPhyLinkDescNode )
+ {
+ VosStatus = vos_list_remove_node( &pPhyCtx->pClientCtx->PhyLinks,
+ &((BslPhyLinksNodeType*)pPhyCtx->pPhyLinkDescNode)->node);
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
+ //Return the PhyLink handle to the free pool
+ VosStatus = vos_list_insert_front(&BslPhyLinksDescPool,&((BslPhyLinksNodeType*)pPhyCtx->pPhyLinkDescNode)->node);
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
+
+ pPhyCtx->pPhyLinkDescNode = NULL;
+ }
+ pPhyCtx->pClientCtx = NULL;//Moved here to bebug the exception
+
+ pPhyCtx->used = FALSE;
+
+} // BslReleasePhyCtx()
+
+/**
+ @brief WLAN_BAPEventCB() - Implements the callback for ALL asynchronous events.
+
+ Including Events resulting from:
+ * HCI Create Physical Link,
+ * Disconnect Physical Link,
+ * Create Logical Link,
+ * Flow Spec Modify,
+ * HCI Reset,
+ * HCI Flush,...
+
+ Also used to return sync events locally by BSL
+
+ @param pHddHdl: [in] The HDD(BSL) specific context for this association.
+ BSL gets this from the downgoing packets Physical handle value.
+ @param pBapHCIEvent: [in] pointer to the union of "HCI Event" structures.
+ Contains all info needed for HCI event.
+ @param AssocSpecificEvent: [in] flag indicates assoc-specific (1) or
+ global (0) event
+
+ @return
+ The result code associated with performing the operation
+
+ VOS_STATUS_E_FAULT: pointer to pBapHCIEvent is NULL
+ VOS_STATUS_SUCCESS: Success
+*/
+static VOS_STATUS WLANBAP_EventCB
+(
+ v_PVOID_t pHddHdl, /* this could refer to either the BSL per
+ association context which got passed in during
+ register data plane OR the BSL per application
+ context passed in during register BAP callbacks
+ based on setting of the Boolean flag below */
+ tpBtampHCI_Event pBapHCIEvent, /* This now encodes ALL event types including
+ Command Complete and Command Status*/
+ v_BOOL_t AssocSpecificEvent /* Flag to indicate global or assoc-specific event */
+)
+{
+ BslClientCtxType* pctx;
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ vos_pkt_t* pVosPkt;
+ v_U32_t PackStatus;
+ static v_U8_t Buff[BSL_MAX_EVENT_SIZE]; // stack overflow?
+ v_U32_t Written = 0; // FramesC REQUIRES this
+ v_U32_t OldMapVal;
+ struct sk_buff *skb = NULL;
+
+ // sanity checking
+ if ( pBapHCIEvent == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB bad input\n" );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB event=%d "
+ "assoc_specific=%d\n", pBapHCIEvent->bapHCIEventCode, AssocSpecificEvent );
+
+ if ( pHddHdl == NULL )
+ {
+ /* Consider the following error scenarios to bypass the NULL check:
+ - create LL without a call for create PL before
+ - delete LL or PL when no AMP connection has been established yet
+ Client context is unimportant from HCI point of view, only needed by the TLV API in BAP
+ TODO: Change the TLV APIs to not to carry the client context; it doesn't use it anyway
+ */
+ if (( AssocSpecificEvent ) &&
+ (BTAMP_TLV_HCI_PHYSICAL_LINK_COMPLETE_EVENT != pBapHCIEvent->bapHCIEventCode) &&
+ (BTAMP_TLV_HCI_DISCONNECT_PHYSICAL_LINK_COMPLETE_EVENT != pBapHCIEvent->bapHCIEventCode))
+ {
+ pctx = gpBslctx;
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_FATAL, "WLANBAP_EventCB bad input\n" );
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+
+
+ if(NULL != pHddHdl)
+ {
+ if ( AssocSpecificEvent )
+ {
+ // get the app context from the assoc context
+ pctx = ((BslPhyLinkCtxType *)pHddHdl)->pClientCtx;
+ }
+ else
+ {
+ pctx = (BslClientCtxType *)pHddHdl;
+ }
+ }
+
+ if(NULL == pctx)
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "pctx is NULL in %s", __FUNCTION__);
+
+ return VOS_STATUS_E_FAULT;
+
+ }
+
+ VosStatus = vos_pkt_get_packet( &pVosPkt, VOS_PKT_TYPE_RX_RAW,
+ BSL_MAX_EVENT_SIZE, 1, 0, NULL, NULL);
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB vos_pkt_get_packet "
+ "failed status=%d\n", VosStatus );
+ return(VosStatus);
+ }
+
+ switch ( pBapHCIEvent->bapHCIEventCode )
+ {
+ /** BT events */
+ case BTAMP_TLV_HCI_COMMAND_COMPLETE_EVENT:
+ {
+ /*
+ BTAMP_TLV_HCI_RESET_CMD:
+ BTAMP_TLV_HCI_FLUSH_CMD:
+ BTAMP_TLV_HCI_LOGICAL_LINK_CANCEL_CMD:
+ BTAMP_TLV_HCI_SET_EVENT_MASK_CMD:
+ BTAMP_TLV_HCI_READ_CONNECTION_ACCEPT_TIMEOUT_CMD:
+ BTAMP_TLV_HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT_CMD:
+ BTAMP_TLV_HCI_READ_LINK_SUPERVISION_TIMEOUT_CMD:
+ BTAMP_TLV_HCI_WRITE_LINK_SUPERVISION_TIMEOUT_CMD:
+ BTAMP_TLV_HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT_CMD:
+ BTAMP_TLV_HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT_CMD:
+ BTAMP_TLV_HCI_SET_EVENT_MASK_PAGE_2_CMD:
+ BTAMP_TLV_HCI_READ_LOCATION_DATA_CMD:
+ BTAMP_TLV_HCI_WRITE_LOCATION_DATA_CMD:
+ BTAMP_TLV_HCI_READ_FLOW_CONTROL_MODE_CMD:
+ BTAMP_TLV_HCI_WRITE_FLOW_CONTROL_MODE_CMD:
+ BTAMP_TLV_HCI_READ_BEST_EFFORT_FLUSH_TO_CMD:
+ BTAMP_TLV_HCI_WRITE_BEST_EFFORT_FLUSH_TO_CMD:
+ BTAMP_TLV_HCI_SET_SHORT_RANGE_MODE_CMD:
+ BTAMP_TLV_HCI_READ_LOCAL_VERSION_INFORMATION_CMD:
+ BTAMP_TLV_HCI_READ_LOCAL_SUPPORTED_COMMANDS_CMD:
+ BTAMP_TLV_HCI_READ_BUFFER_SIZE_CMD:
+ BTAMP_TLV_HCI_READ_DATA_BLOCK_SIZE_CMD:
+ BTAMP_TLV_HCI_READ_FAILED_CONTACT_COUNTER_CMD:
+ BTAMP_TLV_HCI_RESET_FAILED_CONTACT_COUNTER_CMD:
+ BTAMP_TLV_HCI_READ_LINK_QUALITY_CMD:
+ BTAMP_TLV_HCI_READ_RSSI_CMD:
+ BTAMP_TLV_HCI_READ_LOCAL_AMP_INFORMATION_CMD:
+ BTAMP_TLV_HCI_READ_LOCAL_AMP_ASSOC_CMD:
+ BTAMP_TLV_HCI_WRITE_REMOTE_AMP_ASSOC_CMD:
+ BTAMP_TLV_HCI_READ_LOOPBACK_MODE_CMD:
+ BTAMP_TLV_HCI_WRITE_LOOPBACK_MODE_CMD:
+ BTAMP_TLV_HCI_VENDOR_SPECIFIC_CMD_0:
+
+ */
+
+ // pack
+ PackStatus = btampPackTlvHCI_Command_Complete_Event( pctx,
+ &pBapHCIEvent->u.btampCommandCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Command_Complete_Event failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_COMMAND_STATUS_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Command_Status_Event( pctx,
+ &pBapHCIEvent->u.btampCommandStatusEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Command_Status_Event failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_NUM_OF_COMPLETED_PKTS_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Num_Completed_Pkts_Event( pctx,
+ &pBapHCIEvent->u.btampNumOfCompletedPktsEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Num_Completed_Pkts_Event failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_NUM_OF_COMPLETED_DATA_BLOCKS_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Num_Completed_Data_Blocks_Event( pctx,
+ &pBapHCIEvent->u.btampNumOfCompletedDataBlocksEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Num_Completed_Data_Blocks_Event failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_HARDWARE_ERROR_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Hardware_Error_Event( pctx,
+ &pBapHCIEvent->u.btampHardwareErrorEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_FLUSH_OCCURRED_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Flush_Occurred_Event( pctx,
+ &pBapHCIEvent->u.btampFlushOccurredEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Flush_Occurred_Event failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_ENHANCED_FLUSH_COMPLETE_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Enhanced_Flush_Complete_Event( pctx,
+ &pBapHCIEvent->u.btampEnhancedFlushCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Enhanced_Flush_Complete_Event failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_LOOPBACK_COMMAND_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Loopback_Command_Event( pctx,
+ &pBapHCIEvent->u.btampLoopbackCommandEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_DATA_BUFFER_OVERFLOW_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Data_Buffer_Overflow_Event( pctx,
+ &pBapHCIEvent->u.btampDataBufferOverflowEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_QOS_VIOLATION_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Qos_Violation_Event( pctx,
+ &pBapHCIEvent->u.btampQosViolationEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ /** BT v3.0 events */
+ case BTAMP_TLV_HCI_GENERIC_AMP_LINK_KEY_NOTIFICATION_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Generic_AMP_Link_Key_Notification_Event( pctx,
+ &pBapHCIEvent->u.btampGenericAMPLinkKeyNotificationEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_PHYSICAL_LINK_COMPLETE_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Physical_Link_Complete_Event( pctx,
+ &pBapHCIEvent->u.btampPhysicalLinkCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ // look at this event to determine whether to cleanup the PHY context
+ if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
+ WLANBAP_STATUS_SUCCESS )
+ {
+ // register the data plane now
+ VosStatus = WLANBAP_RegisterDataPlane( pctx->bapHdl,
+ WLANBAP_STAFetchPktCB,
+ WLANBAP_STARxCB,
+ WLANBAP_TxCompCB,
+ (BslPhyLinkCtxType *)pHddHdl );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB WLANBAP_RegisterDataPlane "
+ "failed status = %d\n", VosStatus );
+ // we still want to send the event upto app so do not bail
+ }
+ else
+ {
+ // update the phy link handle based map so TX data can start flowing through
+ OldMapVal = vos_atomic_set_U32( (v_U32_t *)BslPhyLinkMap+pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.phy_link_handle,
+ (v_U32_t) pHddHdl );
+
+// VOS_ASSERT( OldMapVal == 0 );//Commented to test reconnect
+ }
+ }
+ else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
+ WLANBAP_ERROR_HOST_REJ_RESOURCES )
+ {
+ BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
+ }
+ else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
+ WLANBAP_ERROR_HOST_TIMEOUT )
+ {
+ //We need to update the phy link handle here to be able to reissue physical link accept
+ // update the phy link handle based map so TX data can start flowing through
+ OldMapVal = vos_atomic_set_U32( (v_U32_t *)BslPhyLinkMap+pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.phy_link_handle,
+ (v_U32_t) pHddHdl );
+
+// VOS_ASSERT( OldMapVal == 0 );//Commented to test reconnect
+
+ BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
+ }
+ else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
+ WLANBAP_ERROR_MAX_NUM_CNCTS )
+ {
+ //We need to update the phy link handle here to be able to reissue physical link /create/accept
+ // update the phy link handle based map so TX data can start flowing through
+ OldMapVal = vos_atomic_set_U32( (v_U32_t *)BslPhyLinkMap+pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.phy_link_handle,
+ (v_U32_t) pHddHdl );
+// VOS_ASSERT( OldMapVal == 0 );//Commented to test reconnect
+
+ BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
+ }
+ else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
+ WLANBAP_ERROR_HOST_TIMEOUT )
+ {
+ BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
+ }
+ else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
+ 0x16 /* WLANBAP_ERROR_FAILED_CONNECTION? */ )
+ {
+ BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
+ }
+ else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
+ 0x8 /* WLANBAP_ERROR_AUTH_FAILED? */ )
+ {
+ BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
+ }
+ else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
+ WLANBAP_ERROR_NO_CNCT )
+ {
+ BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB unexpected HCI Phy Link Comp Evt "
+ "status =%d\n", pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status );
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_CHANNEL_SELECTED_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Channel_Selected_Event( pctx,
+ &pBapHCIEvent->u.btampChannelSelectedEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_DISCONNECT_PHYSICAL_LINK_COMPLETE_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Disconnect_Physical_Link_Complete_Event( pctx,
+ &pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ // we need to cleanup the PHY context always but have these checks to make
+ // sure we catch unexpected behavior, strangely enough even when peer triggers
+ // the disconnect the reason code is still 0x16, weird
+ if ( pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent.status == WLANBAP_STATUS_SUCCESS &&
+ pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent.reason == WLANBAP_ERROR_TERM_BY_LOCAL_HOST )
+ {
+ BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB unexpected HCI Dis Phy Link Comp Evt "
+ "status =%d reason =%d\n", pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent.status,
+ pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent.reason );
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_PHYSICAL_LINK_LOSS_WARNING_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Physical_Link_Loss_Warning_Event( pctx,
+ &pBapHCIEvent->u.btampPhysicalLinkLossWarningEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_PHYSICAL_LINK_RECOVERY_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Physical_Link_Recovery_Event( pctx,
+ &pBapHCIEvent->u.btampPhysicalLinkRecoveryEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_LOGICAL_LINK_COMPLETE_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Logical_Link_Complete_Event( pctx,
+ &pBapHCIEvent->u.btampLogicalLinkCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_DISCONNECT_LOGICAL_LINK_COMPLETE_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Disconnect_Logical_Link_Complete_Event( pctx,
+ &pBapHCIEvent->u.btampDisconnectLogicalLinkCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_FLOW_SPEC_MODIFY_COMPLETE_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Flow_Spec_Modify_Complete_Event( pctx,
+ &pBapHCIEvent->u.btampFlowSpecModifyCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_SHORT_RANGE_MODE_CHANGE_COMPLETE_EVENT:
+ {
+ // pack
+ PackStatus = btampPackTlvHCI_Short_Range_Mode_Change_Complete_Event( pctx,
+ &pBapHCIEvent->u.btampShortRangeModeChangeCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
+
+ if ( !BTAMP_SUCCEEDED( PackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
+ // handle the error
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ break;
+ }
+ default:
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB unexpected event\n" );
+
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ break;
+ }
+ }
+
+ VOS_ASSERT(Written <= BSL_MAX_EVENT_SIZE);
+
+ // stick the event into a VoS pkt
+ VosStatus = vos_pkt_push_head( pVosPkt, Buff, Written );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB vos_pkt_push_head "
+ "status =%d\n", VosStatus );
+
+ // return the packet
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ // Extract the OS packet (skb).
+ // Tell VOS to detach the OS packet from the VOS packet
+ VosStatus = vos_pkt_get_os_packet( pVosPkt, (v_VOID_t **)&skb, VOS_TRUE );
+ if(!VOS_IS_STATUS_SUCCESS( VosStatus ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: Failure extracting skb from vos pkt. "
+ "VosStatus = %d\n", __FUNCTION__, VosStatus );
+
+ // return the packet
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ return(VOS_STATUS_E_FAILURE);
+ }
+
+ //JEZ100922: We are free to return the enclosing VOSS packet.
+ VosStatus = vos_pkt_return_packet( pVosPkt );
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
+
+ //JEZ100809: While an skb is being handled by the kernel, is "skb->dev" de-ref'd?
+ skb->dev = (struct net_device *) gpBslctx->hdev;
+ bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+ //skb->protocol = eth_type_trans(skb, skb->dev);
+ //skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ // This is my receive skb pointer
+ gpBslctx->rx_skb = skb;
+
+ // This is how data and events are passed up to BlueZ
+ hci_recv_frame(gpBslctx->rx_skb);
+
+ return(VOS_STATUS_SUCCESS);
+} // WLANBAP_EventCB()
+
+static VOS_STATUS
+WLANBAP_PhyLinkFailure
+(
+ BslClientCtxType* pctx,
+ v_U8_t phy_link_handle
+)
+{
+ VOS_STATUS vosStatus;
+ tBtampHCI_Event bapHCIEvent;
+
+ /* Format the Physical Link Complete event to return... */
+ bapHCIEvent.bapHCIEventCode = BTAMP_TLV_HCI_PHYSICAL_LINK_COMPLETE_EVENT;
+ bapHCIEvent.u.btampPhysicalLinkCompleteEvent.present = 1;
+ bapHCIEvent.u.btampPhysicalLinkCompleteEvent.status = WLANBAP_ERROR_UNSPECIFIED_ERROR;
+ bapHCIEvent.u.btampPhysicalLinkCompleteEvent.phy_link_handle
+ = phy_link_handle;
+ bapHCIEvent.u.btampPhysicalLinkCompleteEvent.ch_number
+ = 0;
+ //TBD: Could be a cleaner way to get the PhyLinkCtx handle; For now works
+ BslPhyLinkCtx[0].pClientCtx = pctx;
+ vosStatus = WLANBAP_EventCB( &BslPhyLinkCtx[0], &bapHCIEvent, TRUE );
+
+ return vosStatus;
+}
+
+/**
+ @brief BslFindAndInitClientCtx() - This function will find and initialize a client
+ a.k.a app context
+
+ @param pctx : [inout] ptr to the client context
+
+ @return
+ TRUE if all OK, FALSE otherwise
+
+*/
+static BOOL BslFindAndInitClientCtx
+(
+ BslClientCtxType** pctx_
+)
+{
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ BslClientCtxType* pctx;
+ v_U8_t i;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslFindAndInitClientCtx\n" );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,"%s:BslClientLock already inited",__FUNCTION__);
+ // return(0);
+ }
+
+ for ( i=0; i < BSL_MAX_CLIENTS; i++ )
+ {
+ if ( !BslClientCtx[i].used )
+ {
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,"%s:BslClientCtx[%d] selected",__FUNCTION__, i);
+ BslClientCtx[i].used = TRUE;
+ break;
+ }
+ }
+
+ if ( i == BSL_MAX_CLIENTS )
+ {
+ // no more clients can be supported
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslFindAndInitClientCtx no more "
+ "clients can be supported MAX=%d\n", BSL_MAX_CLIENTS );
+ return FALSE;
+ }
+
+ //pctx = BslClientCtx + i;
+ pctx = gpBslctx;
+
+ // get a handle from BAP
+ VosStatus = WLANBAP_GetNewHndl(&pctx->bapHdl);
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ pctx->used = FALSE;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s:WLAN_GetNewHndl Failed",__FUNCTION__);
+
+ return(FALSE);
+ }
+
+ // register the event cb with BAP, this cb is used for BOTH association
+ // specific and non-association specific event notifications by BAP.
+ // However association specific events will be called with a different
+ // cookie that is passed in during the physical link create/accept
+ VosStatus = WLAN_BAPRegisterBAPCallbacks( pctx->bapHdl, WLANBAP_EventCB, pctx );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ pctx->used = FALSE;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s:WLAN_BAPRegsiterBAPCallaback Failed",__FUNCTION__);
+
+ return(FALSE);
+ }
+
+ // init the PhyLinks queue to keep track of the assoc's of this client
+ VosStatus = vos_list_init( &pctx->PhyLinks );
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
+
+ *pctx_ = pctx;
+
+ return(TRUE);
+} //BslFindAndInitClientCtx()
+
+/**
+ @brief BslReleaseClientCtx() - This function will release a client a.k.a. app
+ context
+
+ @param pctx : [in] ptr to the client context
+
+ @return
+ None
+
+*/
+//#if 0
+static void BslReleaseClientCtx
+(
+ BslClientCtxType* pctx
+)
+{
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ vos_list_node_t* pLink;
+ BslPhyLinksNodeType *pPhyNode;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslReleaseClientCtx\n" );
+
+ // an app can do this without cleaning up after itself i.e. it can have active associations and
+ // data pending, we need to cleanup its mess
+
+ // first tell BAP we dont want the handle anymore, BAP will cleanup all the associations and
+ // consume resulting HCI events, so after this we will not get any HCI events. we will also
+ // not see any FetchPktCB and RxPktCB. We can still expect TxCompletePktCB
+ VosStatus = WLANBAP_ReleaseHndl( pctx->bapHdl );
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
+
+
+ // find and free all of the association contexts belonging to this app
+ while ( VOS_IS_STATUS_SUCCESS( VosStatus = vos_list_remove_front( &pctx->PhyLinks, &pLink ) ) )
+ {
+ pPhyNode = (BslPhyLinksNodeType *)pLink;
+
+ // since the phy link has already been removed from the list of active
+ // associations, make sure we dont attempt to do this again
+ pPhyNode->pPhy->pPhyLinkDescNode = NULL;
+
+ BslReleasePhyCtx( pPhyNode->pPhy );
+ }
+
+ VOS_ASSERT( VosStatus == VOS_STATUS_E_EMPTY );
+
+ // destroy the PhyLinks queue
+ VosStatus = vos_list_destroy( &pctx->PhyLinks );
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
+
+ pctx->used = FALSE;
+
+} // BslReleaseClientCtx()
+//#endif
+
+/**
+ @brief BslInitPhyCtx() - Initialize the Phy Context array.
+
+
+ @return
+ TRUE if all OK, FALSE otherwise
+
+*/
+static BOOL BslInitPhyCtx (void)
+{
+ v_U16_t i;
+ // free PHY context
+
+ for ( i=0; i<BSL_MAX_PHY_LINKS; i++ )
+ {
+ BslPhyLinkCtx[i].used = FALSE;
+ }
+
+ return (TRUE);
+} // BslInitPhyCtx()
+
+
+/**
+ @brief BslFindAndInitPhyCtx() - This function will try to find a free physical
+ link a.k.a assocation context and if successful, then init that context
+
+ @param pctx : [in] the client context
+ @param PhyLinkHdl : [in] the physical link handle chosen by application
+ @param ppPhyCtx : [inout] ptr to the physical link context
+
+ @return
+ TRUE if all OK, FALSE otherwise
+
+*/
+static BOOL BslFindAndInitPhyCtx
+(
+ BslClientCtxType* pctx,
+ v_U8_t PhyLinkHdl,
+ BslPhyLinkCtxType** ppPhyCtx
+)
+{
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ v_U16_t i;
+ v_U16_t j;
+ vos_list_node_t* pLink;
+ BslPhyLinksNodeType *pNode;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslFindAndInitPhyCtx\n" );
+
+ for ( i=0; i<BSL_MAX_PHY_LINKS; i++ )
+ {
+ if ( !BslPhyLinkCtx[i].used )
+ {
+ BslPhyLinkCtx[i].used = TRUE;
+ break;
+ }
+ }
+
+ if ( i==BSL_MAX_PHY_LINKS )
+ {
+ return(FALSE);
+ }
+ else
+ {
+
+ // now init this context
+
+ *ppPhyCtx = BslPhyLinkCtx + i;
+
+ // setup a ptr to the app context that this assocation specific context lives in
+ BslPhyLinkCtx[i].pClientCtx = pctx;
+
+ // Mark as used
+ (*ppPhyCtx)->used = TRUE;
+
+ // store the PHY link handle
+ BslPhyLinkCtx[i].PhyLinkHdl = PhyLinkHdl;
+
+ // init the TX queues
+ for ( j=0; j<WLANTL_MAX_AC; j++ )
+ {
+ hdd_list_init( &BslPhyLinkCtx[i].ACLTxQueue[j], HDD_TX_QUEUE_MAX_LEN );
+ //VosStatus = vos_list_init( &BslPhyLinkCtx[i].ACLTxQueue[j] );
+ //VosStatus = vos_list_init( &(BslPhyLinkCtx+i)->ACLTxQueue );
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
+ }
+
+ // need to add this Phy context to the client list of associations,
+ // useful during Close operation
+
+ // get a pkt desc
+ VosStatus = vos_list_remove_front( &BslPhyLinksDescPool, &pLink );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ // this could happen due to pool not being big enough, etc
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslFindAndInitPhyCtx failed to "
+ "get node from BslPhyLinksDescPool vstatus=%d\n", VosStatus );
+ BslReleasePhyCtx( *ppPhyCtx );
+ return FALSE;
+ }
+
+ // stick the VOS pkt into the node
+ pNode = (BslPhyLinksNodeType *) pLink;
+ pNode->node = *pLink;
+ pNode->pPhy = *ppPhyCtx;
+
+
+ // now queue the pkt into the correct queue
+ VosStatus = vos_list_insert_back( &pctx->PhyLinks, pLink );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_ASSERT(0);
+ }
+
+ // need to record the desc for this assocation in the list of
+ // active assocations in client context to allow cleanup later
+ (*ppPhyCtx)->pPhyLinkDescNode = pNode;
+
+ return(TRUE);
+ }
+} // BslFindAndInitPhyCtx()
+
+/**
+ @brief BslProcessHCICommand() - This function will process an HCI command i.e
+ take an HCI command buffer, unpack it and then call the appropriate BAP API
+
+ @param pctx : [in] ptr to the client context
+ @param pBuffer_ : [in] the input buffer containing the HCI command
+ @param Count_ : [in] size of the HCI command buffer
+
+ @return
+ TRUE if all OK, FALSE otherwise
+
+*/
+static BOOL BslProcessHCICommand
+(
+ BslClientCtxType* pctx,
+ LPCVOID pBuffer_,
+ DWORD Count_
+)
+{
+ LPVOID pBuffer = (LPVOID) pBuffer_; // castaway the const-ness of the ptr
+ v_U16_t Count = (v_U16_t) Count_; // this should be OK max size < 1500
+ v_U32_t UnpackStatus;
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ BOOL Status;
+ BslPhyLinkCtxType* pPhyCtx;
+ tBtampHCI_Event HCIEvt;
+ v_U16_t x = 1;
+ int i = 0;
+
+ // the opcode is in LE, if we are LE too then this is fine else we need some
+ // byte swapping
+ v_U16_t cmdOpcode = *(UNALIGNED v_U16_t *)pBuffer;
+ v_U8_t *pBuf = (v_U8_t *)pBuffer;
+ v_U8_t *pTmp = (v_U8_t *)pBuf;
+
+ // TODO: do we really need to do this per call even though the op is quite cheap
+ if(*(v_U8_t *)&x == 0)
+ {
+ // BE
+ cmdOpcode = ( cmdOpcode & 0xFF ) << 8 | ( cmdOpcode & 0xFF00 ) >> 8;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslProcessHCICommand: cmdOpcode = %hx\n", cmdOpcode );
+
+ for(i=0; i<4; i++)
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: *pBuf before advancepTmp[%x] = %x\n", i,pTmp[i] );
+
+ pBuf+=CMD_TLV_TYPE_AND_LEN_SIZE;
+
+
+ switch ( cmdOpcode )
+ {
+ /** BT v3.0 Link Control commands */
+ case BTAMP_TLV_HCI_CREATE_PHYSICAL_LINK_CMD:
+ {
+ tBtampTLVHCI_Create_Physical_Link_Cmd CreatePhysicalLinkCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Create_Physical_Link_Cmd( NULL,
+ pBuf, Count, &CreatePhysicalLinkCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ if(VOS_FALSE == WLANBAP_AmpConnectionAllowed())
+ {
+ VosStatus = WLANBAP_PhyLinkFailure(pctx, CreatePhysicalLinkCmd.phy_link_handle);
+ if ( VOS_STATUS_SUCCESS != VosStatus )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLANBAP_PhyLinkFailure failed");
+ // handle the error
+ return(FALSE);
+ }
+ break;
+ }
+
+ // setup the per PHY link BAP context
+ Status = BslFindAndInitPhyCtx( pctx, CreatePhysicalLinkCmd.phy_link_handle,
+ &pPhyCtx );
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "CreatePhysicalLinkCmd.phy_link_handle=%d\n",CreatePhysicalLinkCmd.phy_link_handle);
+
+ if ( !Status )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: BslFindAndInitPhyCtx failed");
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPPhysicalLinkCreate( pctx->bapHdl,
+ &CreatePhysicalLinkCmd, pPhyCtx, &HCIEvt );
+
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPPhysicalLinkCreate failed status %d", VosStatus);
+ // handle the error
+ BslReleasePhyCtx( pPhyCtx );
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pPhyCtx, &HCIEvt, TRUE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ BslReleasePhyCtx( pPhyCtx );
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_ACCEPT_PHYSICAL_LINK_CMD:
+ {
+ tBtampTLVHCI_Accept_Physical_Link_Cmd AcceptPhysicalLinkCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Accept_Physical_Link_Cmd( NULL,
+ pBuf, Count, &AcceptPhysicalLinkCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Accept_Physical_Link_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ if(VOS_FALSE == WLANBAP_AmpConnectionAllowed())
+ {
+ VosStatus = WLANBAP_PhyLinkFailure(pctx, AcceptPhysicalLinkCmd.phy_link_handle);
+ if ( VOS_STATUS_SUCCESS != VosStatus )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLANBAP_PhyLinkFailure failed");
+ // handle the error
+ return(FALSE);
+ }
+ break;
+ }
+
+ // setup the per PHY link BAP context
+ Status = BslFindAndInitPhyCtx( pctx, AcceptPhysicalLinkCmd.phy_link_handle,
+ &pPhyCtx );
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "AcceptPhysicalLinkCmd.phy_link_handle=%d\n",AcceptPhysicalLinkCmd.phy_link_handle);
+
+ if ( !Status )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: BslFindAndInitPhyCtx failed");
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPPhysicalLinkAccept( pctx->bapHdl,
+ &AcceptPhysicalLinkCmd, pPhyCtx, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPPhysicalLinkAccept failed status %d", VosStatus);
+ // handle the error
+ BslReleasePhyCtx( pPhyCtx );
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pPhyCtx, &HCIEvt, TRUE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ BslReleasePhyCtx( pPhyCtx );
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_DISCONNECT_PHYSICAL_LINK_CMD:
+ {
+ tBtampTLVHCI_Disconnect_Physical_Link_Cmd DisconnectPhysicalLinkCmd;
+ Count = Count - 3;//Type and length field lengths are not needed
+ pTmp = pBuf;
+ for(i=0; i<4; i++)
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: *pBuf in Disconnect phy link pTmp[%x] = %x\n", i,pTmp[i] );
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Disconnect_Physical_Link_Cmd( NULL,
+ pBuf, Count, &DisconnectPhysicalLinkCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Disconnect_Physical_Link_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPPhysicalLinkDisconnect( pctx->bapHdl,
+ &DisconnectPhysicalLinkCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPPhysicalLinkDisconnect failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_CREATE_LOGICAL_LINK_CMD:
+ {
+ tBtampTLVHCI_Create_Logical_Link_Cmd CreateLogicalLinkCmd;
+ Count -= 3; //To send the correct length to unpack event
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Create_Logical_Link_Cmd( NULL,
+ pBuf, Count, &CreateLogicalLinkCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Create_Logical_Link_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPLogicalLinkCreate( pctx->bapHdl,
+ &CreateLogicalLinkCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPLogicalLinkCreate failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_ACCEPT_LOGICAL_LINK_CMD:
+ {
+ tBtampTLVHCI_Accept_Logical_Link_Cmd AcceptLogicalLinkCmd;
+ Count = Count - 3;//Subtract Type and Length fields
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Accept_Logical_Link_Cmd( NULL,
+ pBuf, Count, &AcceptLogicalLinkCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Accept_Logical_Link_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPLogicalLinkAccept( pctx->bapHdl,
+ &AcceptLogicalLinkCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPLogicalLinkAccept failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_DISCONNECT_LOGICAL_LINK_CMD:
+ {
+ tBtampTLVHCI_Disconnect_Logical_Link_Cmd DisconnectLogicalLinkCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Disconnect_Logical_Link_Cmd( NULL,
+ pBuf, Count, &DisconnectLogicalLinkCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Disconnect_Logical_Link_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPLogicalLinkDisconnect( pctx->bapHdl,
+ &DisconnectLogicalLinkCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPLogicalLinkDisconnect failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_LOGICAL_LINK_CANCEL_CMD:
+ {
+ tBtampTLVHCI_Logical_Link_Cancel_Cmd LogicalLinkCancelCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Logical_Link_Cancel_Cmd( NULL,
+ pBuf, Count, &LogicalLinkCancelCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Logical_Link_Cancel_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPLogicalLinkCancel( pctx->bapHdl,
+ &LogicalLinkCancelCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPLogicalLinkCancel failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_FLOW_SPEC_MODIFY_CMD:
+ {
+ tBtampTLVHCI_Flow_Spec_Modify_Cmd FlowSpecModifyCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Flow_Spec_Modify_Cmd( NULL,
+ pBuf, Count, &FlowSpecModifyCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Flow_Spec_Modify_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPFlowSpecModify( pctx->bapHdl,
+ &FlowSpecModifyCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPFlowSpecModify failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ /*
+ Host Controller and Baseband Commands
+ */
+ case BTAMP_TLV_HCI_RESET_CMD:
+ {
+ VosStatus = WLAN_BAPReset( pctx->bapHdl );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReset failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_SET_EVENT_MASK_CMD:
+ {
+ tBtampTLVHCI_Set_Event_Mask_Cmd SetEventMaskCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Set_Event_Mask_Cmd( NULL,
+ pBuf, Count, &SetEventMaskCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Set_Event_Mask_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPSetEventMask( pctx->bapHdl,
+ &SetEventMaskCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPSetEventMask failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_FLUSH_CMD:
+ {
+ tBtampTLVHCI_Flush_Cmd FlushCmd;
+
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Flush_Cmd( NULL,
+ pBuf, Count, &FlushCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Flush_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ /* Flush the TX queue */
+//#ifdef BAP_DEBUG
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s:HCI Flush command - will flush Tx Queue", __FUNCTION__);
+//#endif //BAP_DEBUG
+ // JEZ100604: Temporary short cut
+ pPhyCtx = &BslPhyLinkCtx[0];
+ VosStatus = BslFlushTxQueues ( pPhyCtx);
+
+ /* Acknowledge the command */
+ VosStatus = WLAN_BAPFlush( pctx->bapHdl, &FlushCmd );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLAN_BAPFlush failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_ENHANCED_FLUSH_CMD:
+ {
+ tBtampTLVHCI_Enhanced_Flush_Cmd FlushCmd;
+
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Enhanced_Flush_Cmd( NULL,
+ pBuf, Count, &FlushCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: btampUnpackTlvHCI_Enhanced_Flush_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ /* Flush the TX queue */
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s:HCI Flush command - will flush Tx Queue for pkt type %d", __FUNCTION__, FlushCmd.packet_type);
+ // We support BE traffic only
+ if(WLANTL_AC_BE == FlushCmd.packet_type)
+ {
+ pPhyCtx = &BslPhyLinkCtx[0];
+ VosStatus = BslFlushTxQueues ( pPhyCtx);
+ }
+
+ /* Acknowledge the command */
+ VosStatus = WLAN_EnhancedBAPFlush( pctx->bapHdl, &FlushCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLAN_EnahncedBAPFlush failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_CONNECTION_ACCEPT_TIMEOUT_CMD:
+ {
+ VosStatus = WLAN_BAPReadConnectionAcceptTimeout( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadConnectionAcceptTimeout failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT_CMD:
+ {
+ tBtampTLVHCI_Write_Connection_Accept_Timeout_Cmd WriteConnectionAcceptTimeoutCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Write_Connection_Accept_Timeout_Cmd( NULL,
+ pBuf, Count, &WriteConnectionAcceptTimeoutCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Connection_Accept_Timeout_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPWriteConnectionAcceptTimeout( pctx->bapHdl,
+ &WriteConnectionAcceptTimeoutCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteConnectionAcceptTimeout failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_LINK_SUPERVISION_TIMEOUT_CMD:
+ {
+ tBtampTLVHCI_Read_Link_Supervision_Timeout_Cmd ReadLinkSupervisionTimeoutCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Read_Link_Supervision_Timeout_Cmd( NULL,
+ pBuf, Count, &ReadLinkSupervisionTimeoutCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Link_Supervision_Timeout_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPReadLinkSupervisionTimeout( pctx->bapHdl,
+ &ReadLinkSupervisionTimeoutCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLinkSupervisionTimeout failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_WRITE_LINK_SUPERVISION_TIMEOUT_CMD:
+ {
+ tBtampTLVHCI_Write_Link_Supervision_Timeout_Cmd WriteLinkSupervisionTimeoutCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Write_Link_Supervision_Timeout_Cmd( NULL,
+ pBuf, Count, &WriteLinkSupervisionTimeoutCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Link_Supervision_Timeout_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPWriteLinkSupervisionTimeout( pctx->bapHdl,
+ &WriteLinkSupervisionTimeoutCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteLinkSupervisionTimeout failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ /* v3.0 Host Controller and Baseband Commands */
+ case BTAMP_TLV_HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT_CMD:
+ {
+ VosStatus = WLAN_BAPReadLogicalLinkAcceptTimeout( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLogicalLinkAcceptTimeout failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT_CMD:
+ {
+ tBtampTLVHCI_Write_Logical_Link_Accept_Timeout_Cmd WriteLogicalLinkAcceptTimeoutCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Write_Logical_Link_Accept_Timeout_Cmd( NULL,
+ pBuf, Count, &WriteLogicalLinkAcceptTimeoutCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Logical_Link_Accept_Timeout_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPWriteLogicalLinkAcceptTimeout( pctx->bapHdl,
+ &WriteLogicalLinkAcceptTimeoutCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteLogicalLinkAcceptTimeout failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_SET_EVENT_MASK_PAGE_2_CMD:
+ {
+ tBtampTLVHCI_Set_Event_Mask_Page_2_Cmd SetEventMaskPage2Cmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Set_Event_Mask_Page_2_Cmd( NULL,
+ pBuf, Count, &SetEventMaskPage2Cmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Set_Event_Mask_Page_2_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPSetEventMaskPage2( pctx->bapHdl,
+ &SetEventMaskPage2Cmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPSetEventMaskPage2 failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_LOCATION_DATA_CMD:
+ {
+ VosStatus = WLAN_BAPReadLocationData( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocationData failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_WRITE_LOCATION_DATA_CMD:
+ {
+ tBtampTLVHCI_Write_Location_Data_Cmd WriteLocationDataCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Write_Location_Data_Cmd( NULL,
+ pBuf, Count, &WriteLocationDataCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Location_Data_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPWriteLocationData( pctx->bapHdl,
+ &WriteLocationDataCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteLocationData failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_FLOW_CONTROL_MODE_CMD:
+ {
+ VosStatus = WLAN_BAPReadFlowControlMode( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadFlowControlMode failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_WRITE_FLOW_CONTROL_MODE_CMD:
+ {
+ tBtampTLVHCI_Write_Flow_Control_Mode_Cmd WriteFlowControlModeCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Write_Flow_Control_Mode_Cmd( NULL,
+ pBuf, Count, &WriteFlowControlModeCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Flow_Control_Mode_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPWriteFlowControlMode( pctx->bapHdl,
+ &WriteFlowControlModeCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteFlowControlMode failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT_CMD:
+ {
+ tBtampTLVHCI_Read_Best_Effort_Flush_Timeout_Cmd ReadBestEffortFlushTimeoutCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Read_Best_Effort_Flush_Timeout_Cmd( NULL,
+ pBuf, Count, &ReadBestEffortFlushTimeoutCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Best_Effort_Flush_Timeout_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPReadBestEffortFlushTimeout( pctx->bapHdl,
+ &ReadBestEffortFlushTimeoutCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadBestEffortFlushTimeout failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT_CMD:
+ {
+ tBtampTLVHCI_Write_Best_Effort_Flush_Timeout_Cmd WriteBestEffortFlushTimeoutCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Write_Best_Effort_Flush_Timeout_Cmd( NULL,
+ pBuf, Count, &WriteBestEffortFlushTimeoutCmd);
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Best_Effort_Flush_Timeout_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPWriteBestEffortFlushTimeout( pctx->bapHdl,
+ &WriteBestEffortFlushTimeoutCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteBestEffortFlushTimeout failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ /** opcode definition for this command from AMP HCI CR D9r4 markup */
+ case BTAMP_TLV_HCI_SET_SHORT_RANGE_MODE_CMD:
+ {
+ tBtampTLVHCI_Set_Short_Range_Mode_Cmd SetShortRangeModeCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Set_Short_Range_Mode_Cmd( NULL,
+ pBuf, Count, &SetShortRangeModeCmd);
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Set_Short_Range_Mode_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPSetShortRangeMode( pctx->bapHdl,
+ &SetShortRangeModeCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPSetShortRangeMode failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ /* End of v3.0 Host Controller and Baseband Commands */
+ /*
+ Informational Parameters
+ */
+ case BTAMP_TLV_HCI_READ_LOCAL_VERSION_INFO_CMD:
+ {
+ VosStatus = WLAN_BAPReadLocalVersionInfo( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocalVersionInfo failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_LOCAL_SUPPORTED_CMDS_CMD:
+ {
+ VosStatus = WLAN_BAPReadLocalSupportedCmds( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocalSupportedCmds failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_BUFFER_SIZE_CMD:
+ {
+ VosStatus = WLAN_BAPReadBufferSize( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadBufferSize failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ /* v3.0 Informational commands */
+ case BTAMP_TLV_HCI_READ_DATA_BLOCK_SIZE_CMD:
+ {
+ VosStatus = WLAN_BAPReadDataBlockSize( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadDataBlockSize failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ /*
+ Status Parameters
+ */
+ case BTAMP_TLV_HCI_READ_FAILED_CONTACT_COUNTER_CMD:
+ {
+ tBtampTLVHCI_Read_Failed_Contact_Counter_Cmd ReadFailedContactCounterCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Read_Failed_Contact_Counter_Cmd( NULL,
+ pBuf, Count, &ReadFailedContactCounterCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Failed_Contact_Counter_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPReadFailedContactCounter( pctx->bapHdl,
+ &ReadFailedContactCounterCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadFailedContactCounter failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_RESET_FAILED_CONTACT_COUNTER_CMD:
+ {
+ tBtampTLVHCI_Reset_Failed_Contact_Counter_Cmd ResetFailedContactCounterCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Reset_Failed_Contact_Counter_Cmd( NULL,
+ pBuf, Count, &ResetFailedContactCounterCmd);
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Reset_Failed_Contact_Counter_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPResetFailedContactCounter( pctx->bapHdl,
+ &ResetFailedContactCounterCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPResetFailedContactCounter failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_LINK_QUALITY_CMD:
+ {
+ tBtampTLVHCI_Read_Link_Quality_Cmd ReadLinkQualityCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Read_Link_Quality_Cmd( NULL,
+ pBuf, Count, &ReadLinkQualityCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Link_Quality_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPReadLinkQuality( pctx->bapHdl,
+ &ReadLinkQualityCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLinkQuality failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_RSSI_CMD:
+ {
+ tBtampTLVHCI_Read_RSSI_Cmd ReadRssiCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Read_RSSI_Cmd( NULL,
+ pBuf, Count, &ReadRssiCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_RSSI_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPReadRSSI( pctx->bapHdl,
+ &ReadRssiCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadRSSI failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_LOCAL_AMP_INFORMATION_CMD:
+ {
+ tBtampTLVHCI_Read_Local_AMP_Information_Cmd ReadLocalAmpInformationCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Read_Local_AMP_Information_Cmd( NULL,
+ pBuf, Count, &ReadLocalAmpInformationCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Local_AMP_Information_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPReadLocalAMPInfo( pctx->bapHdl,
+ &ReadLocalAmpInformationCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocalAMPInfo failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_READ_LOCAL_AMP_ASSOC_CMD:
+ {
+ tBtampTLVHCI_Read_Local_AMP_Assoc_Cmd ReadLocalAmpAssocCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Read_Local_AMP_Assoc_Cmd( NULL,
+ pBuf, Count, &ReadLocalAmpAssocCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Local_AMP_Assoc_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPReadLocalAMPAssoc( pctx->bapHdl,
+ &ReadLocalAmpAssocCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocalAMPAssoc failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_WRITE_REMOTE_AMP_ASSOC_CMD:
+ {
+ tBtampTLVHCI_Write_Remote_AMP_ASSOC_Cmd WriteRemoteAmpAssocCmd;
+ // unpack
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: HCI_Write_Remote_AMP_ASSOC_Cmd Count = %d", Count);
+ DUMPLOG(1, __FUNCTION__, "HCI_Write_Remote_AMP_ASSOC cmd",
+ pBuf,
+ Count);
+
+ UnpackStatus = btampUnpackTlvHCI_Write_Remote_AMP_ASSOC_Cmd( NULL,
+ pBuf, Count, &WriteRemoteAmpAssocCmd );
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WriteRemoteAmpAssocCmd.amp_assoc_remaining_length = %d",
+ WriteRemoteAmpAssocCmd.amp_assoc_remaining_length
+ );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Remote_AMP_ASSOC_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+//#define BAP_UNIT_TEST
+#ifdef BAP_UNIT_TEST
+ {
+ unsigned char test_amp_assoc_fragment[] =
+ {
+ 0x01, 0x00, 0x06, 0x00, 0x00, 0xde, 0xad, 0xbe,
+ 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x0c, 0x00, 0x55, 0x53, 0x20, 0xc9, 0x0c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x06, 0x00, 0x55, 0x53,
+ 0x20, 0xc9, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00,
+ 0x00, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+ };
+ WriteRemoteAmpAssocCmd.present = 1;
+ WriteRemoteAmpAssocCmd.phy_link_handle = 1;
+ WriteRemoteAmpAssocCmd.length_so_far = 0;
+ WriteRemoteAmpAssocCmd.amp_assoc_remaining_length = 74;
+ /* Set the amp_assoc_fragment to the right values of MAC addr and
+ * channels
+ */
+ vos_mem_copy(
+ WriteRemoteAmpAssocCmd.amp_assoc_fragment,
+ test_amp_assoc_fragment,
+ sizeof( test_amp_assoc_fragment));
+
+ }
+#endif
+
+ VosStatus = WLAN_BAPWriteRemoteAMPAssoc( pctx->bapHdl,
+ &WriteRemoteAmpAssocCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteRemoteAMPAssoc failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ /*
+ Debug Commands
+ */
+ case BTAMP_TLV_HCI_READ_LOOPBACK_MODE_CMD:
+ {
+ tBtampTLVHCI_Read_Loopback_Mode_Cmd ReadLoopbackModeCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Read_Loopback_Mode_Cmd( NULL,
+ pBuf, Count, &ReadLoopbackModeCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Loopback_Mode_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPReadLoopbackMode( pctx->bapHdl,
+ &ReadLoopbackModeCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLoopbackMode failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_WRITE_LOOPBACK_MODE_CMD:
+ {
+ tBtampTLVHCI_Write_Loopback_Mode_Cmd WriteLoopbackModeCmd;
+ // unpack
+ UnpackStatus = btampUnpackTlvHCI_Write_Loopback_Mode_Cmd( NULL,
+ pBuf, Count, &WriteLoopbackModeCmd );
+
+ if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Loopback_Mode_Cmd failed status %d", UnpackStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ VosStatus = WLAN_BAPWriteLoopbackMode( pctx->bapHdl,
+ &WriteLoopbackModeCmd, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteLoopbackMode failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_VENDOR_SPECIFIC_CMD_0:
+ {
+ VosStatus = WLAN_BAPVendorSpecificCmd0( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPVendorSpecificCmd0 failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ case BTAMP_TLV_HCI_VENDOR_SPECIFIC_CMD_1:
+ {
+ VosStatus = WLAN_BAPVendorSpecificCmd1( pctx->bapHdl, &HCIEvt );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPVendorSpecificCmd1 failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+ break;
+ }
+ default:
+ {
+ /* Unknow opcode. Return a command status event...with "Unknown Opcode" status */
+
+ /* Format the command status event to return... */
+ HCIEvt.bapHCIEventCode = BTAMP_TLV_HCI_COMMAND_STATUS_EVENT;
+ HCIEvt.u.btampCommandStatusEvent.present = 1;
+ HCIEvt.u.btampCommandStatusEvent.status = WLANBAP_ERROR_UNKNOWN_HCI_CMND;
+ HCIEvt.u.btampCommandStatusEvent.num_hci_command_packets = 1;
+ HCIEvt.u.btampCommandStatusEvent.command_opcode
+ = cmdOpcode;
+
+ // this may look strange as this is the function registered
+ // with BAP for the EventCB but we are also going to use it
+ // as a helper function. The difference is that this invocation
+ // runs in HCI command sending caller context while the callback
+ // will happen in BAP's context whatever that may be
+ VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
+ // handle the error
+ return(FALSE);
+ }
+
+
+ break;
+ }
+ }
+
+ return(TRUE);
+} // BslProcessHCICommand()
+
+
+/**
+ @brief BslProcessACLDataTx() - This function will process an egress ACL data packet
+
+ @param pctx : [in] ptr to the client context
+ @param pBuffer_ : [in] ptr to the buffer containing the ACL data packet
+ @param pCount : [in] size of the ACL data packet buffer
+
+ @return
+ TRUE if all OK, FALSE otherwise
+
+*/
+#define BTAMP_USE_VOS_WRAPPER
+//#undef BTAMP_USE_VOS_WRAPPER
+#ifdef BTAMP_USE_VOS_WRAPPER
+static BOOL BslProcessACLDataTx
+(
+ BslClientCtxType* pctx,
+ struct sk_buff *skb,
+ v_SIZE_t* pCount
+)
+#else
+static BOOL BslProcessACLDataTx
+(
+ BslClientCtxType* pctx,
+ LPCVOID pBuffer_,
+ v_SIZE_t* pCount
+)
+#endif
+{
+#ifndef BTAMP_USE_VOS_WRAPPER
+ LPVOID pBuffer = (LPVOID) pBuffer_; // castaway const-ness of ptr
+#endif
+ BOOL findPhyStatus;
+ BslPhyLinkCtxType* pPhyCtx;
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ WLANTL_ACEnumType Ac;
+ hdd_list_node_t* pLink;
+ BslTxListNodeType *pNode;
+ v_SIZE_t ListSize;
+ // I will access the skb in a VOSS packet
+#ifndef BTAMP_USE_VOS_WRAPPER
+ struct sk_buff *skb;
+#endif
+#if 0
+ static int num_packets = 0;
+#endif
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslProcessACLDataTx\n" );
+
+ // need to find the PHY link for this ACL data pkt based on phy_link_handle
+ // TODO need some endian-ness check?
+ ////findPhyStatus = BslFindPhyCtx( pctx, *(v_U8_t *)skb->data, &pPhyCtx );
+ //findPhyStatus = BslFindPhyCtx( pctx, *(v_U8_t *)pBuffer, &pPhyCtx );
+ // JEZ100604: Temporary short cut
+ pPhyCtx = &BslPhyLinkCtx[0];
+ findPhyStatus = VOS_TRUE;
+
+ if ( findPhyStatus )
+ {
+ //Use the skb->cb field to hold the list node information
+ pNode = (BslTxListNodeType *) &skb->cb;
+
+ // This list node info includes the VOS pkt
+ pNode->skb = skb;
+
+ // stick the SKB into the node
+ pLink = (hdd_list_node_t *) pNode;
+ VosStatus = WLANBAP_GetAcFromTxDataPkt(pctx->bapHdl, skb->data, &Ac);
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessACLDataTx WLANBAP_GetAcFromTxDataPkt "
+ "failed status =%d\n", VosStatus );
+
+ Ac = WLANTL_AC_BE;
+ }
+
+ // now queue the pkt into the correct queue
+ // We will want to insert a node of type BslTxListNodeType (was going to be vos_pkt_list_node_t)
+ spin_lock_bh(&pPhyCtx->ACLTxQueue[Ac].lock);
+ VosStatus = hdd_list_insert_back( &pPhyCtx->ACLTxQueue[Ac], pLink );
+ spin_unlock_bh(&pPhyCtx->ACLTxQueue[Ac].lock);
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_ASSERT(0);
+ }
+
+ // determine if there is a need to signal TL through BAP
+ hdd_list_size( &pPhyCtx->ACLTxQueue[Ac], &ListSize );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_ASSERT(0);
+ }
+
+ if ( ListSize == 1 )
+ {
+ // Let TL know we have a packet to send for this AC
+ VosStatus = WLANBAP_STAPktPending( pctx->bapHdl, pPhyCtx->PhyLinkHdl, Ac );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessACLDataTx WLANBAP_STAPktPending "
+ "failed status =%d\n", VosStatus );
+ VOS_ASSERT(0);
+ }
+ }
+
+ return(TRUE);
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessACLDataTx attempting to send "
+ "data for a non-existant assocation\n" );
+
+ return(FALSE);
+ }
+
+
+} // BslProcessACLDataTx()
+
+
+static inline void *hci_get_drvdata(struct hci_dev *hdev)
+{
+ return hdev->driver_data;
+}
+
+static inline void hci_set_drvdata(struct hci_dev *hdev, void *data)
+{
+ hdev->driver_data = data;
+}
+
+/*---------------------------------------------------------------------------
+ * Function definitions
+ *-------------------------------------------------------------------------*/
+
+/**---------------------------------------------------------------------------
+
+ \brief BSL_Init() - Initialize the BSL Misc char driver
+
+ This is called in vos_open(), right after WLANBAP_Open(), as part of
+ bringing up the BT-AMP PAL (BAP)
+ vos_open() will pass in the VOS context. In which a BSL context can be created.
+
+ \param - NA
+
+ \return - 0 for success non-zero for failure
+
+ --------------------------------------------------------------------------*/
+//int BSL_Init (void *pCtx)
+int BSL_Init ( v_PVOID_t pvosGCtx )
+{
+ BslClientCtxType* pctx = NULL;
+ ptBtampHandle bapHdl = NULL; // our handle in BAP
+ //ptBtampContext pBtampCtx = NULL;
+ int err = 0;
+ struct hci_dev *hdev = NULL;
+ //struct net_device *dev = NULL; // Our parent wlan network device
+ hdd_adapter_t *pAdapter = NULL; // Used to retrieve the parent WLAN device
+ hdd_context_t *pHddCtx = NULL;
+ hdd_config_t *pConfig = NULL;
+ hdd_adapter_list_node_t *pAdapterNode = NULL;
+ VOS_STATUS status;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Init");
+
+ /*------------------------------------------------------------------------
+ Allocate (and sanity check?!) BSL control block
+ ------------------------------------------------------------------------*/
+ //vos_alloc_context(pvosGCtx, VOS_MODULE_ID_BSL, (v_VOID_t**)&pctx, sizeof(BslClientCtxType));
+ pctx = &BslClientCtx[0];
+
+ bapHdl = vos_get_context( VOS_MODULE_ID_BAP, pvosGCtx);
+ if ( NULL == bapHdl )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Invalid BAP pointer from pvosGCtx on BSL_Init");
+ return VOS_STATUS_E_FAULT;
+ }
+ // Save away the btamp (actually the vos) context
+ gpCtx = pvosGCtx;
+
+ /* Save away the pointer to the BT-AMP PAL context in the BSL driver context */
+ pctx->bapHdl = bapHdl;
+
+ /* Save away the pointer to the BSL driver context in a global (fix this) */
+ gpBslctx = pctx;
+
+ /* Initialize all the Phy Contexts to un-used */
+ BslInitPhyCtx();
+
+ /* Initialize the Rx fields in the HCI driver context */
+ //pctx->rx_state = RECV_WAIT_PACKET_TYPE;
+ pctx->rx_count = 0;
+ pctx->rx_skb = NULL;
+
+ /* JEZ100713: Temporarily the Tx skb queue will have depth one.*/
+ // Don't disturb tx_skb
+ //pctx->tx_skb = NULL;
+ //pctx->tx_skb = alloc_skb(WLANBAP_MAX_80211_PAL_PDU_SIZE+12, GFP_ATOMIC);
+
+ pctx->hdev = NULL;
+ //Get the HDD context.
+ pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, pvosGCtx );
+ if(NULL != pHddCtx)
+ {
+ pConfig = pHddCtx->cfg_ini;
+ }
+ if(NULL == pConfig)
+ {
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
+ "Didn't register as HCI device");
+ return 0;
+ }
+ else if(0 == pConfig->enableBtAmp)
+ {
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
+ "Didn't register as HCI device, user option(gEnableBtAmp) is set to 0");
+ return 0;
+ }
+
+#ifdef WLAN_SOFTAP_FEATURE
+ if (VOS_STA_SAP_MODE == hdd_get_conparam())
+ {
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+ if ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ if ( WLAN_HDD_SOFTAP == pAdapterNode->pAdapter->device_mode)
+ {
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP);
+ }
+ else if (WLAN_HDD_P2P_GO == pAdapterNode->pAdapter->device_mode)
+ {
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
+ }
+ }
+ }
+ else
+#endif
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
+
+
+ if ( NULL == pAdapter )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Invalid HDD Adapter pointer from pvosGCtx on BSL_Init");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ /* Save away the pointer to the parent WLAN device in BSL driver context */
+ pctx->p_dev = pAdapter->dev;
+
+ /* Initialize HCI device */
+ hdev = hci_alloc_dev();
+ if (!hdev)
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Can't allocate HCI device in BSL_Init");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ /* Save away the HCI device pointer in the BSL driver context */
+ pctx->hdev = hdev;
+
+#if defined HCI_80211 || defined HCI_AMP
+#define BUILD_FOR_BLUETOOTH_NEXT_2_6
+#else
+#undef BUILD_FOR_BLUETOOTH_NEXT_2_6
+#endif
+
+#ifdef BUILD_FOR_BLUETOOTH_NEXT_2_6
+ /* HCI "bus type" of HCI_VIRTUAL should apply */
+ hdev->bus = HCI_VIRTUAL;
+ /* Set the dev_type to BT-AMP 802.11 */
+#ifdef HCI_80211
+ hdev->dev_type = HCI_80211;
+#else
+ hdev->dev_type = HCI_AMP;
+#endif
+#ifdef FEATURE_WLAN_BTAMP_UT
+ /* For the "real" BlueZ build, DON'T Set the device "quirks" to indicate RAW */
+ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+#endif
+#else //BUILD_FOR_BLUETOOTH_NEXT_2_6
+ /* HCI "bus type" of HCI_VIRTUAL should apply */
+ hdev->type = HCI_VIRTUAL;
+ /* Set the dev_type to BT-AMP 802.11 */
+ //hdev->dev_type = HCI_80211;
+ ////hdev->dev_type = HCI_AMP;
+ /* For the "temporary" BlueZ build, Set the device "quirks" to indicate RAW */
+ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+#endif //BUILD_FOR_BLUETOOTH_NEXT_2_6
+ /* Save away the BSL driver pointer in the HCI device context */
+
+ hci_set_drvdata(hdev, pctx);
+ /* Set the parent device for this HCI device. This is our WLAN net_device */
+ SET_HCIDEV_DEV(hdev, &pctx->p_dev->dev);
+
+ hdev->open = BSL_Open;
+ hdev->close = BSL_Close;
+ hdev->flush = BSL_Flush;
+ hdev->send = BSL_Write;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+ hdev->destruct = BSL_Destruct;
+ hdev->owner = THIS_MODULE;
+#endif
+ hdev->ioctl = BSL_IOControl;
+
+
+ /* Timeout before it is safe to send the first HCI packet */
+ msleep(1000);
+
+ /* Register HCI device */
+ err = hci_register_dev(hdev);
+ if (err < 0)
+ {
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Unable to register HCI device, err=%d\n", err);
+ pctx->hdev = NULL;
+ hci_free_dev(hdev);
+ return -ENODEV;
+ }
+
+ pHddCtx->isAmpAllowed = VOS_TRUE;
+ return 0;
+} // BSL_Init()
+
+/**---------------------------------------------------------------------------
+
+ \brief BSL_Deinit() - De-initialize the BSL Misc char driver
+
+ This is called in by WLANBAP_Close() as part of bringing down the BT-AMP PAL (BAP)
+
+ \param - NA
+
+ \return - 0 for success non-zero for failure
+
+ --------------------------------------------------------------------------*/
+
+int BSL_Deinit( v_PVOID_t pvosGCtx )
+{
+ //int err = 0;
+ struct hci_dev *hdev;
+ BslClientCtxType* pctx = NULL;
+
+ //pctx = vos_get_context( VOS_MODULE_ID_BSL, pvosGCtx);
+ pctx = gpBslctx;
+
+ if ( NULL == pctx )
+ {
+ //VOS_TRACE( VOS_MODULE_ID_BSL, VOS_TRACE_LEVEL_ERROR,
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Invalid BSL pointer from pvosGCtx on BSL_Init");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ /* Retrieve the HCI device pointer from the BSL driver context */
+ hdev = pctx->hdev;
+
+ if (!hdev)
+ return 0;
+
+ /* hci_unregister_dev is called again here, in case user didn't call it */
+ /* Unregister device from BlueZ; fcn sends us HCI commands before it returns */
+ /* And then the registered hdev->close fcn should be called by BlueZ (BSL_Close) */
+ hci_unregister_dev(hdev);
+ /* BSL_Close is called again here, in case BlueZ didn't call it */
+ BSL_Close(hdev);
+ hci_free_dev(hdev);
+ pctx->hdev = NULL;
+
+ return 0;
+} // BSL_Deinit()
+
+
+/**
+ @brief BSL_Open() - This function opens a device for reading, and writing.
+ An application indirectly invokes this function when it calls the fopen()
+ system call to open a special device file names.
+
+ @param *hdev : [in] pointer to the open HCI device structure.
+ BSL_Init (Device Manager) function creates and stores this HCI
+ device context in the BSL context.
+
+ @return
+ This function returns a status code. Negative codes are failures.
+
+ NB: I don't seem to be following this convention.
+*/
+//static int BSL_Open(struct inode *pInode, struct file *pFile)
+static int BSL_Open( struct hci_dev *hdev )
+{
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ BslClientCtxType* pctx = (BslClientCtxType *)(hci_get_drvdata(hdev));
+ v_U16_t i;
+ BOOL rval;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Open");
+
+ /* you can only open a btamp device one time */
+ if (bBslInited)
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BSL_Open: Already Opened.");
+ return -EPERM; /* Operation not permitted */
+ }
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSLClientLock already inited");
+ // return -EIO; /* I/O error */
+ return 0;
+ }
+
+ VosStatus = vos_list_init( &BslPhyLinksDescPool );
+
+ if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
+ {
+ //return -EIO; /* I/O error */
+ return 0;
+ }
+
+ // now we need to populate this pool with the free pkt desc from the array
+ for ( i=0; i<BSL_MAX_PHY_LINKS; i++ )
+ {
+ VosStatus = vos_list_insert_front( &BslPhyLinksDescPool, &BslPhyLinksDesc[i].node );
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
+ }
+
+ // This is redundent. See the check above on (fp->private_data != NULL)
+ bBslInited = TRUE;
+
+ rval = BslFindAndInitClientCtx( &pctx );
+
+ if(rval != TRUE)
+ {
+ // Where is the clean-up in case the above BslFindAndInitClientCtx() call
+ // fails?
+ //return -EIO; /* I/O error */
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSLFindAndInitClientContext failed");
+ return 0;
+ }
+
+
+ /* Let Linux fopen() know everything is all right */
+ return 0;
+} // BSL_Open()
+
+/**
+ @brief BSL_Close() - This function closes a device context created by
+ BSL_Open(). May be called more than once during AMP PAL shut down.
+
+ @param *hdev : [in] pointer to the open HCI device structure.
+ BSL_Init (Device Manager) function creates and stores this HCI
+ device context in the BSL context.
+
+ @return
+ TRUE indicates success. FALSE indicates failure.
+*/
+//static int BSL_Close (struct inode *pInode, struct file *pFile)
+static int BSL_Close ( struct hci_dev *hdev )
+{
+ VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
+ BslClientCtxType* pctx;
+ vos_list_node_t* pLink;
+ v_U16_t i;
+ v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
+ hdd_context_t *pHddCtx;
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Close");
+ if (NULL != pVosContext)
+ {
+ pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
+ if (NULL != pHddCtx)
+ {
+ pHddCtx->isAmpAllowed = VOS_FALSE;
+ }
+ }
+
+ // it may seem there is some risk here because we are using a value
+ // passed into us as a pointer. what if this pointer is 0 or points to
+ // someplace bad? as it turns out the caller is device manager and not
+ // the application. kernel should trap such invalid access but we will check
+ // for NULL pointer
+ if ( hdev == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Close: NULL hdev specified");
+ return FALSE;
+ }
+
+ pctx = (BslClientCtxType *)(hci_get_drvdata(hdev));
+
+ if ( pctx == NULL || !bBslInited)
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BSL_Close: %s is not open", hdev->name);
+ return TRUE;
+ }
+
+ // need to cleanup any per PHY state and the common RX state
+ BslReleaseClientCtx( pctx );
+ for ( i=0; i<BslPhyLinksDescPool.count; i++ )
+ {
+ VosStatus = vos_list_remove_front( &BslPhyLinksDescPool, &pLink );
+ //nothing to free as the nodes came from BslPhyLinksDesc, which is a static
+ //this is needed to allow vos_list_destroy() to go through
+ }
+ VosStatus = vos_list_destroy( &BslPhyLinksDescPool );
+
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
+
+
+ bBslInited = FALSE;
+
+// The next line is temporary
+ return(0);
+} //BSL_Close()
+
+/**
+ @brief BSL_IOControl() - This function sends a command to a device.
+
+ @param *hdev : [in] pointer to the open HCI device structure.
+ @param cmd : [in] I/O control operation to perform. These codes are
+ device-specific and are usually exposed to developers through a header file.
+ @param arg : [in] Additional input parameter.
+
+ @return
+ TRUE indicates success. FALSE indicates failure.
+*/
+//static long BSL_IOControl(struct file *pFile, unsigned int cmd, unsigned long arg)
+static int BSL_IOControl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
+{
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_IOControl - not supported");
+ return(TRUE);
+} // BSL_IOControl()
+
+/**
+ @brief BSL_Flush() - This function flushes all pending commands on a device.
+
+ @param *hdev : [in] pointer to the open HCI device structure.
+
+ @return
+ TRUE indicates success. FALSE indicates failure.
+*/
+static int BSL_Flush(struct hci_dev *hdev)
+{
+ VOS_STATUS VosStatus;
+ BslPhyLinkCtxType* pPhyCtx;
+
+ //VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Flush - will flush ALL Tx Queues");
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s - will flush ALL Tx Queues", __FUNCTION__);
+
+ /* Flush the TX queue */
+ // JEZ100604: Temporary short cut
+ pPhyCtx = &BslPhyLinkCtx[0];
+
+ VosStatus = BslFlushTxQueues ( pPhyCtx);
+
+ //return(TRUE);
+ return(0);
+} // BSL_Flush()
+
+/**
+ @brief BSL_Destruct() - This function destroys an HCI device.
+
+ @param *hdev : [in] pointer to the open HCI device structure.
+
+ @return
+ TRUE indicates success. FALSE indicates failure.
+*/
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+static void BSL_Destruct(struct hci_dev *hdev)
+{
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Destruct - not supported");
+ return; //(TRUE);
+} // BSL_Destruct()
+#endif
+
+
+/**
+ @brief BSL_Write() - This function writes data to the device.
+ An application indirectly invokes this function when it calls the fwrite()
+ system call to write to a special device file.
+
+ @param *skb : [in] pointer to the skb being transmitted. This skb contains
+ the HCI command or HCI data. Also a pointer (hdev) to the HCI device struct
+
+ @return
+ The number of bytes written indicates success.
+ Negative values indicate various failures.
+*/
+//static ssize_t BSL_Write(struct file *pFile, const char __user *pBuffer,
+// size_t Count, loff_t *pOff)
+static int BSL_Write(struct sk_buff *skb)
+{
+ struct hci_dev *hdev;
+ BslClientCtxType* pctx;
+ v_SIZE_t written = 0;
+ BOOL status;
+ //char *bslBuff = NULL;
+ BslHciWorkStructure *pHciContext;
+
+ //VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s", __FUNCTION__);
+
+ // Sanity check inputs
+ if ( skb == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: skb is bad i/p", __FUNCTION__);
+ //return -EFAULT; /* Bad address */
+ return 0;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Count (skb->len)=%d", __FUNCTION__, skb->len);
+
+ // Sanity check inputs
+ if ( 0 == skb->len )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: skb is empty", __FUNCTION__);
+ //return -EFAULT; /* Bad address */
+ return 0;
+ }
+
+ hdev = (struct hci_dev *)(skb->dev);
+
+ // Sanity check the HCI device in the skb
+ if ( hdev == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Frame for Unknown HCI device (hdev=NULL)", __FUNCTION__);
+ //return -ENODEV; /* no device */
+ return 0;
+ }
+
+ pctx = (BslClientCtxType *)hci_get_drvdata(hdev);
+
+ // Sanity check inputs
+ if ( pctx == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: pctx is bad i/p", __FUNCTION__);
+ //return -EFAULT; /* Bad address */
+ return 0;
+ /* Maybe I should return "no device" */
+ //return -ENODEV; /* no device */
+ }
+
+ // Switch for each case of packet type
+ switch (bt_cb(skb)->pkt_type)
+ {
+ case HCI_ACLDATA_PKT:
+ // Directly execute the data write
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: HCI ACL data tx, skb=%p",
+ __FUNCTION__, skb);
+ // ACL data
+ hdev->stat.acl_tx++;
+ // Correct way of doing this...
+ written = skb->len;
+#ifdef BTAMP_USE_VOS_WRAPPER
+ status = BslProcessACLDataTx( pctx, skb, &written );
+#else
+ status = BslProcessACLDataTx( pctx, skb->data, &written );
+ // Free up the skb
+ kfree_skb(skb);
+#endif //BTAMP_USE_VOS_WRAPPER
+ break;
+ case HCI_COMMAND_PKT:
+ // Defer the HCI command writes
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: HCI command", __FUNCTION__);
+ hdev->stat.cmd_tx++;
+
+ // Allocate an HCI context. To use as a "container" for the "work" to be deferred.
+ pHciContext = kmalloc(sizeof(*pHciContext), GFP_ATOMIC);
+ if (NULL == pHciContext)
+ {
+ // no memory for HCI context. Nothing we can do but drop
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to allocate context", __FUNCTION__);
+ kfree_skb(skb);
+ return 0;
+ }
+
+ // save away the tx skb in the HCI context...so it can be
+ // retrieved by the work procedure.
+ pHciContext->tx_skb = skb;
+ // save away the pctx context...so it can be retrieved by the work procedure.
+ pHciContext->pctx = pctx;
+ pHciContext->magic = BT_AMP_HCI_CTX_MAGIC;
+ INIT_WORK(&pHciContext->hciInterfaceProcessing,
+ bslWriteFinish);
+
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: Scheduling work for skb %p, BT-AMP Client context %p, work %p",
+ __FUNCTION__, skb, pctx, pHciContext);
+
+ status = schedule_work(&pHciContext->hciInterfaceProcessing);
+
+ // Check result
+ if ( 0 == status )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: hciInterfaceProcessing work already queued. This should never happen.", __FUNCTION__);
+ }
+
+
+ // Temporary way of doing this
+ //written = skb->len-CMD_TLV_TYPE_AND_LEN_SIZE;
+ written = skb->len;
+ break;
+ case HCI_SCODATA_PKT:
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: unknown type", __FUNCTION__);
+ hdev->stat.sco_tx++;
+ // anything else including HCI events and SCO data
+ status = FALSE;
+ // Free up the skb
+ kfree_skb(skb);
+ break;
+ default:
+ // anything else including HCI events and SCO data
+ status = FALSE;
+ // Free up the skb
+ kfree_skb(skb);
+ break;
+ };
+
+
+ // JEZ100809: For the HCI command, will the caller need to wait until the work takes place and
+ // return the ACTUAL amount of data written.
+
+// The next line is temporary
+ //written = skb->len;
+ return(written);
+} // BSL_Write()
+
+/**
+ @brief bslWriteFinish() - This function finished the writes operation
+ started by BSL_Write().
+
+ @param work : [in] pointer to work structure
+
+ @return : void
+
+*/
+static void bslWriteFinish(struct work_struct *work)
+{
+ //BslClientCtxType* pctx =
+ // container_of(work, BslClientCtxType, hciInterfaceProcessing);
+ BslHciWorkStructure *pHciContext =
+ container_of(work, BslHciWorkStructure, hciInterfaceProcessing);
+ BslClientCtxType* pctx = pHciContext->pctx;
+ VOS_STATUS status;
+ struct sk_buff *skb;
+ struct hci_dev *hdev;
+ //char *bslBuff = NULL;
+ v_SIZE_t written = 0;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered, context %p",
+ __FUNCTION__, pctx);
+
+ // Sanity check inputs
+ if ( pctx == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: pctx is bad i/p", __FUNCTION__);
+ return; // -EFAULT; /* Bad address */
+ }
+
+ //skb = pctx->tx_skb;
+ skb = pHciContext->tx_skb;
+ kfree( pHciContext);
+
+ // Sanity check inputs
+ if ( skb == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: skb is bad i/p", __FUNCTION__);
+ return; // -EFAULT; /* Bad address */
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Count (skb->len)=%d", __FUNCTION__, skb->len);
+
+ hdev = (struct hci_dev *)(skb->dev);
+
+ // Sanity check the HCI device in the skb
+ if ( hdev == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Frame for Unknown HCI device (hdev=NULL)", __FUNCTION__);
+ return; // -ENODEV; /* no device */
+ }
+
+
+ // Sanity check inputs
+ if ( pctx != (BslClientCtxType *)hci_get_drvdata(hdev));
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: pctx and hdev not consistent - bad i/p", __FUNCTION__);
+ return; // -EFAULT; /* Bad address */
+ /* Maybe I should return "no device" */
+ //return -ENODEV; /* no device */
+ }
+
+ // Switch for each case of packet type
+ switch (bt_cb(skb)->pkt_type)
+ {
+ case HCI_COMMAND_PKT:
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: HCI command", __FUNCTION__);
+ hdev->stat.cmd_tx++;
+ // HCI command
+ status = BslProcessHCICommand( pctx, skb->data, skb->len-CMD_TLV_TYPE_AND_LEN_SIZE);
+ // Temporary way of doing this
+ //written = skb->len-CMD_TLV_TYPE_AND_LEN_SIZE;
+ written = skb->len;
+ break;
+ case HCI_SCODATA_PKT:
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: unknown type", __FUNCTION__);
+ hdev->stat.sco_tx++;
+ // anything else including HCI events and SCO data
+ status = FALSE;
+ break;
+ default:
+ // anything else including HCI events and SCO data
+ status = FALSE;
+ break;
+ };
+
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: Freeing skb %p",
+ __FUNCTION__, skb);
+
+ consume_skb(skb);
+
+// How do I return the actual number of bytes written to the caller?
+// return(written);
+ return;
+} //bslWriteFinish()
+
+VOS_STATUS WLANBAP_SetConfig
+(
+ WLANBAP_ConfigType *pConfig
+)
+{
+ BslClientCtxType* pctx;
+ VOS_STATUS status;
+ // sanity checking
+ if ( pConfig == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_SetConfig bad input\n" );
+ return VOS_STATUS_E_FAILURE;
+ }
+ pctx = gpBslctx;
+ if ( NULL == pctx )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Invalid BSL pointer from pctx on WLANBAP_SetConfig");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ // get a handle from BAP
+ status = WLANBAP_GetNewHndl(&pctx->bapHdl);
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_SetConfig can't get BAP handle\n" );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+
+ status = WLAN_BAPSetConfig(pctx->bapHdl, pConfig);
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_SetConfig can't set BAP config\n" );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ return(VOS_STATUS_SUCCESS);
+}
+
+VOS_STATUS WLANBAP_RegisterWithHCI(hdd_adapter_t *pAdapter)
+{
+ struct hci_dev *hdev = NULL;
+ BslClientCtxType* pctx = NULL;
+ int err = 0;
+ v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
+ hdd_context_t *pHddCtx;
+
+ pctx = gpBslctx;
+
+ if ( NULL == pctx )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Invalid BSL pointer from pctx on WLANBAP_RegisterWithHCI");
+ return VOS_STATUS_E_FAULT;
+ }
+ if ( NULL == pAdapter )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Invalid HDD Adapter pointer from pvosGCtx on WLANBAP_RegisterWithHCI");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ if(NULL != pctx->hdev)
+ {
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_WARN,
+ "Already registered as HCI device\n");
+ return VOS_STATUS_SUCCESS;
+ }
+
+
+
+ /* Save away the pointer to the parent WLAN device in BSL driver context */
+ pctx->p_dev = pAdapter->dev;
+
+ /* Initialize HCI device */
+ hdev = hci_alloc_dev();
+ if (!hdev)
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Can't allocate HCI device in WLANBAP_RegisterWithHCI");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ /* Save away the HCI device pointer in the BSL driver context */
+ pctx->hdev = hdev;
+
+#if defined HCI_80211 || defined HCI_AMP
+#define BUILD_FOR_BLUETOOTH_NEXT_2_6
+#else
+#undef BUILD_FOR_BLUETOOTH_NEXT_2_6
+#endif
+
+#ifdef BUILD_FOR_BLUETOOTH_NEXT_2_6
+ /* HCI "bus type" of HCI_VIRTUAL should apply */
+ hdev->bus = HCI_VIRTUAL;
+ /* Set the dev_type to BT-AMP 802.11 */
+#ifdef HCI_80211
+ hdev->dev_type = HCI_80211;
+#else
+ hdev->dev_type = HCI_AMP;
+#endif
+#ifdef FEATURE_WLAN_BTAMP_UT
+ /* For the "real" BlueZ build, DON'T Set the device "quirks" to indicate RAW */
+ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+#endif
+#else //BUILD_FOR_BLUETOOTH_NEXT_2_6
+ /* HCI "bus type" of HCI_VIRTUAL should apply */
+ hdev->type = HCI_VIRTUAL;
+ /* Set the dev_type to BT-AMP 802.11 */
+ //hdev->dev_type = HCI_80211;
+ ////hdev->dev_type = HCI_AMP;
+ /* For the "temporary" BlueZ build, Set the device "quirks" to indicate RAW */
+ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+#endif //BUILD_FOR_BLUETOOTH_NEXT_2_6
+ /* Save away the BSL driver pointer in the HCI device context */
+ hci_set_drvdata(hdev, pctx);
+ /* Set the parent device for this HCI device. This is our WLAN net_device */
+ SET_HCIDEV_DEV(hdev, &pctx->p_dev->dev);
+
+ hdev->open = BSL_Open;
+ hdev->close = BSL_Close;
+ hdev->flush = BSL_Flush;
+ hdev->send = BSL_Write;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+ hdev->owner = THIS_MODULE;
+ hdev->destruct = BSL_Destruct;
+#endif
+ hdev->ioctl = BSL_IOControl;
+
+
+ /* Timeout before it is safe to send the first HCI packet */
+ msleep(1000);
+
+ /* Register HCI device */
+ err = hci_register_dev(hdev);
+ if (err < 0)
+ {
+ VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Unable to register HCI device, err=%d\n", err);
+ pctx->hdev = NULL;
+ hci_free_dev(hdev);
+ return VOS_STATUS_E_FAULT;
+ }
+ if (NULL != pVosContext)
+ {
+ pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
+ if (NULL != pHddCtx)
+ {
+ pHddCtx->isAmpAllowed = VOS_TRUE;
+ }
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS WLANBAP_DeregisterFromHCI(void)
+{
+ struct hci_dev *hdev;
+ BslClientCtxType* pctx = NULL;
+
+ pctx = gpBslctx;
+
+ if ( NULL == pctx )
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Invalid BSL pointer from pvosGCtx on WLANBAP_DeregisterFromHCI");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ /* Retrieve the HCI device pointer from the BSL driver context */
+ hdev = pctx->hdev;
+
+ if (!hdev)
+ return VOS_STATUS_E_FAULT;
+
+ /* Unregister device from BlueZ; fcn sends us HCI commands before it returns */
+ /* And then the registered hdev->close fcn should be called by BlueZ (BSL_Close) */
+ hci_unregister_dev(hdev);
+
+ /* BSL_Close is called again here, in case BlueZ didn't call it */
+ BSL_Close(hdev);
+ hci_free_dev(hdev);
+ pctx->hdev = NULL;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS WLANBAP_StopAmp(void)
+{
+ BslClientCtxType* pctx;
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+
+ pctx = gpBslctx;
+
+ if(NULL == pctx)
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Invalid BSL pointer from pvosGCtx on WLANBAP_StopAmp");
+ status = VOS_STATUS_E_FAULT;
+ }
+ else
+ {
+ //is AMP session on, if so disconnect
+ if(VOS_TRUE == WLAN_BAPSessionOn(pctx->bapHdl))
+ {
+ status = WLAN_BAPDisconnect(pctx->bapHdl);
+ }
+ }
+ return status;
+}
+
+v_BOOL_t WLANBAP_AmpSessionOn(void)
+{
+ BslClientCtxType* pctx;
+
+ pctx = gpBslctx;
+ if(NULL == pctx)
+ {
+ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+ "Invalid BSL pointer from pvosGCtx on WLANBAP_AmpSessionOn");
+ return VOS_FALSE;
+ }
+ else
+ {
+ return( WLAN_BAPSessionOn(pctx->bapHdl));
+ }
+}
+
+
+#endif // WLAN_BTAMP_FEATURE
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
new file mode 100644
index 0000000..c988db1
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -0,0 +1,2748 @@
+/*
+ * 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 wlan_hdd_assoc.c
+ \brief WLAN Host Device Driver implementation
+
+ 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.
+
+
+ $Header:$ $DateTime: $ $Author: $
+
+
+ when who what, where, why
+ -------- --- --------------------------------------------------------
+ 05/06/09 Shailender Created module.
+ ==========================================================================*/
+
+#include "wlan_hdd_includes.h"
+#include <aniGlobal.h>
+#include "dot11f.h"
+#include "wlan_nlink_common.h"
+#include "wlan_btc_svc.h"
+#include "wlan_hdd_power.h"
+#ifdef CONFIG_CFG80211
+#include <linux/ieee80211.h>
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+#include "wlan_hdd_cfg80211.h"
+#include "csrInsideApi.h"
+#endif
+#if defined CONFIG_CFG80211
+#include "wlan_hdd_p2p.h"
+#endif
+#include "sme_Api.h"
+
+v_BOOL_t mibIsDot11DesiredBssTypeInfrastructure( hdd_adapter_t *pAdapter );
+
+struct ether_addr
+{
+ u_char ether_addr_octet[6];
+};
+// These are needed to recognize WPA and RSN suite types
+#define HDD_WPA_OUI_SIZE 4
+v_U8_t ccpWpaOui00[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x00 };
+v_U8_t ccpWpaOui01[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x01 };
+v_U8_t ccpWpaOui02[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x02 };
+v_U8_t ccpWpaOui03[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x03 };
+v_U8_t ccpWpaOui04[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x04 };
+v_U8_t ccpWpaOui05[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x05 };
+#ifdef FEATURE_WLAN_CCX
+v_U8_t ccpWpaOui06[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x40, 0x96, 0x00 }; // CCKM
+#endif /* FEATURE_WLAN_CCX */
+#define HDD_RSN_OUI_SIZE 4
+v_U8_t ccpRSNOui00[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x00 }; // group cipher
+v_U8_t ccpRSNOui01[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x01 }; // WEP-40 or RSN
+v_U8_t ccpRSNOui02[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x02 }; // TKIP or RSN-PSK
+v_U8_t ccpRSNOui03[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x03 }; // Reserved
+v_U8_t ccpRSNOui04[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x04 }; // AES-CCMP
+v_U8_t ccpRSNOui05[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x05 }; // WEP-104
+#ifdef FEATURE_WLAN_CCX
+v_U8_t ccpRSNOui06[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x40, 0x96, 0x00 }; // CCKM
+#endif /* FEATURE_WLAN_CCX */
+
+#if defined(WLAN_FEATURE_VOWIFI_11R)
+// Offset where the EID-Len-IE, start.
+#define FT_ASSOC_RSP_IES_OFFSET 6
+#endif
+
+#define BEACON_FRAME_IES_OFFSET 12
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+extern void wlan_hdd_set_mc_addr_list(hdd_context_t *pHddCtx, v_U8_t set);
+#endif
+
+
+static inline v_VOID_t hdd_connSetConnectionState( hdd_station_ctx_t *pHddStaCtx, eConnectionState connState )
+{
+ // save the new connection state
+ pHddStaCtx->conn_info.connState = connState;
+}
+
+// returns FALSE if not connected.
+// returns TRUE for the two 'connected' states (Infra Associated or IBSS Connected ).
+// returns the connection state. Can specify NULL if you dont' want to get the actual state.
+
+static inline v_BOOL_t hdd_connGetConnectionState( hdd_station_ctx_t *pHddStaCtx,
+ eConnectionState *pConnState )
+{
+ v_BOOL_t fConnected;
+ eConnectionState connState;
+
+ // get the connection state.
+ connState = pHddStaCtx->conn_info.connState;
+ // Set the fConnected return variable based on the Connected State.
+ if ( eConnectionState_Associated == connState ||
+ eConnectionState_IbssConnected == connState )
+ {
+ fConnected = VOS_TRUE;
+ }
+ else
+ {
+ fConnected = VOS_FALSE;
+ }
+
+ if ( pConnState )
+ {
+ *pConnState = connState;
+ }
+
+ return( fConnected );
+}
+
+v_BOOL_t hdd_connIsConnected( hdd_station_ctx_t *pHddStaCtx )
+{
+ return( hdd_connGetConnectionState( pHddStaCtx, NULL ) );
+}
+
+//TODO - Not used anyhwere. Can be removed.
+#if 0
+//
+v_BOOL_t hdd_connIsConnectedInfra( hdd_adapter_t *pAdapter )
+{
+ v_BOOL_t fConnectedInfra = FALSE;
+ eConnectionState connState;
+
+ if ( hdd_connGetConnectionState( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connState ) )
+ {
+ if ( eConnectionState_Associated == connState )
+ {
+ fConnectedInfra = TRUE;
+ }
+ }
+
+ return( fConnectedInfra );
+}
+#endif
+
+static inline v_BOOL_t hdd_connGetConnectedCipherAlgo( hdd_station_ctx_t *pHddStaCtx, eCsrEncryptionType *pConnectedCipherAlgo )
+{
+ v_BOOL_t fConnected = VOS_FALSE;
+
+ fConnected = hdd_connGetConnectionState( pHddStaCtx, NULL );
+
+ if ( pConnectedCipherAlgo )
+ {
+ *pConnectedCipherAlgo = pHddStaCtx->conn_info.ucEncryptionType;
+ }
+
+ return( fConnected );
+}
+
+inline v_BOOL_t hdd_connGetConnectedBssType( hdd_station_ctx_t *pHddStaCtx, eMib_dot11DesiredBssType *pConnectedBssType )
+{
+ v_BOOL_t fConnected = VOS_FALSE;
+
+ fConnected = hdd_connGetConnectionState( pHddStaCtx, NULL );
+
+ if ( pConnectedBssType )
+ {
+ *pConnectedBssType = pHddStaCtx->conn_info.connDot11DesiredBssType;
+ }
+
+ return( fConnected );
+}
+
+static inline void hdd_connSaveConnectedBssType( hdd_station_ctx_t *pHddStaCtx, eCsrRoamBssType csrRoamBssType )
+{
+ switch( csrRoamBssType )
+ {
+ case eCSR_BSS_TYPE_INFRASTRUCTURE:
+ pHddStaCtx->conn_info.connDot11DesiredBssType = eMib_dot11DesiredBssType_infrastructure;
+ break;
+
+ case eCSR_BSS_TYPE_IBSS:
+ case eCSR_BSS_TYPE_START_IBSS:
+ pHddStaCtx->conn_info.connDot11DesiredBssType = eMib_dot11DesiredBssType_independent;
+ break;
+
+ /** We will never set the BssType to 'any' when attempting a connection
+ so CSR should never send this back to us.*/
+ case eCSR_BSS_TYPE_ANY:
+ default:
+ VOS_ASSERT( 0 );
+ break;
+ }
+
+}
+
+void hdd_connSaveConnectInfo( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType )
+{
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ eCsrEncryptionType encryptType = eCSR_ENCRYPT_TYPE_NONE;
+
+ VOS_ASSERT( pRoamInfo );
+
+ if ( pRoamInfo )
+ {
+ // Save the BSSID for the connection...
+ if ( eCSR_BSS_TYPE_INFRASTRUCTURE == eBssType )
+ {
+ VOS_ASSERT( pRoamInfo->pBssDesc );
+ vos_mem_copy(pHddStaCtx->conn_info.bssId, pRoamInfo->bssid,6 );
+
+ // Save the Station ID for this station from the 'Roam Info'.
+ //For IBSS mode, staId is assigned in NEW_PEER_IND
+ //For reassoc, the staID doesn't change and it may be invalid in this structure
+ //so no change here.
+ if( !pRoamInfo->fReassocReq )
+ {
+ pHddStaCtx->conn_info.staId [0]= pRoamInfo->staId;
+ }
+ }
+ else if ( eCSR_BSS_TYPE_IBSS == eBssType )
+ {
+ vos_mem_copy(pHddStaCtx->conn_info.bssId, pRoamInfo->bssid,sizeof(pRoamInfo->bssid) );
+ }
+ else
+ {
+ // can't happen. We need a valid IBSS or Infra setting in the BSSDescription
+ // or we can't function.
+ VOS_ASSERT( 0 );
+ }
+
+ // notify WMM
+ hdd_wmm_connect(pAdapter, pRoamInfo, eBssType);
+
+ if( !pRoamInfo->u.pConnectedProfile )
+ {
+ VOS_ASSERT( pRoamInfo->u.pConnectedProfile );
+ }
+ else
+ {
+ // Get Multicast Encryption Type
+ encryptType = pRoamInfo->u.pConnectedProfile->mcEncryptionType;
+ pHddStaCtx->conn_info.mcEncryptionType = encryptType;
+ // Get Unicast Encrytion Type
+ encryptType = pRoamInfo->u.pConnectedProfile->EncryptionType;
+ pHddStaCtx->conn_info.ucEncryptionType = encryptType;
+
+ pHddStaCtx->conn_info.authType = pRoamInfo->u.pConnectedProfile->AuthType;
+
+ pHddStaCtx->conn_info.operationChannel = pRoamInfo->u.pConnectedProfile->operationChannel;
+
+ // Save the ssid for the connection
+ vos_mem_copy( &pHddStaCtx->conn_info.SSID.SSID, &pRoamInfo->u.pConnectedProfile->SSID, sizeof( tSirMacSSid ) );
+ }
+ }
+
+ // save the connected BssType
+ hdd_connSaveConnectedBssType( pHddStaCtx, eBssType );
+
+}
+
+#if defined(WLAN_FEATURE_VOWIFI_11R)
+/*
+ * Send the 11R key information to the supplicant.
+ * Only then can the supplicant generate the PMK-R1.
+ * (BTW, the CCX supplicant also needs the Assoc Resp IEs
+ * for the same purpose.)
+ *
+ * Mainly the Assoc Rsp IEs are passed here. For the IMDA
+ * this contains the R1KHID, R0KHID and the MDID.
+ * For FT, this consists of the Reassoc Rsp FTIEs.
+ * This is the Assoc Response.
+ */
+static void hdd_SendFTAssocResponse(struct net_device *dev, hdd_adapter_t *pAdapter,
+ tCsrRoamInfo *pCsrRoamInfo)
+{
+ union iwreq_data wrqu;
+ char *buff;
+ unsigned int len = 0;
+ u8 *pFTAssocRsp = NULL;
+
+ if (pCsrRoamInfo->nAssocRspLength == 0)
+ {
+ hddLog(LOGE,
+ "%s: pCsrRoamInfo->nAssocRspLength=%d",
+ __func__, (int)pCsrRoamInfo->nAssocRspLength);
+ return;
+ }
+
+ pFTAssocRsp = (u8 *)(pCsrRoamInfo->pbFrames + pCsrRoamInfo->nBeaconLength +
+ pCsrRoamInfo->nAssocReqLength);
+ if (pFTAssocRsp == NULL)
+ {
+ hddLog(LOGE, "%s: AssocReq or AssocRsp is NULL", __func__);
+ return;
+ }
+
+ // pFTAssocRsp needs to point to the IEs
+ pFTAssocRsp += FT_ASSOC_RSP_IES_OFFSET;
+ hddLog(LOG1, "%s: AssocRsp is now at %02x%02x", __func__,
+ (unsigned int)pFTAssocRsp[0],
+ (unsigned int)pFTAssocRsp[1]);
+
+ // We need to send the IEs to the supplicant.
+ buff = kmalloc(IW_GENERIC_IE_MAX, GFP_ATOMIC);
+ if (buff == NULL)
+ {
+ hddLog(LOGE, "%s: kmalloc unable to allocate memory", __func__);
+ return;
+ }
+
+ // Send the Assoc Resp, the supplicant needs this for initial Auth.
+ len = pCsrRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET;
+ wrqu.data.length = len;
+ memset(buff, 0, IW_GENERIC_IE_MAX);
+ memcpy(buff, pFTAssocRsp, len);
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, buff);
+
+ kfree(buff);
+}
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+
+/*---------------------------------------------------
+ *
+ * Send the FTIEs, RIC IEs during FT. This is eventually
+ * used to send the FT events to the supplicant
+ *
+ * At the reception of Auth2 we send the RIC followed
+ * by the auth response IEs to the supplicant.
+ * Once both are received in the supplicant, an FT
+ * event is generated to the supplicant.
+ *
+ *---------------------------------------------------
+ */
+void hdd_SendFTEvent(hdd_adapter_t *pAdapter)
+{
+ union iwreq_data wrqu;
+ //struct wpabuf *ric = NULL;
+ char *buff;
+ tANI_U16 auth_resp_len = 0;
+ tANI_U32 ric_ies_length = 0;
+ tANI_U16 str_len;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ // We need to send the IEs to the supplicant.
+ buff = kmalloc(IW_CUSTOM_MAX, GFP_ATOMIC);
+ vos_mem_zero(buff, IW_CUSTOM_MAX);
+ if (buff == NULL)
+ {
+ hddLog(LOGE, "%s: kmalloc unable to allocate memory", __func__);
+ return;
+ }
+
+ // Sme needs to send the RIC IEs first
+ str_len = strlcpy(buff, "RIC=", IW_CUSTOM_MAX);
+ sme_GetRICIEs( pHddCtx->hHal, (u8 *)&(buff[str_len]),
+ (IW_CUSTOM_MAX - str_len), &ric_ies_length );
+ if (ric_ies_length == 0)
+ {
+ hddLog(LOGW, "%s: RIC IEs is of length 0 not sending RIC Information for now", __func__);
+ }
+ else
+ {
+ wrqu.data.length = str_len + ric_ies_length;
+ wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buff);
+ }
+
+ // Sme needs to provide the Auth Resp
+ vos_mem_zero(buff, IW_CUSTOM_MAX);
+ str_len = strlcpy(buff, "AUTH=", IW_CUSTOM_MAX);
+ sme_GetFTPreAuthResponse(pHddCtx->hHal, (u8 *)&buff[str_len],
+ (IW_CUSTOM_MAX - str_len), &auth_resp_len);
+
+ if (auth_resp_len == 0)
+ {
+ hddLog(LOGE, "%s: AuthRsp FTIES is of length 0", __func__);
+ return;
+ }
+
+ wrqu.data.length = str_len + auth_resp_len;
+ wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buff);
+
+ kfree(buff);
+}
+
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+#ifdef FEATURE_WLAN_CCX
+
+/*
+ * Send the CCX required "new AP Channel info" to the supplicant.
+ * (This keeps the supplicant "up to date" on the current channel.)
+ *
+ * The current (new AP) channel information is passed in.
+ */
+static void hdd_SendNewAPChannelInfo(struct net_device *dev, hdd_adapter_t *pAdapter,
+ tCsrRoamInfo *pCsrRoamInfo)
+{
+ union iwreq_data wrqu;
+ tSirBssDescription *descriptor = pCsrRoamInfo->pBssDesc;
+
+
+ if (descriptor == NULL)
+ {
+ hddLog(LOGE,
+ "%s: pCsrRoamInfo->pBssDesc=%p\n",
+ __func__, descriptor);
+ return;
+ }
+
+ // Send the Channel event, the supplicant needs this to generate the Adjacent AP report.
+ hddLog(LOGW, "%s: Sending up an SIOCGIWFREQ, channelId=%d\n", __func__, descriptor->channelId);
+ memset(&wrqu, '\0', sizeof(wrqu));
+ wrqu.freq.m = descriptor->channelId;
+ wrqu.freq.e = 0;
+ wrqu.freq.i = 0;
+ wireless_send_event(pAdapter->dev, SIOCGIWFREQ, &wrqu, NULL);
+}
+
+#endif /* FEATURE_WLAN_CCX */
+
+void hdd_SendUpdateBeaconIEsEvent(hdd_adapter_t *pAdapter, tCsrRoamInfo *pCsrRoamInfo)
+{
+ union iwreq_data wrqu;
+ u8 *pBeaconIes;
+ u8 currentLen = 0;
+ char *buff;
+ int totalIeLen = 0, currentOffset = 0, strLen;
+
+ memset(&wrqu, '\0', sizeof(wrqu));
+
+ if (0 == pCsrRoamInfo->nBeaconLength)
+ {
+ hddLog(LOGE, "%s: pCsrRoamInfo->nBeaconFrameLength = 0", __func__);
+ return;
+ }
+ pBeaconIes = (u8 *)(pCsrRoamInfo->pbFrames + BEACON_FRAME_IES_OFFSET);
+ if (pBeaconIes == NULL)
+ {
+ hddLog(LOGE, "%s: Beacon IEs is NULL", __func__);
+ return;
+ }
+
+ // pBeaconIes needs to point to the IEs
+ hddLog(LOG1, "%s: Beacon IEs is now at %02x%02x", __func__,
+ (unsigned int)pBeaconIes[0],
+ (unsigned int)pBeaconIes[1]);
+ hddLog(LOG1, "%s: Beacon IEs length = %d", __func__, pCsrRoamInfo->nBeaconLength - BEACON_FRAME_IES_OFFSET);
+
+ // We need to send the IEs to the supplicant.
+ buff = kmalloc(IW_CUSTOM_MAX, GFP_ATOMIC);
+ if (buff == NULL)
+ {
+ hddLog(LOGE, "%s: kmalloc unable to allocate memory", __func__);
+ return;
+ }
+ vos_mem_zero(buff, IW_CUSTOM_MAX);
+
+ strLen = strlcpy(buff,"BEACONIEs=", IW_CUSTOM_MAX);
+ currentLen = strLen + 1;
+
+ totalIeLen = pCsrRoamInfo->nBeaconLength - BEACON_FRAME_IES_OFFSET;
+ do
+ {
+ /* If the beacon size exceeds max CUSTOM event size, break it into chunks of CUSTOM event
+ * max size and send it to supplicant. Changes are done in supplicant to handle this */
+ vos_mem_zero(&buff[strLen + 1], IW_CUSTOM_MAX - (strLen + 1));
+ currentLen = VOS_MIN(totalIeLen, IW_CUSTOM_MAX - (strLen + 1) - 1);
+ vos_mem_copy(&buff[strLen + 1], pBeaconIes+currentOffset, currentLen);
+ currentOffset += currentLen;
+ totalIeLen -= currentLen;
+ wrqu.data.length = strLen + 1 + currentLen;
+ if (totalIeLen)
+ buff[strLen] = 1; // This tells supplicant more chunks are pending
+ else
+ buff[strLen] = 0; // For last chunk of beacon IE to supplicant
+
+ hddLog(LOG1, "%s: Beacon IEs length to supplicant = %d", __func__, currentLen);
+ wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buff);
+ } while (totalIeLen > 0);
+
+ kfree(buff);
+}
+
+static void hdd_SendAssociationEvent(struct net_device *dev,tCsrRoamInfo *pCsrRoamInfo)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ union iwreq_data wrqu;
+ int we_event;
+ char *msg;
+ int type = -1;
+
+#if defined (WLAN_FEATURE_VOWIFI_11R)
+ // Added to find the auth type on the fly at run time
+ // rather than with cfg to see if FT is enabled
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrRoamProfile* pRoamProfile = &(pWextState->roamProfile);
+#endif
+
+ memset(&wrqu, '\0', sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ we_event = SIOCGIWAP;
+
+ if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)/* Associated */
+ {
+ memcpy(wrqu.ap_addr.sa_data, pCsrRoamInfo->pBssDesc->bssId, sizeof(pCsrRoamInfo->pBssDesc->bssId));
+ type = WLAN_STA_ASSOC_DONE_IND;
+
+ pr_info("wlan: connected to %02x:%02x:%02x:%02x:%02x:%02x\n",
+ wrqu.ap_addr.sa_data[0],
+ wrqu.ap_addr.sa_data[1],
+ wrqu.ap_addr.sa_data[2],
+ wrqu.ap_addr.sa_data[3],
+ wrqu.ap_addr.sa_data[4],
+ wrqu.ap_addr.sa_data[5]);
+ hdd_SendUpdateBeaconIEsEvent(pAdapter, pCsrRoamInfo);
+
+ /* Send IWEVASSOCRESPIE Event if WLAN_FEATURE_CIQ_METRICS is Enabled Or
+ * Send IWEVASSOCRESPIE Event if WLAN_FEATURE_VOWIFI_11R is Enabled
+ * and fFTEnable is TRUE */
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ // Send FT Keys to the supplicant when FT is enabled
+ if ((pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_FT_RSN_PSK) ||
+ (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_FT_RSN)
+#ifdef FEATURE_WLAN_CCX
+ || (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_CCKM_RSN) ||
+ (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_CCKM_WPA)
+#endif
+ )
+ {
+ hdd_SendFTAssocResponse(dev, pAdapter, pCsrRoamInfo);
+ }
+#endif
+ }
+ else if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState) // IBss Associated
+ {
+ memcpy(wrqu.ap_addr.sa_data, pHddStaCtx->conn_info.bssId, sizeof(wrqu.ap_addr.sa_data));
+ type = WLAN_STA_ASSOC_DONE_IND;
+ pr_info("wlan: new IBSS connection to %02x:%02x:%02x:%02x:%02x:%02x",
+ pHddStaCtx->conn_info.bssId[0],
+ pHddStaCtx->conn_info.bssId[1],
+ pHddStaCtx->conn_info.bssId[2],
+ pHddStaCtx->conn_info.bssId[3],
+ pHddStaCtx->conn_info.bssId[4],
+ pHddStaCtx->conn_info.bssId[5]);
+ }
+ else /* Not Associated */
+ {
+ pr_info("wlan: disconnected\n");
+ type = WLAN_STA_DISASSOC_DONE_IND;
+ memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
+ }
+
+ msg = NULL;
+ /*During the WLAN uninitialization,supplicant is stopped before the
+ driver so not sending the status of the connection to supplicant*/
+ if(pHddCtx->isLoadUnloadInProgress != TRUE)
+ {
+ wireless_send_event(dev, we_event, &wrqu, msg);
+#ifdef FEATURE_WLAN_CCX
+ if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)/* Associated */
+ {
+ if ( (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_CCKM_RSN) ||
+ (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_CCKM_WPA) )
+ hdd_SendNewAPChannelInfo(dev, pAdapter, pCsrRoamInfo);
+ }
+#endif
+ }
+ send_btc_nlink_msg(type, 0);
+}
+
+void hdd_connRemoveConnectInfo( hdd_station_ctx_t *pHddStaCtx )
+{
+ // Remove staId, bssId and peerMacAddress
+ pHddStaCtx->conn_info.staId [ 0 ] = 0;
+ vos_mem_zero( &pHddStaCtx->conn_info.bssId, sizeof( v_MACADDR_t ) );
+ vos_mem_zero( &pHddStaCtx->conn_info.peerMacAddress[ 0 ], sizeof( v_MACADDR_t ) );
+
+ // Clear all security settings
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+ pHddStaCtx->conn_info.mcEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ pHddStaCtx->conn_info.ucEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
+
+ vos_mem_zero( &pHddStaCtx->conn_info.Keys, sizeof( tCsrKeys ) );
+
+ // Set not-connected state
+ pHddStaCtx->conn_info.connDot11DesiredBssType = eCSR_BSS_TYPE_ANY;
+ hdd_connSetConnectionState( pHddStaCtx, eConnectionState_NotConnected );
+
+ vos_mem_zero( &pHddStaCtx->conn_info.SSID, sizeof( tCsrSSIDInfo ) );
+}
+/* TODO Revist this function. and data path */
+static VOS_STATUS hdd_roamDeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
+{
+ VOS_STATUS vosStatus;
+ hdd_disconnect_tx_rx(pAdapter);
+ vosStatus = WLANTL_ClearSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staId );
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "%s: WLANTL_ClearSTAClient() failed to for staID %d. "
+ "Status= %d [0x%08lX]",
+ __FUNCTION__, staId, vosStatus, vosStatus );
+ }
+ return( vosStatus );
+}
+
+
+static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
+ tANI_U32 roamId, eRoamCmdStatus roamStatus,
+ eCsrRoamResult roamResult )
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ struct net_device *dev = pAdapter->dev;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ // notify apps that we can't pass traffic anymore
+ netif_tx_disable(dev);
+ netif_carrier_off(dev);
+
+ hdd_connSetConnectionState( pHddStaCtx, eConnectionState_NotConnected );
+ /* If only STA mode is on */
+ if((pHddCtx->concurrency_mode <= 1) && (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
+ {
+ pHddCtx->isAmpAllowed = VOS_TRUE;
+ }
+ hdd_clearRoamProfileIe( pAdapter );
+
+ // indicate 'disconnect' status to wpa_supplicant...
+ hdd_SendAssociationEvent(dev,pRoamInfo);
+#ifdef CONFIG_CFG80211
+ /* indicate disconnected event to nl80211 */
+ if(roamStatus != eCSR_ROAM_IBSS_LEAVE)
+ {
+ /*During the WLAN uninitialization,supplicant is stopped before the
+ driver so not sending the status of the connection to supplicant*/
+ if(pHddCtx->isLoadUnloadInProgress != TRUE)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: sent disconnected event to nl80211",
+ __func__);
+ /* To avoid wpa_supplicant sending "HANGED" CMD to ICS UI */
+ if( eCSR_ROAM_LOSTLINK == roamStatus )
+ {
+ cfg80211_disconnected(dev, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, NULL, 0, GFP_KERNEL);
+ }
+ else
+ {
+ cfg80211_disconnected(dev, WLAN_REASON_UNSPECIFIED, NULL, 0, GFP_KERNEL);
+ }
+
+ //If the Device Mode is Station
+ // and the P2P Client is Connected
+ //Enable BMPS
+ if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
+ (vos_concurrent_sessions_running()))
+ {
+ //Enable BMPS only of other Session is P2P Client
+ hdd_context_t *pHddCtx = NULL;
+ v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
+
+ if (NULL != pVosContext)
+ {
+ pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
+
+ if(NULL != pHddCtx)
+ {
+ //Only P2P Client is there Enable Bmps back
+ if((0 == pHddCtx->no_of_sessions[VOS_STA_SAP_MODE]) &&
+ (0 == pHddCtx->no_of_sessions[VOS_P2P_GO_MODE]) &&
+ (1 == pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE]))
+ {
+ hdd_enable_bmps_imps(pHddCtx);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
+
+ //We should clear all sta register with TL, for now, only one.
+ status = hdd_roamDeregisterSTA( pAdapter, pHddStaCtx->conn_info.staId [0] );
+ if ( !VOS_IS_STATUS_SUCCESS(status ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "hdd_roamDeregisterSTA() failed to for staID %d. "
+ "Status= %d [0x%x]",
+ pHddStaCtx->conn_info.staId[0], status, status );
+
+ status = eHAL_STATUS_FAILURE;
+ }
+
+ pHddCtx->sta_to_adapter[pHddStaCtx->conn_info.staId[0]] = NULL;
+ // Clear saved connection information in HDD
+ hdd_connRemoveConnectInfo( pHddStaCtx );
+
+ //Unblock anyone waiting for disconnect to complete
+ complete(&pAdapter->disconnect_comp_var);
+ return( status );
+}
+static VOS_STATUS hdd_roamRegisterSTA( hdd_adapter_t *pAdapter,
+ tCsrRoamInfo *pRoamInfo,
+ v_U8_t staId,
+ v_MACADDR_t *pPeerMacAddress,
+ tSirBssDescription *pBssDesc )
+{
+ VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
+ WLAN_STADescType staDesc = {0};
+ eCsrEncryptionType connectedCipherAlgo;
+ v_BOOL_t fConnected;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ // Get the Station ID from the one saved during the assocation.
+ staDesc.ucSTAId = staId;
+
+ if ( pHddStaCtx->conn_info.connDot11DesiredBssType == eMib_dot11DesiredBssType_infrastructure)
+ {
+ staDesc.wSTAType = WLAN_STA_INFRA;
+
+ // grab the bssid from the connection info in the adapter structure and hand that
+ // over to TL when registering.
+ vos_mem_copy( staDesc.vSTAMACAddress.bytes, pHddStaCtx->conn_info.bssId,sizeof(pHddStaCtx->conn_info.bssId) );
+ }
+ else
+ {
+ // for an IBSS 'connect', setup the Station Descriptor for TL.
+ staDesc.wSTAType = WLAN_STA_IBSS;
+
+ // Note that for IBSS, the STA MAC address and BSSID are goign to be different where
+ // in infrastructure, they are the same (BSSID is the MAC address of the AP). So,
+ // for IBSS we have a second field to pass to TL in the STA descriptor that we don't
+ // pass when making an Infrastructure connection.
+ vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
+ vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, pHddStaCtx->conn_info.bssId,6 );
+ }
+
+ vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
+
+ // set the QoS field appropriately
+ if (hdd_wmm_is_active(pAdapter))
+ {
+ staDesc.ucQosEnabled = 1;
+ }
+ else
+ {
+ staDesc.ucQosEnabled = 0;
+ }
+
+ fConnected = hdd_connGetConnectedCipherAlgo( pHddStaCtx, &connectedCipherAlgo );
+ if ( connectedCipherAlgo != eCSR_ENCRYPT_TYPE_NONE )
+ {
+ staDesc.ucProtectedFrame = 1;
+ }
+ else
+ {
+ staDesc.ucProtectedFrame = 0;
+
+ }
+
+#ifdef FEATURE_WLAN_CCX
+ staDesc.ucIsCcxSta = pRoamInfo->isCCXAssoc;
+#endif //FEATURE_WLAN_CCX
+
+#ifdef VOLANS_ENABLE_SW_REPLAY_CHECK
+ /* check whether replay check is valid for the station or not */
+ if( (eCSR_ENCRYPT_TYPE_TKIP == connectedCipherAlgo) || (eCSR_ENCRYPT_TYPE_AES == connectedCipherAlgo))
+ {
+ /* Encryption mode is either TKIP or AES
+ and replay check is valid for only these
+ two encryption modes */
+ staDesc.ucIsReplayCheckValid = VOS_TRUE;
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "HDD register TL ucIsReplayCheckValid %d: Replay check is needed for station", staDesc.ucIsReplayCheckValid);
+ }
+
+ else
+ {
+ /* For other encryption modes replay check is
+ not needed */
+ staDesc.ucIsReplayCheckValid = VOS_FALSE;
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "HDD register TL ucIsReplayCheckValid %d", staDesc.ucIsReplayCheckValid);
+ }
+#endif
+
+#ifdef FEATURE_WLAN_WAPI
+ hddLog(LOG1, "%s: WAPI STA Registered: %d", __FUNCTION__, pAdapter->wapi_info.fIsWapiSta);
+ if (pAdapter->wapi_info.fIsWapiSta)
+ {
+ staDesc.ucIsWapiSta = 1;
+ }
+ else
+ {
+ staDesc.ucIsWapiSta = 0;
+ }
+#endif /* FEATURE_WLAN_WAPI */
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ "HDD register TL Sec_enabled= %d.", staDesc.ucProtectedFrame );
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ // UMA is Not ready yet, Xlation will be done by TL
+ staDesc.ucSwFrameTXXlation = 1;
+#else
+ /* Enable UMA for TX translation only when there is no concurrent session active */
+ if (vos_concurrent_sessions_running())
+ {
+ staDesc.ucSwFrameTXXlation = 1;
+ }
+ else
+ {
+ staDesc.ucSwFrameTXXlation = 0;
+ }
+#endif
+ staDesc.ucSwFrameRXXlation = 1;
+ staDesc.ucAddRmvLLC = 1;
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "HDD register TL QoS_enabled=%d",
+ staDesc.ucQosEnabled );
+ // Initialize signatures and state
+ staDesc.ucUcastSig = pRoamInfo->ucastSig;
+ staDesc.ucBcastSig = pRoamInfo->bcastSig;
+ staDesc.ucInitState = pRoamInfo->fAuthRequired ?
+ WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
+ // Register the Station with TL...
+ vosStatus = WLANTL_RegisterSTAClient( pHddCtx->pvosContext,
+ hdd_rx_packet_cbk,
+ hdd_tx_complete_cbk,
+ hdd_tx_fetch_packet_cbk, &staDesc,
+ pBssDesc->rssi );
+
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08lX]",
+ vosStatus, vosStatus );
+ return vosStatus;
+ }
+
+ // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
+ // then go to 'authenticated'. For all other authentication types (those that do
+ // not require upper layer authentication) we can put TL directly into 'authenticated'
+ // state.
+
+ VOS_ASSERT( fConnected );
+
+ if ( !pRoamInfo->fAuthRequired )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", pHddStaCtx->conn_info.staId[ 0 ] );
+
+ // Connections that do not need Upper layer auth, transition TL directly
+ // to 'Authenticated' state.
+ vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId,
+ WLANTL_STA_AUTHENTICATED );
+
+ pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE;
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pHddStaCtx->conn_info.staId[ 0 ] );
+
+ vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId,
+ WLANTL_STA_CONNECTED );
+
+ pHddStaCtx->conn_info.uIsAuthenticated = VOS_FALSE;
+ }
+ return( vosStatus );
+}
+
+#ifdef FEATURE_WLAN_CCX
+static void hdd_SendReAssocEvent(struct net_device *dev, hdd_adapter_t *pAdapter,
+ tCsrRoamInfo *pCsrRoamInfo, v_U8_t *reqRsnIe, tANI_U32 reqRsnLength)
+{
+ unsigned int len = 0;
+ u8 *pFTAssocRsp = NULL;
+ v_U8_t rspRsnIe[IW_GENERIC_IE_MAX];
+ tANI_U32 rspRsnLength = 0;
+ struct ieee80211_channel *chan;
+
+ if (pCsrRoamInfo == NULL)
+ return;
+
+ if (pCsrRoamInfo->nAssocRspLength == 0)
+ return;
+
+ pFTAssocRsp = (u8 *)(pCsrRoamInfo->pbFrames + pCsrRoamInfo->nBeaconLength +
+ pCsrRoamInfo->nAssocReqLength);
+ if (pFTAssocRsp == NULL)
+ return;
+
+ //pFTAssocRsp needs to point to the IEs
+ pFTAssocRsp += FT_ASSOC_RSP_IES_OFFSET;
+ hddLog(LOG1, "%s: AssocRsp is now at %02x%02x\n", __func__,
+ (unsigned int)pFTAssocRsp[0],
+ (unsigned int)pFTAssocRsp[1]);
+
+ // Send the Assoc Resp, the supplicant needs this for initial Auth.
+ len = pCsrRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET;
+ rspRsnLength = len;
+ memset(rspRsnIe, 0, IW_GENERIC_IE_MAX);
+ memcpy(rspRsnIe, pFTAssocRsp, len);
+
+ chan = ieee80211_get_channel(pAdapter->wdev.wiphy, (int) pCsrRoamInfo->pBssDesc->channelId);
+ cfg80211_roamed(dev,chan,pCsrRoamInfo->bssid,
+ reqRsnIe, reqRsnLength,
+ rspRsnIe, rspRsnLength,GFP_KERNEL);
+}
+#endif /* FEATURE_WLAN_CCX */
+
+static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
+ tANI_U32 roamId, eRoamCmdStatus roamStatus,
+ eCsrRoamResult roamResult )
+{
+ struct net_device *dev = pAdapter->dev;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ VOS_STATUS vosStatus;
+#ifdef FEATURE_WLAN_CCX
+ int ft_carrier_on = FALSE;
+#endif
+ int status;
+
+ if ( eCSR_ROAM_RESULT_ASSOCIATED == roamResult )
+ {
+ hdd_connSetConnectionState( pHddStaCtx, eConnectionState_Associated );
+
+ // Save the connection info from CSR...
+ hdd_connSaveConnectInfo( pAdapter, pRoamInfo, eCSR_BSS_TYPE_INFRASTRUCTURE );
+#ifdef FEATURE_WLAN_WAPI
+ if ( pRoamInfo->u.pConnectedProfile->AuthType == eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE ||
+ pRoamInfo->u.pConnectedProfile->AuthType == eCSR_AUTH_TYPE_WAPI_WAI_PSK )
+ {
+ pAdapter->wapi_info.fIsWapiSta = 1;
+ }
+ else
+ {
+ pAdapter->wapi_info.fIsWapiSta = 0;
+ }
+#endif /* FEATURE_WLAN_WAPI */
+
+ // indicate 'connect' status to userspace
+ hdd_SendAssociationEvent(dev,pRoamInfo);
+
+
+ // Initialize the Linkup event completion variable
+ INIT_COMPLETION(pAdapter->linkup_event_var);
+
+ /*
+ Sometimes Switching ON the Carrier is taking time to activate the device properly. Before allowing any
+ packet to go up to the application, device activation has to be ensured for proper queue mapping by the
+ kernel. we have registered net device notifier for device change notification. With this we will come to
+ know that the device is getting activated properly.
+ */
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ if (pHddStaCtx->ft_carrier_on == FALSE)
+ {
+#endif
+ // Enable Linkup Event Servicing which allows the net device notifier to set the linkup event variable
+ pAdapter->isLinkUpSvcNeeded = TRUE;
+
+ // Enable Linkup Event Servicing which allows the net device notifier to set the linkup event variable
+ pAdapter->isLinkUpSvcNeeded = TRUE;
+
+ // Switch on the Carrier to activate the device
+ netif_carrier_on(dev);
+
+ // Wait for the Link to up to ensure all the queues are set properly by the kernel
+ status = wait_for_completion_interruptible_timeout(&pAdapter->linkup_event_var,
+ msecs_to_jiffies(ASSOC_LINKUP_TIMEOUT));
+ if(!status)
+ {
+ hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning:ASSOC_LINKUP_TIMEOUT", __func__);
+ }
+
+ // Disable Linkup Event Servicing - no more service required from the net device notifier call
+ pAdapter->isLinkUpSvcNeeded = FALSE;
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ }
+ else {
+ pHddStaCtx->ft_carrier_on = FALSE;
+#ifdef FEATURE_WLAN_CCX
+ ft_carrier_on = TRUE;
+#endif /* FEATURE_WLAN_CCX */
+ }
+#endif
+ pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter;
+
+ //For reassoc, the station is already registered, all we need is to change the state
+ //of the STA in TL.
+ //If authentication is required (WPA/WPA2/DWEP), change TL to CONNECTED instead of AUTHENTICATED
+ if( !pRoamInfo->fReassocReq )
+ {
+#ifdef CONFIG_CFG80211
+ v_U8_t reqRsnIe[DOT11F_IE_RSN_MAX_LEN];
+ v_U8_t rspRsnIe[DOT11F_IE_RSN_MAX_LEN];
+ tANI_U32 reqRsnLength = DOT11F_IE_RSN_MAX_LEN;
+ tANI_U32 rspRsnLength = DOT11F_IE_RSN_MAX_LEN;
+ struct cfg80211_bss *bss;
+
+ /* add bss_id to cfg80211 data base */
+ bss = wlan_hdd_cfg80211_update_bss_db(pAdapter, pRoamInfo);
+ if (NULL == bss)
+ {
+ pr_err("wlan: Not able to create BSS entry\n");
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* wpa supplicant expecting WPA/RSN IE in connect result */
+ csrRoamGetWpaRsnReqIE(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ &reqRsnLength,
+ reqRsnIe);
+
+ csrRoamGetWpaRsnRspIE(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ &rspRsnLength,
+ rspRsnIe);
+#ifdef FEATURE_WLAN_CCX
+ if(ft_carrier_on)
+ hdd_SendReAssocEvent(dev, pAdapter, pRoamInfo, reqRsnIe, reqRsnLength);
+ else
+#endif /* FEATURE_WLAN_CCX */
+
+ {
+ /* inform connect result to nl80211 */
+ cfg80211_connect_result(dev, pRoamInfo->bssid,
+ reqRsnIe, reqRsnLength,
+ rspRsnIe, rspRsnLength,
+ WLAN_STATUS_SUCCESS,
+ GFP_KERNEL);
+
+ cfg80211_put_bss(bss);
+ }
+#endif
+
+ // Register the Station with TL after associated...
+ vosStatus = hdd_roamRegisterSTA( pAdapter,
+ pRoamInfo,
+ pHddStaCtx->conn_info.staId[ 0 ],
+ NULL,
+ pRoamInfo->pBssDesc );
+ }
+ else
+ {
+ //Reassoc successfully
+ if( pRoamInfo->fAuthRequired )
+ {
+ vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, pHddStaCtx->conn_info.staId[ 0 ],
+ WLANTL_STA_CONNECTED );
+ pHddStaCtx->conn_info.uIsAuthenticated = VOS_FALSE;
+ }
+ else
+ {
+ vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, pHddStaCtx->conn_info.staId[ 0 ],
+ WLANTL_STA_AUTHENTICATED );
+ pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE;
+ }
+ }
+
+ if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ // perform any WMM-related association processing
+ hdd_wmm_assoc(pAdapter, pRoamInfo, eCSR_BSS_TYPE_INFRASTRUCTURE);
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "Cannot register STA with TL. Failed with vosStatus = %d [%08lX]",
+ vosStatus, vosStatus );
+ }
+
+ // Start the Queue
+ netif_tx_wake_all_queues(dev);
+ }
+ else
+ {
+ char country_code[3] = SME_INVALID_COUNTRY_CODE;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
+
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ pr_info("wlan: connection failed\n");
+
+ /*Handle all failure conditions*/
+ hdd_connSetConnectionState( pHddStaCtx, eConnectionState_NotConnected);
+ if((pHddCtx->concurrency_mode <= 1) && (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
+ {
+ pHddCtx->isAmpAllowed = VOS_TRUE;
+ }
+
+ //If the Device Mode is Station
+ // and the P2P Client is Connected
+ //Enable BMPS
+ if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
+ (vos_concurrent_sessions_running()))
+ {
+ //Enable BMPS only of other Session is P2P Client
+ hdd_context_t *pHddCtx = NULL;
+ v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
+
+ if (NULL != pVosContext)
+ {
+ pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
+
+ if(NULL != pHddCtx)
+ {
+ //Only P2P Client is there Enable Bmps back
+ if((0 == pHddCtx->no_of_sessions[VOS_STA_SAP_MODE]) &&
+ (0 == pHddCtx->no_of_sessions[VOS_P2P_GO_MODE]) &&
+ (1 == pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE]))
+ {
+ hdd_enable_bmps_imps(pHddCtx);
+ }
+ }
+ }
+ }
+
+#ifdef CONFIG_CFG80211
+ /* inform association failure event to nl80211 */
+ cfg80211_connect_result(dev, pWextState->req_bssId,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
+#endif
+
+ netif_tx_disable(dev);
+ netif_carrier_off(dev);
+
+ /* Association failed; Reset the country code information
+ * so that it re-initialize the valid channel list*/
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
+ "%s: Association failed and resetting the country code"
+ "to default \n",__func__);
+
+ status = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL,
+ &country_code[0], pAdapter,
+ pHddCtx->pvosContext);
+ if( 0 != status )
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: SME Change Country code to default failed \n",__func__);
+ }
+ }
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/**============================================================================
+ *
+ @brief roamRoamIbssIndicationHandler() - Here we update the status of the
+ Ibss when we receive information that we have started/joined an ibss session
+ We always return SUCCESS.
+
+ ===========================================================================*/
+static eHalStatus roamRoamIbssIndicationHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
+ tANI_U32 roamId, eRoamCmdStatus roamStatus,
+ eCsrRoamResult roamResult )
+{
+ switch( roamResult )
+ {
+ // both IBSS Started and IBSS Join should come in here.
+ case eCSR_ROAM_RESULT_IBSS_STARTED:
+ case eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS:
+ {
+ // we should have a pRoamInfo on this callback...
+ VOS_ASSERT( pRoamInfo );
+
+ // When IBSS Started comes from CSR, we need to move connection state to
+ // IBSS Disconnected (meaning no peers are in the IBSS).
+ hdd_connSetConnectionState( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), eConnectionState_IbssDisconnected );
+
+ break;
+ }
+
+ case eCSR_ROAM_RESULT_IBSS_START_FAILED:
+ {
+ VOS_ASSERT( pRoamInfo );
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return( eHAL_STATUS_SUCCESS );
+}
+
+/**============================================================================
+ *
+ @brief roamSaveIbssStation() - Save the IBSS peer MAC address in the adapter.
+ This information is passed to iwconfig later. The peer that joined
+ last is passed as information to iwconfig.
+ If we add HDD_MAX_NUM_IBSS_STA or less STA we return success else we
+ return FALSE.
+
+ ===========================================================================*/
+static int roamSaveIbssStation( hdd_station_ctx_t *pHddStaCtx, v_U8_t staId, v_MACADDR_t *peerMacAddress )
+{
+ int fSuccess = FALSE;
+ int idx = 0;
+
+ for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
+ {
+ if ( 0 == pHddStaCtx->conn_info.staId[ idx ] )
+ {
+ pHddStaCtx->conn_info.staId[ idx ] = staId;
+
+ vos_copy_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ idx ], peerMacAddress );
+
+ fSuccess = TRUE;
+ break;
+ }
+ }
+
+ return( fSuccess );
+}
+/**============================================================================
+ *
+ @brief roamRemoveIbssStation() - Remove the IBSS peer MAC address in the adapter.
+ If we remove HDD_MAX_NUM_IBSS_STA or less STA we return success else we
+ return FALSE.
+
+ ===========================================================================*/
+static int roamRemoveIbssStation( hdd_station_ctx_t *pHddStaCtx, v_U8_t staId )
+{
+ int fSuccess = FALSE;
+ int idx = 0;
+ v_U8_t valid_idx = 0;
+ v_U8_t del_idx = 0;
+
+ for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
+ {
+ if ( staId == pHddStaCtx->conn_info.staId[ idx ] )
+ {
+ pHddStaCtx->conn_info.staId[ idx ] = 0;
+
+ vos_zero_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ idx ] );
+
+ fSuccess = TRUE;
+ // Note the deleted Index, if its 0 we need special handling
+ del_idx = idx;
+ }
+ else
+ {
+ if (pHddStaCtx->conn_info.staId[idx] != 0)
+ {
+ valid_idx = idx;
+ }
+ }
+ }
+
+ // Find next active staId, to have a valid sta trigger for TL.
+ if (fSuccess == TRUE)
+ {
+ if (del_idx == 0)
+ {
+ if (pHddStaCtx->conn_info.staId[valid_idx] != 0)
+ {
+ pHddStaCtx->conn_info.staId[0] = pHddStaCtx->conn_info.staId[valid_idx];
+ vos_copy_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ 0 ],
+ &pHddStaCtx->conn_info.peerMacAddress[ valid_idx ]);
+
+ pHddStaCtx->conn_info.staId[valid_idx] = 0;
+ vos_zero_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ valid_idx ] );
+ }
+ }
+ }
+ return( fSuccess );
+}
+
+/**============================================================================
+ *
+ @brief roamIbssConnectHandler() : We update the status of the IBSS to
+ connected in this function.
+
+ ===========================================================================*/
+static eHalStatus roamIbssConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo )
+{
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "IBSS Connect Indication from SME!!!" );
+ // Set the internal connection state to show 'IBSS Connected' (IBSS with a partner stations)...
+ hdd_connSetConnectionState( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), eConnectionState_IbssConnected );
+
+ // Save the connection info from CSR...
+ hdd_connSaveConnectInfo( pAdapter, pRoamInfo, eCSR_BSS_TYPE_IBSS );
+
+ // Send the bssid address to the wext.
+ hdd_SendAssociationEvent(pAdapter->dev, pRoamInfo);
+#ifdef CONFIG_CFG80211
+ /* add bss_id to cfg80211 data base */
+ wlan_hdd_cfg80211_update_bss_db(pAdapter, pRoamInfo);
+ /* send ibss join indication to nl80211 */
+ cfg80211_ibss_joined(pAdapter->dev, &pRoamInfo->bssid[0], GFP_KERNEL);
+#endif
+
+ return( eHAL_STATUS_SUCCESS );
+}
+/**============================================================================
+ *
+ @brief hdd_RoamSetKeyCompleteHandler() - Update the security parameters.
+
+ ===========================================================================*/
+static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
+ tANI_U32 roamId, eRoamCmdStatus roamStatus,
+ eCsrRoamResult roamResult )
+{
+ eCsrEncryptionType connectedCipherAlgo;
+ v_BOOL_t fConnected = FALSE;
+ VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ ENTER();
+ // if ( WPA ), tell TL to go to 'authenticated' after the keys are set.
+ // then go to 'authenticated'. For all other authentication types (those that do
+ // not require upper layer authentication) we can put TL directly into 'authenticated'
+ // state.
+ fConnected = hdd_connGetConnectedCipherAlgo( pHddStaCtx, &connectedCipherAlgo );
+ if( fConnected )
+ {
+ // TODO: Considering getting a state machine in HDD later.
+ // This routuine is invoked twice. 1)set PTK 2)set GTK. The folloing if statement will be
+ // TRUE when setting GTK. At this time we don't handle the state in detail.
+ // Related CR: 174048 - TL not in authenticated state
+ if(( eCSR_ROAM_RESULT_AUTHENTICATED == roamResult ) && (pRoamInfo != NULL) && !pRoamInfo->fAuthRequired)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ "Key set for StaId= %d. Changing TL state to AUTHENTICATED", pHddStaCtx->conn_info.staId[ 0 ] );
+
+ // Connections that do not need Upper layer authentication, transition TL
+ // to 'Authenticated' state after the keys are set.
+ vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, pHddStaCtx->conn_info.staId[ 0 ],
+ WLANTL_STA_AUTHENTICATED );
+
+ pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE;
+ }
+
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+ }
+ else
+ {
+ // possible disassoc after issuing set key and waiting set key complete
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+ }
+
+ EXIT();
+ return( eHAL_STATUS_SUCCESS );
+}
+/**============================================================================
+ *
+ @brief hdd_RoamMicErrorIndicationHandler() - This function indicates the Mic failure to the supplicant.
+ ===========================================================================*/
+static eHalStatus hdd_RoamMicErrorIndicationHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
+ tANI_U32 roamId, eRoamCmdStatus roamStatus, eCsrRoamResult roamResult )
+{
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ if( eConnectionState_Associated == pHddStaCtx->conn_info.connState &&
+ TKIP_COUNTER_MEASURE_STOPED == pHddStaCtx->WextState.mTKIPCounterMeasures )
+ {
+ struct iw_michaelmicfailure msg;
+ union iwreq_data wreq;
+ memset(&msg, '\0', sizeof(msg));
+ msg.src_addr.sa_family = ARPHRD_ETHER;
+ memcpy(msg.src_addr.sa_data, pRoamInfo->u.pMICFailureInfo->taMacAddr, sizeof(pRoamInfo->u.pMICFailureInfo->taMacAddr));
+ hddLog(LOG1, "MIC MAC %02x:%02x:%02x:%02x:%02x:%02x",
+ msg.src_addr.sa_data[0],
+ msg.src_addr.sa_data[1],
+ msg.src_addr.sa_data[2],
+ msg.src_addr.sa_data[3],
+ msg.src_addr.sa_data[4],
+ msg.src_addr.sa_data[5]);
+
+ if(pRoamInfo->u.pMICFailureInfo->multicast == eSIR_TRUE)
+ msg.flags = IW_MICFAILURE_GROUP;
+ else
+ msg.flags = IW_MICFAILURE_PAIRWISE;
+ memset(&wreq, 0, sizeof(wreq));
+ wreq.data.length = sizeof(msg);
+ wireless_send_event(pAdapter->dev, IWEVMICHAELMICFAILURE, &wreq, (char *)&msg);
+#ifdef CONFIG_CFG80211
+ /* inform mic failure to nl80211 */
+ cfg80211_michael_mic_failure(pAdapter->dev,
+ pRoamInfo->u.pMICFailureInfo->taMacAddr,
+ ((pRoamInfo->u.pMICFailureInfo->multicast == eSIR_TRUE) ?
+ NL80211_KEYTYPE_GROUP :
+ NL80211_KEYTYPE_PAIRWISE),
+ pRoamInfo->u.pMICFailureInfo->keyId,
+ pRoamInfo->u.pMICFailureInfo->TSC,
+ GFP_KERNEL);
+#endif
+
+ }
+
+ return( eHAL_STATUS_SUCCESS );
+}
+
+/**============================================================================
+ *
+ @brief roamRoamConnectStatusUpdateHandler() - The Ibss connection status is
+ updated regularly here in this function.
+
+ ===========================================================================*/
+static eHalStatus roamRoamConnectStatusUpdateHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
+ tANI_U32 roamId, eRoamCmdStatus roamStatus,
+ eCsrRoamResult roamResult )
+{
+ VOS_STATUS vosStatus;
+
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ switch( roamResult )
+ {
+ case eCSR_ROAM_RESULT_IBSS_NEW_PEER:
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "IBSS New Peer indication from SME "
+ "with peerMac %2x-%2x-%2x-%2x-%2x-%2x and stationID= %d",
+ pRoamInfo->peerMac[0], pRoamInfo->peerMac[1], pRoamInfo->peerMac[2],
+ pRoamInfo->peerMac[3], pRoamInfo->peerMac[4], pRoamInfo->peerMac[5],
+ pRoamInfo->staId );
+
+ if ( !roamSaveIbssStation( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pRoamInfo->staId, (v_MACADDR_t *)pRoamInfo->peerMac ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "New IBSS peer but we already have the max we can handle. Can't register this one" );
+ break;
+ }
+
+ pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter;
+
+ // Register the Station with TL for the new peer.
+ vosStatus = hdd_roamRegisterSTA( pAdapter,
+ pRoamInfo,
+ pRoamInfo->staId,
+ (v_MACADDR_t *)pRoamInfo->peerMac,
+ pRoamInfo->pBssDesc );
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Cannot register STA with TL for IBSS. Failed with vosStatus = %d [%08lX]",
+ vosStatus, vosStatus );
+ }
+
+ netif_carrier_on(pAdapter->dev);
+ netif_tx_start_all_queues(pAdapter->dev);
+ break;
+ }
+
+ case eCSR_ROAM_RESULT_IBSS_CONNECT:
+ {
+
+ roamIbssConnectHandler( pAdapter, pRoamInfo );
+
+ break;
+ }
+ case eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED:
+ {
+
+ if ( !roamRemoveIbssStation( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pRoamInfo->staId ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "IBSS peer departed by cannot find peer in our registration table with TL" );
+ }
+
+ hdd_roamDeregisterSTA( pAdapter, pRoamInfo->staId );
+
+ pHddCtx->sta_to_adapter[pRoamInfo->staId] = NULL;
+
+ break;
+ }
+ case eCSR_ROAM_RESULT_IBSS_INACTIVE:
+ {
+ // Stop only when we are inactive
+ netif_tx_disable(pAdapter->dev);
+ netif_carrier_off(pAdapter->dev);
+ hdd_connSetConnectionState( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), eConnectionState_NotConnected );
+
+ // Send the bssid address to the wext.
+ hdd_SendAssociationEvent(pAdapter->dev, pRoamInfo);
+ // clean up data path
+ hdd_disconnect_tx_rx(pAdapter);
+ break;
+ }
+ default:
+ break;
+
+ }
+
+ return( eHAL_STATUS_SUCCESS );
+}
+
+eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U32 roamId,
+ eRoamCmdStatus roamStatus, eCsrRoamResult roamResult )
+{
+ eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+ hdd_adapter_t *pAdapter = (hdd_adapter_t *)pContext;
+ hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "CSR Callback: status= %d result= %d roamID=%ld",
+ roamStatus, roamResult, roamId );
+ switch( roamStatus )
+ {
+ case eCSR_ROAM_SESSION_OPENED:
+ if(pAdapter != NULL)
+ {
+ set_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
+ complete(&pAdapter->session_open_comp_var);
+ }
+ break;
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ /* We did pre-auth,then we attempted a 11r or ccx reassoc.
+ * reassoc failed due to failure, timeout, reject from ap
+ * in any case tell the OS, our carrier is off and mark
+ * interface down */
+ case eCSR_ROAM_FT_REASSOC_FAILED:
+ hddLog(LOG1, FL("Reassoc Failed\n"));
+ halStatus = hdd_DisConnectHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult );
+ /* Check if Mcast/Bcast Filters are set, if yes clear the filters here */
+ if ((WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set == TRUE) {
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#ifdef MSM_PLATFORM
+ hdd_conf_mcastbcast_filter((WLAN_HDD_GET_CTX(pAdapter)), FALSE);
+#endif
+#endif
+ (WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set = FALSE;
+ }
+ pHddStaCtx->ft_carrier_on = FALSE;
+ break;
+
+ case eCSR_ROAM_FT_START:
+ // When we roam for CCX and 11r, we dont want the
+ // OS to be informed that the link is down. So mark
+ // the link ready for ft_start. After this the
+ // eCSR_ROAM_SHOULD_ROAM will be received.
+ // Where in we will not mark the link down
+ // Also we want to stop tx at this point when we will be
+ // doing disassoc at this time. This saves 30-60 msec
+ // after reassoc. We see old traffic from old connection on new channel
+ {
+ struct net_device *dev = pAdapter->dev;
+ netif_tx_disable(dev);
+ }
+ pHddStaCtx->ft_carrier_on = TRUE;
+ break;
+#endif
+
+ case eCSR_ROAM_SHOULD_ROAM:
+ // Dont need to do anything
+ {
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ struct net_device *dev = pAdapter->dev;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ // notify apps that we can't pass traffic anymore
+ netif_tx_disable(dev);
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ if (pHddStaCtx->ft_carrier_on == FALSE)
+ {
+#endif
+ netif_carrier_off(dev);
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ }
+#endif
+
+ //We should clear all sta register with TL, for now, only one.
+ status = hdd_roamDeregisterSTA( pAdapter, pHddStaCtx->conn_info.staId [0] );
+ if ( !VOS_IS_STATUS_SUCCESS(status ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ FL("hdd_roamDeregisterSTA() failed to for staID %d. Status= %d [0x%x]"),
+ pHddStaCtx->conn_info.staId[0], status, status );
+ status = eHAL_STATUS_FAILURE;
+ }
+
+ // Clear saved connection information in HDD
+ hdd_connRemoveConnectInfo( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) );
+ }
+ break;
+ case eCSR_ROAM_LOSTLINK:
+ case eCSR_ROAM_DISASSOCIATED:
+ {
+ char country_code[3] = SME_INVALID_COUNTRY_CODE;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "****eCSR_ROAM_DISASSOCIATED****");
+ halStatus = hdd_DisConnectHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult );
+ /* Check if Mcast/Bcast Filters are set, if yes clear the filters here */
+ if ((WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set == TRUE) {
+ hdd_conf_mcastbcast_filter((WLAN_HDD_GET_CTX(pAdapter)), FALSE);
+ (WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set = FALSE;
+ }
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ if (pHddCtx->cfg_ini->isMcAddrListFilter)
+ {
+ /*Multicast addr filtering is enabled*/
+ if(pHddCtx->mc_addr_list.isFilterApplied)
+ {
+ /*Filter applied during suspend mode*/
+ /*Clear it here*/
+ wlan_hdd_set_mc_addr_list(pHddCtx, FALSE);
+ }
+ }
+#endif
+
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
+ "%s: Disconnected from the AP and "
+ "resetting the country code to default\n",__func__);
+ /*reset the country code of previous connection*/
+ status = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL,
+ &country_code[0], pAdapter,
+ pHddCtx->pvosContext
+ );
+ if( 0 != status )
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: SME Change Country code to default failed \n",__func__);
+ }
+ }
+ break;
+ case eCSR_ROAM_IBSS_LEAVE:
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "****eCSR_ROAM_IBSS_LEAVE****");
+ halStatus = hdd_DisConnectHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult );
+ break;
+ case eCSR_ROAM_ASSOCIATION_COMPLETION:
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "****eCSR_ROAM_ASSOCIATION_COMPLETION****");
+ if ( (roamResult != eCSR_ROAM_RESULT_ASSOCIATED)
+ && ( (pWextState->roamProfile.EncryptionType.encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
+ || (pWextState->roamProfile.EncryptionType.encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104_STATICKEY)
+ )
+ && (eCSR_AUTH_TYPE_SHARED_KEY != pWextState->roamProfile.AuthType.authType[0])
+ )
+ {
+ v_U32_t roamId = 0;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "****WEP open authentication failed, trying with shared authentication****");
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
+ pWextState->roamProfile.AuthType.authType[0] = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
+ pWextState->roamProfile.csrPersona = pAdapter->device_mode;
+ halStatus = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &(pWextState->roamProfile), &roamId);
+ }
+ else
+ {
+ halStatus = hdd_AssociationCompletionHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult );
+ }
+
+ break;
+ case eCSR_ROAM_ASSOCIATION_FAILURE:
+ halStatus = hdd_AssociationCompletionHandler( pAdapter,
+ pRoamInfo, roamId, roamStatus, roamResult );
+ break;
+ case eCSR_ROAM_IBSS_IND:
+ halStatus = roamRoamIbssIndicationHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult );
+ break;
+
+ case eCSR_ROAM_CONNECT_STATUS_UPDATE:
+ halStatus = roamRoamConnectStatusUpdateHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult );
+ break;
+
+ case eCSR_ROAM_MIC_ERROR_IND:
+ halStatus = hdd_RoamMicErrorIndicationHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult );
+ break;
+
+ case eCSR_ROAM_SET_KEY_COMPLETE:
+ halStatus = hdd_RoamSetKeyCompleteHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult );
+ break;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eCSR_ROAM_FT_RESPONSE:
+ hdd_SendFTEvent(pAdapter);
+ break;
+#endif
+
+#ifdef WLAN_FEATURE_P2P
+ case eCSR_ROAM_INDICATE_MGMT_FRAME:
+ hdd_indicateMgmtFrame( pAdapter,
+ pRoamInfo->nFrameLength,
+ pRoamInfo->pbFrames,
+ pRoamInfo->frameType,
+ pRoamInfo->rxChan );
+ break;
+ case eCSR_ROAM_REMAIN_CHAN_READY:
+ hdd_remainChanReadyHandler( pAdapter );
+ break;
+ case eCSR_ROAM_SEND_ACTION_CNF:
+ hdd_sendActionCnf( pAdapter,
+ (roamResult == eCSR_ROAM_RESULT_NONE) ? TRUE : FALSE );
+ break;
+#endif
+ default:
+ break;
+ }
+ return( halStatus );
+}
+eCsrAuthType hdd_TranslateRSNToCsrAuthType( u_int8_t auth_suite[4])
+{
+ eCsrAuthType auth_type;
+ // is the auth type supported?
+ if ( memcmp(auth_suite , ccpRSNOui01, 4) == 0)
+ {
+ auth_type = eCSR_AUTH_TYPE_RSN;
+ } else
+ if (memcmp(auth_suite , ccpRSNOui02, 4) == 0)
+ {
+ auth_type = eCSR_AUTH_TYPE_RSN_PSK;
+ } else
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (memcmp(auth_suite , ccpRSNOui04, 4) == 0)
+ {
+ // Check for 11r FT Authentication with PSK
+ auth_type = eCSR_AUTH_TYPE_FT_RSN_PSK;
+ } else
+ if (memcmp(auth_suite , ccpRSNOui03, 4) == 0)
+ {
+ // Check for 11R FT Authentication with 802.1X
+ auth_type = eCSR_AUTH_TYPE_FT_RSN;
+ } else
+#endif
+#ifdef FEATURE_WLAN_CCX
+ if (memcmp(auth_suite , ccpRSNOui06, 4) == 0)
+ {
+ auth_type = eCSR_AUTH_TYPE_CCKM_RSN;
+ } else
+#endif /* FEATURE_WLAN_CCX */
+ {
+ auth_type = eCSR_AUTH_TYPE_UNKNOWN;
+ }
+ return auth_type;
+}
+#ifdef WLAN_SOFTAP_FEATURE
+eCsrAuthType
+hdd_TranslateWPAToCsrAuthType(u_int8_t auth_suite[4])
+#else
+static eCsrAuthType hdd_TranslateWPAToCsrAuthType(u_int8_t auth_suite[4])
+#endif
+{
+ eCsrAuthType auth_type;
+ // is the auth type supported?
+ if ( memcmp(auth_suite , ccpWpaOui01, 4) == 0)
+ {
+ auth_type = eCSR_AUTH_TYPE_WPA;
+ } else
+ if (memcmp(auth_suite , ccpWpaOui02, 4) == 0)
+ {
+ auth_type = eCSR_AUTH_TYPE_WPA_PSK;
+ } else
+#ifdef FEATURE_WLAN_CCX
+ if (memcmp(auth_suite , ccpWpaOui06, 4) == 0)
+ {
+ auth_type = eCSR_AUTH_TYPE_CCKM_WPA;
+ } else
+#endif /* FEATURE_WLAN_CCX */
+ {
+ auth_type = eCSR_AUTH_TYPE_UNKNOWN;
+ }
+ hddLog(LOG1, FL("auth_type: %d"), auth_type);
+ return auth_type;
+}
+#ifdef WLAN_SOFTAP_FEATURE
+eCsrEncryptionType
+hdd_TranslateRSNToCsrEncryptionType(u_int8_t cipher_suite[4])
+#else
+static eCsrEncryptionType hdd_TranslateRSNToCsrEncryptionType(u_int8_t cipher_suite[4])
+#endif
+{
+ eCsrEncryptionType cipher_type;
+ // is the cipher type supported?
+ if ( memcmp(cipher_suite , ccpRSNOui04, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_AES;
+ }
+ else if (memcmp(cipher_suite , ccpRSNOui02, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_TKIP;
+ }
+ else if (memcmp(cipher_suite , ccpRSNOui00, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_NONE;
+ }
+ else if (memcmp(cipher_suite , ccpRSNOui01, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ }
+ else if (memcmp(cipher_suite , ccpRSNOui05, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
+ }
+ else
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_FAILED;
+ }
+ hddLog(LOG1, FL("cipher_type: %d"), cipher_type);
+ return cipher_type;
+}
+/* To find if the MAC address is NULL */
+static tANI_U8 hdd_IsMACAddrNULL (tANI_U8 *macAddr, tANI_U8 length)
+{
+ int i;
+ for (i = 0; i < length; i++)
+ {
+ if (0x00 != (macAddr[i]))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+} /****** end hdd_IsMACAddrNULL() ******/
+#ifdef WLAN_SOFTAP_FEATURE
+eCsrEncryptionType
+hdd_TranslateWPAToCsrEncryptionType(u_int8_t cipher_suite[4])
+#else
+static eCsrEncryptionType
+hdd_TranslateWPAToCsrEncryptionType(u_int8_t cipher_suite[4])
+#endif
+{
+ eCsrEncryptionType cipher_type;
+ // is the cipher type supported?
+ if ( memcmp(cipher_suite , ccpWpaOui04, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_AES;
+ } else
+ if (memcmp(cipher_suite , ccpWpaOui02, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_TKIP;
+ } else
+ if (memcmp(cipher_suite , ccpWpaOui00, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_NONE;
+ } else
+ if (memcmp(cipher_suite , ccpWpaOui01, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ } else
+ if (memcmp(cipher_suite , ccpWpaOui05, 4) == 0)
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
+ } else
+ {
+ cipher_type = eCSR_ENCRYPT_TYPE_FAILED;
+ }
+ hddLog(LOG1, FL("cipher_type: %d"), cipher_type);
+ return cipher_type;
+}
+
+static tANI_S32 hdd_ProcessGENIE(hdd_adapter_t *pAdapter,
+ struct ether_addr *pBssid,
+ eCsrEncryptionType *pEncryptType,
+ eCsrEncryptionType *mcEncryptType,
+ eCsrAuthType *pAuthType,
+ u_int16_t gen_ie_len,
+ u_int8_t *gen_ie)
+{
+ tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ eHalStatus result;
+ tDot11fIERSN dot11RSNIE;
+ tDot11fIEWPA dot11WPAIE;
+ tANI_U32 i;
+ tANI_U8 *pRsnIe;
+ tANI_U16 RSNIeLen;
+ tPmkidCacheInfo PMKIDCache[4]; // Local transfer memory
+
+ /* Clear struct of tDot11fIERSN and tDot11fIEWPA specifically setting present
+ flag to 0 */
+ memset( &dot11WPAIE, 0 , sizeof(tDot11fIEWPA) );
+ memset( &dot11RSNIE, 0 , sizeof(tDot11fIERSN) );
+
+ // Validity checks
+ if ((gen_ie_len < VOS_MIN(DOT11F_IE_RSN_MIN_LEN, DOT11F_IE_WPA_MIN_LEN)) ||
+ (gen_ie_len > VOS_MAX(DOT11F_IE_RSN_MAX_LEN, DOT11F_IE_WPA_MAX_LEN)) )
+ return -EINVAL;
+ // Type check
+ if ( gen_ie[0] == DOT11F_EID_RSN)
+ {
+ // Validity checks
+ if ((gen_ie_len < DOT11F_IE_RSN_MIN_LEN ) ||
+ (gen_ie_len > DOT11F_IE_RSN_MAX_LEN) )
+ {
+ return -EINVAL;
+ }
+ // Skip past the EID byte and length byte
+ pRsnIe = gen_ie + 2;
+ RSNIeLen = gen_ie_len - 2;
+ // Unpack the RSN IE
+ dot11fUnpackIeRSN((tpAniSirGlobal) halHandle,
+ pRsnIe,
+ RSNIeLen,
+ &dot11RSNIE);
+ // Copy out the encryption and authentication types
+ hddLog(LOG1, FL("%s: pairwise cipher suite count: %d"),
+ __FUNCTION__, dot11RSNIE.pwise_cipher_suite_count );
+ hddLog(LOG1, FL("%s: authentication suite count: %d"),
+ __FUNCTION__, dot11RSNIE.akm_suite_count);
+ /*Here we have followed the apple base code,
+ but probably I suspect we can do something different*/
+ //dot11RSNIE.akm_suite_count
+ // Just translate the FIRST one
+ *pAuthType = hdd_TranslateRSNToCsrAuthType(dot11RSNIE.akm_suites[0]);
+ //dot11RSNIE.pwise_cipher_suite_count
+ *pEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.pwise_cipher_suites[0]);
+ //dot11RSNIE.gp_cipher_suite_count
+ *mcEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.gp_cipher_suite);
+ // Set the PMKSA ID Cache for this interface
+ for (i=0; i<dot11RSNIE.pmkid_count; i++)
+ {
+ if ( pBssid == NULL)
+ {
+ break;
+ }
+ if ( hdd_IsMACAddrNULL( (u_char *) pBssid , sizeof( (char *) pBssid)))
+ {
+ break;
+ }
+ // For right now, I assume setASSOCIATE() has passed in the bssid.
+ vos_mem_copy(PMKIDCache[i].BSSID,
+ pBssid, ETHER_ADDR_LEN);
+ vos_mem_copy(PMKIDCache[i].PMKID,
+ dot11RSNIE.pmkid[i],
+ CSR_RSN_PMKID_SIZE);
+ }
+ // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
+ hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with cache entry %ld."),
+ __FUNCTION__, i );
+ // Finally set the PMKSA ID Cache in CSR
+ result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
+ PMKIDCache,
+ dot11RSNIE.pmkid_count );
+ }
+ else if (gen_ie[0] == DOT11F_EID_WPA)
+ {
+ // Validity checks
+ if ((gen_ie_len < DOT11F_IE_WPA_MIN_LEN ) ||
+ (gen_ie_len > DOT11F_IE_WPA_MAX_LEN))
+ {
+ return -EINVAL;
+ }
+ // Skip past the EID byte and length byte - and four byte WiFi OUI
+ pRsnIe = gen_ie + 2 + 4;
+ RSNIeLen = gen_ie_len - (2 + 4);
+ // Unpack the WPA IE
+ dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
+ pRsnIe,
+ RSNIeLen,
+ &dot11WPAIE);
+ // Copy out the encryption and authentication types
+ hddLog(LOG1, FL("%s: WPA unicast cipher suite count: %d"),
+ __FUNCTION__, dot11WPAIE.unicast_cipher_count );
+ hddLog(LOG1, FL("%s: WPA authentication suite count: %d"),
+ __FUNCTION__, dot11WPAIE.auth_suite_count);
+ //dot11WPAIE.auth_suite_count
+ // Just translate the FIRST one
+ *pAuthType = hdd_TranslateWPAToCsrAuthType(dot11WPAIE.auth_suites[0]);
+ //dot11WPAIE.unicast_cipher_count
+ *pEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.unicast_ciphers[0]);
+ //dot11WPAIE.unicast_cipher_count
+ *mcEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
+ }
+ else
+ {
+ hddLog(LOGW, FL("gen_ie[0]: %d"), gen_ie[0]);
+ return -EINVAL;
+ }
+ return 0;
+}
+int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType)
+{
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ v_U32_t status = 0;
+ eCsrEncryptionType RSNEncryptType;
+ eCsrEncryptionType mcRSNEncryptType;
+ struct ether_addr bSsid; // MAC address of assoc peer
+ // MAC address of assoc peer
+ // But, this routine is only called when we are NOT associated.
+ vos_mem_copy(bSsid.ether_addr_octet,
+ pWextState->roamProfile.BSSIDs.bssid,
+ sizeof(bSsid.ether_addr_octet));
+ if (pWextState->WPARSNIE[0] == DOT11F_EID_RSN || pWextState->WPARSNIE[0] == DOT11F_EID_WPA)
+ {
+ //continue
+ }
+ else
+ {
+ return 0;
+ }
+ // The actual processing may eventually be more extensive than this.
+ // Right now, just consume any PMKIDs that are sent in by the app.
+ status = hdd_ProcessGENIE(pAdapter,
+ &bSsid, // MAC address of assoc peer
+ &RSNEncryptType,
+ &mcRSNEncryptType,
+ RSNAuthType,
+ pWextState->WPARSNIE[1]+2,
+ pWextState->WPARSNIE);
+ if (status == 0)
+ {
+ // Now copy over all the security attributes you have parsed out
+ pWextState->roamProfile.EncryptionType.numEntries = 1;
+ pWextState->roamProfile.mcEncryptionType.numEntries = 1;
+
+ pWextState->roamProfile.EncryptionType.encryptionType[0] = RSNEncryptType; // Use the cipher type in the RSN IE
+ pWextState->roamProfile.mcEncryptionType.encryptionType[0] = mcRSNEncryptType;
+ hddLog( LOG1, "%s: CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d", __FUNCTION__, *RSNAuthType, RSNEncryptType, mcRSNEncryptType);
+ }
+ return 0;
+}
+int hdd_set_csr_auth_type ( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType)
+{
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrRoamProfile* pRoamProfile = &(pWextState->roamProfile);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ ENTER();
+
+ pRoamProfile->AuthType.numEntries = 1;
+ hddLog( LOG1, "%s: pHddStaCtx->conn_info.authType = %d\n", __FUNCTION__, pHddStaCtx->conn_info.authType);
+
+ switch( pHddStaCtx->conn_info.authType)
+ {
+ case eCSR_AUTH_TYPE_OPEN_SYSTEM:
+#ifdef FEATURE_WLAN_CCX
+ case eCSR_AUTH_TYPE_CCKM_WPA:
+ case eCSR_AUTH_TYPE_CCKM_RSN:
+#endif
+ if (pWextState->wpaVersion & IW_AUTH_WPA_VERSION_DISABLED) {
+
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM ;
+ } else
+ if (pWextState->wpaVersion & IW_AUTH_WPA_VERSION_WPA) {
+
+#ifdef FEATURE_WLAN_CCX
+ if ((RSNAuthType == eCSR_AUTH_TYPE_CCKM_WPA) &&
+ ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)
+ == IW_AUTH_KEY_MGMT_802_1X)) {
+ hddLog( LOG1, "%s: set authType to CCKM WPA. AKM also 802.1X.\n", __FUNCTION__);
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_CCKM_WPA;
+ } else
+ if ((RSNAuthType == eCSR_AUTH_TYPE_CCKM_WPA)) {
+ hddLog( LOG1, "%s: Last chance to set authType to CCKM WPA.\n", __FUNCTION__);
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_CCKM_WPA;
+ } else
+#endif
+ if((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)
+ == IW_AUTH_KEY_MGMT_802_1X) {
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WPA;
+ } else
+ if ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_PSK)
+ == IW_AUTH_KEY_MGMT_PSK) {
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WPA_PSK;
+ } else {
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WPA_NONE;
+ }
+ }
+ if (pWextState->wpaVersion & IW_AUTH_WPA_VERSION_WPA2) {
+#ifdef FEATURE_WLAN_CCX
+ if ((RSNAuthType == eCSR_AUTH_TYPE_CCKM_RSN) &&
+ ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)
+ == IW_AUTH_KEY_MGMT_802_1X)) {
+ hddLog( LOG1, "%s: set authType to CCKM RSN. AKM also 802.1X.\n", __FUNCTION__);
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_CCKM_RSN;
+ } else
+ if ((RSNAuthType == eCSR_AUTH_TYPE_CCKM_RSN)) {
+ hddLog( LOG1, "%s: Last chance to set authType to CCKM RSN.\n", __FUNCTION__);
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_CCKM_RSN;
+ } else
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if ((RSNAuthType == eCSR_AUTH_TYPE_FT_RSN) &&
+ ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)
+ == IW_AUTH_KEY_MGMT_802_1X)) {
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_FT_RSN;
+ }
+ if ((RSNAuthType == eCSR_AUTH_TYPE_FT_RSN_PSK) &&
+ ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_PSK)
+ == IW_AUTH_KEY_MGMT_PSK)) {
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_FT_RSN_PSK;
+ } else
+#endif
+
+ if( (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)
+ == IW_AUTH_KEY_MGMT_802_1X) {
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN;
+ } else
+ if ( (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_PSK)
+ == IW_AUTH_KEY_MGMT_PSK) {
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN_PSK;
+ } else {
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_UNKNOWN;
+ }
+ }
+ break;
+
+ case eCSR_AUTH_TYPE_SHARED_KEY:
+
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_SHARED_KEY;
+ break;
+ default:
+
+#ifdef FEATURE_WLAN_CCX
+ hddLog( LOG1, "%s: In default, unknown auth type.\n", __FUNCTION__);
+#endif /* FEATURE_WLAN_CCX */
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_UNKNOWN;
+ break;
+ }
+
+ hddLog( LOG1, "%s Set roam Authtype to %d",
+ __FUNCTION__, pWextState->roamProfile.AuthType.authType[0]);
+
+ EXIT();
+ return 0;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief iw_set_essid() -
+ This function sets the ssid received from wpa_supplicant
+ to the CSR roam profile.
+
+ \param - dev - Pointer to the net device.
+ - info - Pointer to the iw_request_info.
+ - wrqu - Pointer to the iwreq_data.
+ - extra - Pointer to the data.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+int iw_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ v_U32_t status = 0;
+ hdd_wext_state_t *pWextState;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ v_U32_t roamId;
+ tCsrRoamProfile *pRoamProfile;
+ eMib_dot11DesiredBssType connectedBssType;
+ eCsrAuthType RSNAuthType;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ if(pWextState->mTKIPCounterMeasures == TKIP_COUNTER_MEASURE_STARTED) {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s :Counter measure is in progress", __func__);
+ return -EBUSY;
+ }
+ if( SIR_MAC_MAX_SSID_LENGTH < wrqu->essid.length )
+ return -EINVAL;
+ pRoamProfile = &pWextState->roamProfile;
+ if (pRoamProfile)
+ {
+ if ( hdd_connGetConnectedBssType( pHddStaCtx, &connectedBssType ) ||
+ ( eMib_dot11DesiredBssType_independent == pHddStaCtx->conn_info.connDot11DesiredBssType ))
+ {
+ VOS_STATUS vosStatus;
+ // need to issue a disconnect to CSR.
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+ vosStatus = sme_RoamDisconnect( hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED );
+
+ if(VOS_STATUS_SUCCESS == vosStatus)
+ wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+ }
+ }
+ /** wpa_supplicant 0.8.x, wext driver uses */
+ else
+ {
+ return -EINVAL;
+ }
+ /** wpa_supplicant 0.8.x, wext driver uses */
+#ifdef CONFIG_CFG80211
+ /** when cfg80211 defined, wpa_supplicant wext driver uses
+ zero-length, null-string ssid for force disconnection.
+ after disconnection (if previously connected) and cleaning ssid,
+ driver MUST return success */
+ if ( 0 == wrqu->essid.length ) {
+ return 0;
+ }
+#endif
+
+ status = hdd_wmm_get_uapsd_mask(pAdapter,
+ &pWextState->roamProfile.uapsd_mask);
+ if (VOS_STATUS_SUCCESS != status)
+ {
+ pWextState->roamProfile.uapsd_mask = 0;
+ }
+ pWextState->roamProfile.SSIDs.numOfSSIDs = 1;
+
+ pWextState->roamProfile.SSIDs.SSIDList->SSID.length = wrqu->essid.length;
+
+ vos_mem_zero(pWextState->roamProfile.SSIDs.SSIDList->SSID.ssId, sizeof(pWextState->roamProfile.SSIDs.SSIDList->SSID.ssId));
+ vos_mem_copy((void *)(pWextState->roamProfile.SSIDs.SSIDList->SSID.ssId), extra, wrqu->essid.length);
+ if (IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion ||
+ IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion ) {
+
+ //set gen ie
+ hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
+
+ //set auth
+ hdd_set_csr_auth_type(pAdapter, RSNAuthType);
+ }
+#ifdef FEATURE_WLAN_WAPI
+ hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __FUNCTION__);
+ if (pAdapter->wapi_info.nWapiMode)
+ {
+ switch (pAdapter->wapi_info.wapiAuthMode)
+ {
+ case WAPI_AUTH_MODE_PSK:
+ {
+ hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __FUNCTION__, pAdapter->wapi_info.wapiAuthMode);
+ pRoamProfile->AuthType.numEntries = 1;
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
+ break;
+ }
+ case WAPI_AUTH_MODE_CERT:
+ {
+ hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __FUNCTION__, pAdapter->wapi_info.wapiAuthMode);
+ pRoamProfile->AuthType.numEntries = 1;
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
+ break;
+ }
+ } // End of switch
+ if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
+ pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
+ {
+ hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __FUNCTION__);
+ pRoamProfile->EncryptionType.numEntries = 1;
+ pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
+ pRoamProfile->mcEncryptionType.numEntries = 1;
+ pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
+ }
+ }
+#endif /* FEATURE_WLAN_WAPI */
+ /* if previous genIE is not NULL, update AssocIE */
+ if (0 != pWextState->genIE.length)
+ {
+ memset( &pWextState->assocAddIE, 0, sizeof(pWextState->assocAddIE) );
+ memcpy( pWextState->assocAddIE.addIEdata, pWextState->genIE.addIEdata,
+ pWextState->genIE.length);
+ pWextState->assocAddIE.length = pWextState->genIE.length;
+ pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
+ pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
+
+ /* clear previous genIE after use it */
+ memset( &pWextState->genIE, 0, sizeof(pWextState->genIE) );
+ }
+
+ /* assumes it is not WPS Association by default, except when pAddIEAssoc has WPS IE */
+ pWextState->roamProfile.bWPSAssociation = FALSE;
+
+ if (NULL != wlan_hdd_get_wps_ie_ptr(pWextState->roamProfile.pAddIEAssoc,
+ pWextState->roamProfile.nAddIEAssocLength))
+ pWextState->roamProfile.bWPSAssociation = TRUE;
+
+
+ // Disable auto BMPS entry by PMC until DHCP is done
+ sme_SetDHCPTillPowerActiveFlag(WLAN_HDD_GET_HAL_CTX(pAdapter), TRUE);
+
+ pWextState->roamProfile.csrPersona = pAdapter->device_mode;
+ (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
+ status = sme_RoamConnect( hHal,pAdapter->sessionId, &(pWextState->roamProfile),&roamId);
+ pRoamProfile->ChannelInfo.ChannelList = NULL;
+ pRoamProfile->ChannelInfo.numOfChannels = 0;
+
+ EXIT();
+ return status;
+}
+/**---------------------------------------------------------------------------
+
+ \brief iw_get_essid() -
+ This function returns the essid to the wpa_supplicant.
+
+ \param - dev - Pointer to the net device.
+ - info - Pointer to the iw_request_info.
+ - wrqu - Pointer to the iwreq_data.
+ - extra - Pointer to the data.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+int iw_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *wextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ ENTER();
+
+ if((pHddStaCtx->conn_info.connState == eConnectionState_Associated &&
+ wextBuf->roamProfile.SSIDs.SSIDList->SSID.length > 0) ||
+ ((pHddStaCtx->conn_info.connState == eConnectionState_IbssConnected ||
+ pHddStaCtx->conn_info.connState == eConnectionState_IbssDisconnected) &&
+ wextBuf->roamProfile.SSIDs.SSIDList->SSID.length > 0))
+ {
+ dwrq->length = pHddStaCtx->conn_info.SSID.SSID.length;
+ memcpy(extra, pHddStaCtx->conn_info.SSID.SSID.ssId, dwrq->length);
+ dwrq->flags = 1;
+ } else {
+ memset(extra, 0, dwrq->length);
+ dwrq->length = 0;
+ dwrq->flags = 0;
+ }
+ EXIT();
+ return 0;
+}
+/**---------------------------------------------------------------------------
+
+ \brief iw_set_auth() -
+ This function sets the auth type received from the wpa_supplicant.
+
+ \param - dev - Pointer to the net device.
+ - info - Pointer to the iw_request_info.
+ - wrqu - Pointer to the iwreq_data.
+ - extra - Pointer to the data.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+int iw_set_auth(struct net_device *dev,struct iw_request_info *info,
+ union iwreq_data *wrqu,char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
+ eCsrEncryptionType mcEncryptionType;
+ eCsrEncryptionType ucEncryptionType;
+
+ ENTER();
+ switch(wrqu->param.flags & IW_AUTH_INDEX)
+ {
+ case IW_AUTH_WPA_VERSION:
+
+ pWextState->wpaVersion = wrqu->param.value;
+
+ break;
+
+ case IW_AUTH_CIPHER_PAIRWISE:
+ {
+ if(wrqu->param.value & IW_AUTH_CIPHER_NONE) {
+ ucEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ }
+ else if(wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
+ ucEncryptionType = eCSR_ENCRYPT_TYPE_TKIP;
+ }
+ else if(wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
+ ucEncryptionType = eCSR_ENCRYPT_TYPE_AES;
+ }
+
+ else if(wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
+
+ if( (IW_AUTH_KEY_MGMT_802_1X
+ == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) )
+ && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) )
+ /*Dynamic WEP key*/
+ ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP40;
+ else
+ /*Static WEP key*/
+ ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ }
+ else if(wrqu->param.value & IW_AUTH_CIPHER_WEP104) {
+
+ if( ( IW_AUTH_KEY_MGMT_802_1X
+ == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) )
+ && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
+ /*Dynamic WEP key*/
+ ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP104;
+ else
+ /*Static WEP key*/
+ ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
+
+ }
+ else {
+
+ hddLog(LOGW, "%s value %d UNKNOWN IW_AUTH_CIPHER",
+ __FUNCTION__, wrqu->param.value);
+ return -EINVAL;
+ }
+
+ pRoamProfile->EncryptionType.numEntries = 1;
+ pRoamProfile->EncryptionType.encryptionType[0] = ucEncryptionType;
+ }
+ break;
+ case IW_AUTH_CIPHER_GROUP:
+ {
+ if(wrqu->param.value & IW_AUTH_CIPHER_NONE) {
+ mcEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ }
+
+ else if(wrqu->param.value & IW_AUTH_CIPHER_TKIP) {
+ mcEncryptionType = eCSR_ENCRYPT_TYPE_TKIP;
+ }
+
+ else if(wrqu->param.value & IW_AUTH_CIPHER_CCMP) {
+ mcEncryptionType = eCSR_ENCRYPT_TYPE_AES;
+ }
+
+ else if(wrqu->param.value & IW_AUTH_CIPHER_WEP40) {
+
+ if( ( IW_AUTH_KEY_MGMT_802_1X
+ == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
+ && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
+
+ mcEncryptionType = eCSR_ENCRYPT_TYPE_WEP40;
+
+ else
+ mcEncryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ }
+
+ else if(wrqu->param.value & IW_AUTH_CIPHER_WEP104)
+ {
+ /*Dynamic WEP keys won't work with shared keys*/
+ if( ( IW_AUTH_KEY_MGMT_802_1X
+ == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
+ && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
+ {
+ mcEncryptionType = eCSR_ENCRYPT_TYPE_WEP104;
+ }
+ else
+ {
+ mcEncryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
+ }
+ }
+ else {
+
+ hddLog(LOGW, "%s value %d UNKNOWN IW_AUTH_CIPHER",
+ __FUNCTION__, wrqu->param.value);
+ return -EINVAL;
+ }
+
+ pRoamProfile->mcEncryptionType.numEntries = 1;
+ pRoamProfile->mcEncryptionType.encryptionType[0] = mcEncryptionType;
+ }
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ {
+ /*Save the auth algo here and set auth type to SME Roam profile
+ in the iw_set_ap_address*/
+ if( wrqu->param.value & IW_AUTH_ALG_OPEN_SYSTEM)
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+
+ else if(wrqu->param.value & IW_AUTH_ALG_SHARED_KEY)
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
+
+ else if(wrqu->param.value & IW_AUTH_ALG_LEAP)
+ /*Not supported*/
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+ pWextState->roamProfile.AuthType.authType[0] = pHddStaCtx->conn_info.authType;
+ }
+ break;
+
+ case IW_AUTH_KEY_MGMT:
+ {
+#ifdef FEATURE_WLAN_CCX
+#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
+ /*Check for CCKM AKM type */
+ if ( wrqu->param.value & IW_AUTH_KEY_MGMT_CCKM) {
+ //hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: CCKM AKM Set %d\n", __FUNCTION__, wrqu->param.value);
+ hddLog(VOS_TRACE_LEVEL_INFO,"%s: CCKM AKM Set %d\n", __FUNCTION__, wrqu->param.value);
+ /* Set the CCKM bit in authKeyMgmt */
+ /* Right now, this breaks all ref to authKeyMgmt because our
+ * code doesn't realize it is a "bitfield"
+ */
+ pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
+ /*Set the key management to 802.1X*/
+ //pWextState->authKeyMgmt = IW_AUTH_KEY_MGMT_802_1X;
+ pWextState->isCCXConnection = eANI_BOOLEAN_TRUE;
+ //This is test code. I need to actually KNOW whether this is an RSN Assoc or WPA.
+ pWextState->collectedAuthType = eCSR_AUTH_TYPE_CCKM_RSN;
+ } else if ( wrqu->param.value & IW_AUTH_KEY_MGMT_PSK) {
+ /*Save the key management*/
+ pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
+ //pWextState->authKeyMgmt = wrqu->param.value;
+ //This is test code. I need to actually KNOW whether this is an RSN Assoc or WPA.
+ pWextState->collectedAuthType = eCSR_AUTH_TYPE_RSN;
+ } else if (!( wrqu->param.value & IW_AUTH_KEY_MGMT_802_1X)) {
+ pWextState->collectedAuthType = eCSR_AUTH_TYPE_NONE; //eCSR_AUTH_TYPE_WPA_NONE
+ /*Save the key management anyway*/
+ pWextState->authKeyMgmt = wrqu->param.value;
+ } else { // It must be IW_AUTH_KEY_MGMT_802_1X
+ /*Save the key management*/
+ pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
+ //pWextState->authKeyMgmt = wrqu->param.value;
+ //This is test code. I need to actually KNOW whether this is an RSN Assoc or WPA.
+ pWextState->collectedAuthType = eCSR_AUTH_TYPE_RSN;
+ }
+#else
+ /*Save the key management*/
+ pWextState->authKeyMgmt = wrqu->param.value;
+#endif /* FEATURE_WLAN_CCX */
+ }
+ break;
+
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ {
+ if(wrqu->param.value) {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "Counter Measure started %d", wrqu->param.value);
+ pWextState->mTKIPCounterMeasures = TKIP_COUNTER_MEASURE_STARTED;
+ }
+ else {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "Counter Measure stopped=%d", wrqu->param.value);
+ pWextState->mTKIPCounterMeasures = TKIP_COUNTER_MEASURE_STOPED;
+ }
+ }
+ break;
+ case IW_AUTH_DROP_UNENCRYPTED:
+ case IW_AUTH_WPA_ENABLED:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_ROAMING_CONTROL:
+ case IW_AUTH_PRIVACY_INVOKED:
+
+ default:
+
+ hddLog(LOGW, "%s called with unsupported auth type %d", __FUNCTION__,
+ wrqu->param.flags & IW_AUTH_INDEX);
+ break;
+ }
+
+ EXIT();
+ return 0;
+}
+/**---------------------------------------------------------------------------
+
+ \brief iw_get_auth() -
+ This function returns the auth type to the wpa_supplicant.
+
+ \param - dev - Pointer to the net device.
+ - info - Pointer to the iw_request_info.
+ - wrqu - Pointer to the iwreq_data.
+ - extra - Pointer to the data.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+int iw_get_auth(struct net_device *dev,struct iw_request_info *info,
+ union iwreq_data *wrqu,char *extra)
+{
+ hdd_adapter_t* pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
+ ENTER();
+ switch(pRoamProfile->negotiatedAuthType)
+ {
+ case eCSR_AUTH_TYPE_WPA_NONE:
+ wrqu->param.flags = IW_AUTH_WPA_VERSION;
+ wrqu->param.value = IW_AUTH_WPA_VERSION_DISABLED;
+ break;
+ case eCSR_AUTH_TYPE_WPA:
+ wrqu->param.flags = IW_AUTH_WPA_VERSION;
+ wrqu->param.value = IW_AUTH_WPA_VERSION_WPA;
+ break;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eCSR_AUTH_TYPE_FT_RSN:
+#endif
+ case eCSR_AUTH_TYPE_RSN:
+ wrqu->param.flags = IW_AUTH_WPA_VERSION;
+ wrqu->param.value = IW_AUTH_WPA_VERSION_WPA2;
+ break;
+ case eCSR_AUTH_TYPE_OPEN_SYSTEM:
+ wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM;
+ break;
+ case eCSR_AUTH_TYPE_SHARED_KEY:
+ wrqu->param.value = IW_AUTH_ALG_SHARED_KEY;
+ break;
+ case eCSR_AUTH_TYPE_UNKNOWN:
+ hddLog(LOG1,"%s called with unknown auth type", __FUNCTION__);
+ wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM;
+ break;
+ case eCSR_AUTH_TYPE_AUTOSWITCH:
+ wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM;
+ break;
+ case eCSR_AUTH_TYPE_WPA_PSK:
+ hddLog(LOG1,"%s called with unknown auth type", __FUNCTION__);
+ wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM;
+ return -EIO;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eCSR_AUTH_TYPE_FT_RSN_PSK:
+#endif
+ case eCSR_AUTH_TYPE_RSN_PSK:
+ hddLog(LOG1,"%s called with unknown auth type", __FUNCTION__);
+ wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM;
+ return -EIO;
+ default:
+ hddLog(LOG1,"%s called with unknown auth type", __FUNCTION__);
+ wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM;
+ return -EIO;
+ }
+ if(((wrqu->param.flags & IW_AUTH_INDEX) == IW_AUTH_CIPHER_PAIRWISE))
+ {
+ switch(pRoamProfile->negotiatedUCEncryptionType)
+ {
+ case eCSR_ENCRYPT_TYPE_NONE:
+ wrqu->param.value = IW_AUTH_CIPHER_NONE;
+ break;
+ case eCSR_ENCRYPT_TYPE_WEP40:
+ case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
+ wrqu->param.value = IW_AUTH_CIPHER_WEP40;
+ break;
+ case eCSR_ENCRYPT_TYPE_TKIP:
+ wrqu->param.value = IW_AUTH_CIPHER_TKIP;
+ break;
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
+ wrqu->param.value = IW_AUTH_CIPHER_WEP104;
+ break;
+ case eCSR_ENCRYPT_TYPE_AES:
+ wrqu->param.value = IW_AUTH_CIPHER_CCMP;
+ break;
+ default:
+ hddLog(LOG1, "%s called with unknown auth type", __FUNCTION__);
+ return -EIO;
+ }
+ }
+
+ if(((wrqu->param.flags & IW_AUTH_INDEX) == IW_AUTH_CIPHER_GROUP))
+ {
+ switch(pRoamProfile->negotiatedMCEncryptionType)
+ {
+ case eCSR_ENCRYPT_TYPE_NONE:
+ wrqu->param.value = IW_AUTH_CIPHER_NONE;
+ break;
+ case eCSR_ENCRYPT_TYPE_WEP40:
+ case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
+ wrqu->param.value = IW_AUTH_CIPHER_WEP40;
+ break;
+ case eCSR_ENCRYPT_TYPE_TKIP:
+ wrqu->param.value = IW_AUTH_CIPHER_TKIP;
+ break;
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
+ wrqu->param.value = IW_AUTH_CIPHER_WEP104;
+ break;
+ case eCSR_ENCRYPT_TYPE_AES:
+ wrqu->param.value = IW_AUTH_CIPHER_CCMP;
+ break;
+ default:
+ hddLog(LOG1, "%s called with unknown auth type", __FUNCTION__);
+ return -EIO;
+ }
+ }
+
+ hddLog(LOG1, "%s called with auth type %d",
+ __FUNCTION__, pRoamProfile->AuthType.authType[0]);
+ EXIT();
+ return 0;
+}
+/**---------------------------------------------------------------------------
+
+ \brief iw_set_ap_address() -
+ This function calls the sme_RoamConnect function to associate
+ to the AP with the specified BSSID received from the wpa_supplicant.
+
+ \param - dev - Pointer to the net device.
+ - info - Pointer to the iw_request_info.
+ - wrqu - Pointer to the iwreq_data.
+ - extra - Pointer to the data.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+int iw_set_ap_address(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(WLAN_HDD_GET_PRIV_PTR(dev));
+ v_U8_t *pMacAddress=NULL;
+ ENTER();
+ pMacAddress = (v_U8_t*) wrqu->ap_addr.sa_data;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%02x:%02x:%02x:%02x:%02x:%02x",pMacAddress[0],pMacAddress[1],
+ pMacAddress[2],pMacAddress[3],pMacAddress[4],pMacAddress[5]);
+ vos_mem_copy( pHddStaCtx->conn_info.bssId, pMacAddress, sizeof( tCsrBssid ));
+ EXIT();
+
+ return 0;
+}
+/**---------------------------------------------------------------------------
+
+ \brief iw_get_ap_address() -
+ This function returns the BSSID to the wpa_supplicant
+ \param - dev - Pointer to the net device.
+ - info - Pointer to the iw_request_info.
+ - wrqu - Pointer to the iwreq_data.
+ - extra - Pointer to the data.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+int iw_get_ap_address(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ //hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(WLAN_HDD_GET_PRIV_PTR(dev));
+
+ ENTER();
+
+ if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
+ (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
+ {
+ memcpy(wrqu->ap_addr.sa_data,pHddStaCtx->conn_info.bssId,sizeof(wrqu->ap_addr.sa_data));
+ }
+ else
+ {
+ memset(wrqu->ap_addr.sa_data,0,sizeof(wrqu->ap_addr.sa_data));
+ }
+ EXIT();
+ return 0;
+}
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
new file mode 100644
index 0000000..f921155
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -0,0 +1,3123 @@
+/*
+ * 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.
+ */
+
+/**=========================================================================
+
+ EDIT HISTORY FOR FILE
+
+
+ This section contains comments describing changes made to the module.
+ Notice that changes are listed in reverse chronological order.
+
+
+ $Header:$ $DateTime: $ $Author: $
+
+
+ when who what, where, why
+ -------- --- --------------------------------------------------------
+ 07/27/09 kanand Created module.
+
+ ==========================================================================*/
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+
+
+#include <linux/firmware.h>
+#include <linux/string.h>
+#include <wlan_hdd_includes.h>
+#include <wlan_hdd_main.h>
+#include <wlan_hdd_assoc.h>
+#include <wlan_hdd_cfg.h>
+#include <linux/string.h>
+#include <vos_types.h>
+#include <csrApi.h>
+#include <pmcApi.h>
+#include <wlan_hdd_misc.h>
+
+
+REG_TABLE_ENTRY g_registry_table[] =
+{
+ REG_VARIABLE( CFG_RTS_THRESHOLD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, RTSThreshold,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_RTS_THRESHOLD_DEFAULT,
+ CFG_RTS_THRESHOLD_MIN,
+ CFG_RTS_THRESHOLD_MAX ),
+
+ REG_VARIABLE( CFG_FRAG_THRESHOLD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, FragmentationThreshold,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FRAG_THRESHOLD_DEFAULT,
+ CFG_FRAG_THRESHOLD_MIN,
+ CFG_FRAG_THRESHOLD_MAX ),
+
+ REG_VARIABLE( CFG_CALIBRATION_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Calibration,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_CALIBRATION_DEFAULT,
+ CFG_CALIBRATION_MIN,
+ CFG_CALIBRATION_MAX ),
+
+ REG_VARIABLE( CFG_CALIBRATION_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, CalibrationPeriod,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_CALIBRATION_PERIOD_DEFAULT,
+ CFG_CALIBRATION_PERIOD_MIN,
+ CFG_CALIBRATION_PERIOD_MAX ),
+
+ REG_VARIABLE( CFG_OPERATING_CHANNEL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, OperatingChannel,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_OPERATING_CHANNEL_DEFAULT,
+ CFG_OPERATING_CHANNEL_MIN,
+ CFG_OPERATING_CHANNEL_MAX ),
+
+ REG_VARIABLE( CFG_SHORT_SLOT_TIME_ENABLED_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, ShortSlotTimeEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_SHORT_SLOT_TIME_ENABLED_DEFAULT,
+ CFG_SHORT_SLOT_TIME_ENABLED_MIN,
+ CFG_SHORT_SLOT_TIME_ENABLED_MAX ),
+
+ REG_VARIABLE( CFG_11D_SUPPORT_ENABLED_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Is11dSupportEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_11D_SUPPORT_ENABLED_DEFAULT,
+ CFG_11D_SUPPORT_ENABLED_MIN,
+ CFG_11D_SUPPORT_ENABLED_MAX ),
+
+ REG_VARIABLE( CFG_ENFORCE_11D_CHANNELS_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fEnforce11dChannels,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_ENFORCE_11D_CHANNELS_DEFAULT,
+ CFG_ENFORCE_11D_CHANNELS_MIN,
+ CFG_ENFORCE_11D_CHANNELS_MAX ),
+
+ REG_VARIABLE( CFG_COUNTRY_CODE_PRIORITY_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fSupplicantCountryCodeHasPriority,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_COUNTRY_CODE_PRIORITY_DEFAULT,
+ CFG_COUNTRY_CODE_PRIORITY_MIN,
+ CFG_COUNTRY_CODE_PRIORITY_MAX),
+
+ REG_VARIABLE( CFG_ENFORCE_COUNTRY_CODE_MATCH_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fEnforceCountryCodeMatch,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_ENFORCE_COUNTRY_CODE_MATCH_DEFAULT,
+ CFG_ENFORCE_COUNTRY_CODE_MATCH_MIN,
+ CFG_ENFORCE_COUNTRY_CODE_MATCH_MAX ),
+
+ REG_VARIABLE( CFG_ENFORCE_DEFAULT_DOMAIN_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fEnforceDefaultDomain,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_ENFORCE_DEFAULT_DOMAIN_DEFAULT,
+ CFG_ENFORCE_DEFAULT_DOMAIN_MIN,
+ CFG_ENFORCE_DEFAULT_DOMAIN_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_ID1_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg1Id,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_ID1_DEFAULT,
+ CFG_GENERIC_ID1_MIN,
+ CFG_GENERIC_ID1_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_ID2_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg2Id,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_ID2_DEFAULT,
+ CFG_GENERIC_ID2_MIN,
+ CFG_GENERIC_ID2_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_ID3_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg3Id,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_ID3_DEFAULT,
+ CFG_GENERIC_ID3_MIN,
+ CFG_GENERIC_ID3_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_ID4_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg4Id,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_ID4_DEFAULT,
+ CFG_GENERIC_ID4_MIN,
+ CFG_GENERIC_ID4_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_ID5_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg5Id,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_ID5_DEFAULT,
+ CFG_GENERIC_ID5_MIN,
+ CFG_GENERIC_ID5_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_VALUE1_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg1Value,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_VALUE1_DEFAULT,
+ CFG_GENERIC_VALUE1_MIN,
+ CFG_GENERIC_VALUE1_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_VALUE2_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg2Value,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_VALUE2_DEFAULT,
+ CFG_GENERIC_VALUE2_MIN,
+ CFG_GENERIC_VALUE2_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_VALUE3_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg3Value,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_VALUE3_DEFAULT,
+ CFG_GENERIC_VALUE3_MIN,
+ CFG_GENERIC_VALUE3_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_VALUE4_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg4Value,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_VALUE4_DEFAULT,
+ CFG_GENERIC_VALUE4_MIN,
+ CFG_GENERIC_VALUE4_MAX ),
+
+ REG_VARIABLE( CFG_GENERIC_VALUE5_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, Cfg5Value,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GENERIC_VALUE5_DEFAULT,
+ CFG_GENERIC_VALUE5_MIN,
+ CFG_GENERIC_VALUE5_MAX ),
+
+ REG_VARIABLE( CFG_HEARTBEAT_THRESH_24_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, HeartbeatThresh24,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_HEARTBEAT_THRESH_24_DEFAULT,
+ CFG_HEARTBEAT_THRESH_24_MIN,
+ CFG_HEARTBEAT_THRESH_24_MAX ),
+
+ REG_VARIABLE_STRING( CFG_POWER_USAGE_NAME, WLAN_PARAM_String,
+ hdd_config_t, PowerUsageControl,
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_POWER_USAGE_DEFAULT ),
+
+ REG_VARIABLE( CFG_ENABLE_SUSPEND_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nEnableSuspend,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_SUSPEND_DEFAULT,
+ CFG_ENABLE_SUSPEND_MIN,
+ CFG_ENABLE_SUSPEND_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_ENABLE_DRIVER_STOP_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nEnableDriverStop,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_ENABLE_DRIVER_STOP_DEFAULT,
+ CFG_ENABLE_ENABLE_DRIVER_STOP_MIN,
+ CFG_ENABLE_ENABLE_DRIVER_STOP_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_IMPS_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fIsImpsEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_IMPS_DEFAULT,
+ CFG_ENABLE_IMPS_MIN,
+ CFG_ENABLE_IMPS_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_LOGP_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fIsLogpEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_LOGP_DEFAULT,
+ CFG_ENABLE_LOGP_MIN,
+ CFG_ENABLE_LOGP_MAX ),
+
+ REG_VARIABLE( CFG_IMPS_MINIMUM_SLEEP_TIME_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nImpsMinSleepTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_IMPS_MINIMUM_SLEEP_TIME_DEFAULT,
+ CFG_IMPS_MINIMUM_SLEEP_TIME_MIN,
+ CFG_IMPS_MINIMUM_SLEEP_TIME_MAX ),
+
+ REG_VARIABLE( CFG_IMPS_MAXIMUM_SLEEP_TIME_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nImpsMaxSleepTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_IMPS_MAXIMUM_SLEEP_TIME_DEFAULT,
+ CFG_IMPS_MAXIMUM_SLEEP_TIME_MIN,
+ CFG_IMPS_MAXIMUM_SLEEP_TIME_MAX ),
+
+ REG_VARIABLE( CFG_IMPS_MODERATE_SLEEP_TIME_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nImpsModSleepTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_IMPS_MODERATE_SLEEP_TIME_DEFAULT,
+ CFG_IMPS_MODERATE_SLEEP_TIME_MIN,
+ CFG_IMPS_MODERATE_SLEEP_TIME_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_BMPS_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fIsBmpsEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_BMPS_DEFAULT,
+ CFG_ENABLE_BMPS_MIN,
+ CFG_ENABLE_BMPS_MAX ),
+
+ REG_VARIABLE( CFG_BMPS_MINIMUM_LI_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nBmpsMinListenInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_BMPS_MINIMUM_LI_DEFAULT,
+ CFG_BMPS_MINIMUM_LI_MIN,
+ CFG_BMPS_MINIMUM_LI_MAX ),
+
+ REG_VARIABLE( CFG_BMPS_MAXIMUM_LI_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nBmpsMaxListenInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_BMPS_MAXIMUM_LI_DEFAULT,
+ CFG_BMPS_MAXIMUM_LI_MIN,
+ CFG_BMPS_MAXIMUM_LI_MAX ),
+
+ REG_VARIABLE( CFG_BMPS_MODERATE_LI_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nBmpsModListenInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_BMPS_MODERATE_LI_DEFAULT,
+ CFG_BMPS_MODERATE_LI_MIN,
+ CFG_BMPS_MODERATE_LI_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_AUTO_BMPS_TIMER_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fIsAutoBmpsTimerEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_AUTO_BMPS_TIMER_DEFAULT,
+ CFG_ENABLE_AUTO_BMPS_TIMER_MIN,
+ CFG_ENABLE_AUTO_BMPS_TIMER_MAX ),
+
+ REG_VARIABLE( CFG_AUTO_BMPS_TIMER_VALUE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nAutoBmpsTimerValue,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AUTO_BMPS_TIMER_VALUE_DEFAULT,
+ CFG_AUTO_BMPS_TIMER_VALUE_MIN,
+ CFG_AUTO_BMPS_TIMER_VALUE_MAX ),
+
+ REG_VARIABLE( CFG_DOT11_MODE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, dot11Mode,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_DOT11_MODE_DEFAULT,
+ CFG_DOT11_MODE_MIN,
+ CFG_DOT11_MODE_MAX ),
+
+ REG_VARIABLE( CFG_CHANNEL_BONDING_MODE_24GHZ_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nChannelBondingMode24GHz,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_CHANNEL_BONDING_MODE_DEFAULT,
+ CFG_CHANNEL_BONDING_MODE_MIN,
+ CFG_CHANNEL_BONDING_MODE_MAX),
+
+ REG_VARIABLE( CFG_CHANNEL_BONDING_MODE_5GHZ_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nChannelBondingMode5GHz,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_CHANNEL_BONDING_MODE_DEFAULT,
+ CFG_CHANNEL_BONDING_MODE_MIN,
+ CFG_CHANNEL_BONDING_MODE_MAX),
+
+ REG_VARIABLE( CFG_MAX_RX_AMPDU_FACTOR_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, MaxRxAmpduFactor,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK ,
+ CFG_MAX_RX_AMPDU_FACTOR_DEFAULT,
+ CFG_MAX_RX_AMPDU_FACTOR_MIN,
+ CFG_MAX_RX_AMPDU_FACTOR_MAX),
+
+ REG_VARIABLE( CFG_FIXED_RATE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, TxRate,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_FIXED_RATE_DEFAULT,
+ CFG_FIXED_RATE_MIN,
+ CFG_FIXED_RATE_MAX ),
+
+ REG_VARIABLE( CFG_SHORT_GI_20MHZ_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, ShortGI20MhzEnable,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_SHORT_GI_20MHZ_DEFAULT,
+ CFG_SHORT_GI_20MHZ_MIN,
+ CFG_SHORT_GI_20MHZ_MAX ),
+
+ REG_VARIABLE( CFG_BLOCK_ACK_AUTO_SETUP_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, BlockAckAutoSetup,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_BLOCK_ACK_AUTO_SETUP_DEFAULT,
+ CFG_BLOCK_ACK_AUTO_SETUP_MIN,
+ CFG_BLOCK_ACK_AUTO_SETUP_MAX ),
+
+ REG_VARIABLE( CFG_SCAN_RESULT_AGE_COUNT_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, ScanResultAgeCount,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_SCAN_RESULT_AGE_COUNT_DEFAULT,
+ CFG_SCAN_RESULT_AGE_COUNT_MIN,
+ CFG_SCAN_RESULT_AGE_COUNT_MAX ),
+
+ REG_VARIABLE( CFG_SCAN_RESULT_AGE_TIME_NCNPS_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nScanAgeTimeNCNPS,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_SCAN_RESULT_AGE_TIME_NCNPS_DEFAULT,
+ CFG_SCAN_RESULT_AGE_TIME_NCNPS_MIN,
+ CFG_SCAN_RESULT_AGE_TIME_NCNPS_MAX ),
+
+ REG_VARIABLE( CFG_SCAN_RESULT_AGE_TIME_NCPS_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nScanAgeTimeNCPS,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_SCAN_RESULT_AGE_TIME_NCPS_DEFAULT,
+ CFG_SCAN_RESULT_AGE_TIME_NCPS_MIN,
+ CFG_SCAN_RESULT_AGE_TIME_NCPS_MAX ),
+
+ REG_VARIABLE( CFG_SCAN_RESULT_AGE_TIME_CNPS_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nScanAgeTimeCNPS,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_SCAN_RESULT_AGE_TIME_CNPS_DEFAULT,
+ CFG_SCAN_RESULT_AGE_TIME_CNPS_MIN,
+ CFG_SCAN_RESULT_AGE_TIME_CNPS_MAX ),
+
+ REG_VARIABLE( CFG_SCAN_RESULT_AGE_TIME_CPS_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nScanAgeTimeCPS,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_SCAN_RESULT_AGE_TIME_CPS_DEFAULT,
+ CFG_SCAN_RESULT_AGE_TIME_CPS_MIN,
+ CFG_SCAN_RESULT_AGE_TIME_CPS_MAX ),
+
+ REG_VARIABLE( CFG_RSSI_CATEGORY_GAP_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nRssiCatGap,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_RSSI_CATEGORY_GAP_DEFAULT,
+ CFG_RSSI_CATEGORY_GAP_MIN,
+ CFG_RSSI_CATEGORY_GAP_MAX ),
+
+ REG_VARIABLE( CFG_STAT_TIMER_INTERVAL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nStatTimerInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_STAT_TIMER_INTERVAL_DEFAULT,
+ CFG_STAT_TIMER_INTERVAL_MIN,
+ CFG_STAT_TIMER_INTERVAL_MAX ),
+
+ REG_VARIABLE( CFG_SHORT_PREAMBLE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fIsShortPreamble,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_SHORT_PREAMBLE_DEFAULT,
+ CFG_SHORT_PREAMBLE_MIN,
+ CFG_SHORT_PREAMBLE_MAX ),
+
+ REG_VARIABLE( CFG_IBSS_AUTO_BSSID_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fIsAutoIbssBssid,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_IBSS_AUTO_BSSID_DEFAULT,
+ CFG_IBSS_AUTO_BSSID_MIN,
+ CFG_IBSS_AUTO_BSSID_MAX ),
+
+ REG_VARIABLE_STRING( CFG_IBSS_BSSID_NAME, WLAN_PARAM_MacAddr,
+ hdd_config_t, IbssBssid,
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_IBSS_BSSID_DEFAULT ),
+
+ REG_VARIABLE_STRING( CFG_INTF0_MAC_ADDR_NAME, WLAN_PARAM_MacAddr,
+ hdd_config_t, intfMacAddr[0],
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_INTF0_MAC_ADDR_DEFAULT ),
+
+ REG_VARIABLE_STRING( CFG_INTF1_MAC_ADDR_NAME, WLAN_PARAM_MacAddr,
+ hdd_config_t, intfMacAddr[1],
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_INTF1_MAC_ADDR_DEFAULT ),
+
+ REG_VARIABLE_STRING( CFG_INTF2_MAC_ADDR_NAME, WLAN_PARAM_MacAddr,
+ hdd_config_t, intfMacAddr[2],
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_INTF2_MAC_ADDR_DEFAULT ),
+
+ REG_VARIABLE_STRING( CFG_INTF3_MAC_ADDR_NAME, WLAN_PARAM_MacAddr,
+ hdd_config_t, intfMacAddr[3],
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_INTF3_MAC_ADDR_DEFAULT ),
+
+#ifdef WLAN_SOFTAP_FEATURE
+ REG_VARIABLE( CFG_AP_QOS_UAPSD_MODE_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, apUapsdEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_QOS_UAPSD_MODE_DEFAULT,
+ CFG_AP_QOS_UAPSD_MODE_MIN,
+ CFG_AP_QOS_UAPSD_MODE_MAX ),
+
+ REG_VARIABLE_STRING( CFG_AP_COUNTRY_CODE, WLAN_PARAM_String,
+ hdd_config_t, apCntryCode,
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_AP_COUNTRY_CODE_DEFAULT ),
+
+ REG_VARIABLE( CFG_AP_ENABLE_PROTECTION_MODE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, apProtEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_ENABLE_PROTECTION_MODE_DEFAULT,
+ CFG_AP_ENABLE_PROTECTION_MODE_MIN,
+ CFG_AP_ENABLE_PROTECTION_MODE_MAX ),
+
+ REG_VARIABLE( CFG_AP_PROTECTION_MODE_NAME, WLAN_PARAM_HexInteger,
+ hdd_config_t, apProtection,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_PROTECTION_MODE_DEFAULT,
+ CFG_AP_PROTECTION_MODE_MIN,
+ CFG_AP_PROTECTION_MODE_MAX ),
+
+ REG_VARIABLE( CFG_AP_OBSS_PROTECTION_MODE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, apOBSSProtEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_OBSS_PROTECTION_MODE_DEFAULT,
+ CFG_AP_OBSS_PROTECTION_MODE_MIN,
+ CFG_AP_OBSS_PROTECTION_MODE_MAX ),
+
+ REG_VARIABLE( CFG_AP_STA_SECURITY_SEPERATION_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, apDisableIntraBssFwd,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_STA_SECURITY_SEPERATION_DEFAULT,
+ CFG_AP_STA_SECURITY_SEPERATION_MIN,
+ CFG_AP_STA_SECURITY_SEPERATION_MAX ),
+
+ REG_VARIABLE( CFG_FRAMES_PROCESSING_TH_MODE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, MinFramesProcThres,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FRAMES_PROCESSING_TH_DEFAULT,
+ CFG_FRAMES_PROCESSING_TH_MIN,
+ CFG_FRAMES_PROCESSING_TH_MAX ),
+
+ REG_VARIABLE(CFG_SAP_CHANNEL_SELECT_START_CHANNEL , WLAN_PARAM_Integer,
+ hdd_config_t, apStartChannelNum,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_SAP_CHANNEL_SELECT_START_CHANNEL_DEFAULT,
+ CFG_SAP_CHANNEL_SELECT_START_CHANNEL_MIN,
+ CFG_SAP_CHANNEL_SELECT_START_CHANNEL_MAX ),
+
+ REG_VARIABLE(CFG_SAP_CHANNEL_SELECT_END_CHANNEL , WLAN_PARAM_Integer,
+ hdd_config_t, apEndChannelNum,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_SAP_CHANNEL_SELECT_END_CHANNEL_DEFAULT,
+ CFG_SAP_CHANNEL_SELECT_END_CHANNEL_MIN,
+ CFG_SAP_CHANNEL_SELECT_END_CHANNEL_MAX ),
+
+ REG_VARIABLE(CFG_SAP_CHANNEL_SELECT_OPERATING_BAND , WLAN_PARAM_Integer,
+ hdd_config_t, apOperatingBand,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_DEFAULT,
+ CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_MIN,
+ CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_MAX ),
+
+ REG_VARIABLE(CFG_SAP_AUTO_CHANNEL_SELECTION_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, apAutoChannelSelection,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_SAP_AUTO_CHANNEL_SELECTION_DEFAULT,
+ CFG_SAP_AUTO_CHANNEL_SELECTION_MIN,
+ CFG_SAP_AUTO_CHANNEL_SELECTION_MAX ),
+
+ REG_VARIABLE(CFG_ENABLE_LTE_COEX , WLAN_PARAM_Integer,
+ hdd_config_t, enableLTECoex,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_LTE_COEX_DEFAULT,
+ CFG_ENABLE_LTE_COEX_MIN,
+ CFG_ENABLE_LTE_COEX_MAX ),
+
+ REG_VARIABLE( CFG_AP_KEEP_ALIVE_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, apKeepAlivePeriod,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_KEEP_ALIVE_PERIOD_DEFAULT,
+ CFG_AP_KEEP_ALIVE_PERIOD_MIN,
+ CFG_AP_KEEP_ALIVE_PERIOD_MAX),
+
+ REG_VARIABLE( CFG_GO_KEEP_ALIVE_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, goKeepAlivePeriod,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_GO_KEEP_ALIVE_PERIOD_DEFAULT,
+ CFG_GO_KEEP_ALIVE_PERIOD_MIN,
+ CFG_GO_KEEP_ALIVE_PERIOD_MAX),
+
+#endif
+ REG_VARIABLE(CFG_DISABLE_PACKET_FILTER , WLAN_PARAM_Integer,
+ hdd_config_t, disablePacketFilter,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_DISABLE_PACKET_FILTER_DEFAULT,
+ CFG_DISABLE_PACKET_FILTER_MIN,
+ CFG_DISABLE_PACKET_FILTER_MAX ),
+
+ REG_VARIABLE( CFG_BEACON_INTERVAL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nBeaconInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_BEACON_INTERVAL_DEFAULT,
+ CFG_BEACON_INTERVAL_MIN,
+ CFG_BEACON_INTERVAL_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_HANDOFF_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fIsHandoffEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_HANDOFF_DEFAULT,
+ CFG_ENABLE_HANDOFF_MIN,
+ CFG_ENABLE_HANDOFF_MAX ),
+
+
+ REG_VARIABLE( CFG_ENABLE_IDLE_SCAN_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, nEnableIdleScan,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_IDLE_SCAN_DEFAULT,
+ CFG_ENABLE_IDLE_SCAN_MIN,
+ CFG_ENABLE_IDLE_SCAN_MAX ),
+
+ REG_VARIABLE( CFG_ROAMING_TIME_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, nRoamingTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ROAMING_TIME_DEFAULT,
+ CFG_ROAMING_TIME_MIN,
+ CFG_ROAMING_TIME_MAX ),
+
+ REG_VARIABLE( CFG_VCC_RSSI_TRIGGER_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, nVccRssiTrigger,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_VCC_RSSI_TRIGGER_DEFAULT,
+ CFG_VCC_RSSI_TRIGGER_MIN,
+ CFG_VCC_RSSI_TRIGGER_MAX ),
+
+ REG_VARIABLE( CFG_VCC_UL_MAC_LOSS_THRESH_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, nVccUlMacLossThreshold,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_VCC_UL_MAC_LOSS_THRESH_DEFAULT,
+ CFG_VCC_UL_MAC_LOSS_THRESH_MIN,
+ CFG_VCC_UL_MAC_LOSS_THRESH_MAX ),
+
+ REG_VARIABLE( CFG_PASSIVE_MAX_CHANNEL_TIME_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nPassiveMaxChnTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_PASSIVE_MAX_CHANNEL_TIME_DEFAULT,
+ CFG_PASSIVE_MAX_CHANNEL_TIME_MIN,
+ CFG_PASSIVE_MAX_CHANNEL_TIME_MAX ),
+
+ REG_VARIABLE( CFG_PASSIVE_MIN_CHANNEL_TIME_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nPassiveMinChnTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_PASSIVE_MIN_CHANNEL_TIME_DEFAULT,
+ CFG_PASSIVE_MIN_CHANNEL_TIME_MIN,
+ CFG_PASSIVE_MIN_CHANNEL_TIME_MAX ),
+
+ REG_VARIABLE( CFG_ACTIVE_MAX_CHANNEL_TIME_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nActiveMaxChnTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ACTIVE_MAX_CHANNEL_TIME_DEFAULT,
+ CFG_ACTIVE_MAX_CHANNEL_TIME_MIN,
+ CFG_ACTIVE_MAX_CHANNEL_TIME_MAX ),
+
+ REG_VARIABLE( CFG_ACTIVE_MIN_CHANNEL_TIME_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nActiveMinChnTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ACTIVE_MIN_CHANNEL_TIME_DEFAULT,
+ CFG_ACTIVE_MIN_CHANNEL_TIME_MIN,
+ CFG_ACTIVE_MIN_CHANNEL_TIME_MAX ),
+
+ REG_VARIABLE( CFG_MAX_PS_POLL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nMaxPsPoll,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_MAX_PS_POLL_DEFAULT,
+ CFG_MAX_PS_POLL_MIN,
+ CFG_MAX_PS_POLL_MAX ),
+
+ REG_VARIABLE( CFG_MAX_TX_POWER_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nTxPowerCap,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_MAX_TX_POWER_DEFAULT,
+ CFG_MAX_TX_POWER_MIN,
+ CFG_MAX_TX_POWER_MAX ),
+
+ REG_VARIABLE( CFG_LOW_GAIN_OVERRIDE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fIsLowGainOverride,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_LOW_GAIN_OVERRIDE_DEFAULT,
+ CFG_LOW_GAIN_OVERRIDE_MIN,
+ CFG_LOW_GAIN_OVERRIDE_MAX ),
+
+ REG_VARIABLE( CFG_RSSI_FILTER_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nRssiFilterPeriod,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_RSSI_FILTER_PERIOD_DEFAULT,
+ CFG_RSSI_FILTER_PERIOD_MIN,
+ CFG_RSSI_FILTER_PERIOD_MAX ),
+
+ REG_VARIABLE( CFG_IGNORE_DTIM_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fIgnoreDtim,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_IGNORE_DTIM_DEFAULT,
+ CFG_IGNORE_DTIM_MIN,
+ CFG_IGNORE_DTIM_MAX ),
+
+ REG_VARIABLE( CFG_RX_ANT_CONFIGURATION_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nRxAnt,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_RX_ANT_CONFIGURATION_NAME_DEFAULT,
+ CFG_RX_ANT_CONFIGURATION_NAME_MIN,
+ CFG_RX_ANT_CONFIGURATION_NAME_MAX ),
+
+ REG_VARIABLE( CFG_FW_HEART_BEAT_MONITORING_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fEnableFwHeartBeatMonitoring,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FW_HEART_BEAT_MONITORING_DEFAULT,
+ CFG_FW_HEART_BEAT_MONITORING_MIN,
+ CFG_FW_HEART_BEAT_MONITORING_MAX ),
+
+ REG_VARIABLE( CFG_FW_BEACON_FILTERING_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fEnableFwBeaconFiltering,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FW_BEACON_FILTERING_DEFAULT,
+ CFG_FW_BEACON_FILTERING_MIN,
+ CFG_FW_BEACON_FILTERING_MAX ),
+
+ REG_VARIABLE( CFG_FW_RSSI_MONITORING_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fEnableFwRssiMonitoring,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FW_RSSI_MONITORING_DEFAULT,
+ CFG_FW_RSSI_MONITORING_MIN,
+ CFG_FW_RSSI_MONITORING_MAX ),
+
+ REG_VARIABLE( CFG_DATA_INACTIVITY_TIMEOUT_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nDataInactivityTimeout,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_DATA_INACTIVITY_TIMEOUT_DEFAULT,
+ CFG_DATA_INACTIVITY_TIMEOUT_MIN,
+ CFG_DATA_INACTIVITY_TIMEOUT_MAX ),
+
+ REG_VARIABLE( CFG_NTH_BEACON_FILTER_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nthBeaconFilter,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_NTH_BEACON_FILTER_DEFAULT,
+ CFG_NTH_BEACON_FILTER_MIN,
+ CFG_NTH_BEACON_FILTER_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_MODE_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, WmmMode,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_MODE_DEFAULT,
+ CFG_QOS_WMM_MODE_MIN,
+ CFG_QOS_WMM_MODE_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_80211E_ENABLED_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, b80211eIsEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_80211E_ENABLED_DEFAULT,
+ CFG_QOS_WMM_80211E_ENABLED_MIN,
+ CFG_QOS_WMM_80211E_ENABLED_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_UAPSD_MASK_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, UapsdMask,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_UAPSD_MASK_DEFAULT,
+ CFG_QOS_WMM_UAPSD_MASK_MIN,
+ CFG_QOS_WMM_UAPSD_MASK_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_MAX_SP_LEN_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, MaxSpLength,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_MAX_SP_LEN_DEFAULT,
+ CFG_QOS_WMM_MAX_SP_LEN_MIN,
+ CFG_QOS_WMM_MAX_SP_LEN_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraUapsdVoSrvIntv,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_MIN,
+ CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraUapsdVoSuspIntv,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_MIN,
+ CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraUapsdViSrvIntv,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_MIN,
+ CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraUapsdViSuspIntv,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_MIN,
+ CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraUapsdBeSrvIntv,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_MIN,
+ CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraUapsdBeSuspIntv,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_MIN,
+ CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraUapsdBkSrvIntv,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_MIN,
+ CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraUapsdBkSuspIntv,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_DEFAULT,
+ CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_MIN,
+ CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_MAX ),
+
+#ifdef FEATURE_WLAN_CCX
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, InfraInactivityInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_DEFAULT,
+ CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_MIN,
+ CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_MAX),
+ REG_VARIABLE( CFG_CCX_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, isCcxIniFeatureEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_CCX_FEATURE_ENABLED_DEFAULT,
+ CFG_CCX_FEATURE_ENABLED_MIN,
+ CFG_CCX_FEATURE_ENABLED_MAX),
+#endif // FEATURE_WLAN_CCX
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ REG_VARIABLE( CFG_FT_RSSI_FILTER_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, FTRssiFilterPeriod,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FT_RSSI_FILTER_PERIOD_DEFAULT,
+ CFG_FT_RSSI_FILTER_PERIOD_MIN,
+ CFG_FT_RSSI_FILTER_PERIOD_MAX ),
+
+
+ // flag to turn ON/OFF 11r and CCX FastTransition
+ REG_VARIABLE( CFG_FAST_TRANSITION_ENABLED_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, isFastTransitionEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT,
+ CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
+ CFG_FAST_TRANSITION_ENABLED_NAME_MAX),
+#endif
+
+ REG_VARIABLE( CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, PktClassificationBasis,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_PKT_CLASSIFY_BASIS_DEFAULT,
+ CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN,
+ CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_VO_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraDirAcVo,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_DIR_AC_VO_DEFAULT,
+ CFG_QOS_WMM_INFRA_DIR_AC_VO_MIN,
+ CFG_QOS_WMM_INFRA_DIR_AC_VO_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraNomMsduSizeAcVo,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_DEFAULT,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_MIN,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraMeanDataRateAcVo,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_DEFAULT,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_MIN,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraMinPhyRateAcVo,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_DEFAULT,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_MIN,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_SBA_AC_VO_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraSbaAcVo,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_SBA_AC_VO_DEFAULT,
+ CFG_QOS_WMM_INFRA_SBA_AC_VO_MIN,
+ CFG_QOS_WMM_INFRA_SBA_AC_VO_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_VI_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraDirAcVi,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_DIR_AC_VI_DEFAULT,
+ CFG_QOS_WMM_INFRA_DIR_AC_VI_MIN,
+ CFG_QOS_WMM_INFRA_DIR_AC_VI_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraNomMsduSizeAcVi,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_DEFAULT,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_MIN,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraMeanDataRateAcVi,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_DEFAULT,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_MIN,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraMinPhyRateAcVi,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_DEFAULT,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_MIN,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_SBA_AC_VI_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraSbaAcVi,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_SBA_AC_VI_DEFAULT,
+ CFG_QOS_WMM_INFRA_SBA_AC_VI_MIN,
+ CFG_QOS_WMM_INFRA_SBA_AC_VI_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_BE_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraDirAcBe,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_DIR_AC_BE_DEFAULT,
+ CFG_QOS_WMM_INFRA_DIR_AC_BE_MIN,
+ CFG_QOS_WMM_INFRA_DIR_AC_BE_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraNomMsduSizeAcBe,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_DEFAULT,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_MIN,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraMeanDataRateAcBe,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_DEFAULT,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_MIN,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraMinPhyRateAcBe,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_DEFAULT,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_MIN,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_SBA_AC_BE_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraSbaAcBe,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_SBA_AC_BE_DEFAULT,
+ CFG_QOS_WMM_INFRA_SBA_AC_BE_MIN,
+ CFG_QOS_WMM_INFRA_SBA_AC_BE_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_BK_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, InfraDirAcBk,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_DIR_AC_BK_DEFAULT,
+ CFG_QOS_WMM_INFRA_DIR_AC_BK_MIN,
+ CFG_QOS_WMM_INFRA_DIR_AC_BK_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraNomMsduSizeAcBk,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_DEFAULT,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_MIN,
+ CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraMeanDataRateAcBk,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_DEFAULT,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_MIN,
+ CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraMinPhyRateAcBk,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_DEFAULT,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_MIN,
+ CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_INFRA_SBA_AC_BK_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, InfraSbaAcBk,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_INFRA_SBA_AC_BK_DEFAULT,
+ CFG_QOS_WMM_INFRA_SBA_AC_BK_MIN,
+ CFG_QOS_WMM_INFRA_SBA_AC_BK_MAX ),
+
+ REG_VARIABLE( CFG_TL_WFQ_BK_WEIGHT_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, WfqBkWeight,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TL_WFQ_BK_WEIGHT_DEFAULT,
+ CFG_TL_WFQ_BK_WEIGHT_MIN,
+ CFG_TL_WFQ_BK_WEIGHT_MAX ),
+
+ REG_VARIABLE( CFG_TL_WFQ_BE_WEIGHT_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, WfqBeWeight,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TL_WFQ_BE_WEIGHT_DEFAULT,
+ CFG_TL_WFQ_BE_WEIGHT_MIN,
+ CFG_TL_WFQ_BE_WEIGHT_MAX ),
+
+ REG_VARIABLE( CFG_TL_WFQ_VI_WEIGHT_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, WfqViWeight,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TL_WFQ_VI_WEIGHT_DEFAULT,
+ CFG_TL_WFQ_VI_WEIGHT_MIN,
+ CFG_TL_WFQ_VI_WEIGHT_MAX ),
+
+ REG_VARIABLE( CFG_TL_WFQ_VO_WEIGHT_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, WfqVoWeight,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TL_WFQ_VO_WEIGHT_DEFAULT,
+ CFG_TL_WFQ_VO_WEIGHT_MIN,
+ CFG_TL_WFQ_VO_WEIGHT_MAX ),
+
+ REG_VARIABLE( CFG_TL_DELAYED_TRGR_FRM_INT_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, DelayedTriggerFrmInt,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TL_DELAYED_TRGR_FRM_INT_DEFAULT,
+ CFG_TL_DELAYED_TRGR_FRM_INT_MIN,
+ CFG_TL_DELAYED_TRGR_FRM_INT_MAX ),
+
+ REG_VARIABLE_STRING( CFG_WOWL_PATTERN_NAME, WLAN_PARAM_String,
+ hdd_config_t, wowlPattern,
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_WOWL_PATTERN_DEFAULT ),
+
+ REG_VARIABLE( CFG_QOS_IMPLICIT_SETUP_ENABLED_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, bImplicitQosEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_IMPLICIT_SETUP_ENABLED_DEFAULT,
+ CFG_QOS_IMPLICIT_SETUP_ENABLED_MIN,
+ CFG_QOS_IMPLICIT_SETUP_ENABLED_MAX ),
+
+ REG_VARIABLE( CFG_19P2_MHZ_PMIC_CLK_ENABLED_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, b19p2MhzPmicClkEnabled,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_19P2_MHZ_PMIC_CLK_ENABLED_DEFAULT,
+ CFG_19P2_MHZ_PMIC_CLK_ENABLED_MIN,
+ CFG_19P2_MHZ_PMIC_CLK_ENABLED_MAX ),
+
+ REG_VARIABLE( CFG_BTC_EXECUTION_MODE_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, btcExecutionMode,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_BTC_EXECUTION_MODE_DEFAULT,
+ CFG_BTC_EXECUTION_MODE_MIN,
+ CFG_BTC_EXECUTION_MODE_MAX ),
+
+ REG_VARIABLE( CFG_BTC_DHCP_PROTECTION_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, btcConsBtSlotsToBlockDuringDhcp,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_BTC_DHCP_PROTECTION_DEFAULT,
+ CFG_BTC_DHCP_PROTECTION_MIN,
+ CFG_BTC_DHCP_PROTECTION_MAX ),
+
+ REG_VARIABLE( CFG_BTC_A2DP_DHCP_PROTECTION_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, btcA2DPBtSubIntervalsDuringDhcp,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_BTC_A2DP_DHCP_PROTECTION_DEFAULT,
+ CFG_BTC_A2DP_DHCP_PROTECTION_MIN,
+ CFG_BTC_A2DP_DHCP_PROTECTION_MAX ),
+
+#ifdef WLAN_SOFTAP_FEATURE
+ REG_VARIABLE( CFG_AP_LISTEN_MODE_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, nEnableListenMode,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_LISTEN_MODE_DEFAULT,
+ CFG_AP_LISTEN_MODE_MIN,
+ CFG_AP_LISTEN_MODE_MAX ),
+
+ REG_VARIABLE( CFG_AP_AUTO_SHUT_OFF , WLAN_PARAM_Integer,
+ hdd_config_t, nAPAutoShutOff,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_AUTO_SHUT_OFF_DEFAULT,
+ CFG_AP_AUTO_SHUT_OFF_MIN,
+ CFG_AP_AUTO_SHUT_OFF_MAX ),
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI
+ REG_VARIABLE( CFG_RRM_ENABLE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fRrmEnable,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_RRM_ENABLE_DEFAULT,
+ CFG_RRM_ENABLE_MIN,
+ CFG_RRM_ENABLE_MAX ),
+
+ REG_VARIABLE( CFG_RRM_OPERATING_CHAN_MAX_DURATION_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nInChanMeasMaxDuration,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_RRM_OPERATING_CHAN_MAX_DURATION_DEFAULT,
+ CFG_RRM_OPERATING_CHAN_MAX_DURATION_MIN,
+ CFG_RRM_OPERATING_CHAN_MAX_DURATION_MAX ),
+
+ REG_VARIABLE( CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nOutChanMeasMaxDuration,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_DEFAULT,
+ CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_MIN,
+ CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_MAX ),
+
+ REG_VARIABLE( CFG_RRM_MEAS_RANDOMIZATION_INTVL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nRrmRandnIntvl,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_RRM_MEAS_RANDOMIZATION_INTVL_DEFAULT,
+ CFG_RRM_MEAS_RANDOMIZATION_INTVL_MIN,
+ CFG_RRM_MEAS_RANDOMIZATION_INTVL_MAX ),
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ REG_VARIABLE( CFG_FT_ENABLE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fFTEnable,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FT_ENABLE_DEFAULT,
+ CFG_FT_ENABLE_MIN,
+ CFG_FT_ENABLE_MAX ),
+
+ REG_VARIABLE( CFG_FT_RESOURCE_REQ_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fFTResourceReqSupported,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FT_RESOURCE_REQ_DEFAULT,
+ CFG_FT_RESOURCE_REQ_MIN,
+ CFG_FT_RESOURCE_REQ_MAX ),
+#endif
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ REG_VARIABLE( CFG_NEIGHBOR_SCAN_TIMER_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nNeighborScanPeriod,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT,
+ CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
+ CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX ),
+
+ REG_VARIABLE( CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nNeighborReassocRssiThreshold,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_DEFAULT,
+ CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_MIN,
+ CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_MAX ),
+
+ REG_VARIABLE( CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nNeighborLookupRssiThreshold,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT,
+ CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
+ CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX ),
+
+ REG_VARIABLE_STRING( CFG_NEIGHBOR_SCAN_CHAN_LIST_NAME, WLAN_PARAM_String,
+ hdd_config_t, neighborScanChanList,
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_NEIGHBOR_SCAN_CHAN_LIST_DEFAULT ),
+
+ REG_VARIABLE( CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nNeighborScanMinChanTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT,
+ CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
+ CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX ),
+
+ REG_VARIABLE( CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nNeighborScanMaxChanTime,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT,
+ CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
+ CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX ),
+
+ REG_VARIABLE( CFG_11R_NEIGHBOR_REQ_MAX_TRIES_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nMaxNeighborReqTries,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_11R_NEIGHBOR_REQ_MAX_TRIES_DEFAULT,
+ CFG_11R_NEIGHBOR_REQ_MAX_TRIES_MIN,
+ CFG_11R_NEIGHBOR_REQ_MAX_TRIES_MAX),
+
+ REG_VARIABLE( CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nNeighborResultsRefreshPeriod,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT,
+ CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN,
+ CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX ),
+#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */
+
+ REG_VARIABLE( CFG_QOS_WMM_BURST_SIZE_DEFN_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, burstSizeDefinition,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_BURST_SIZE_DEFN_DEFAULT,
+ CFG_QOS_WMM_BURST_SIZE_DEFN_MIN,
+ CFG_QOS_WMM_BURST_SIZE_DEFN_MAX ),
+
+ REG_VARIABLE( CFG_MCAST_BCAST_FILTER_SETTING_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, mcastBcastFilterSetting,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_MCAST_BCAST_FILTER_SETTING_DEFAULT,
+ CFG_MCAST_BCAST_FILTER_SETTING_MIN,
+ CFG_MCAST_BCAST_FILTER_SETTING_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_HOST_ARPOFFLOAD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fhostArpOffload,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_HOST_ARPOFFLOAD_DEFAULT,
+ CFG_ENABLE_HOST_ARPOFFLOAD_MIN,
+ CFG_ENABLE_HOST_ARPOFFLOAD_MAX ),
+
+ REG_VARIABLE( CFG_QOS_WMM_TS_INFO_ACK_POLICY_NAME , WLAN_PARAM_HexInteger,
+ hdd_config_t, tsInfoAckPolicy,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_WMM_TS_INFO_ACK_POLICY_DEFAULT,
+ CFG_QOS_WMM_TS_INFO_ACK_POLICY_MIN,
+ CFG_QOS_WMM_TS_INFO_ACK_POLICY_MAX ),
+
+ REG_VARIABLE( CFG_SINGLE_TID_RC_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, bSingleTidRc,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_SINGLE_TID_RC_DEFAULT,
+ CFG_SINGLE_TID_RC_MIN,
+ CFG_SINGLE_TID_RC_MAX),
+
+ REG_VARIABLE( CFG_DYNAMIC_PSPOLL_VALUE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, dynamicPsPollValue,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_DYNAMIC_PSPOLL_VALUE_DEFAULT,
+ CFG_DYNAMIC_PSPOLL_VALUE_MIN,
+ CFG_DYNAMIC_PSPOLL_VALUE_MAX ),
+
+ REG_VARIABLE( CFG_TELE_BCN_WAKEUP_EN_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, teleBcnWakeupEn,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TELE_BCN_WAKEUP_EN_DEFAULT,
+ CFG_TELE_BCN_WAKEUP_EN_MIN,
+ CFG_TELE_BCN_WAKEUP_EN_MAX ),
+
+ REG_VARIABLE( CFG_INFRA_STA_KEEP_ALIVE_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, infraStaKeepAlivePeriod,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_INFRA_STA_KEEP_ALIVE_PERIOD_DEFAULT,
+ CFG_INFRA_STA_KEEP_ALIVE_PERIOD_MIN,
+ CFG_INFRA_STA_KEEP_ALIVE_PERIOD_MAX),
+
+ REG_VARIABLE( CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, AddTSWhenACMIsOff,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_DEFAULT,
+ CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_MIN,
+ CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_MAX ),
+
+
+ REG_VARIABLE( CFG_VALIDATE_SCAN_LIST_NAME , WLAN_PARAM_Integer,
+ hdd_config_t, fValidateScanList,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_VALIDATE_SCAN_LIST_DEFAULT,
+ CFG_VALIDATE_SCAN_LIST_MIN,
+ CFG_VALIDATE_SCAN_LIST_MAX ),
+
+ REG_VARIABLE( CFG_NULLDATA_AP_RESP_TIMEOUT_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nNullDataApRespTimeout,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_NULLDATA_AP_RESP_TIMEOUT_DEFAULT,
+ CFG_NULLDATA_AP_RESP_TIMEOUT_MIN,
+ CFG_NULLDATA_AP_RESP_TIMEOUT_MAX ),
+
+ REG_VARIABLE( CFG_AP_DATA_AVAIL_POLL_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, apDataAvailPollPeriodInMs,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_DATA_AVAIL_POLL_PERIOD_DEFAULT,
+ CFG_AP_DATA_AVAIL_POLL_PERIOD_MIN,
+ CFG_AP_DATA_AVAIL_POLL_PERIOD_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_BTAMP_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enableBtAmp,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_BTAMP_DEFAULT,
+ CFG_ENABLE_BTAMP_MIN,
+ CFG_ENABLE_BTAMP_MAX ),
+
+#ifdef WLAN_BTAMP_FEATURE
+ REG_VARIABLE( CFG_BT_AMP_PREFERRED_CHANNEL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, preferredChannel,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_BT_AMP_PREFERRED_CHANNEL_DEFAULT,
+ CFG_BT_AMP_PREFERRED_CHANNEL_MIN,
+ CFG_BT_AMP_PREFERRED_CHANNEL_MAX ),
+#endif //WLAN_BTAMP_FEATURE
+ REG_VARIABLE( CFG_BAND_CAPABILITY_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nBandCapability,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_BAND_CAPABILITY_DEFAULT,
+ CFG_BAND_CAPABILITY_MIN,
+ CFG_BAND_CAPABILITY_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_BEACON_EARLY_TERMINATION_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, fEnableBeaconEarlyTermination,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_BEACON_EARLY_TERMINATION_DEFAULT,
+ CFG_ENABLE_BEACON_EARLY_TERMINATION_MIN,
+ CFG_ENABLE_BEACON_EARLY_TERMINATION_MAX ),
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ /* note that since the default value is out of range we cannot
+ enable range check, otherwise we get a system log message */
+ REG_VARIABLE( CFG_WDI_TRACE_ENABLE_DAL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, wdiTraceEnableDAL,
+ VAR_FLAGS_OPTIONAL,
+ CFG_WDI_TRACE_ENABLE_DEFAULT,
+ CFG_WDI_TRACE_ENABLE_MIN,
+ CFG_WDI_TRACE_ENABLE_MAX ),
+
+ REG_VARIABLE( CFG_WDI_TRACE_ENABLE_CTL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, wdiTraceEnableCTL,
+ VAR_FLAGS_OPTIONAL,
+ CFG_WDI_TRACE_ENABLE_DEFAULT,
+ CFG_WDI_TRACE_ENABLE_MIN,
+ CFG_WDI_TRACE_ENABLE_MAX ),
+
+ REG_VARIABLE( CFG_WDI_TRACE_ENABLE_DAT_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, wdiTraceEnableDAT,
+ VAR_FLAGS_OPTIONAL,
+ CFG_WDI_TRACE_ENABLE_DEFAULT,
+ CFG_WDI_TRACE_ENABLE_MIN,
+ CFG_WDI_TRACE_ENABLE_MAX ),
+
+ REG_VARIABLE( CFG_WDI_TRACE_ENABLE_PAL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, wdiTraceEnablePAL,
+ VAR_FLAGS_OPTIONAL,
+ CFG_WDI_TRACE_ENABLE_DEFAULT,
+ CFG_WDI_TRACE_ENABLE_MIN,
+ CFG_WDI_TRACE_ENABLE_MAX ),
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+ REG_VARIABLE( CFG_TELE_BCN_TRANS_LI_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nTeleBcnTransListenInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TELE_BCN_TRANS_LI_DEFAULT,
+ CFG_TELE_BCN_TRANS_LI_MIN,
+ CFG_TELE_BCN_TRANS_LI_MAX ),
+
+ REG_VARIABLE( CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nTeleBcnTransLiNumIdleBeacons,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_DEFAULT,
+ CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_MIN,
+ CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_MAX ),
+
+ REG_VARIABLE( CFG_TELE_BCN_MAX_LI_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nTeleBcnMaxListenInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TELE_BCN_MAX_LI_DEFAULT,
+ CFG_TELE_BCN_MAX_LI_MIN,
+ CFG_TELE_BCN_MAX_LI_MAX ),
+
+ REG_VARIABLE( CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, nTeleBcnMaxLiNumIdleBeacons,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_DEFAULT,
+ CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_MIN,
+ CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_MAX ),
+
+ REG_VARIABLE( CFG_BCN_EARLY_TERM_WAKE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, bcnEarlyTermWakeInterval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_BCN_EARLY_TERM_WAKE_DEFAULT,
+ CFG_BCN_EARLY_TERM_WAKE_MIN,
+ CFG_BCN_EARLY_TERM_WAKE_MAX ),
+
+ REG_VARIABLE( CFG_AP_DATA_AVAIL_POLL_PERIOD_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, apDataAvailPollPeriodInMs,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AP_DATA_AVAIL_POLL_PERIOD_DEFAULT,
+ CFG_AP_DATA_AVAIL_POLL_PERIOD_MIN,
+ CFG_AP_DATA_AVAIL_POLL_PERIOD_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_CLOSE_LOOP_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enableCloseLoop,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_CLOSE_LOOP_DEFAULT,
+ CFG_ENABLE_CLOSE_LOOP_MIN,
+ CFG_ENABLE_CLOSE_LOOP_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_BYPASS_11D_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enableBypass11d,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_BYPASS_11D_DEFAULT,
+ CFG_ENABLE_BYPASS_11D_MIN,
+ CFG_ENABLE_BYPASS_11D_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_DFS_CHNL_SCAN_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enableDFSChnlScan,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_DFS_CHNL_SCAN_DEFAULT,
+ CFG_ENABLE_DFS_CHNL_SCAN_MIN,
+ CFG_ENABLE_DFS_CHNL_SCAN_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_DYNAMIC_DTIM_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enableDynamicDTIM,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_DYNAMIC_DTIM_DEFAULT,
+ CFG_ENABLE_DYNAMIC_DTIM_MIN,
+ CFG_ENABLE_DYNAMIC_DTIM_MAX ),
+
+ REG_VARIABLE( CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enableAutomaticTxPowerControl,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_DEFAULT,
+ CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_MIN,
+ CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_MAX ),
+
+ REG_VARIABLE( CFG_SHORT_GI_40MHZ_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, ShortGI40MhzEnable,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_SHORT_GI_40MHZ_DEFAULT,
+ CFG_SHORT_GI_40MHZ_MIN,
+ CFG_SHORT_GI_40MHZ_MAX ),
+
+ REG_DYNAMIC_VARIABLE( CFG_REPORT_MAX_LINK_SPEED, WLAN_PARAM_Integer,
+ hdd_config_t, reportMaxLinkSpeed,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_REPORT_MAX_LINK_SPEED_DEFAULT,
+ CFG_REPORT_MAX_LINK_SPEED_MIN,
+ CFG_REPORT_MAX_LINK_SPEED_MAX,
+ NULL, 0 ),
+
+ REG_DYNAMIC_VARIABLE( CFG_LINK_SPEED_RSSI_HIGH, WLAN_PARAM_SignedInteger,
+ hdd_config_t, linkSpeedRssiHigh,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_LINK_SPEED_RSSI_HIGH_DEFAULT,
+ CFG_LINK_SPEED_RSSI_HIGH_MIN,
+ CFG_LINK_SPEED_RSSI_HIGH_MAX,
+ NULL, 0 ),
+
+ REG_DYNAMIC_VARIABLE( CFG_LINK_SPEED_RSSI_LOW, WLAN_PARAM_SignedInteger,
+ hdd_config_t, linkSpeedRssiLow,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_LINK_SPEED_RSSI_LOW_DEFAULT,
+ CFG_LINK_SPEED_RSSI_LOW_MIN,
+ CFG_LINK_SPEED_RSSI_LOW_MAX,
+ NULL, 0 ),
+
+#ifdef WLAN_FEATURE_P2P
+ REG_VARIABLE( CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, isP2pDeviceAddrAdministrated,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_DEFAULT,
+ CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_MIN,
+ CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_MAX ),
+#endif
+
+REG_VARIABLE( CFG_ENABLE_MCC_ENABLED_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enableMCC,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_MCC_ENABLED_DEFAULT,
+ CFG_ENABLE_MCC_ENABLED_MIN,
+ CFG_ENABLE_MCC_ENABLED_MAX ),
+
+ REG_VARIABLE( CFG_THERMAL_MIGRATION_ENABLE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, thermalMitigationEnable,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_THERMAL_MIGRATION_ENABLE_DEFAULT,
+ CFG_THERMAL_MIGRATION_ENABLE_MIN,
+ CFG_THERMAL_MIGRATION_ENABLE_MAX ),
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ REG_VARIABLE( CFG_MC_ADDR_LIST_FILTER_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, isMcAddrListFilter,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_MC_ADDR_LIST_FILTER_DEFAULT,
+ CFG_MC_ADDR_LIST_FILTER_MIN,
+ CFG_MC_ADDR_LIST_FILTER_MAX ),
+#endif
+
+REG_VARIABLE( CFG_ENABLE_MODULATED_DTIM_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enableModulatedDTIM,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_MODULATED_DTIM_DEFAULT,
+ CFG_ENABLE_MODULATED_DTIM_MIN,
+ CFG_ENABLE_MODULATED_DTIM_MAX ),
+
+};
+
+/*
+ * This function returns a pointer to the character after the occurence
+ * of a new line character. It also modifies the original string by replacing
+ * the '\n' character with the null character.
+ * Function returns NULL if no new line character was found before end of
+ * string was reached
+ */
+static char* get_next_line(char* str)
+{
+ char c;
+
+ if( str == NULL || *str == '\0') {
+ return NULL;
+ }
+
+ c = *str;
+ while(c != '\n' && c != '\0' && c != 0xd) {
+ str = str + 1;
+ c = *str;
+ }
+
+ if (c == '\0' ) {
+ return NULL;
+ }
+ else
+ {
+ *str = '\0';
+ return (str+1);
+ }
+
+ return NULL;
+}
+
+// look for space. Ascii values to look are -
+// 0x09 == horizontal tab
+// 0x0a == Newline ("\n")
+// 0x0b == vertical tab
+// 0x0c == Newpage or feed form.
+// 0x0d == carriage return (CR or "\r")
+// Null ('\0') should not considered as space.
+#define i_isspace(ch) (((ch) >= 0x09 && (ch) <= 0x0d) || (ch) == ' ')
+
+/*
+ * This function trims any leading and trailing white spaces
+ */
+static char *i_trim(char *str)
+
+{
+ char *ptr;
+
+ if(*str == '\0') return str;
+
+ /* Find the first non white-space*/
+ for (ptr = str; i_isspace(*ptr); ptr++);
+ if (*ptr == '\0')
+ return str;
+
+ /* This is the new start of the string*/
+ str = ptr;
+
+ /* Find the last non white-space */
+ ptr += strlen(ptr) - 1;
+ for (; ptr != str && i_isspace(*ptr); ptr--);
+ /* Null terminate the following character */
+ ptr[1] = '\0';
+
+ return str;
+}
+
+
+//Structure to store each entry in qcom_cfg.ini file
+typedef struct
+{
+ char *name;
+ char *value;
+}tCfgIniEntry;
+
+static VOS_STATUS hdd_apply_cfg_ini( hdd_context_t * pHddCtx,
+ tCfgIniEntry* iniTable, unsigned long entries);
+
+#ifdef WLAN_CFG_DEBUG
+void dump_cfg_ini (tCfgIniEntry* iniTable, unsigned long entries)
+{
+ unsigned long i;
+
+ for (i = 0; i < entries; i++) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "%s entry Name=[%s] value=[%s]",
+ WLAN_INI_FILE, iniTable[i].name, iniTable[i].value);
+ }
+}
+#endif
+
+/*
+ * This function reads the qcom_cfg.ini file and
+ * parses each 'Name=Value' pair in the ini file
+ */
+VOS_STATUS hdd_parse_config_ini(hdd_context_t* pHddCtx)
+{
+ int status, i=0;
+ /** Pointer for firmware image data */
+ const struct firmware *fw = NULL;
+ char *buffer, *line,*pTemp;
+ size_t size;
+ char *name, *value;
+ tCfgIniEntry cfgIniTable[MAX_CFG_INI_ITEMS];
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+
+ memset(cfgIniTable, 0, sizeof(cfgIniTable));
+
+ status = request_firmware(&fw, WLAN_INI_FILE, pHddCtx->parent_dev);
+
+ if(status)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: request_firmware failed %d\n",__FUNCTION__, status);
+ return VOS_STATUS_E_FAILURE;
+ }
+ if(!fw || !fw->data || !fw->size)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: %s download failed\n",
+ __FUNCTION__, WLAN_INI_FILE);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ hddLog(LOG1, "%s: qcom_cfg.ini Size %d\n",__FUNCTION__, fw->size);
+
+ buffer = (char*)vos_mem_malloc(fw->size);
+
+ if(NULL == buffer) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: kmalloc failure",__FUNCTION__);
+ release_firmware(fw);
+ return VOS_STATUS_E_FAILURE;
+ }
+ pTemp = buffer;
+
+ vos_mem_copy((void*)buffer,(void *)fw->data, fw->size);
+ size = fw->size;
+
+ while (buffer != NULL)
+ {
+ line = get_next_line(buffer);
+ buffer = i_trim(buffer);
+
+ hddLog(LOG1, "%s: item", buffer);
+
+ if(strlen((char*)buffer) == 0 || *buffer == '#') {
+ buffer = line;
+ continue;
+ }
+ else if(strncmp(buffer, "END", 3) == 0 ) {
+ break;
+ }
+ else
+ {
+ name = buffer;
+ while(*buffer != '=' && *buffer != '\0')
+ buffer++;
+ if(*buffer != '\0') {
+ *buffer++ = '\0';
+ i_trim(name);
+ if(strlen (name) != 0) {
+ buffer = i_trim(buffer);
+ if(strlen(buffer)>0) {
+ value = buffer;
+ while(!i_isspace(*buffer) && *buffer != '\0')
+ buffer++;
+ *buffer = '\0';
+ cfgIniTable[i].name= name;
+ cfgIniTable[i++].value= value;
+ if(i >= MAX_CFG_INI_ITEMS) {
+ hddLog(LOGE,"%s: Number of items in %s > %d \n",
+ __FUNCTION__, WLAN_INI_FILE, MAX_CFG_INI_ITEMS);
+ break;
+ }
+ }
+ }
+ }
+ }
+ buffer = line;
+ }
+
+ //Loop through the registry table and apply all these configs
+ vos_status = hdd_apply_cfg_ini(pHddCtx, cfgIniTable, i);
+
+ release_firmware(fw);
+ vos_mem_free(pTemp);
+ return vos_status;
+}
+
+
+static void print_hdd_cfg(hdd_context_t *pHddCtx)
+{
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "*********Config values in HDD Adapter*******");
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [RTSThreshold] Value = %lu",pHddCtx->cfg_ini->RTSThreshold) ;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [OperatingChannel] Value = [%u]",pHddCtx->cfg_ini->OperatingChannel);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [PowerUsageControl] Value = [%s]",pHddCtx->cfg_ini->PowerUsageControl);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fIsImpsEnabled] Value = [%u]",pHddCtx->cfg_ini->fIsImpsEnabled);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [AutoBmpsTimerEnabled] Value = [%u]",pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nAutoBmpsTimerValue] Value = [%lu]",pHddCtx->cfg_ini->nAutoBmpsTimerValue);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nVccRssiTrigger] Value = [%u]",pHddCtx->cfg_ini->nVccRssiTrigger);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIbssBssid] Value =[0x%x 0x%x 0x%x 0x%x 0x%x 0x%x]",
+ pHddCtx->cfg_ini->IbssBssid.bytes[0],pHddCtx->cfg_ini->IbssBssid.bytes[1],
+ pHddCtx->cfg_ini->IbssBssid.bytes[2],pHddCtx->cfg_ini->IbssBssid.bytes[3],
+ pHddCtx->cfg_ini->IbssBssid.bytes[4],pHddCtx->cfg_ini->IbssBssid.bytes[5]);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Name = [Intf0MacAddress] Value =[0x%x 0x%x 0x%x 0x%x 0x%x 0x%x]",
+ pHddCtx->cfg_ini->intfMacAddr[0].bytes[0],
+ pHddCtx->cfg_ini->intfMacAddr[0].bytes[1],
+ pHddCtx->cfg_ini->intfMacAddr[0].bytes[2],
+ pHddCtx->cfg_ini->intfMacAddr[0].bytes[3],
+ pHddCtx->cfg_ini->intfMacAddr[0].bytes[4],
+ pHddCtx->cfg_ini->intfMacAddr[0].bytes[5]);
+
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Name = [Intf1MacAddress] Value =[0x%x 0x%x 0x%x 0x%x 0x%x 0x%x]",
+ pHddCtx->cfg_ini->intfMacAddr[1].bytes[0],
+ pHddCtx->cfg_ini->intfMacAddr[1].bytes[1],
+ pHddCtx->cfg_ini->intfMacAddr[1].bytes[2],
+ pHddCtx->cfg_ini->intfMacAddr[1].bytes[3],
+ pHddCtx->cfg_ini->intfMacAddr[1].bytes[4],
+ pHddCtx->cfg_ini->intfMacAddr[1].bytes[5]);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Name = [Intf2MacAddress] Value =[0x%x 0x%x 0x%x 0x%x 0x%x 0x%x]",
+ pHddCtx->cfg_ini->intfMacAddr[2].bytes[0],
+ pHddCtx->cfg_ini->intfMacAddr[2].bytes[1],
+ pHddCtx->cfg_ini->intfMacAddr[2].bytes[2],
+ pHddCtx->cfg_ini->intfMacAddr[2].bytes[3],
+ pHddCtx->cfg_ini->intfMacAddr[2].bytes[4],
+ pHddCtx->cfg_ini->intfMacAddr[2].bytes[5]);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Name = [Intf3MacAddress] Value =[0x%x 0x%x 0x%x 0x%x 0x%x 0x%x]",
+ pHddCtx->cfg_ini->intfMacAddr[3].bytes[0],
+ pHddCtx->cfg_ini->intfMacAddr[3].bytes[1],
+ pHddCtx->cfg_ini->intfMacAddr[3].bytes[2],
+ pHddCtx->cfg_ini->intfMacAddr[3].bytes[3],
+ pHddCtx->cfg_ini->intfMacAddr[3].bytes[4],
+ pHddCtx->cfg_ini->intfMacAddr[3].bytes[5]);
+
+#ifdef WLAN_SOFTAP_FEATURE
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApEnableUapsd] value = [%u]\n",pHddCtx->cfg_ini->apUapsdEnabled);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAPCntryCode] Value =[%c%c%c]\n",
+ pHddCtx->cfg_ini->apCntryCode[0],pHddCtx->cfg_ini->apCntryCode[1],
+ pHddCtx->cfg_ini->apCntryCode[2]);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableApProt] value = [%u]", pHddCtx->cfg_ini->apProtEnabled);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAPAutoShutOff] Value = [%u]\n", pHddCtx->cfg_ini->nAPAutoShutOff);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableListenMode] Value = [%u]\n", pHddCtx->cfg_ini->nEnableListenMode);
+ VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApProtection] value = [%u]\n",pHddCtx->cfg_ini->apProtection);
+ VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableApOBSSProt] value = [%u]\n",pHddCtx->cfg_ini->apOBSSProtEnabled);
+ VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApAutoChannelSelection] value = [%u]\n",pHddCtx->cfg_ini->apAutoChannelSelection);
+#endif
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ChannelBondingMode] Value = [%lu]",pHddCtx->cfg_ini->nChannelBondingMode24GHz);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ChannelBondingMode] Value = [%lu]",pHddCtx->cfg_ini->nChannelBondingMode5GHz);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [dot11Mode] Value = [%lu]",pHddCtx->cfg_ini->dot11Mode);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [WmmMode] Value = [%u] ",pHddCtx->cfg_ini->WmmMode);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [UapsdMask] Value = [0x%x] ",pHddCtx->cfg_ini->UapsdMask);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [PktClassificationBasis] Value = [%u] ",pHddCtx->cfg_ini->PktClassificationBasis);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ImplicitQosIsEnabled] Value = [%u]",(int)pHddCtx->cfg_ini->bImplicitQosEnabled);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdVoSrvIntv] Value = [%lu] ",pHddCtx->cfg_ini->InfraUapsdVoSrvIntv);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdVoSuspIntv] Value = [%lu] ",pHddCtx->cfg_ini->InfraUapsdVoSuspIntv);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdViSrvIntv] Value = [%lu] ",pHddCtx->cfg_ini->InfraUapsdViSrvIntv);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdViSuspIntv] Value = [%lu] ",pHddCtx->cfg_ini->InfraUapsdViSuspIntv);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdBeSrvIntv] Value = [%lu] ",pHddCtx->cfg_ini->InfraUapsdBeSrvIntv);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdBeSuspIntv] Value = [%lu] ",pHddCtx->cfg_ini->InfraUapsdBeSuspIntv);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdBkSrvIntv] Value = [%lu] ",pHddCtx->cfg_ini->InfraUapsdBkSrvIntv);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdBkSuspIntv] Value = [%lu] ",pHddCtx->cfg_ini->InfraUapsdBkSuspIntv);
+#ifdef FEATURE_WLAN_CCX
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraInactivityInterval] Value = [%lu] ",pHddCtx->cfg_ini->InfraInactivityInterval);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [CcxEnabled] Value = [%lu] ",pHddCtx->cfg_ini->isCcxIniFeatureEnabled);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [FastTransitionEnabled] Value = [%lu] ",pHddCtx->cfg_ini->isFastTransitionEnabled);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gTxPowerCap] Value = [%lu] dBm ",pHddCtx->cfg_ini->nTxPowerCap);
+#endif
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraDirAcVo] Value = [%u] ",pHddCtx->cfg_ini->InfraDirAcVo);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraNomMsduSizeAcVo] Value = [0x%x] ",pHddCtx->cfg_ini->InfraNomMsduSizeAcVo);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMeanDataRateAcVo] Value = [0x%lx] ",pHddCtx->cfg_ini->InfraMeanDataRateAcVo);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMinPhyRateAcVo] Value = [0x%lx] ",pHddCtx->cfg_ini->InfraMinPhyRateAcVo);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraSbaAcVo] Value = [0x%x] ",pHddCtx->cfg_ini->InfraSbaAcVo);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraDirAcVi] Value = [%u] ",pHddCtx->cfg_ini->InfraDirAcVi);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraNomMsduSizeAcVi] Value = [0x%x] ",pHddCtx->cfg_ini->InfraNomMsduSizeAcVi);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMeanDataRateAcVi] Value = [0x%lx] ",pHddCtx->cfg_ini->InfraMeanDataRateAcVi);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMinPhyRateAcVi] Value = [0x%lx] ",pHddCtx->cfg_ini->InfraMinPhyRateAcVi);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraSbaAcVi] Value = [0x%x] ",pHddCtx->cfg_ini->InfraSbaAcVi);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraDirAcBe] Value = [%u] ",pHddCtx->cfg_ini->InfraDirAcBe);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraNomMsduSizeAcBe] Value = [0x%x] ",pHddCtx->cfg_ini->InfraNomMsduSizeAcBe);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMeanDataRateAcBe] Value = [0x%lx] ",pHddCtx->cfg_ini->InfraMeanDataRateAcBe);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMinPhyRateAcBe] Value = [0x%lx] ",pHddCtx->cfg_ini->InfraMinPhyRateAcBe);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraSbaAcBe] Value = [0x%x] ",pHddCtx->cfg_ini->InfraSbaAcBe);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraDirAcBk] Value = [%u] ",pHddCtx->cfg_ini->InfraDirAcBk);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraNomMsduSizeAcBk] Value = [0x%x] ",pHddCtx->cfg_ini->InfraNomMsduSizeAcBk);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMeanDataRateAcBk] Value = [0x%lx] ",pHddCtx->cfg_ini->InfraMeanDataRateAcBk);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMinPhyRateAcBk] Value = [0x%lx] ",pHddCtx->cfg_ini->InfraMinPhyRateAcBk);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraSbaAcBk] Value = [0x%x] ",pHddCtx->cfg_ini->InfraSbaAcBk);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [WfqBkWeight] Value = [%u] ",pHddCtx->cfg_ini->WfqBkWeight);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [WfqBeWeight] Value = [%u] ",pHddCtx->cfg_ini->WfqBeWeight);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [WfqViWeight] Value = [%u] ",pHddCtx->cfg_ini->WfqViWeight);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [WfqVoWeight] Value = [%u] ",pHddCtx->cfg_ini->WfqVoWeight);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [DelayedTriggerFrmInt] Value = [%lu] ",pHddCtx->cfg_ini->DelayedTriggerFrmInt);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [mcastBcastFilterSetting] Value = [%u] ",pHddCtx->cfg_ini->mcastBcastFilterSetting);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fhostArpOffload] Value = [%u] ",pHddCtx->cfg_ini->fhostArpOffload);
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fFTEnable] Value = [%lu] ",pHddCtx->cfg_ini->fFTEnable);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fFTResourceReqSupported] Value = [%lu] ",pHddCtx->cfg_ini->fFTResourceReqSupported);
+#endif
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborReassocRssiThreshold] Value = [%lu] ",pHddCtx->cfg_ini->nNeighborReassocRssiThreshold);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborLookupRssiThreshold] Value = [%lu] ",pHddCtx->cfg_ini->nNeighborLookupRssiThreshold);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborScanMinChanTime] Value = [%lu] ",pHddCtx->cfg_ini->nNeighborScanMinChanTime);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborScanMaxChanTime] Value = [%lu] ",pHddCtx->cfg_ini->nNeighborScanMaxChanTime);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nMaxNeighborRetries] Value = [%lu] ",pHddCtx->cfg_ini->nMaxNeighborReqTries);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborScanPeriod] Value = [%lu] ",pHddCtx->cfg_ini->nNeighborScanPeriod);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborScanResultsRefreshPeriod] Value = [%lu] ",pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod);
+#endif
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [burstSizeDefinition] Value = [0x%x] ",pHddCtx->cfg_ini->burstSizeDefinition);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [tsInfoAckPolicy] Value = [0x%x] ",pHddCtx->cfg_ini->tsInfoAckPolicy);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [rfSettlingTimeUs] Value = [%u] ",pHddCtx->cfg_ini->rfSettlingTimeUs);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [bSingleTidRc] Value = [%u] ",pHddCtx->cfg_ini->bSingleTidRc);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gDynamicPSPollvalue] Value = [%u] ",pHddCtx->cfg_ini->dynamicPsPollValue);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAddTSWhenACMIsOff] Value = [%u] ",pHddCtx->cfg_ini->AddTSWhenACMIsOff);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gValidateScanList] Value = [%u] ",pHddCtx->cfg_ini->fValidateScanList);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gStaKeepAlivePeriod] Value = [%u] ",pHddCtx->cfg_ini->infraStaKeepAlivePeriod);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApDataAvailPollInterVal] Value = [%u] ",pHddCtx->cfg_ini->apDataAvailPollPeriodInMs);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableBtAmp] Value = [%u] ",pHddCtx->cfg_ini->enableBtAmp);
+#ifdef WLAN_BTAMP_FEATURE
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [BtAmpPreferredChannel] Value = [%u] ",pHddCtx->cfg_ini->preferredChannel);
+#endif //WLAN_BTAMP_FEATURE
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [BandCapability] Value = [%u] ",pHddCtx->cfg_ini->nBandCapability);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fEnableBeaconEarlyTermination] Value = [%u] ",pHddCtx->cfg_ini->fEnableBeaconEarlyTermination);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [teleBcnWakeupEnable] Value = [%u] ",pHddCtx->cfg_ini->teleBcnWakeupEn);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [transListenInterval] Value = [%u] ",pHddCtx->cfg_ini->nTeleBcnTransListenInterval);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [transLiNumIdleBeacons] Value = [%u] ",pHddCtx->cfg_ini->nTeleBcnTransLiNumIdleBeacons);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [maxListenInterval] Value = [%u] ",pHddCtx->cfg_ini->nTeleBcnMaxListenInterval);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [maxLiNumIdleBeacons] Value = [%u] ",pHddCtx->cfg_ini->nTeleBcnMaxLiNumIdleBeacons);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [bcnEarlyTermWakeInterval] Value = [%u] ",pHddCtx->cfg_ini->bcnEarlyTermWakeInterval);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApDataAvailPollInterVal] Value = [%u] ",pHddCtx->cfg_ini->apDataAvailPollPeriodInMs);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableBypass11d] Value = [%u] ",pHddCtx->cfg_ini->enableBypass11d);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableDFSChnlScan] Value = [%u] ",pHddCtx->cfg_ini->enableDFSChnlScan);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gReportMaxLinkSpeed] Value = [%u] ",pHddCtx->cfg_ini->reportMaxLinkSpeed);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [thermalMitigationEnable] Value = [%u] ",pHddCtx->cfg_ini->thermalMitigationEnable);
+}
+
+
+#define CFG_VALUE_MAX_LEN 256
+#define CFG_ENTRY_MAX_LEN (32+CFG_VALUE_MAX_LEN)
+VOS_STATUS hdd_cfg_get_config(hdd_context_t *pHddCtx, char *pBuf, int buflen)
+{
+ unsigned int idx;
+ REG_TABLE_ENTRY *pRegEntry = g_registry_table;
+ unsigned long cRegTableEntries = sizeof(g_registry_table) / sizeof( g_registry_table[ 0 ]);
+ v_U32_t value;
+ char valueStr[CFG_VALUE_MAX_LEN];
+ char configStr[CFG_ENTRY_MAX_LEN];
+ char *fmt;
+ void *pField;
+ v_MACADDR_t *pMacAddr;
+ char *pCur = pBuf;
+ int curlen;
+
+ // start with an empty string
+ *pCur = '\0';
+
+ for ( idx = 0; idx < cRegTableEntries; idx++, pRegEntry++ )
+ {
+ pField = ( (v_U8_t *)pHddCtx->cfg_ini) + pRegEntry->VarOffset;
+
+ if ( ( WLAN_PARAM_Integer == pRegEntry->RegType ) ||
+ ( WLAN_PARAM_SignedInteger == pRegEntry->RegType ) ||
+ ( WLAN_PARAM_HexInteger == pRegEntry->RegType ) )
+ {
+ value = 0;
+ memcpy( &value, pField, pRegEntry->VarSize );
+ if ( WLAN_PARAM_HexInteger == pRegEntry->RegType )
+ {
+ fmt = "%x";
+ }
+ else if ( WLAN_PARAM_SignedInteger == pRegEntry->RegType )
+ {
+ fmt = "%d";
+ }
+ else
+ {
+ fmt = "%u";
+ }
+ snprintf(valueStr, CFG_VALUE_MAX_LEN, fmt, value);
+ }
+ else if ( WLAN_PARAM_String == pRegEntry->RegType )
+ {
+ snprintf(valueStr, CFG_VALUE_MAX_LEN, "%s", (char *)pField);
+ }
+ else if ( WLAN_PARAM_MacAddr == pRegEntry->RegType )
+ {
+ pMacAddr = (v_MACADDR_t *) pField;
+ snprintf(valueStr, CFG_VALUE_MAX_LEN,
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ pMacAddr->bytes[0],
+ pMacAddr->bytes[1],
+ pMacAddr->bytes[2],
+ pMacAddr->bytes[3],
+ pMacAddr->bytes[4],
+ pMacAddr->bytes[5]);
+ }
+ else
+ {
+ snprintf(valueStr, CFG_VALUE_MAX_LEN, "(unhandled)");
+ }
+ curlen = snprintf(configStr, CFG_ENTRY_MAX_LEN,
+ "%s=[%s]%s\n",
+ pRegEntry->RegName,
+ valueStr,
+ test_bit(idx, (void *)&pHddCtx->cfg_ini->bExplicitCfg) ?
+ "*" : "");
+
+ // ideally we want to return the config to the application
+ // however the config is too big so we just printk() for now
+#ifdef RETURN_IN_BUFFER
+ if (curlen <= buflen)
+ {
+ // copy string + '\0'
+ memcpy(pCur, configStr, curlen+1);
+
+ // account for addition;
+ pCur += curlen;
+ buflen -= curlen;
+ }
+ else
+ {
+ // buffer space exhausted, return what we have
+ return VOS_STATUS_E_RESOURCES;
+ }
+#else
+ printk(KERN_CRIT "%s", configStr);
+#endif // RETURN_IN_BUFFER
+
+}
+
+#ifndef RETURN_IN_BUFFER
+ // notify application that output is in system log
+ snprintf(pCur, buflen, "WLAN configuration written to system log");
+#endif // RETURN_IN_BUFFER
+
+ return VOS_STATUS_SUCCESS;
+}
+
+static VOS_STATUS find_cfg_item (tCfgIniEntry* iniTable, unsigned long entries,
+ char *name, char** value)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ unsigned long i;
+
+ for (i = 0; i < entries; i++) {
+ if (strcmp(iniTable[i].name, name) == 0) {
+ *value = iniTable[i].value;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Found %s entry for Name=[%s] Value=[%s] ",
+ WLAN_INI_FILE, name, *value);
+ return VOS_STATUS_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+static int parseHexDigit(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c-'0';
+ if (c >= 'a' && c <= 'f')
+ return c-'a'+10;
+ if (c >= 'A' && c <= 'F')
+ return c-'A'+10;
+
+ return 0;
+}
+
+
+static VOS_STATUS hdd_apply_cfg_ini( hdd_context_t *pHddCtx, tCfgIniEntry* iniTable, unsigned long entries)
+{
+ VOS_STATUS match_status = VOS_STATUS_E_FAILURE;
+ VOS_STATUS ret_status = VOS_STATUS_SUCCESS;
+ unsigned int idx;
+ void *pField;
+ char *value_str = NULL;
+ unsigned long len_value_str;
+ char *candidate;
+ v_U32_t value;
+ v_S31_t svalue;
+ void *pStructBase = pHddCtx->cfg_ini;
+ REG_TABLE_ENTRY *pRegEntry = g_registry_table;
+ unsigned long cRegTableEntries = sizeof(g_registry_table) / sizeof( g_registry_table[ 0 ]);
+ v_U32_t cbOutString;
+ int i;
+
+ // sanity test
+ if (MAX_CFG_INI_ITEMS < cRegTableEntries)
+ {
+ hddLog(LOGE, "%s: MAX_CFG_INI_ITEMS too small, must be at least %d",
+ __FUNCTION__, cRegTableEntries);
+ }
+
+ for ( idx = 0; idx < cRegTableEntries; idx++, pRegEntry++ )
+ {
+ //Calculate the address of the destination field in the structure.
+ pField = ( (v_U8_t *)pStructBase )+ pRegEntry->VarOffset;
+
+ match_status = find_cfg_item(iniTable, entries, pRegEntry->RegName, &value_str);
+
+ if( (match_status != VOS_STATUS_SUCCESS) && ( pRegEntry->Flags & VAR_FLAGS_REQUIRED ) )
+ {
+ // If we could not read the cfg item and it is required, this is an error.
+ hddLog(LOGE, "%s: Failed to read required config parameter %s",
+ __FUNCTION__, pRegEntry->RegName);
+ ret_status = VOS_STATUS_E_FAILURE;
+ break;
+ }
+
+ if ( ( WLAN_PARAM_Integer == pRegEntry->RegType ) ||
+ ( WLAN_PARAM_HexInteger == pRegEntry->RegType ) )
+ {
+ // If successfully read from the registry, use the value read.
+ // If not, use the default value.
+ if ( match_status == VOS_STATUS_SUCCESS && (WLAN_PARAM_Integer == pRegEntry->RegType)) {
+ value = simple_strtoul(value_str, NULL, 10);
+ }
+ else if ( match_status == VOS_STATUS_SUCCESS && (WLAN_PARAM_HexInteger == pRegEntry->RegType)) {
+ value = simple_strtoul(value_str, NULL, 16);
+ }
+ else {
+ value = pRegEntry->VarDefault;
+ }
+
+ // If this parameter needs range checking, do it here.
+ if ( pRegEntry->Flags & VAR_FLAGS_RANGE_CHECK )
+ {
+ if ( value > pRegEntry->VarMax )
+ {
+ hddLog(LOGE, "%s: Reg Parameter %s > allowed Maximum [%lu > %lu]. Enforcing Maximum",
+ __FUNCTION__, pRegEntry->RegName, value, pRegEntry->VarMax );
+ value = pRegEntry->VarMax;
+ }
+
+ if ( value < pRegEntry->VarMin )
+ {
+ hddLog(LOGE, "%s: Reg Parameter %s < allowed Minimum [%lu < %lu]. Enforcing Minimum",
+ __FUNCTION__, pRegEntry->RegName, value, pRegEntry->VarMin);
+ value = pRegEntry->VarMin;
+ }
+ }
+ // If this parameter needs range checking, do it here.
+ else if ( pRegEntry->Flags & VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT )
+ {
+ if ( value > pRegEntry->VarMax )
+ {
+ hddLog(LOGE, "%s: Reg Parameter %s > allowed Maximum [%lu > %lu]. Enforcing Default= %lu",
+ __FUNCTION__, pRegEntry->RegName, value, pRegEntry->VarMax, pRegEntry->VarDefault );
+ value = pRegEntry->VarDefault;
+ }
+
+ if ( value < pRegEntry->VarMin )
+ {
+ hddLog(LOGE, "%s: Reg Parameter %s < allowed Minimum [%lu < %lu]. Enforcing Default= %lu",
+ __FUNCTION__, pRegEntry->RegName, value, pRegEntry->VarMin, pRegEntry->VarDefault );
+ value = pRegEntry->VarDefault;
+ }
+ }
+
+ // Move the variable into the output field.
+ memcpy( pField, &value, pRegEntry->VarSize );
+ }
+ else if ( WLAN_PARAM_SignedInteger == pRegEntry->RegType )
+ {
+ // If successfully read from the registry, use the value read.
+ // If not, use the default value.
+ if (VOS_STATUS_SUCCESS == match_status)
+ {
+ svalue = simple_strtol(value_str, NULL, 10);
+ }
+ else
+ {
+ svalue = (v_S31_t)pRegEntry->VarDefault;
+ }
+
+ // If this parameter needs range checking, do it here.
+ if ( pRegEntry->Flags & VAR_FLAGS_RANGE_CHECK )
+ {
+ if ( svalue > (v_S31_t)pRegEntry->VarMax )
+ {
+ hddLog(LOGE, "%s: Reg Parameter %s > allowed Maximum "
+ "[%ld > %ld]. Enforcing Maximum", __FUNCTION__,
+ pRegEntry->RegName, svalue, (int)pRegEntry->VarMax );
+ svalue = (v_S31_t)pRegEntry->VarMax;
+ }
+
+ if ( svalue < (v_S31_t)pRegEntry->VarMin )
+ {
+ hddLog(LOGE, "%s: Reg Parameter %s < allowed Minimum "
+ "[%ld < %ld]. Enforcing Minimum", __FUNCTION__,
+ pRegEntry->RegName, svalue, (int)pRegEntry->VarMin);
+ svalue = (v_S31_t)pRegEntry->VarMin;
+ }
+ }
+ // If this parameter needs range checking, do it here.
+ else if ( pRegEntry->Flags & VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT )
+ {
+ if ( svalue > (v_S31_t)pRegEntry->VarMax )
+ {
+ hddLog(LOGE, "%s: Reg Parameter %s > allowed Maximum "
+ "[%ld > %ld]. Enforcing Default= %ld",
+ __FUNCTION__, pRegEntry->RegName, svalue,
+ (int)pRegEntry->VarMax,
+ (int)pRegEntry->VarDefault );
+ svalue = (v_S31_t)pRegEntry->VarDefault;
+ }
+
+ if ( svalue < (v_S31_t)pRegEntry->VarMin )
+ {
+ hddLog(LOGE, "%s: Reg Parameter %s < allowed Minimum "
+ "[%ld < %ld]. Enforcing Default= %ld",
+ __FUNCTION__, pRegEntry->RegName, svalue,
+ (int)pRegEntry->VarMin,
+ (int)pRegEntry->VarDefault);
+ svalue = pRegEntry->VarDefault;
+ }
+ }
+
+ // Move the variable into the output field.
+ memcpy( pField, &svalue, pRegEntry->VarSize );
+ }
+ // Handle string parameters
+ else if ( WLAN_PARAM_String == pRegEntry->RegType )
+ {
+#ifdef WLAN_CFG_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "RegName = %s, VarOffset %u VarSize %u VarDefault %s\n",
+ pRegEntry->RegName, pRegEntry->VarOffset, pRegEntry->VarSize, (char*)pRegEntry->VarDefault);
+#endif
+
+ if ( match_status == VOS_STATUS_SUCCESS)
+ {
+ len_value_str = strlen(value_str);
+
+ if(len_value_str > (pRegEntry->VarSize - 1)) {
+ hddLog(LOGE, "%s: Invalid Value=[%s] specified for Name=[%s] in %s\n",
+ __FUNCTION__, value_str, pRegEntry->RegName, WLAN_INI_FILE);
+ cbOutString = utilMin( strlen( (char *)pRegEntry->VarDefault ), pRegEntry->VarSize - 1 );
+ memcpy( pField, (void *)(pRegEntry->VarDefault), cbOutString );
+ ( (v_U8_t *)pField )[ cbOutString ] = '\0';
+ }
+ else
+ {
+ memcpy( pField, (void *)(value_str), len_value_str);
+ ( (v_U8_t *)pField )[ len_value_str ] = '\0';
+ }
+ }
+ else
+ {
+ // Failed to read the string parameter from the registry. Use the default.
+ cbOutString = utilMin( strlen( (char *)pRegEntry->VarDefault ), pRegEntry->VarSize - 1 );
+ memcpy( pField, (void *)(pRegEntry->VarDefault), cbOutString );
+ ( (v_U8_t *)pField )[ cbOutString ] = '\0';
+ }
+ }
+ else if ( WLAN_PARAM_MacAddr == pRegEntry->RegType )
+ {
+ if(pRegEntry->VarSize != VOS_MAC_ADDR_SIZE) {
+ hddLog(LOGE, "%s: Invalid VarSize %u for Name=[%s]\n",
+ __FUNCTION__, pRegEntry->VarSize, pRegEntry->RegName);
+ continue;
+ }
+ candidate = (char*)pRegEntry->VarDefault;
+ if ( match_status == VOS_STATUS_SUCCESS) {
+ len_value_str = strlen(value_str);
+ if(len_value_str != (VOS_MAC_ADDR_SIZE*2)) {
+ hddLog(LOGE, "%s: Invalid MAC addr [%s] specified for Name=[%s] in %s\n",
+ __FUNCTION__, value_str, pRegEntry->RegName, WLAN_INI_FILE);
+ }
+ else
+ candidate = value_str;
+ }
+ //parse the string and store it in the byte array
+ for(i=0; i<VOS_MAC_ADDR_SIZE; i++)
+ {
+ ((char*)pField)[i] =
+ (char)(parseHexDigit(candidate[i*2])*16 + parseHexDigit(candidate[i*2+1]));
+ }
+ }
+ else
+ {
+ hddLog(LOGE, "%s: Unknown param type for name[%s] in registry table\n",
+ __FUNCTION__, pRegEntry->RegName);
+ }
+
+ // did we successfully parse a cfg item for this parameter?
+ if( (match_status == VOS_STATUS_SUCCESS) &&
+ (idx < MAX_CFG_INI_ITEMS) )
+ {
+ set_bit(idx, (void *)&pHddCtx->cfg_ini->bExplicitCfg);
+ }
+ }
+
+ print_hdd_cfg(pHddCtx);
+
+ return( ret_status );
+}
+
+eCsrPhyMode hdd_cfg_xlate_to_csr_phy_mode( eHddDot11Mode dot11Mode )
+{
+ switch (dot11Mode)
+ {
+ case (eHDD_DOT11_MODE_abg):
+ return eCSR_DOT11_MODE_abg;
+ case (eHDD_DOT11_MODE_11b):
+ return eCSR_DOT11_MODE_11b;
+ case (eHDD_DOT11_MODE_11g):
+ return eCSR_DOT11_MODE_11g;
+ default:
+ case (eHDD_DOT11_MODE_11n):
+ return eCSR_DOT11_MODE_11n;
+ case (eHDD_DOT11_MODE_11g_ONLY):
+ return eCSR_DOT11_MODE_11g_ONLY;
+ case (eHDD_DOT11_MODE_11n_ONLY):
+ return eCSR_DOT11_MODE_11n_ONLY;
+ case (eHDD_DOT11_MODE_11b_ONLY):
+ return eCSR_DOT11_MODE_11b_ONLY;
+ case (eHDD_DOT11_MODE_AUTO):
+ return eCSR_DOT11_MODE_AUTO;
+ }
+
+}
+
+static void hdd_set_btc_config(hdd_context_t *pHddCtx)
+{
+ hdd_config_t *pConfig = pHddCtx->cfg_ini;
+ tSmeBtcConfig btcParams;
+
+ sme_BtcGetConfig(pHddCtx->hHal, &btcParams);
+
+ btcParams.btcExecutionMode = pConfig->btcExecutionMode;
+
+ btcParams.btcConsBtSlotsToBlockDuringDhcp = pConfig->btcConsBtSlotsToBlockDuringDhcp;
+
+ btcParams.btcA2DPBtSubIntervalsDuringDhcp = pConfig->btcA2DPBtSubIntervalsDuringDhcp;
+
+ sme_BtcSetConfig(pHddCtx->hHal, &btcParams);
+}
+
+static void hdd_set_power_save_config(hdd_context_t *pHddCtx, tSmeConfigParams *smeConfig)
+{
+ hdd_config_t *pConfig = pHddCtx->cfg_ini;
+
+ tPmcBmpsConfigParams bmpsParams;
+
+ sme_GetConfigPowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE, &bmpsParams);
+
+ if (strcmp(pConfig->PowerUsageControl, "Min") == 0)
+ {
+ smeConfig->csrConfig.impsSleepTime = pConfig->nImpsMinSleepTime;
+ bmpsParams.bmpsPeriod = pConfig->nBmpsMinListenInterval;
+ bmpsParams.enableBeaconEarlyTermination = pConfig->fEnableBeaconEarlyTermination;
+ bmpsParams.bcnEarlyTermWakeInterval = pConfig->bcnEarlyTermWakeInterval;
+ }
+ if (strcmp(pConfig->PowerUsageControl, "Max") == 0)
+ {
+ smeConfig->csrConfig.impsSleepTime = pConfig->nImpsMaxSleepTime;
+ bmpsParams.bmpsPeriod = pConfig->nBmpsMaxListenInterval;
+ bmpsParams.enableBeaconEarlyTermination = pConfig->fEnableBeaconEarlyTermination;
+ bmpsParams.bcnEarlyTermWakeInterval = pConfig->bcnEarlyTermWakeInterval;
+ }
+ if (strcmp(pConfig->PowerUsageControl, "Mod") == 0)
+ {
+ smeConfig->csrConfig.impsSleepTime = pConfig->nImpsModSleepTime;
+ bmpsParams.bmpsPeriod = pConfig->nBmpsModListenInterval;
+ bmpsParams.enableBeaconEarlyTermination = pConfig->fEnableBeaconEarlyTermination;
+ bmpsParams.bcnEarlyTermWakeInterval = pConfig->bcnEarlyTermWakeInterval;
+ }
+
+ if (pConfig->fIsImpsEnabled)
+ {
+ sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ }
+ else
+ {
+ sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ }
+
+ if (pConfig->fIsBmpsEnabled)
+ {
+ sme_EnablePowerSave (pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+ }
+ else
+ {
+ sme_DisablePowerSave (pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+ }
+
+ bmpsParams.trafficMeasurePeriod = pConfig->nAutoBmpsTimerValue;
+
+ if (sme_SetConfigPowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE, &bmpsParams)== eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE, "SetConfigPowerSave failed to set BMPS params\n");
+ }
+
+ if(pConfig->fIsAutoBmpsTimerEnabled)
+ {
+ sme_StartAutoBmpsTimer(pHddCtx->hHal);
+ }
+
+}
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+static VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 *len, tANI_U8 intArrayMaxLen )
+{
+ char *s = str;
+
+ if( str == NULL || intArray == NULL || len == NULL )
+ {
+ return VOS_STATUS_E_INVAL;
+ }
+ *len = 0;
+
+#ifdef VERSION_USING_STRPBRK
+ while ( (s != NULL) && (*len < intArrayMaxLen) )
+ {
+ int val;
+ //Increment length only if sscanf succesfully extracted one element.
+ //Any other return value means error. Ignore it.
+ if( sscanf(s, "%d", &val ) == 1 )
+ {
+ intArray[*len] = (tANI_U8) val;
+ *len += 1;
+ }
+ s = strpbrk( s, "," );
+ if( s )
+ s++;
+ }
+#else
+ while( (*s != '\0') && (*len < intArrayMaxLen) )
+ {
+ unsigned long val;
+
+ val = simple_strtoul( s, &s, 10 );
+ if( val )
+ {
+ intArray[*len] = (tANI_U8) val;
+ *len += 1;
+ }
+ if( *s )
+ s++;
+ }
+#endif
+
+ return VOS_STATUS_SUCCESS;
+
+}
+#endif
+
+
+v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx )
+{
+ v_BOOL_t fStatus = TRUE;
+
+ hdd_config_t *pConfig = pHddCtx->cfg_ini;
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SHORT_GI_20MHZ,
+ pConfig->ShortGI20MhzEnable, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_SHORT_GI_20MHZ to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_CAL_CONTROL, pConfig->Calibration,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_CAL_CONTROL to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_CAL_PERIOD, pConfig->CalibrationPeriod,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_CAL_PERIOD to CCM\n");
+ }
+
+ if ( 0 != pConfig->Cfg1Id )
+ {
+ if (ccmCfgSetInt(pHddCtx->hHal, pConfig->Cfg1Id, pConfig->Cfg1Value, NULL,
+ eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on Cfg1Id to CCM\n");
+ }
+
+ }
+
+ if ( 0 != pConfig->Cfg2Id )
+ {
+ if (ccmCfgSetInt(pHddCtx->hHal, pConfig->Cfg2Id, pConfig->Cfg2Value,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on Cfg2Id to CCM\n");
+ }
+ }
+
+ if ( 0 != pConfig->Cfg3Id )
+ {
+ if (ccmCfgSetInt(pHddCtx->hHal, pConfig->Cfg3Id, pConfig->Cfg3Value,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on Cfg3Id to CCM\n");
+ }
+ }
+
+ if ( 0 != pConfig->Cfg4Id )
+ {
+ if (ccmCfgSetInt(pHddCtx->hHal, pConfig->Cfg4Id, pConfig->Cfg4Value,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on Cfg4Id to CCM\n");
+ }
+ }
+
+ if ( 0 != pConfig->Cfg5Id )
+ {
+ if (ccmCfgSetInt(pHddCtx->hHal, pConfig->Cfg5Id, pConfig->Cfg5Value,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on Cfg5Id to CCM\n");
+ }
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BA_AUTO_SETUP, pConfig->BlockAckAutoSetup,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_BA_AUTO_SETUP to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_FIXED_RATE, pConfig->TxRate,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_FIXED_RATE to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MAX_RX_AMPDU_FACTOR,
+ pConfig->MaxRxAmpduFactor, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Could not pass on WNI_CFG_HT_AMPDU_PARAMS_MAX_RX_AMPDU_FACTOR to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SHORT_PREAMBLE, pConfig->fIsShortPreamble,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Could not pass on WNI_CFG_SHORT_PREAMBLE to CCM\n");
+ }
+
+ if (pConfig->fIsAutoIbssBssid)
+ {
+ if (ccmCfgSetStr(pHddCtx->hHal, WNI_CFG_BSSID, (v_U8_t *)"000000000000",
+ sizeof(v_BYTE_t) * VOS_MAC_ADDR_SIZE, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Could not pass on WNI_CFG_BSSID to CCM\n");
+ }
+ }
+ else
+ {
+ if ( VOS_FALSE == vos_is_macaddr_group( &pConfig->IbssBssid ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ "MAC Addr (IBSS BSSID) read from Registry is: %02x-%02x-%02x-%02x-%02x-%02x",
+ pConfig->IbssBssid.bytes[0], pConfig->IbssBssid.bytes[1], pConfig->IbssBssid.bytes[2],
+ pConfig->IbssBssid.bytes[3], pConfig->IbssBssid.bytes[4], pConfig->IbssBssid.bytes[5]);
+ if (ccmCfgSetStr(pHddCtx->hHal, WNI_CFG_BSSID, pConfig->IbssBssid.bytes,
+ sizeof(v_BYTE_t) * VOS_MAC_ADDR_SIZE, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Could not pass on WNI_CFG_BSSID to CCM\n");
+ }
+ }
+ else
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Could not pass on WNI_CFG_BSSID to CCM\n");
+ }
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BEACON_INTERVAL, pConfig->nBeaconInterval,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_BEACON_INTERVAL to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MAX_PS_POLL, pConfig->nMaxPsPoll,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_MAX_PS_POLL to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_CURRENT_RX_ANTENNA, pConfig-> nRxAnt, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Failure: Could not pass on WNI_CFG_CURRENT_RX_ANTENNA configuration info to HAL\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LOW_GAIN_OVERRIDE, pConfig->fIsLowGainOverride,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_LOW_GAIN_OVERRIDE to HAL\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RSSI_FILTER_PERIOD, pConfig->nRssiFilterPeriod,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_RSSI_FILTER_PERIOD to CCM\n");
+ }
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_FT_RSSI_FILTER_PERIOD, pConfig->FTRssiFilterPeriod,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_FT_RSSI_FILTER_PERIOD to CCM\n");
+ }
+#endif
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, pConfig->fIgnoreDtim,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_IGNORE_DTIM configuration to CCM\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_ENABLE_HEART_BEAT, pConfig->fEnableFwHeartBeatMonitoring,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Failure: Could not pass on WNI_CFG_PS_HEART_BEAT configuration info to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_ENABLE_BCN_FILTER, pConfig->fEnableFwBeaconFiltering,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Failure: Could not pass on WNI_CFG_PS_BCN_FILTER configuration info to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_ENABLE_RSSI_MONITOR, pConfig->fEnableFwRssiMonitoring,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Failure: Could not pass on WNI_CFG_PS_RSSI_MONITOR configuration info to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, pConfig->nDataInactivityTimeout,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT configuration info to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_NTH_BEACON_FILTER, pConfig->nthBeaconFilter,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_NTH_BEACON_FILTER configuration info to CCM\n");
+ }
+
+#ifdef WLAN_SOFTAP_FEATURE
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_LTE_COEX, pConfig->enableLTECoex,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_LTE_COEX to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE, pConfig->nEnableListenMode,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE to CCM\n");
+ }
+
+ WLANSAP_SetChannelRange(pHddCtx->hHal, pConfig->apStartChannelNum, pConfig->apEndChannelNum, pConfig->apOperatingBand);
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_AP_KEEP_ALIVE_TIMEOUT, pConfig->apKeepAlivePeriod,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_AP_KEEP_ALIVE_TIMEOUT to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_GO_KEEP_ALIVE_TIMEOUT, pConfig->goKeepAlivePeriod,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_GO_KEEP_ALIVE_TIMEOUT to CCM\n");
+ }
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RRM_ENABLED, pConfig->fRrmEnable,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_RRM_ENABLE configuration info to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RRM_OPERATING_CHAN_MAX, pConfig->nInChanMeasMaxDuration,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_RRM_OPERATING_CHAN_MAX configuration info to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, pConfig->nOutChanMeasMaxDuration,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_RRM_OUT_CHAN_MAX configuration info to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MCAST_BCAST_FILTER_SETTING, pConfig->mcastBcastFilterSetting,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+#endif
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SINGLE_TID_RC, pConfig->bSingleTidRc,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_SINGLE_TID_RC configuration info to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_WAKEUP_EN, pConfig->teleBcnWakeupEn,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_WAKEUP_EN configuration info to CCM\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_TRANS_LI, pConfig->nTeleBcnTransListenInterval,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_TRANS_LI configuration info to CCM\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_MAX_LI, pConfig->nTeleBcnMaxListenInterval,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_MAX_LI configuration info to CCM\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS, pConfig->nTeleBcnTransLiNumIdleBeacons,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS configuration info to CCM\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS, pConfig->nTeleBcnMaxLiNumIdleBeacons,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS configuration info to CCM\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RF_SETTLING_TIME_CLK, pConfig->rfSettlingTimeUs,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_RF_SETTLING_TIME_CLK configuration info to CCM\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD, pConfig->infraStaKeepAlivePeriod,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD configuration info to CCM\n" );
+ }
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_DYNAMIC_PS_POLL_VALUE, pConfig->dynamicPsPollValue,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_DYNAMIC_PS_POLL_VALUE configuration info to CCM\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT, pConfig->nNullDataApRespTimeout,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_PS_NULLDATA_DELAY_TIMEOUT configuration info to CCM\n" );
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD, pConfig->apDataAvailPollPeriodInMs,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD configuration info to CCM\n" );
+ }
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, pConfig->FragmentationThreshold,
+ NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_FRAGMENTATION_THRESHOLD configuration info to CCM\n" );
+ }
+ if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RTS_THRESHOLD, pConfig->RTSThreshold,
+ NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_RTS_THRESHOLD configuration info to CCM\n" );
+ }
+
+ if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_11D_ENABLED, pConfig->Is11dSupportEnabled,
+ NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_11D_ENABLED configuration info to CCM\n" );
+ }
+ if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_HEART_BEAT_THRESHOLD, pConfig->HeartbeatThresh24,
+ NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_HEART_BEAT_THRESHOLD configuration info to CCM\n" );
+ }
+
+#endif
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD, pConfig->apDataAvailPollPeriodInMs,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE,"Failure: Could not pass on WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD configuration info to CCM\n" );
+ }
+
+ if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_CLOSE_LOOP,
+ pConfig->enableCloseLoop, NULL, eANI_BOOLEAN_FALSE)
+ ==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_CLOSE_LOOP to CCM\n");
+ }
+
+ if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TX_PWR_CTRL_ENABLE,
+ pConfig->enableAutomaticTxPowerControl, NULL, eANI_BOOLEAN_FALSE)
+ ==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_TX_PWR_CTRL_ENABLE to CCM\n");
+ }
+
+ if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SHORT_GI_40MHZ,
+ pConfig->ShortGI40MhzEnable, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ fStatus = FALSE;
+ hddLog(LOGE, "Could not pass on WNI_CFG_SHORT_GI_40MHZ to CCM\n");
+ }
+
+ return fStatus;
+}
+
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_init_set_sme_config() -
+
+ This function initializes the sme configuration parameters
+
+ \param - pHddCtx - Pointer to the HDD Adapter.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ eHalStatus halStatus;
+ tSmeConfigParams smeConfig;
+
+ hdd_config_t *pConfig = pHddCtx->cfg_ini;
+
+ vos_mem_zero( &smeConfig, sizeof( smeConfig ) );
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s bWmmIsEnabled=%d 802_11e_enabled=%d dot11Mode=%d\n", __func__,
+ pConfig->WmmMode, pConfig->b80211eIsEnabled, pConfig->dot11Mode);
+
+ // Config params obtained from the registry
+ smeConfig.csrConfig.RTSThreshold = pConfig->RTSThreshold;
+ smeConfig.csrConfig.FragmentationThreshold = pConfig->FragmentationThreshold;
+ smeConfig.csrConfig.shortSlotTime = pConfig->ShortSlotTimeEnabled;
+ smeConfig.csrConfig.Is11dSupportEnabled = pConfig->Is11dSupportEnabled;
+ smeConfig.csrConfig.HeartbeatThresh24 = pConfig->HeartbeatThresh24;
+
+ smeConfig.csrConfig.phyMode = hdd_cfg_xlate_to_csr_phy_mode ( pConfig->dot11Mode );
+
+ smeConfig.csrConfig.channelBondingMode24GHz = pConfig->nChannelBondingMode24GHz;
+ smeConfig.csrConfig.channelBondingMode5GHz = pConfig->nChannelBondingMode5GHz;
+ smeConfig.csrConfig.TxRate = pConfig->TxRate;
+ smeConfig.csrConfig.nScanResultAgeCount = pConfig->ScanResultAgeCount;
+ smeConfig.csrConfig.scanAgeTimeNCNPS = pConfig->nScanAgeTimeNCNPS;
+ smeConfig.csrConfig.scanAgeTimeNCPS = pConfig->nScanAgeTimeNCPS;
+ smeConfig.csrConfig.scanAgeTimeCNPS = pConfig->nScanAgeTimeCNPS;
+ smeConfig.csrConfig.scanAgeTimeCPS = pConfig->nScanAgeTimeCPS;
+ smeConfig.csrConfig.AdHocChannel24 = pConfig->OperatingChannel;
+ smeConfig.csrConfig.fEnforce11dChannels = pConfig->fEnforce11dChannels;
+ smeConfig.csrConfig.fSupplicantCountryCodeHasPriority = pConfig->fSupplicantCountryCodeHasPriority;
+ smeConfig.csrConfig.fEnforceCountryCodeMatch = pConfig->fEnforceCountryCodeMatch;
+ smeConfig.csrConfig.fEnforceDefaultDomain = pConfig->fEnforceDefaultDomain;
+ smeConfig.csrConfig.bCatRssiOffset = pConfig->nRssiCatGap;
+ smeConfig.csrConfig.vccRssiThreshold = pConfig->nVccRssiTrigger;
+ smeConfig.csrConfig.vccUlMacLossThreshold = pConfig->nVccUlMacLossThreshold;
+ smeConfig.csrConfig.nRoamingTime = pConfig->nRoamingTime;
+ smeConfig.csrConfig.IsIdleScanEnabled = pConfig->nEnableIdleScan;
+ smeConfig.csrConfig.nActiveMaxChnTime = pConfig->nActiveMaxChnTime;
+ smeConfig.csrConfig.nActiveMinChnTime = pConfig->nActiveMinChnTime;
+ smeConfig.csrConfig.nPassiveMaxChnTime = pConfig->nPassiveMaxChnTime;
+ smeConfig.csrConfig.nPassiveMinChnTime = pConfig->nPassiveMinChnTime;
+ smeConfig.csrConfig.Is11eSupportEnabled = pConfig->b80211eIsEnabled;
+ smeConfig.csrConfig.WMMSupportMode = pConfig->WmmMode;
+
+#if defined WLAN_FEATURE_VOWIFI
+ smeConfig.rrmConfig.rrmEnabled = pConfig->fRrmEnable;
+ smeConfig.rrmConfig.maxRandnInterval = pConfig->nRrmRandnIntvl;
+#endif
+ //Remaining config params not obtained from registry
+ // On RF EVB beacon using channel 1.
+
+ smeConfig.csrConfig.AdHocChannel5G = 44;
+ smeConfig.csrConfig.ProprietaryRatesEnabled = 0;
+ smeConfig.csrConfig.HeartbeatThresh50 = 40;
+ if( smeConfig.csrConfig.Is11dSupportEnabled )
+ {
+ smeConfig.csrConfig.Is11hSupportEnabled = 1;
+ }
+ else
+ {
+ smeConfig.csrConfig.Is11hSupportEnabled = 0;
+ }
+ smeConfig.csrConfig.bandCapability = pConfig->nBandCapability;
+ smeConfig.csrConfig.cbChoice = 0;
+ smeConfig.csrConfig.bgScanInterval = 0;
+ smeConfig.csrConfig.eBand = pConfig->nBandCapability;
+ smeConfig.csrConfig.nTxPowerCap = pConfig->nTxPowerCap;
+ smeConfig.csrConfig.fEnableBypass11d = pConfig->enableBypass11d;
+ smeConfig.csrConfig.fEnableDFSChnlScan = pConfig->enableDFSChnlScan;
+
+ //FIXME 11d config is hardcoded
+#ifdef WLAN_SOFTAP_FEATURE
+ if ( VOS_STA_SAP_MODE != hdd_get_conparam()){
+#endif
+ smeConfig.csrConfig.Csr11dinfo.Channels.numChannels = 0;
+
+ //if there is a requirement that HDD will control the default channel list &
+ //country code (say from .ini file) we need to add some logic here. Otherwise
+ //the default 11d info should come from NV as per our current implementation
+
+#ifdef WLAN_SOFTAP_FEATURE
+ }
+ else{
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "AP country Code %s", pConfig->apCntryCode);
+
+ if (memcmp(pConfig->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0)
+ sme_setRegInfo(pHddCtx->hHal, pConfig->apCntryCode);
+ sme_set11dinfo(pHddCtx->hHal, &smeConfig);
+ }
+#endif
+ hdd_set_power_save_config(pHddCtx, &smeConfig);
+ hdd_set_btc_config(pHddCtx);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ smeConfig.csrConfig.csr11rConfig.IsFTResourceReqSupported = pConfig->fFTResourceReqSupported;
+#endif
+#ifdef FEATURE_WLAN_CCX
+ smeConfig.csrConfig.isCcxIniFeatureEnabled = pConfig->isCcxIniFeatureEnabled;
+#endif
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX)
+ smeConfig.csrConfig.isFastTransitionEnabled = pConfig->isFastTransitionEnabled;
+#endif
+
+#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
+ smeConfig.csrConfig.neighborRoamConfig.nNeighborReassocRssiThreshold = pConfig->nNeighborReassocRssiThreshold;
+ smeConfig.csrConfig.neighborRoamConfig.nNeighborLookupRssiThreshold = pConfig->nNeighborLookupRssiThreshold;
+ smeConfig.csrConfig.neighborRoamConfig.nNeighborScanMaxChanTime = pConfig->nNeighborScanMaxChanTime;
+ smeConfig.csrConfig.neighborRoamConfig.nNeighborScanMinChanTime = pConfig->nNeighborScanMinChanTime;
+ smeConfig.csrConfig.neighborRoamConfig.nNeighborScanTimerPeriod = pConfig->nNeighborScanPeriod;
+ smeConfig.csrConfig.neighborRoamConfig.nMaxNeighborRetries = pConfig->nMaxNeighborReqTries;
+ smeConfig.csrConfig.neighborRoamConfig.nNeighborResultsRefreshPeriod = pConfig->nNeighborResultsRefreshPeriod;
+ hdd_string_to_u8_array( pConfig->neighborScanChanList,
+ smeConfig.csrConfig.neighborRoamConfig.neighborScanChanList.channelList,
+ &smeConfig.csrConfig.neighborRoamConfig.neighborScanChanList.numChannels,
+ WNI_CFG_VALID_CHANNEL_LIST_LEN );
+#endif
+
+ smeConfig.csrConfig.addTSWhenACMIsOff = pConfig->AddTSWhenACMIsOff;
+ smeConfig.csrConfig.fValidateList = pConfig->fValidateScanList;
+
+ //Enable/Disable MCC
+ smeConfig.csrConfig.fEnableMCCMode = pConfig->enableMCC;
+
+ halStatus = sme_UpdateConfig( pHddCtx->hHal, &smeConfig);
+ if ( !HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+
+
+ return status;
+}
+
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_execute_config_command() -
+
+ This function executes an arbitrary configuration set command
+
+ \param - pHddCtx - Pointer to the HDD Adapter.
+ \parmm - command - a configuration command of the form:
+ <name>=<value>
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+VOS_STATUS hdd_execute_config_command(hdd_context_t *pHddCtx, char *command)
+{
+ size_t tableSize = sizeof(g_registry_table)/sizeof(g_registry_table[0]);
+ REG_TABLE_ENTRY *pRegEntry;
+ char *clone;
+ char *pCmd;
+ void *pField;
+ char *name;
+ char *value_str;
+ v_U32_t value;
+ v_S31_t svalue;
+ size_t len_value_str;
+ unsigned int idx;
+ unsigned int i;
+ VOS_STATUS vstatus;
+
+ // assume failure until proven otherwise
+ vstatus = VOS_STATUS_E_FAILURE;
+
+ // clone the command so that we can manipulate it
+ clone = kstrdup(command, GFP_ATOMIC);
+ if (NULL == clone)
+ {
+ hddLog(LOGE, "%s: memory allocation failure, unable to process [%s]",
+ __FUNCTION__, command);
+ return vstatus;
+ }
+
+ // 'clone' will point to the beginning of the string so it can be freed
+ // 'pCmd' will be used to walk/parse the command
+ pCmd = clone;
+
+ // get rid of leading/trailing whitespace
+ pCmd = i_trim(pCmd);
+ if ('\0' == *pCmd)
+ {
+ // only whitespace
+ hddLog(LOGE, "%s: invalid command, only whitespace:[%s]",
+ __FUNCTION__, command);
+ goto done;
+ }
+
+ // parse the <name> = <value>
+ name = pCmd;
+ while (('=' != *pCmd) && ('\0' != *pCmd))
+ {
+ pCmd++;
+ }
+ if ('\0' == *pCmd)
+ {
+ // did not find '='
+ hddLog(LOGE, "%s: invalid command, no '=':[%s]",
+ __FUNCTION__, command);
+ goto done;
+ }
+
+ // replace '=' with NUL to terminate the <name>
+ *pCmd++ = '\0';
+ name = i_trim(name);
+ if ('\0' == *name)
+ {
+ // did not find a name
+ hddLog(LOGE, "%s: invalid command, no <name>:[%s]",
+ __FUNCTION__, command);
+ goto done;
+ }
+
+ value_str = i_trim(pCmd);
+ if ('\0' == *value_str)
+ {
+ // did not find a value
+ hddLog(LOGE, "%s: invalid command, no <value>:[%s]",
+ __FUNCTION__, command);
+ goto done;
+ }
+
+ // lookup the configuration item
+ for (idx = 0; idx < tableSize; idx++)
+ {
+ if (0 == strcmp(name, g_registry_table[idx].RegName))
+ {
+ // found a match
+ break;
+ }
+ }
+ if (tableSize == idx)
+ {
+ // did not match the name
+ hddLog(LOGE, "%s: invalid command, unknown configuration item:[%s]",
+ __FUNCTION__, command);
+ goto done;
+ }
+
+ pRegEntry = &g_registry_table[idx];
+ if (!(pRegEntry->Flags & VAR_FLAGS_DYNAMIC_CFG))
+ {
+ // does not support dynamic configuration
+ hddLog(LOGE, "%s: invalid command, %s does not support "
+ "dynamic configuration", __FUNCTION__, name);
+ goto done;
+ }
+
+ pField = ((v_U8_t *)pHddCtx->cfg_ini) + pRegEntry->VarOffset;
+
+ switch (pRegEntry->RegType)
+ {
+ case WLAN_PARAM_Integer:
+ value = simple_strtoul(value_str, NULL, 10);
+ if (value < pRegEntry->VarMin)
+ {
+ // out of range
+ hddLog(LOGE, "%s: invalid command, value %u < min value %u",
+ __FUNCTION__, value, pRegEntry->VarMin);
+ goto done;
+ }
+ if (value > pRegEntry->VarMax)
+ {
+ // out of range
+ hddLog(LOGE, "%s: invalid command, value %u > max value %u",
+ __FUNCTION__, value, pRegEntry->VarMax);
+ goto done;
+ }
+ memcpy(pField, &value, pRegEntry->VarSize);
+ break;
+
+ case WLAN_PARAM_HexInteger:
+ value = simple_strtoul(value_str, NULL, 16);
+ if (value < pRegEntry->VarMin)
+ {
+ // out of range
+ hddLog(LOGE, "%s: invalid command, value %x < min value %x",
+ __FUNCTION__, value, pRegEntry->VarMin);
+ goto done;
+ }
+ if (value > pRegEntry->VarMax)
+ {
+ // out of range
+ hddLog(LOGE, "%s: invalid command, value %x > max value %x",
+ __FUNCTION__, value, pRegEntry->VarMax);
+ goto done;
+ }
+ memcpy(pField, &value, pRegEntry->VarSize);
+ break;
+
+ case WLAN_PARAM_SignedInteger:
+ svalue = simple_strtol(value_str, NULL, 10);
+ if (svalue < (v_S31_t)pRegEntry->VarMin)
+ {
+ // out of range
+ hddLog(LOGE, "%s: invalid command, value %d < min value %d",
+ __FUNCTION__, svalue, (int)pRegEntry->VarMin);
+ goto done;
+ }
+ if (svalue > (v_S31_t)pRegEntry->VarMax)
+ {
+ // out of range
+ hddLog(LOGE, "%s: invalid command, value %d > max value %d",
+ __FUNCTION__, svalue, (int)pRegEntry->VarMax);
+ goto done;
+ }
+ memcpy(pField, &svalue, pRegEntry->VarSize);
+ break;
+
+ case WLAN_PARAM_String:
+ len_value_str = strlen(value_str);
+ if (len_value_str > (pRegEntry->VarSize - 1))
+ {
+ // too big
+ hddLog(LOGE,
+ "%s: invalid command, string [%s] length "
+ "%u exceeds maximum length %u",
+ __FUNCTION__, value_str,
+ len_value_str, (pRegEntry->VarSize - 1));
+ goto done;
+ }
+ // copy string plus NUL
+ memcpy(pField, value_str, (len_value_str + 1));
+ break;
+
+ case WLAN_PARAM_MacAddr:
+ len_value_str = strlen(value_str);
+ if (len_value_str != (VOS_MAC_ADDR_SIZE * 2))
+ {
+ // out of range
+ hddLog(LOGE,
+ "%s: invalid command, MAC address [%s] length "
+ "%u is not expected length %u",
+ __FUNCTION__, value_str,
+ len_value_str, (VOS_MAC_ADDR_SIZE * 2));
+ goto done;
+ }
+ //parse the string and store it in the byte array
+ for (i = 0; i < VOS_MAC_ADDR_SIZE; i++)
+ {
+ ((char*)pField)[i] = (char)
+ ((parseHexDigit(value_str[(i * 2)]) * 16) +
+ parseHexDigit(value_str[(i * 2) + 1]));
+ }
+ break;
+
+ default:
+ goto done;
+ }
+
+ // if we get here, we had a successful modification
+ vstatus = VOS_STATUS_SUCCESS;
+
+ // config table has been modified, is there a notifier?
+ if (NULL != pRegEntry->pfnDynamicNotify)
+ {
+ (pRegEntry->pfnDynamicNotify)(pHddCtx, pRegEntry->NotifyId);
+ }
+
+ // note that this item was explicitly configured
+ if (idx < MAX_CFG_INI_ITEMS)
+ {
+ set_bit(idx, (void *)&pHddCtx->cfg_ini->bExplicitCfg);
+ }
+ done:
+ kfree(clone);
+ return vstatus;
+}
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
new file mode 100644
index 0000000..dc8f4c5
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -0,0 +1,5114 @@
+/*
+ * 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 wlan_hdd_cfg80211.c
+
+ \brief WLAN Host Device Driver implementation
+
+ 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.
+
+
+ $Header:$ $DateTime: $ $Author: $
+
+
+ when who what, where, why
+ -------- --- --------------------------------------------------------
+ 21/12/09 Ashwani Created module.
+
+ 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
+ Ganesh K
+ ==========================================================================*/
+
+#ifdef CONFIG_CFG80211
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/wireless.h>
+#include <wlan_hdd_includes.h>
+#include <net/arp.h>
+#include <net/cfg80211.h>
+#include <linux/wireless.h>
+#include <wlan_hdd_wowl.h>
+#include <aniGlobal.h>
+#include "ccmApi.h"
+#include "sirParams.h"
+#include "dot11f.h"
+#include "wlan_hdd_assoc.h"
+#include "wlan_hdd_wext.h"
+#include "sme_Api.h"
+#include "wlan_hdd_p2p.h"
+#include "wlan_hdd_cfg80211.h"
+#include "wlan_hdd_hostapd.h"
+#include "sapInternal.h"
+#include "wlan_hdd_softap_tx_rx.h"
+#include "wlan_hdd_main.h"
+#ifdef WLAN_BTAMP_FEATURE
+#include "bap_hdd_misc.h"
+#endif
+#include <qc_sap_ioctl.h>
+
+#define g_mode_rates_size (12)
+#define a_mode_rates_size (8)
+#define FREQ_BASE_80211G (2407)
+#define FREQ_BAND_DIFF_80211G (5)
+#define MAX_SCAN_SSID 2
+#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
+ ((int) OFFSET_OF( tSirBssDescription, ieFields)))
+
+#define HDD2GHZCHAN(freq, chan, flag) { \
+ .band = IEEE80211_BAND_2GHZ, \
+ .center_freq = (freq), \
+ .hw_value = (chan),\
+ .flags = (flag), \
+ .max_antenna_gain = 0 ,\
+ .max_power = 30, \
+}
+
+#define HDD5GHZCHAN(freq, chan, flag) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .center_freq = (freq), \
+ .hw_value = (chan),\
+ .flags = (flag), \
+ .max_antenna_gain = 0 ,\
+ .max_power = 30, \
+}
+
+#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
+{\
+ .bitrate = rate, \
+ .hw_value = rate_id, \
+ .flags = flag, \
+}
+
+static const u32 hdd_cipher_suites[] =
+{
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+#ifdef FEATURE_WLAN_CCX
+#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
+ WLAN_CIPHER_SUITE_KRK,
+ WLAN_CIPHER_SUITE_CCMP,
+#else
+ WLAN_CIPHER_SUITE_CCMP,
+#endif
+#ifdef FEATURE_WLAN_WAPI
+ WLAN_CIPHER_SUITE_SMS4,
+#endif
+};
+
+static inline int is_broadcast_ether_addr(const u8 *addr)
+{
+ return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
+ (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
+}
+
+static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
+{
+ HDD2GHZCHAN(2412, 1, 0) ,
+ HDD2GHZCHAN(2417, 2, 0) ,
+ HDD2GHZCHAN(2422, 3, 0) ,
+ HDD2GHZCHAN(2427, 4, 0) ,
+ HDD2GHZCHAN(2432, 5, 0) ,
+ HDD2GHZCHAN(2437, 6, 0) ,
+ HDD2GHZCHAN(2442, 7, 0) ,
+ HDD2GHZCHAN(2447, 8, 0) ,
+ HDD2GHZCHAN(2452, 9, 0) ,
+ HDD2GHZCHAN(2457, 10, 0) ,
+ HDD2GHZCHAN(2462, 11, 0) ,
+ HDD2GHZCHAN(2467, 12, 0) ,
+ HDD2GHZCHAN(2472, 13, 0) ,
+ HDD2GHZCHAN(2484, 14, 0) ,
+};
+
+#ifdef WLAN_FEATURE_P2P
+static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
+{
+ HDD2GHZCHAN(2412, 1, 0) ,
+ HDD2GHZCHAN(2437, 6, 0) ,
+ HDD2GHZCHAN(2462, 11, 0) ,
+};
+#endif
+
+static struct ieee80211_channel hdd_channels_5_GHZ[] =
+{
+ HDD5GHZCHAN(5180, 36, 0) ,
+ HDD5GHZCHAN(5200, 40, 0) ,
+ HDD5GHZCHAN(5220, 44, 0) ,
+ HDD5GHZCHAN(5240, 48, 0) ,
+ HDD5GHZCHAN(5260, 52, 0) ,
+ HDD5GHZCHAN(5280, 56, 0) ,
+ HDD5GHZCHAN(5300, 60, 0) ,
+ HDD5GHZCHAN(5320, 64, 0) ,
+ HDD5GHZCHAN(5500,100, 0) ,
+ HDD5GHZCHAN(5520,104, 0) ,
+ HDD5GHZCHAN(5540,108, 0) ,
+ HDD5GHZCHAN(5560,112, 0) ,
+ HDD5GHZCHAN(5580,116, 0) ,
+ HDD5GHZCHAN(5600,120, 0) ,
+ HDD5GHZCHAN(5620,124, 0) ,
+ HDD5GHZCHAN(5640,128, 0) ,
+ HDD5GHZCHAN(5660,132, 0) ,
+ HDD5GHZCHAN(5680,136, 0) ,
+ HDD5GHZCHAN(5700,140, 0) ,
+ HDD5GHZCHAN(5745,149, 0) ,
+ HDD5GHZCHAN(5765,153, 0) ,
+ HDD5GHZCHAN(5785,157, 0) ,
+ HDD5GHZCHAN(5805,161, 0) ,
+ HDD5GHZCHAN(5825,165, 0) ,
+};
+
+static struct ieee80211_rate g_mode_rates[] =
+{
+ HDD_G_MODE_RATETAB(10, 0x1, 0),
+ HDD_G_MODE_RATETAB(20, 0x2, 0),
+ HDD_G_MODE_RATETAB(55, 0x4, 0),
+ HDD_G_MODE_RATETAB(110, 0x8, 0),
+ HDD_G_MODE_RATETAB(60, 0x10, 0),
+ HDD_G_MODE_RATETAB(90, 0x20, 0),
+ HDD_G_MODE_RATETAB(120, 0x40, 0),
+ HDD_G_MODE_RATETAB(180, 0x80, 0),
+ HDD_G_MODE_RATETAB(240, 0x100, 0),
+ HDD_G_MODE_RATETAB(360, 0x200, 0),
+ HDD_G_MODE_RATETAB(480, 0x400, 0),
+ HDD_G_MODE_RATETAB(540, 0x800, 0),
+};
+
+static struct ieee80211_rate a_mode_rates[] =
+{
+ HDD_G_MODE_RATETAB(60, 0x10, 0),
+ HDD_G_MODE_RATETAB(90, 0x20, 0),
+ HDD_G_MODE_RATETAB(120, 0x40, 0),
+ HDD_G_MODE_RATETAB(180, 0x80, 0),
+ HDD_G_MODE_RATETAB(240, 0x100, 0),
+ HDD_G_MODE_RATETAB(360, 0x200, 0),
+ HDD_G_MODE_RATETAB(480, 0x400, 0),
+ HDD_G_MODE_RATETAB(540, 0x800, 0),
+};
+
+static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
+{
+ .channels = hdd_channels_2_4_GHZ,
+ .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
+ .band = IEEE80211_BAND_2GHZ,
+ .bitrates = g_mode_rates,
+ .n_bitrates = g_mode_rates_size,
+ .ht_cap.ht_supported = 1,
+ .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
+ | IEEE80211_HT_CAP_GRN_FLD
+ | IEEE80211_HT_CAP_DSSSCCK40
+ | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
+ .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+ .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+ .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
+ .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
+};
+
+#ifdef WLAN_FEATURE_P2P
+static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
+{
+ .channels = hdd_social_channels_2_4_GHZ,
+ .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
+ .band = IEEE80211_BAND_2GHZ,
+ .bitrates = g_mode_rates,
+ .n_bitrates = g_mode_rates_size,
+ .ht_cap.ht_supported = 1,
+ .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
+ | IEEE80211_HT_CAP_GRN_FLD
+ | IEEE80211_HT_CAP_DSSSCCK40
+ | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
+ .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+ .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+ .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
+ .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
+};
+#endif
+
+static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
+{
+ .channels = hdd_channels_5_GHZ,
+ .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
+ .band = IEEE80211_BAND_5GHZ,
+ .bitrates = a_mode_rates,
+ .n_bitrates = a_mode_rates_size,
+ .ht_cap.ht_supported = 1,
+ .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
+ | IEEE80211_HT_CAP_GRN_FLD
+ | IEEE80211_HT_CAP_DSSSCCK40
+ | IEEE80211_HT_CAP_LSIG_TXOP_PROT
+ | IEEE80211_HT_CAP_SGI_40
+ | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
+ .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+ .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+ .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
+ .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
+};
+
+/* This structure contain information what kind of frame are expected in
+ TX/RX direction for each kind of interface */
+static const struct ieee80211_txrx_stypes
+wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
+ [NL80211_IFTYPE_STATION] = {
+ .tx = 0xffff,
+ .rx = BIT(SIR_MAC_MGMT_ACTION) |
+ BIT(SIR_MAC_MGMT_PROBE_REQ),
+ },
+ [NL80211_IFTYPE_AP] = {
+ .tx = 0xffff,
+ .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
+ BIT(SIR_MAC_MGMT_REASSOC_REQ) |
+ BIT(SIR_MAC_MGMT_PROBE_REQ) |
+ BIT(SIR_MAC_MGMT_DISASSOC) |
+ BIT(SIR_MAC_MGMT_AUTH) |
+ BIT(SIR_MAC_MGMT_DEAUTH) |
+ BIT(SIR_MAC_MGMT_ACTION),
+ },
+#ifdef WLAN_FEATURE_P2P
+ [NL80211_IFTYPE_P2P_CLIENT] = {
+ .tx = 0xffff,
+ .rx = BIT(SIR_MAC_MGMT_ACTION) |
+ BIT(SIR_MAC_MGMT_PROBE_REQ),
+ },
+ [NL80211_IFTYPE_P2P_GO] = {
+ /* This is also same as for SoftAP */
+ .tx = 0xffff,
+ .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
+ BIT(SIR_MAC_MGMT_REASSOC_REQ) |
+ BIT(SIR_MAC_MGMT_PROBE_REQ) |
+ BIT(SIR_MAC_MGMT_DISASSOC) |
+ BIT(SIR_MAC_MGMT_AUTH) |
+ BIT(SIR_MAC_MGMT_DEAUTH) |
+ BIT(SIR_MAC_MGMT_ACTION),
+ },
+#endif
+};
+
+static struct cfg80211_ops wlan_hdd_cfg80211_ops;
+
+/* Data rate 100KBPS based on IE Index */
+struct index_data_rate_type
+{
+ v_U8_t beacon_rate_index;
+ v_U16_t supported_rate[4];
+};
+
+/* 11B, 11G Rate table include Basic rate and Extended rate
+ The IDX field is the rate index
+ The HI field is the rate when RSSI is strong or being ignored
+ (in this case we report actual rate)
+ The MID field is the rate when RSSI is moderate
+ (in this case we cap 11b rates at 5.5 and 11g rates at 24)
+ The LO field is the rate when RSSI is low
+ (in this case we don't report rates, actual current rate used)
+ */
+static const struct
+{
+ v_U8_t beacon_rate_index;
+ v_U16_t supported_rate[3];
+} supported_data_rate[] =
+{
+/* IDX HI MID LO (RSSI-based index */
+ {2, { 10, 10, 0}},
+ {4, { 20, 20, 0}},
+ {11, { 55, 55, 0}},
+ {12, { 60, 60, 0}},
+ {18, { 90, 90, 0}},
+ {22, {110, 55, 0}},
+ {24, {120, 120, 0}},
+ {36, {180, 180, 0}},
+ {44, {220, 220, 0}},
+ {48, {240, 240, 0}},
+ {66, {330, 240, 0}},
+ {72, {360, 240, 0}},
+ {96, {480, 240, 0}},
+ {108, {540, 240, 0}}
+};
+
+/* MCS Based rate table */
+static struct index_data_rate_type supported_mcs_rate[] =
+{
+/* MCS L20 L40 S20 S40 */
+ {0, {65, 135, 72, 150}},
+ {1, {130, 270, 144, 300}},
+ {2, {195, 405, 217, 450}},
+ {3, {260, 540, 289, 600}},
+ {4, {390, 810, 433, 900}},
+ {5, {520, 1080, 578, 1200}},
+ {6, {585, 1215, 650, 1350}},
+ {7, {650, 1350, 722, 1500}}
+};
+
+extern struct net_device_ops net_ops_struct;
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_init
+ * This function is called by hdd_wlan_startup()
+ * during initialization.
+ * This function is used to initialize and register wiphy structure.
+ */
+struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
+{
+ struct wiphy *wiphy;
+ ENTER();
+
+ /*
+ * Create wiphy device
+ */
+ wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
+
+ if (!wiphy)
+ {
+ /* Print error and jump into err label and free the memory */
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
+ return NULL;
+ }
+
+ return wiphy;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_update_band
+ * This function is called from the supplicant through a
+ * private ioctl to change the band value
+ */
+int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
+{
+ switch(eBand)
+ {
+ case eCSR_BAND_24:
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
+ wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+ break;
+ case eCSR_BAND_5G:
+ wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
+ break;
+ case eCSR_BAND_ALL:
+ default:
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
+ }
+ return 0;
+}
+/*
+ * FUNCTION: wlan_hdd_cfg80211_init
+ * This function is called by hdd_wlan_startup()
+ * during initialization.
+ * This function is used to initialize and register wiphy structure.
+ */
+int wlan_hdd_cfg80211_register(struct device *dev,
+ struct wiphy *wiphy,
+ hdd_config_t *pCfg
+ )
+{
+ /* Now bind the underlying wlan device with wiphy */
+ set_wiphy_dev(wiphy, dev);
+
+ wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
+
+ wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
+ | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
+ | WIPHY_FLAG_CUSTOM_REGULATORY;
+
+ wiphy->max_scan_ssids = MAX_SCAN_SSID;
+
+ wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
+
+ /* Supports STATION & AD-HOC modes right now */
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
+ | BIT(NL80211_IFTYPE_ADHOC)
+#ifdef WLAN_FEATURE_P2P
+ | BIT(NL80211_IFTYPE_P2P_CLIENT)
+ | BIT(NL80211_IFTYPE_P2P_GO)
+#endif
+ | BIT(NL80211_IFTYPE_AP);
+
+ /* Before registering we need to update the ht capabilitied based
+ * on ini values*/
+ if( !pCfg->ShortGI20MhzEnable )
+ {
+ wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
+ wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
+ wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
+ }
+
+ if( !pCfg->ShortGI40MhzEnable )
+ {
+ wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
+ }
+
+ if( !pCfg->nChannelBondingMode5GHz )
+ {
+ wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
+
+ /*Initialize band capability*/
+ switch(pCfg->nBandCapability)
+ {
+ case eCSR_BAND_24:
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
+ break;
+ case eCSR_BAND_5G:
+#ifdef WLAN_FEATURE_P2P
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
+#endif
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
+ break;
+ case eCSR_BAND_ALL:
+ default:
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
+ }
+ /*Initialise the supported cipher suite details*/
+ wiphy->cipher_suites = hdd_cipher_suites;
+ wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
+
+ /*signal strength in mBm (100*dBm) */
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+#ifdef WLAN_FEATURE_P2P
+ wiphy->max_remain_on_channel_duration = 1000;
+#endif
+#endif
+
+ /* Register our wiphy dev with cfg80211 */
+ if (0 > wiphy_register(wiphy))
+ {
+ /* print eror */
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
+ return -EIO;
+ }
+
+ EXIT();
+ return 0;
+}
+
+/* In this function we will do all post VOS start initialization.
+ In this function we will register for all frame in which supplicant
+ is interested.
+*/
+void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
+{
+#ifdef WLAN_FEATURE_P2P
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ /* Register for all P2P action, public action etc frames */
+ v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
+
+ /* Right now we are registering these frame when driver is getting
+ initialized. Once we will move to 2.6.37 kernel, in which we have
+ frame register ops, we will move this code as a part of that */
+ /* GAS Initial Request */
+ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
+
+ /* GAS Initial Response */
+ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
+
+ /* GAS Comeback Request */
+ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
+
+ /* GAS Comeback Response */
+ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
+
+ /* P2P Public Action */
+ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
+ P2P_PUBLIC_ACTION_FRAME_SIZE );
+
+ /* P2P Action */
+ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)P2P_ACTION_FRAME,
+ P2P_ACTION_FRAME_SIZE );
+#endif /* WLAN_FEATURE_P2P */
+}
+
+void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
+{
+#ifdef WLAN_FEATURE_P2P
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ /* Register for all P2P action, public action etc frames */
+ v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
+
+ /* Right now we are registering these frame when driver is getting
+ initialized. Once we will move to 2.6.37 kernel, in which we have
+ frame register ops, we will move this code as a part of that */
+ /* GAS Initial Request */
+
+ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
+
+ /* GAS Initial Response */
+ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
+
+ /* GAS Comeback Request */
+ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
+
+ /* GAS Comeback Response */
+ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
+
+ /* P2P Public Action */
+ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
+ P2P_PUBLIC_ACTION_FRAME_SIZE );
+
+ /* P2P Action */
+ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)P2P_ACTION_FRAME,
+ P2P_ACTION_FRAME_SIZE );
+#endif /* WLAN_FEATURE_P2P */
+}
+
+#ifdef FEATURE_WLAN_WAPI
+void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
+ const u8 *mac_addr, u8 *key , int key_Len)
+{
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ tCsrRoamSetKey setKey;
+ v_BOOL_t isConnected = TRUE;
+ int status = 0;
+ v_U32_t roamId= 0xFF;
+ tANI_U8 *pKeyPtr = NULL;
+ int n = 0;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
+ __func__,pAdapter->device_mode);
+
+ setKey.keyId = key_index; // Store Key ID
+ setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
+ setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
+ setKey.paeRole = 0 ; // the PAE role
+ if (!mac_addr || is_broadcast_ether_addr(mac_addr))
+ {
+ vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
+ }
+ else
+ {
+ isConnected = hdd_connIsConnected(pHddStaCtx);
+ vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
+ }
+ setKey.keyLength = key_Len;
+ pKeyPtr = setKey.Key;
+ memcpy( pKeyPtr, key, key_Len);
+
+ hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
+ __func__, key_Len);
+ for (n = 0 ; n < key_Len; n++)
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
+ __func__,n,setKey.Key[n]);
+
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
+ if ( isConnected )
+ {
+ status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, &setKey, &roamId );
+ }
+ if ( status != 0 )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] sme_RoamSetKey returned ERROR status= %d",
+ __LINE__, status );
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+ }
+}
+#endif /* FEATURE_WLAN_WAPI*/
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
+ beacon_data_t **ppBeacon,
+ struct beacon_parameters *params)
+{
+ int size;
+ beacon_data_t *beacon = NULL;
+ beacon_data_t *old = NULL;
+ int head_len,tail_len;
+
+ if (params->head && !params->head_len)
+ return -EINVAL;
+
+ old = pAdapter->sessionCtx.ap.beacon;
+
+ if (!params->head && !old)
+ return -EINVAL;
+
+ if (params->tail && !params->tail_len)
+ return -EINVAL;
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
+ /* Kernel 3.0 is not updating dtim_period for set beacon */
+ if (!params->dtim_period)
+ return -EINVAL;
+#endif
+
+ if(params->head)
+ head_len = params->head_len;
+ else
+ head_len = old->head_len;
+
+ if(params->tail || !old)
+ tail_len = params->tail_len;
+ else
+ tail_len = old->tail_len;
+
+ size = sizeof(beacon_data_t) + head_len + tail_len;
+
+ beacon = kzalloc(size, GFP_KERNEL);
+
+ if( beacon == NULL )
+ return -ENOMEM;
+
+ if(params->dtim_period || !old )
+ beacon->dtim_period = params->dtim_period;
+ else
+ beacon->dtim_period = old->dtim_period;
+
+ beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
+ beacon->tail = beacon->head + head_len;
+ beacon->head_len = head_len;
+ beacon->tail_len = tail_len;
+
+ if(params->head) {
+ memcpy (beacon->head,params->head,beacon->head_len);
+ }
+ else {
+ if(old)
+ memcpy (beacon->head,old->head,beacon->head_len);
+ }
+
+ if(params->tail) {
+ memcpy (beacon->tail,params->tail,beacon->tail_len);
+ }
+ else {
+ if(old)
+ memcpy (beacon->tail,old->tail,beacon->tail_len);
+ }
+
+ *ppBeacon = beacon;
+
+ kfree(old);
+
+ return 0;
+
+}
+#endif //LINUX_VERSION_CODE
+
+v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
+{
+ int left = length;
+ v_U8_t *ptr = pIes;
+ v_U8_t elem_id,elem_len;
+
+ while(left >= 2)
+ {
+ elem_id = ptr[0];
+ elem_len = ptr[1];
+ left -= 2;
+ if(elem_len > left)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "****Invalid IEs eid = %d elem_len=%d left=%d*****\n",
+ eid,elem_len,left);
+ return NULL;
+ }
+ if (elem_id == eid)
+ {
+ return ptr;
+ }
+
+ left -= elem_len;
+ ptr += (elem_len + 2);
+ }
+ return NULL;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+/* Check if rate is 11g rate or not */
+static int wlan_hdd_rate_is_11g(u8 rate)
+{
+ u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
+ u8 i;
+ for (i = 0; i < 8; i++)
+ {
+ if(rate == gRateArray[i])
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Check for 11g rate and set proper 11g only mode */
+static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
+ u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
+{
+ u8 i, num_rates = pIe[0];
+
+ pIe += 1;
+ for ( i = 0; i < num_rates; i++)
+ {
+ if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
+ {
+ /* If rate set have 11g rate than change the mode to 11G */
+ *pSapHw_mode = eSAP_DOT11_MODE_11g;
+ if (pIe[i] & BASIC_RATE_MASK)
+ {
+ /* If we have 11g rate as basic rate, it means mode
+ is 11g only mode.
+ */
+ *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
+ *pCheckRatesfor11g = FALSE;
+ }
+ }
+ else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
+ {
+ *require_ht = TRUE;
+ }
+ }
+ return;
+}
+
+static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
+{
+ tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
+ beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
+ struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
+ u8 checkRatesfor11g = TRUE;
+ u8 require_ht = FALSE;
+ u8 *pIe=NULL;
+
+ pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
+
+ pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
+ pBeacon->head_len, WLAN_EID_SUPP_RATES);
+ if (pIe != NULL)
+ {
+ pIe += 1;
+ wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
+ &pConfig->SapHw_mode);
+ }
+
+ pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
+ WLAN_EID_EXT_SUPP_RATES);
+ if (pIe != NULL)
+ {
+
+ pIe += 1;
+ wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
+ &pConfig->SapHw_mode);
+ }
+
+ if( pConfig->channel > 14 )
+ {
+ pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
+ }
+
+ pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
+ WLAN_EID_HT_CAPABILITY);
+
+ if(pIe)
+ {
+ pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
+ if(require_ht)
+ pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
+ }
+}
+
+static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
+ struct beacon_parameters *params)
+{
+ v_U8_t *genie;
+ v_U8_t total_ielen = 0, ielen = 0;
+ v_U8_t *pIe = NULL;
+ v_U8_t addIE[1] = {0};
+ beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
+
+ genie = vos_mem_malloc(MAX_GENIE_LEN);
+
+ if(genie == NULL) {
+
+ return -ENOMEM;
+ }
+
+ pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
+
+ if(pIe)
+ {
+ /*Copy the wps IE*/
+ ielen = pIe[1] + 2;
+ if( ielen <=MAX_GENIE_LEN)
+ {
+ vos_mem_copy(genie, pIe, ielen);
+ }
+ else
+ {
+ hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
+ return -EINVAL;
+ }
+ total_ielen = ielen;
+ }
+
+#ifdef WLAN_FEATURE_WFD
+ pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
+
+ if(pIe)
+ {
+ ielen = pIe[1] + 2;
+ if(total_ielen + ielen <= MAX_GENIE_LEN) {
+ vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
+ }
+ else {
+ hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
+ return -EINVAL;
+ }
+ total_ielen += ielen;
+ }
+#endif
+
+#ifdef WLAN_FEATURE_P2P
+ pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
+
+ if(pIe)
+ {
+ ielen = pIe[1] + 2;
+ if(total_ielen + ielen <= MAX_GENIE_LEN)
+ {
+ vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
+ }
+ else
+ {
+ hddLog( VOS_TRACE_LEVEL_ERROR,
+ "**Wps Ie+ P2pIE Length is too big***\n");
+ return -EINVAL;
+ }
+ total_ielen += ielen;
+ }
+#endif
+
+ if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
+ eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
+ return -EINVAL;
+ }
+
+ if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
+ test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
+ eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
+ ==eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
+ return -EINVAL;
+ }
+
+ // Added for ProResp IE
+ if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
+ {
+ u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
+ u8 probe_rsp_ie_len[3] = {0};
+ u8 counter = 0;
+ /* Check Probe Resp Length if it is greater then 255 then Store
+ Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
+ WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
+ Store More then 255 bytes into One Variable.
+ */
+ while ((rem_probe_resp_ie_len > 0) && (counter < 3))
+ {
+ if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
+ {
+ probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
+ rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
+ }
+ else
+ {
+ probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
+ rem_probe_resp_ie_len = 0;
+ }
+ }
+
+ rem_probe_resp_ie_len = 0;
+
+ if (probe_rsp_ie_len[0] > 0)
+ {
+ if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
+ (tANI_U8*)¶ms->proberesp_ies[rem_probe_resp_ie_len],
+ probe_rsp_ie_len[0], NULL,
+ eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
+ return -EINVAL;
+ }
+ rem_probe_resp_ie_len += probe_rsp_ie_len[0];
+ }
+
+ if (probe_rsp_ie_len[1] > 0)
+ {
+ if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
+ (tANI_U8*)¶ms->proberesp_ies[rem_probe_resp_ie_len],
+ probe_rsp_ie_len[1], NULL,
+ eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
+ return -EINVAL;
+ }
+ rem_probe_resp_ie_len += probe_rsp_ie_len[1];
+ }
+
+ if (probe_rsp_ie_len[2] > 0)
+ {
+ if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
+ (tANI_U8*)¶ms->proberesp_ies[rem_probe_resp_ie_len],
+ probe_rsp_ie_len[2], NULL,
+ eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
+ return -EINVAL;
+ }
+ rem_probe_resp_ie_len += probe_rsp_ie_len[2];
+ }
+
+ if (probe_rsp_ie_len[1] == 0 )
+ {
+ if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
+ eANI_BOOLEAN_FALSE) )
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
+ }
+ }
+
+ if (probe_rsp_ie_len[2] == 0 )
+ {
+ if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
+ eANI_BOOLEAN_FALSE) )
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
+ }
+ }
+
+ if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
+ test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
+ eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
+ == eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
+ return -EINVAL;
+ }
+ }
+ else
+ {
+ // Reset WNI_CFG_PROBE_RSP Flags
+ wlan_hdd_reset_prob_rspies(pHostapdAdapter);
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: No Probe Response IE received in set beacon",
+ __func__);
+ }
+
+ // Added for AssocResp IE
+ if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
+ {
+ if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
+ params->assocresp_ies_len, NULL,
+ eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
+ return -EINVAL;
+ }
+
+ if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
+ test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
+ eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
+ == eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
+ return -EINVAL;
+ }
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: No Assoc Response IE received in set beacon",
+ __func__);
+
+ if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
+ eANI_BOOLEAN_FALSE) )
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
+ }
+ }
+
+ vos_mem_free(genie);
+ return 0;
+}
+#endif //LINUX_VERSION_CODE
+
+/*
+ * FUNCTION: wlan_hdd_validate_operation_channel
+ * called by wlan_hdd_cfg80211_start_bss() and
+ * wlan_hdd_cfg80211_set_channel()
+ * This function validates whether given channel is part of valid
+ * channel list.
+ */
+static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
+{
+
+ v_U32_t num_ch = 0;
+ u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ u32 indx = 0;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+
+ num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+
+ if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
+ valid_ch, &num_ch))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: failed to get valid channel list\n", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ for (indx = 0; indx < num_ch; indx++)
+ {
+ if (channel == valid_ch[indx])
+ {
+ break;
+ }
+ }
+
+ if (indx >= num_ch)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid Channel [%d] \n", __func__, channel);
+ return VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
+ struct beacon_parameters *params)
+{
+ tsap_Config_t *pConfig;
+ beacon_data_t *pBeacon = NULL;
+ struct ieee80211_mgmt *pMgmt_frame;
+ v_U8_t *pIe=NULL;
+ v_U16_t capab_info;
+ eCsrAuthType RSNAuthType;
+ eCsrEncryptionType RSNEncryptType;
+ eCsrEncryptionType mcRSNEncryptType;
+ int status = VOS_STATUS_SUCCESS;
+ tpWLAN_SAPEventCB pSapEventCallback;
+ hdd_hostapd_state_t *pHostapdState;
+ v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+ struct qc_mac_acl_entry *acl_entry = NULL;
+ v_SINT_t i;
+
+ ENTER();
+
+ pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
+
+ pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
+
+ pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
+
+ pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
+
+ pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
+
+ //channel is already set in the set_channel Call back
+ //pConfig->channel = pCommitConfig->channel;
+
+ /*Protection parameter to enable or disable*/
+ pConfig->protEnabled =
+ (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
+
+ pConfig->dtim_period = pBeacon->dtim_period;
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
+ pConfig->dtim_period);
+
+
+ pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
+ WLAN_EID_COUNTRY);
+ if(pIe)
+ {
+ tANI_BOOLEAN restartNeeded;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
+
+ pConfig->ieee80211d = 1;
+ vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
+ sme_setRegInfo(hHal, pConfig->countryCode);
+ sme_ResetCountryCodeInformation(hHal, &restartNeeded);
+ /*
+ * If auto channel is configured i.e. channel is 0,
+ * so skip channel validation.
+ */
+ if( AUTO_CHANNEL_SELECT != pConfig->channel )
+ {
+ if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
+ return -EINVAL;
+ }
+ }
+ }
+ else
+ {
+ pConfig->ieee80211d = 0;
+ }
+ pConfig->authType = eSAP_AUTO_SWITCH;
+
+ capab_info = pMgmt_frame->u.beacon.capab_info;
+
+ pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
+ WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
+
+ (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
+
+ /*Set wps station to configured*/
+ pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
+
+ if(pIe)
+ {
+ if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
+ {
+ hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
+ return -EINVAL;
+ }
+ else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
+ {
+ hddLog( VOS_TRACE_LEVEL_ERROR, "** WPS IE(len %d) ***\n", (pIe[1]+2));
+ /* Check 15 bit of WPS IE as it contain information for wps state
+ * WPS state
+ */
+ if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
+ {
+ pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
+ } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
+ {
+ pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
+ }
+ }
+ }
+ else
+ {
+ pConfig->wps_state = SAP_WPS_DISABLED;
+ }
+ pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
+
+ pConfig->RSNWPAReqIELength = 0;
+ pConfig->pRSNWPAReqIE = NULL;
+ pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
+ WLAN_EID_RSN);
+ if(pIe && pIe[1])
+ {
+ pConfig->RSNWPAReqIELength = pIe[1] + 2;
+ memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
+ pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
+ /* The actual processing may eventually be more extensive than
+ * this. Right now, just consume any PMKIDs that are sent in
+ * by the app.
+ * */
+ status = hdd_softap_unpackIE(
+ vos_get_context( VOS_MODULE_ID_SME, pVosContext),
+ &RSNEncryptType,
+ &mcRSNEncryptType,
+ &RSNAuthType,
+ pConfig->pRSNWPAReqIE[1]+2,
+ pConfig->pRSNWPAReqIE );
+
+ if( VOS_STATUS_SUCCESS == status )
+ {
+ /* Now copy over all the security attributes you have
+ * parsed out
+ * */
+ pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
+ pConfig->mcRSNEncryptType = mcRSNEncryptType;
+ (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
+ = RSNEncryptType;
+ hddLog( LOG1, FL("%s: CSR AuthType = %d, "
+ "EncryptionType = %d mcEncryptionType = %d\n"),
+ RSNAuthType, RSNEncryptType, mcRSNEncryptType);
+ }
+ }
+
+ pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
+ pBeacon->tail, pBeacon->tail_len);
+
+ if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
+ {
+ if (pConfig->pRSNWPAReqIE)
+ {
+ /*Mixed mode WPA/WPA2*/
+ memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
+ pConfig->RSNWPAReqIELength += pIe[1] + 2;
+ }
+ else
+ {
+ pConfig->RSNWPAReqIELength = pIe[1] + 2;
+ memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
+ pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
+ status = hdd_softap_unpackIE(
+ vos_get_context( VOS_MODULE_ID_SME, pVosContext),
+ &RSNEncryptType,
+ &mcRSNEncryptType,
+ &RSNAuthType,
+ pConfig->pRSNWPAReqIE[1]+2,
+ pConfig->pRSNWPAReqIE );
+
+ if( VOS_STATUS_SUCCESS == status )
+ {
+ /* Now copy over all the security attributes you have
+ * parsed out
+ * */
+ pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
+ pConfig->mcRSNEncryptType = mcRSNEncryptType;
+ (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
+ = RSNEncryptType;
+ hddLog( LOG1, FL("%s: CSR AuthType = %d, "
+ "EncryptionType = %d mcEncryptionType = %d\n"),
+ RSNAuthType, RSNEncryptType, mcRSNEncryptType);
+ }
+ }
+ }
+
+ pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
+
+ if (params->ssid != NULL)
+ {
+ memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
+ pConfig->SSIDinfo.ssid.length = params->ssid_len;
+ if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
+ pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
+ }
+ vos_mem_copy(pConfig->self_macaddr.bytes,
+ pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
+
+ /* default value */
+ pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
+ pConfig->num_accept_mac = 0;
+ pConfig->num_deny_mac = 0;
+
+ pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
+ pBeacon->tail, pBeacon->tail_len);
+
+ /* pIe for black list is following form:
+ type : 1 byte
+ length : 1 byte
+ OUI : 4 bytes
+ acl type : 1 byte
+ no of mac addr in black list: 1 byte
+ list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
+ */
+ if ((pIe != NULL) && (pIe[1] != 0))
+ {
+ pConfig->SapMacaddr_acl = pIe[6];
+ pConfig->num_deny_mac = pIe[7];
+ hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
+ pIe[6], pIe[7]);
+ if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
+ pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
+ acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
+ for (i = 0; i < pConfig->num_deny_mac; i++)
+ {
+ vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
+ acl_entry++;
+ }
+ }
+ pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
+ pBeacon->tail, pBeacon->tail_len);
+
+ /* pIe for white list is following form:
+ type : 1 byte
+ length : 1 byte
+ OUI : 4 bytes
+ acl type : 1 byte
+ no of mac addr in white list: 1 byte
+ list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
+ */
+ if ((pIe != NULL) && (pIe[1] != 0))
+ {
+ pConfig->SapMacaddr_acl = pIe[6];
+ pConfig->num_accept_mac = pIe[7];
+ hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
+ pIe[6], pIe[7]);
+ if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
+ pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
+ acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
+ for (i = 0; i < pConfig->num_accept_mac; i++)
+ {
+ vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
+ acl_entry++;
+ }
+ }
+ wlan_hdd_set_sapHwmode(pHostapdAdapter);
+
+ // ht_capab is not what the name conveys,this is used for protection bitmap
+ pConfig->ht_capab =
+ (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
+
+ if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
+ {
+ hddLog(LOGE, FL("SAP Not able to set AP IEs"));
+ return -EINVAL;
+ }
+
+ //Uapsd Enabled Bit
+ pConfig->UapsdEnable =
+ (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
+ //Enable OBSS protection
+ pConfig->obssProtEnabled =
+ (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
+
+ hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
+ MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
+ hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
+ hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
+ (int)pConfig->channel);
+ hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
+ hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
+ pConfig->authType);
+ hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
+ hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
+ hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
+ pConfig->protEnabled, pConfig->obssProtEnabled);
+
+ if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
+ {
+ //Bss already started. just return.
+ //TODO Probably it should update some beacon params.
+ hddLog( LOGE, "Bss Already started...Ignore the request");
+ EXIT();
+ return 0;
+ }
+
+ pConfig->persona = pHostapdAdapter->device_mode;
+
+ pSapEventCallback = hdd_hostapd_SAPEventCB;
+ if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
+ (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
+ {
+ hddLog(LOGE,FL("SAP Start Bss fail\n"));
+ return -EINVAL;
+ }
+
+ hddLog(LOGE,
+ FL("Waiting for Scan to complete(auto mode) and BSS to start"));
+
+ status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
+
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ ("ERROR: HDD vos wait for single_event failed!!\n"));
+ VOS_ASSERT(0);
+ }
+
+ //Succesfully started Bss update the state bit.
+ set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
+
+ pHostapdState->bCommit = TRUE;
+ EXIT();
+
+ return 0;
+}
+
+static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct beacon_parameters *params)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ int status=VOS_STATUS_SUCCESS;
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
+
+ if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
+#endif
+ )
+ {
+ beacon_data_t *old,*new;
+
+ old = pAdapter->sessionCtx.ap.beacon;
+
+ if (old)
+ return -EALREADY;
+
+ status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s:Error!!! Allocating the new beacon\n",__func__);
+ return -EINVAL;
+ }
+
+ pAdapter->sessionCtx.ap.beacon = new;
+
+ status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
+ }
+
+ EXIT();
+ return status;
+}
+
+static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct beacon_parameters *params)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ int status=VOS_STATUS_SUCCESS;
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
+ __func__,pAdapter->device_mode);
+
+ if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
+#endif
+ )
+ {
+ beacon_data_t *old,*new;
+
+ old = pAdapter->sessionCtx.ap.beacon;
+
+ if (!old)
+ return -ENOENT;
+
+ status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
+
+ if(status != VOS_STATUS_SUCCESS) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Error!!! Allocating the new beacon\n",__func__);
+ return -EINVAL;
+ }
+
+ pAdapter->sessionCtx.ap.beacon = new;
+
+ status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
+ }
+
+ EXIT();
+ return status;
+}
+
+static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
+ struct net_device *dev)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx;
+ VOS_STATUS status = 0;
+
+ ENTER();
+
+ if (NULL == pAdapter)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD adapter context is Null", __FUNCTION__);
+ return -ENODEV;
+ }
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return -EAGAIN;
+ }
+
+ pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
+ __func__,pAdapter->device_mode);
+
+ if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
+#endif
+ )
+ {
+ beacon_data_t *old;
+
+ old = pAdapter->sessionCtx.ap.beacon;
+
+ if (!old)
+ return -ENOENT;
+
+#ifdef CONFIG_CFG80211
+ hdd_cleanup_actionframe(pHddCtx, pAdapter);
+#endif
+
+ mutex_lock(&pHddCtx->sap_lock);
+ if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
+ {
+ if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
+ {
+ hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
+
+ status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
+
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ ("ERROR: HDD vos wait for single_event failed!!\n"));
+ VOS_ASSERT(0);
+ }
+ }
+ clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
+ }
+ mutex_unlock(&pHddCtx->sap_lock);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s:Error!!! Stopping the BSS\n",__func__);
+ return -EINVAL;
+ }
+
+ if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
+ ==eHAL_STATUS_FAILURE)
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
+ }
+
+ if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
+ WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
+ eANI_BOOLEAN_FALSE) )
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
+ }
+
+ // Reset WNI_CFG_PROBE_RSP Flags
+ wlan_hdd_reset_prob_rspies(pAdapter);
+
+ pAdapter->sessionCtx.ap.beacon = NULL;
+ kfree(old);
+ }
+ EXIT();
+ return status;
+}
+#endif //LINUX_VERSION_CODE
+
+static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
+ struct net_device *dev,
+ struct bss_parameters *params)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
+ __func__,pAdapter->device_mode);
+
+ if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
+#endif
+ )
+ {
+ /* ap_isolate == -1 means that in change bss, upper layer doesn't
+ * want to update this parameter */
+ if (-1 != params->ap_isolate)
+ {
+ pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
+ }
+ }
+
+ EXIT();
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_change_iface
+ * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
+ */
+int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
+ struct net_device *ndev,
+ enum nl80211_iftype type,
+ u32 *flags,
+ struct vif_params *params
+ )
+{
+ struct wireless_dev *wdev;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ tCsrRoamProfile *pRoamProfile = NULL;
+ eCsrRoamBssType LastBSSType;
+ hdd_config_t *pConfig = pHddCtx->cfg_ini;
+ eMib_dot11DesiredBssType connectedBssType;
+ VOS_STATUS status;
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return -EAGAIN;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
+ __func__, pAdapter->device_mode);
+
+ wdev = ndev->ieee80211_ptr;
+
+#ifdef WLAN_BTAMP_FEATURE
+ if((NL80211_IFTYPE_P2P_CLIENT == type)||
+ (NL80211_IFTYPE_ADHOC == type)||
+ (NL80211_IFTYPE_AP == type)||
+ (NL80211_IFTYPE_P2P_GO == type))
+ {
+ pHddCtx->isAmpAllowed = VOS_FALSE;
+ // stop AMP traffic
+ status = WLANBAP_StopAmp();
+ if(VOS_STATUS_SUCCESS != status )
+ {
+ pHddCtx->isAmpAllowed = VOS_TRUE;
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to stop AMP", __func__);
+ return -EINVAL;
+ }
+ }
+#endif //WLAN_BTAMP_FEATURE
+ /* Reset the current device mode bit mask*/
+ wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
+
+ if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
+#endif
+ )
+ {
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ pRoamProfile = &pWextState->roamProfile;
+ LastBSSType = pRoamProfile->BSSType;
+
+ switch (type)
+ {
+ case NL80211_IFTYPE_STATION:
+#ifdef WLAN_FEATURE_P2P
+ case NL80211_IFTYPE_P2P_CLIENT:
+#endif
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: setting interface Type to INFRASTRUCTURE", __func__);
+ pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
+ pRoamProfile->phyMode =
+ hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
+ wdev->iftype = type;
+#ifdef WLAN_FEATURE_P2P
+ pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
+ WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
+#endif
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: setting interface Type to ADHOC", __func__);
+ pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
+ pRoamProfile->phyMode =
+ hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
+ wdev->iftype = type;
+ break;
+
+ case NL80211_IFTYPE_AP:
+#ifdef WLAN_FEATURE_P2P
+ case NL80211_IFTYPE_P2P_GO:
+#endif
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: setting interface Type to %s", __func__,
+ (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
+
+ //De-init the adapter.
+ hdd_stop_adapter( pHddCtx, pAdapter );
+ hdd_deinit_adapter( pHddCtx, pAdapter );
+ memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
+#ifdef WLAN_SOFTAP_FEATURE
+#ifdef WLAN_FEATURE_P2P
+ pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
+ WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
+#else
+ pAdapter->device_mode = WLAN_HDD_SOFTAP;
+#endif
+ hdd_set_ap_ops( pAdapter->dev );
+
+ status = hdd_init_ap_mode(pAdapter);
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Error initializing the ap mode", __func__);
+ return -EINVAL;
+ }
+ hdd_set_conparam(1);
+
+#endif
+ /*interface type changed update in wiphy structure*/
+ if(wdev)
+ {
+ wdev->iftype = type;
+ pHddCtx->change_iface = type;
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: ERROR !!!! Wireless dev is NULL", __func__);
+ return -EINVAL;
+ }
+ goto done;
+ }
+
+ default:
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
+ __func__);
+ return -EOPNOTSUPP;
+ }
+ }
+ else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
+#endif
+ )
+ {
+ switch(type)
+ {
+ case NL80211_IFTYPE_STATION:
+#ifdef WLAN_FEATURE_P2P
+ case NL80211_IFTYPE_P2P_CLIENT:
+#endif
+ case NL80211_IFTYPE_ADHOC:
+ wdev->iftype = type;
+#ifdef WLAN_FEATURE_P2P
+ pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
+ WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
+#endif
+ hdd_set_conparam(0);
+ pHddCtx->change_iface = type;
+ hdd_stop_adapter( pHddCtx, pAdapter );
+ hdd_deinit_adapter( pHddCtx, pAdapter );
+ memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
+ hdd_set_station_ops( pAdapter->dev );
+ status = hdd_init_station_mode( pAdapter );
+ if( VOS_STATUS_SUCCESS != status )
+ return -EOPNOTSUPP;
+ goto done;
+ case NL80211_IFTYPE_AP:
+#ifdef WLAN_FEATURE_P2P
+ case NL80211_IFTYPE_P2P_GO:
+#endif
+ wdev->iftype = type;
+#ifdef WLAN_FEATURE_P2P
+ pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
+ WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
+#endif
+ goto done;
+ default:
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
+ __func__);
+ return -EOPNOTSUPP;
+
+ }
+
+ }
+ else
+ {
+ return -EOPNOTSUPP;
+ }
+
+
+ if(pRoamProfile)
+ {
+ if ( LastBSSType != pRoamProfile->BSSType )
+ {
+ /*interface type changed update in wiphy structure*/
+ wdev->iftype = type;
+
+ /*the BSS mode changed, We need to issue disconnect
+ if connected or in IBSS disconnect state*/
+ if ( hdd_connGetConnectedBssType(
+ WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
+ ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
+ {
+ /*need to issue a disconnect to CSR.*/
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+ if( eHAL_STATUS_SUCCESS ==
+ sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
+ {
+ wait_for_completion_interruptible_timeout(
+ &pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+ }
+ }
+ }
+ }
+
+done:
+ /*set bitmask based on updated value*/
+ wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
+#ifdef WLAN_BTAMP_FEATURE
+ if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
+ (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
+ {
+ //we are ok to do AMP
+ pHddCtx->isAmpAllowed = VOS_TRUE;
+ }
+#endif //WLAN_BTAMP_FEATURE
+ EXIT();
+ return 0;
+}
+
+static int wlan_hdd_change_station(struct wiphy *wiphy,
+ struct net_device *dev,
+ u8 *mac,
+ struct station_parameters *params)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
+ v_MACADDR_t STAMacAddress;
+
+ vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
+
+ if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
+#ifdef WLAN_FEATURE_P2P
+ || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
+#endif
+ )
+ {
+ if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
+ {
+ status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
+ WLANTL_STA_AUTHENTICATED);
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Station MAC address does not matching", __FUNCTION__);
+ return -EINVAL;
+ }
+ }
+
+ return status;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
+ * This function is used to get peer station index in IBSS mode
+ */
+static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
+{
+ u8 idx = 0;
+ u8 temp[VOS_MAC_ADDR_SIZE] = {0};
+ ENTER();
+ memset(temp, 0, VOS_MAC_ADDR_SIZE);
+ for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
+ {
+ if ( (0 !=
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
+ && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
+ temp, VOS_MAC_ADDR_SIZE)
+ )
+ {
+ return idx;
+ }
+ }
+ return idx;
+}
+
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_add_key
+ * This function is used to initialize the key information
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index, bool pairwise,
+ const u8 *mac_addr,
+ struct key_params *params
+ )
+#else
+static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index, const u8 *mac_addr,
+ struct key_params *params
+ )
+#endif
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
+ tCsrRoamSetKey setKey;
+ u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+ int status = 0;
+ v_U32_t roamId= 0xFF;
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
+ hdd_hostapd_state_t *pHostapdState;
+ VOS_STATUS vos_status;
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
+ __func__,pAdapter->device_mode);
+
+ if (CSR_MAX_NUM_KEY <= key_index)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
+ key_index);
+
+ return -EINVAL;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: called with key index = %d & key length %d",
+ __func__, key_index, params->key_len);
+
+ /*extract key idx, key len and key*/
+ vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
+ setKey.keyId = key_index;
+ setKey.keyLength = params->key_len;
+ vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
+
+ switch (params->cipher)
+ {
+ case WLAN_CIPHER_SUITE_WEP40:
+ setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ break;
+
+ case WLAN_CIPHER_SUITE_WEP104:
+ setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
+ break;
+
+ case WLAN_CIPHER_SUITE_TKIP:
+ {
+ u8 *pKey = &setKey.Key[0];
+ setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
+
+ vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
+
+ /*Supplicant sends the 32bytes key in this order
+
+ |--------------|----------|----------|
+ | Tk1 |TX-MIC | RX Mic |
+ |--------------|----------|----------|
+ <---16bytes---><--8bytes--><--8bytes-->
+
+ */
+ /*Sme expects the 32 bytes key to be in the below order
+
+ |--------------|----------|----------|
+ | Tk1 |RX-MIC | TX Mic |
+ |--------------|----------|----------|
+ <---16bytes---><--8bytes--><--8bytes-->
+ */
+ /* Copy the Temporal Key 1 (TK1) */
+ vos_mem_copy(pKey, params->key,16);
+
+ /*Copy the rx mic first*/
+ vos_mem_copy(&pKey[16],¶ms->key[24],8);
+
+ /*Copy the tx mic */
+ vos_mem_copy(&pKey[24],¶ms->key[16],8);
+
+
+ break;
+ }
+
+ case WLAN_CIPHER_SUITE_CCMP:
+ setKey.encType = eCSR_ENCRYPT_TYPE_AES;
+ break;
+
+#ifdef FEATURE_WLAN_WAPI
+ case WLAN_CIPHER_SUITE_SMS4:
+ {
+ vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
+ wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
+ params->key, params->key_len);
+ return 0;
+ }
+#endif
+#ifdef FEATURE_WLAN_CCX
+ case WLAN_CIPHER_SUITE_KRK:
+ setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
+ break;
+#endif
+ default:
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
+ __func__, params->cipher);
+ return -EOPNOTSUPP;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
+ __func__, setKey.encType);
+
+
+
+ if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
+#endif
+ )
+ {
+
+
+ if (
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ (!pairwise)
+#else
+ (!mac_addr || is_broadcast_ether_addr(mac_addr))
+#endif
+ )
+ {
+ /* set group key*/
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s- %d: setting Broacast key",
+ __func__, __LINE__);
+ setKey.keyDirection = eSIR_RX_ONLY;
+ vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
+ }
+ else
+ {
+ /* set pairwise key*/
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s- %d: setting pairwise key",
+ __func__, __LINE__);
+ setKey.keyDirection = eSIR_TX_RX;
+ vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
+ }
+
+ pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
+ if( pHostapdState->bssState == BSS_START )
+ {
+ status = WLANSAP_SetKeySta( pVosContext, &setKey);
+
+ if ( status != eHAL_STATUS_SUCCESS )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
+ __LINE__, status );
+ }
+ }
+
+ /* Saving WEP keys */
+ else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
+ eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
+ {
+ //Save the wep key in ap context. Issue setkey after the BSS is started.
+ hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
+ vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
+ }
+ else
+ {
+ //Save the key in ap context. Issue setkey after the BSS is started.
+ hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
+ vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
+ }
+ }
+ else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
+#endif
+ )
+ {
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
+
+ vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
+ params->key, params->key_len);
+
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
+
+ if (!( ( IW_AUTH_KEY_MGMT_802_1X
+ == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
+ && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
+ )
+ &&
+ ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
+ || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
+ )
+ )
+ {
+ /* in case of static WEP, macaddr/bssid is not coming from nl80211
+ * interface, copy bssid for pairwise key and group macaddr for
+ * group key initialization*/
+
+ tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
+
+ pWextState->roamProfile.negotiatedUCEncryptionType =
+ pHddStaCtx->conn_info.ucEncryptionType =
+ ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
+ eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
+ eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
+
+
+ hddLog(VOS_TRACE_LEVEL_INFO_MED,
+ "%s: Negotiated encryption type %d", __func__,
+ pWextState->roamProfile.negotiatedUCEncryptionType);
+
+ sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
+ &pWextState->roamProfile, true);
+ setKey.keyLength = 0;
+ setKey.keyDirection = eSIR_TX_RX;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ if (pairwise)
+ {
+#endif
+ if (mac_addr)
+ {
+ vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
+ }
+ else
+ {
+ /* macaddr is NULL, set the peerMac to bssId in case of BSS,
+ * and peerMacAddress in case of IBSS*/
+ if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
+ {
+ u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
+ if (HDD_MAX_NUM_IBSS_STA != staidx)
+ {
+ vos_mem_copy(setKey.peerMac,
+ &pHddStaCtx->conn_info.peerMacAddress[staidx],
+ WNI_CFG_BSSID_LEN);
+
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
+ __func__);
+ return -EOPNOTSUPP;
+ }
+ }
+ else
+ {
+ vos_mem_copy(setKey.peerMac,
+ &pHddStaCtx->conn_info.bssId[0],
+ WNI_CFG_BSSID_LEN);
+ }
+ }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ }
+ else
+ {
+ /* set group key*/
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s- %d: setting Group key",
+ __func__, __LINE__);
+ setKey.keyDirection = eSIR_RX_ONLY;
+ vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
+ }
+#endif
+ }
+ else if (
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ (!pairwise)
+#else
+ (!mac_addr || is_broadcast_ether_addr(mac_addr))
+#endif
+ )
+ {
+ /* set group key*/
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s- %d: setting Group key",
+ __func__, __LINE__);
+ setKey.keyDirection = eSIR_RX_ONLY;
+ vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
+ }
+ else
+ {
+ /* set pairwise key*/
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s- %d: setting pairwise key",
+ __func__, __LINE__);
+ setKey.keyDirection = eSIR_TX_RX;
+ vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO_MED,
+ "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
+ __func__, setKey.peerMac[0], setKey.peerMac[1],
+ setKey.peerMac[2], setKey.peerMac[3],
+ setKey.peerMac[4], setKey.peerMac[5],
+ setKey.keyDirection);
+
+ vos_status = wlan_hdd_check_ula_done(pAdapter);
+
+ if ( vos_status != VOS_STATUS_SUCCESS )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
+ __LINE__, vos_status );
+
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+
+ return -EINVAL;
+
+ }
+
+
+ /* issue set key request to SME*/
+ status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, &setKey, &roamId );
+
+ if ( 0 != status )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_RoamSetKey failed, returned %d", __func__, status);
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+ return -EINVAL;
+ }
+
+
+ /* in case of IBSS as there was no information available about WEP keys during
+ * IBSS join, group key intialized with NULL key, so re-initialize group key
+ * with correct value*/
+ if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
+ !( ( IW_AUTH_KEY_MGMT_802_1X
+ == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
+ && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
+ )
+ &&
+ ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
+ || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
+ )
+ )
+ {
+ setKey.keyDirection = eSIR_RX_ONLY;
+ vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
+
+ hddLog(VOS_TRACE_LEVEL_INFO_MED,
+ "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
+ __func__, setKey.peerMac[0], setKey.peerMac[1],
+ setKey.peerMac[2], setKey.peerMac[3],
+ setKey.peerMac[4], setKey.peerMac[5],
+ setKey.keyDirection);
+
+ status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, &setKey, &roamId );
+
+ if ( 0 != status )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
+ __func__, status);
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_get_key
+ * This function is used to get the key information
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+static int wlan_hdd_cfg80211_get_key(
+ struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index, bool pairwise,
+ const u8 *mac_addr, void *cookie,
+ void (*callback)(void *cookie, struct key_params*)
+ )
+#else
+static int wlan_hdd_cfg80211_get_key(
+ struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index, const u8 *mac_addr, void *cookie,
+ void (*callback)(void *cookie, struct key_params*)
+ )
+#endif
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
+ hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
+ struct key_params params;
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
+ __func__,pAdapter->device_mode);
+
+ memset(¶ms, 0, sizeof(params));
+
+ if (CSR_MAX_NUM_KEY <= key_index)
+ {
+ return -EINVAL;
+ }
+
+ switch(pRoamProfile->EncryptionType.encryptionType[0])
+ {
+ case eCSR_ENCRYPT_TYPE_NONE:
+ params.cipher = IW_AUTH_CIPHER_NONE;
+ break;
+
+ case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
+ case eCSR_ENCRYPT_TYPE_WEP40:
+ params.cipher = WLAN_CIPHER_SUITE_WEP40;
+ break;
+
+ case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
+ case eCSR_ENCRYPT_TYPE_WEP104:
+ params.cipher = WLAN_CIPHER_SUITE_WEP104;
+ break;
+
+ case eCSR_ENCRYPT_TYPE_TKIP:
+ params.cipher = WLAN_CIPHER_SUITE_TKIP;
+ break;
+
+ case eCSR_ENCRYPT_TYPE_AES:
+ params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+ break;
+
+ default:
+ params.cipher = IW_AUTH_CIPHER_NONE;
+ break;
+ }
+
+ params.key_len = pRoamProfile->Keys.KeyLength[key_index];
+ params.seq_len = 0;
+ params.seq = NULL;
+ params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
+ callback(cookie, ¶ms);
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_del_key
+ * This function is used to delete the key information
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index,
+ bool pairwise,
+ const u8 *mac_addr
+ )
+#else
+static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index,
+ const u8 *mac_addr
+ )
+#endif
+{
+ int status = 0;
+
+ //This code needs to be revisited. There is sme_removeKey API, we should
+ //plan to use that. After the change to use correct index in setkey,
+ //it is observed that this is invalidating peer
+ //key index whenever re-key is done. This is affecting data link.
+ //It should be ok to ignore del_key.
+#if 0
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
+ u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+ tCsrRoamSetKey setKey;
+ v_U32_t roamId= 0xFF;
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
+ __func__,pAdapter->device_mode);
+
+ if (CSR_MAX_NUM_KEY <= key_index)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
+ key_index);
+
+ return -EINVAL;
+ }
+
+ vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
+ setKey.keyId = key_index;
+
+ if (mac_addr)
+ vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
+ else
+ vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
+
+ setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
+
+ if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
+#endif
+ )
+ {
+
+ hdd_hostapd_state_t *pHostapdState =
+ WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
+ if( pHostapdState->bssState == BSS_START)
+ {
+ status = WLANSAP_SetKeySta( pVosContext, &setKey);
+
+ if ( status != eHAL_STATUS_SUCCESS )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
+ __LINE__, status );
+ }
+ }
+ }
+ else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
+#endif
+ )
+ {
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
+
+ hddLog(VOS_TRACE_LEVEL_INFO_MED,
+ "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
+ __func__, setKey.peerMac[0], setKey.peerMac[1],
+ setKey.peerMac[2], setKey.peerMac[3],
+ setKey.peerMac[4], setKey.peerMac[5]);
+ if(pAdapter->sessionCtx.station.conn_info.connState ==
+ eConnectionState_Associated)
+ {
+ status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, &setKey, &roamId );
+
+ if ( 0 != status )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_RoamSetKey failure, returned %d",
+ __func__, status);
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+ return -EINVAL;
+ }
+ }
+ }
+#endif
+ return status;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_set_default_key
+ * This function is used to set the default tx key index
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index,
+ bool unicast, bool multicast)
+#else
+static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index)
+#endif
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ int status = 0;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
+ __func__,pAdapter->device_mode, key_index);
+
+ if (CSR_MAX_NUM_KEY <= key_index)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
+ key_index);
+
+ return -EINVAL;
+ }
+
+
+ if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
+#endif
+ )
+ {
+ if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
+ (eCSR_ENCRYPT_TYPE_TKIP !=
+ pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
+ (eCSR_ENCRYPT_TYPE_AES !=
+ pWextState->roamProfile.EncryptionType.encryptionType[0])
+ )
+ {
+ /* if default key index is not same as previous one,
+ * then update the default key index */
+
+ tCsrRoamSetKey setKey;
+ v_U32_t roamId= 0xFF;
+ tCsrKeys *Keys = &pWextState->roamProfile.Keys;
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
+ __func__, key_index);
+
+ Keys->defaultIndex = (u8)key_index;
+ vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
+ setKey.keyId = key_index;
+ setKey.keyLength = Keys->KeyLength[key_index];
+
+ vos_mem_copy(&setKey.Key[0],
+ &Keys->KeyMaterial[key_index][0],
+ Keys->KeyLength[key_index]);
+
+ setKey.keyDirection = eSIR_TX_ONLY;
+
+ vos_mem_copy(setKey.peerMac,
+ &pHddStaCtx->conn_info.bssId[0],
+ WNI_CFG_BSSID_LEN);
+
+ setKey.encType =
+ pWextState->roamProfile.EncryptionType.encryptionType[0];
+
+ /* issue set key request */
+ status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, &setKey, &roamId );
+
+ if ( 0 != status )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_RoamSetKey failed, returned %d", __func__,
+ status);
+ return -EINVAL;
+ }
+ }
+ }
+
+ /* In SoftAp mode setting key direction for default mode */
+ else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
+ {
+ if ( (eCSR_ENCRYPT_TYPE_TKIP !=
+ pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
+ (eCSR_ENCRYPT_TYPE_AES !=
+ pWextState->roamProfile.EncryptionType.encryptionType[0])
+ )
+ {
+ /* Saving key direction for default key index to TX default */
+ hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
+ pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * FUNCTION: wlan_hdd_cfg80211_set_channel
+ * This function is used to set the channel number
+ */
+int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type
+ )
+{
+ v_U32_t num_ch = 0;
+ u32 channel = 0;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
+ int freq = chan->center_freq; /* freq is in MHZ */
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: device_mode = %d freq = %d \n",__func__,
+ pAdapter->device_mode, chan->center_freq);
+
+ /*
+ * Do freq to chan conversion
+ * TODO: for 11a
+ */
+
+ channel = ieee80211_frequency_to_channel(freq);
+
+ /* Check freq range */
+ if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
+ (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Channel [%d] is outside valid range from %d to %d\n",
+ __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
+ WNI_CFG_CURRENT_CHANNEL_STAMAX);
+ return -EINVAL;
+ }
+
+ num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+
+ if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
+#ifdef WLAN_FEATURE_P2P
+ && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
+#endif
+ )
+ {
+ if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid Channel [%d] \n", __func__, channel);
+ return -EINVAL;
+ }
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: set channel to [%d] for device mode =%d",
+ __func__, channel,pAdapter->device_mode);
+ }
+ if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
+#endif
+ )
+ {
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
+ {
+ /* Link is up then return cant set channel*/
+ hddLog( VOS_TRACE_LEVEL_ERROR,
+ "%s: IBSS Associated, can't set the channel\n", __func__);
+ return -EINVAL;
+ }
+
+ num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
+ pHddStaCtx->conn_info.operationChannel = channel;
+ pRoamProfile->ChannelInfo.ChannelList =
+ &pHddStaCtx->conn_info.operationChannel;
+ }
+ else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
+#ifdef WLAN_FEATURE_P2P
+ || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
+#endif
+ )
+ {
+ (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
+
+ if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
+ {
+ hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
+
+ /* If auto channel selection is configured as enable/ 1 then ignore
+ channel set by supplicant
+ */
+ if ( cfg_param->apAutoChannelSelection )
+ {
+ (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: set channel to auto channel (0) for device mode =%d",
+ __func__, pAdapter->device_mode);
+ }
+ }
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Invalid device mode failed to set valid channel", __func__);
+ return -EINVAL;
+ }
+ EXIT();
+ return 0;
+}
+
+
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_inform_bss
+ * This function is used to inform the BSS details to nl80211 interface.
+ */
+static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
+ hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
+{
+ struct net_device *dev = pAdapter->dev;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
+ int chan_no;
+ int ie_length;
+ const char *ie;
+ unsigned int freq;
+ struct ieee80211_channel *chan;
+ int rssi = 0;
+ struct cfg80211_bss *bss = NULL;
+
+ ENTER();
+
+ if( NULL == pBssDesc )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
+ return bss;
+ }
+
+ chan_no = pBssDesc->channelId;
+ ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
+ ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
+
+ if( NULL == ie )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
+ return bss;
+ }
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
+ if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
+ {
+ freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
+ }
+ else
+ {
+ freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
+ }
+#else
+ freq = ieee80211_channel_to_frequency(chan_no);
+#endif
+
+ chan = __ieee80211_get_channel(wiphy, freq);
+
+ bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
+ &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
+ WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+ if (bss == NULL)
+ {
+ rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
+
+ return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
+ le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
+ pBssDesc->capabilityInfo,
+ pBssDesc->beaconInterval, ie, ie_length,
+ rssi, GFP_KERNEL ));
+}
+ else
+ {
+ return bss;
+ }
+}
+
+
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
+ * This function is used to inform the BSS details to nl80211 interface.
+ */
+struct cfg80211_bss*
+wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
+ tSirBssDescription *bss_desc
+ )
+{
+ /*
+ cfg80211_inform_bss() is not updating ie field of bss entry, if entry
+ already exists in bss data base of cfg80211 for that particular BSS ID.
+ Using cfg80211_inform_bss_frame to update the bss entry instead of
+ cfg80211_inform_bss, But this call expects mgmt packet as input. As of
+ now there is no possibility to get the mgmt(probe response) frame from PE,
+ converting bss_desc to ieee80211_mgmt(probe response) and passing to
+ cfg80211_inform_bss_frame.
+ */
+ struct net_device *dev = pAdapter->dev;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ int chan_no = bss_desc->channelId;
+ int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
+ const char *ie =
+ ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
+ unsigned int freq;
+ struct ieee80211_channel *chan;
+ struct ieee80211_mgmt *mgmt =
+ kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
+ struct cfg80211_bss *bss_status = NULL;
+ size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
+ int rssi = 0;
+
+ ENTER();
+
+ memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
+ memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
+ sizeof (bss_desc->timeStamp));
+ mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
+ mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
+ memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
+
+ mgmt->frame_control |=
+ (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
+ if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
+ (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
+ {
+ freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
+ }
+ else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
+ (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
+
+ {
+ freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
+ }
+ else
+ {
+ kfree(mgmt);
+ return NULL;
+ }
+#else
+ freq = ieee80211_channel_to_frequency(chan_no);
+#endif
+ chan = __ieee80211_get_channel(wiphy, freq);
+
+ /*To keep the rssi icon of the connected AP in the scan window
+ *and the rssi icon of the wireless networks in sync
+ * */
+ if (( eConnectionState_Associated ==
+ pAdapter->sessionCtx.station.conn_info.connState ) &&
+ ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
+ pAdapter->sessionCtx.station.conn_info.bssId,
+ WNI_CFG_BSSID_LEN)))
+ {
+ /* supplicant takes the signal strength in terms of mBm(100*dBm) */
+ rssi = (pAdapter->rssi * 100);
+ }
+ else
+ {
+ rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
+ }
+
+ bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
+ frame_len, rssi, GFP_KERNEL);
+ kfree(mgmt);
+ return bss_status;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_update_bss_db
+ * This function is used to update the BSS data base of CFG8011
+ */
+struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
+ tCsrRoamInfo *pRoamInfo
+ )
+{
+ tCsrRoamConnectedProfile roamProfile;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ struct cfg80211_bss *bss = NULL;
+
+ ENTER();
+
+ memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
+ sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
+
+ if (NULL != roamProfile.pBssDesc)
+ {
+ bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
+ &roamProfile);
+
+ if (NULL == bss)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
+ __func__);
+ }
+
+ sme_RoamFreeConnectProfile(hHal, &roamProfile);
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
+ __func__);
+ }
+ return bss;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_update_bss
+ */
+static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
+ hdd_adapter_t *pAdapter
+ )
+{
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ tCsrScanResultInfo *pScanResult;
+ eHalStatus status = 0;
+ tScanResultHandle pResult;
+ struct cfg80211_bss *bss_status = NULL;
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return -EAGAIN;
+ }
+
+ /*
+ * start getting scan results and populate cgf80211 BSS database
+ */
+ status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
+
+ /* no scan results */
+ if (NULL == pResult)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
+ return status;
+ }
+
+ pScanResult = sme_ScanResultGetFirst(hHal, pResult);
+
+ while (pScanResult)
+ {
+ /*
+ * cfg80211_inform_bss() is not updating ie field of bss entry, if
+ * entry already exists in bss data base of cfg80211 for that
+ * particular BSS ID. Using cfg80211_inform_bss_frame to update the
+ * bss entry instead of cfg80211_inform_bss, But this call expects
+ * mgmt packet as input. As of now there is no possibility to get
+ * the mgmt(probe response) frame from PE, converting bss_desc to
+ * ieee80211_mgmt(probe response) and passing to c
+ * fg80211_inform_bss_frame.
+ * */
+
+ bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
+ &pScanResult->BssDescriptor);
+
+
+ if (NULL == bss_status)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: NULL returned by cfg80211_inform_bss\n", __func__);
+ }
+ else
+ {
+ cfg80211_put_bss(bss_status);
+ }
+
+ pScanResult = sme_ScanResultGetNext(hHal, pResult);
+ }
+
+ sme_ScanResultPurge(hHal, pResult);
+
+ return 0;
+}
+
+/*
+ * FUNCTION: hdd_cfg80211_scan_done_callback
+ * scanning callback function, called after finishing scan
+ *
+ */
+static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
+ void *pContext, tANI_U32 scanId, eCsrScanStatus status)
+{
+ struct net_device *dev = (struct net_device *) pContext;
+ //struct wireless_dev *wdev = dev->ieee80211_ptr;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
+ hdd_scaninfo_t *pScanInfo = &pAdapter->scan_info;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ struct cfg80211_scan_request *req = NULL;
+ int ret = 0;
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s called with halHandle = %p, pContext = %p,"
+ "scanID = %d, returned status = %d\n",
+ __func__, halHandle, pContext, (int) scanId, (int) status);
+
+ //Block on scan req completion variable. Can't wait forever though.
+ ret = wait_for_completion_interruptible_timeout(
+ &pScanInfo->scan_req_completion_event,
+ msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
+ if (!ret)
+ {
+ VOS_ASSERT(pScanInfo->mScanPending);
+ return 0;
+ }
+
+ if(pScanInfo->mScanPending != VOS_TRUE)
+ {
+ VOS_ASSERT(pScanInfo->mScanPending);
+ return 0;
+ }
+
+ /* Check the scanId */
+ if (pScanInfo->scanId != scanId)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s called with mismatched scanId pScanInfo->scanId = %d "
+ "scanId = %d \n", __func__, (int) pScanInfo->scanId,
+ (int) scanId);
+ }
+
+ /* Scan is no longer pending */
+ pScanInfo->mScanPending = VOS_FALSE;
+
+ ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
+ pAdapter);
+
+ if (0 > ret)
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
+
+
+ /* If any client wait scan result through WEXT
+ * send scan done event to client */
+ if (pAdapter->scan_info.waitScanResult)
+ {
+ /* The other scan request waiting for current scan finish
+ * Send event to notify current scan finished */
+ if(WEXT_SCAN_PENDING_DELAY == pAdapter->scan_info.scan_pending_option)
+ {
+ vos_event_set(&pAdapter->scan_info.scan_finished_event);
+ }
+ /* Send notify to WEXT client */
+ else if(WEXT_SCAN_PENDING_PIGGYBACK == pAdapter->scan_info.scan_pending_option)
+ {
+ struct net_device *dev = pAdapter->dev;
+ union iwreq_data wrqu;
+ int we_event;
+ char *msg;
+
+ memset(&wrqu, '\0', sizeof(wrqu));
+ we_event = SIOCGIWSCAN;
+ msg = NULL;
+ wireless_send_event(dev, we_event, &wrqu, msg);
+ }
+ }
+ pAdapter->scan_info.waitScanResult = FALSE;
+
+ /* Get the Scan Req */
+ req = pAdapter->request;
+
+ if (!req)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
+ return 0;
+ }
+
+ /*
+ * setting up 0, just in case.
+ */
+ req->n_ssids = 0;
+ req->n_channels = 0;
+ req->ie = 0;
+
+ /*
+ * cfg80211_scan_done informing NL80211 about completion
+ * of scanning
+ */
+ cfg80211_scan_done(req, false);
+ complete(&pAdapter->abortscan_event_var);
+ pAdapter->request = NULL;
+
+#ifdef WLAN_FEATURE_P2P
+ /* Flush out scan result after p2p_serach is done */
+ if(pScanInfo->p2pSearch )
+ {
+ tANI_U8 sessionId = pAdapter->sessionId;
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
+ {
+ sessionId = pAdapter->p2pSessionId;
+ }
+ sme_ScanFlushResult(WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId);
+ pScanInfo->p2pSearch = 0;
+ }
+#endif
+
+ EXIT();
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_scan
+ * this scan respond to scan trigger and update cfg80211 scan database
+ * later, scan dump command can be used to recieve scan results
+ */
+int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_scan_request *request)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
+ tCsrScanRequest scanRequest;
+ tANI_U8 *channelList = NULL, i;
+ v_U32_t scanId = 0;
+ int status = 0;
+ hdd_scaninfo_t *pScanInfo = &pAdapter->scan_info;
+#ifdef WLAN_FEATURE_P2P
+ v_U8_t* pP2pIe = NULL;
+#endif
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
+ __func__,pAdapter->device_mode);
+#ifdef WLAN_BTAMP_FEATURE
+ //Scan not supported when AMP traffic is on.
+ if( VOS_TRUE == WLANBAP_AmpSessionOn() )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: No scanning when AMP is on", __func__);
+ return -EOPNOTSUPP;
+ }
+#endif
+ //Scan on any other interface is not supported.
+ if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Not scanning on device_mode = %d",
+ __func__, pAdapter->device_mode);
+ return -EOPNOTSUPP;
+ }
+
+ if (TRUE == pScanInfo->mScanPending)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
+ return -EBUSY;
+ }
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s:LOGP in Progress. Ignore!!!", __func__);
+ return -EAGAIN;
+ }
+
+ if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
+ "%s: Aquire lock fail", __func__);
+ return -EAGAIN;
+ }
+ if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
+ {
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ "%s: MAX TM Level Scan not allowed", __func__);
+ mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
+ return -EBUSY;
+ }
+ mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
+
+ vos_mem_zero( &scanRequest, sizeof(scanRequest));
+
+ if (NULL != request)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
+ (int)request->n_ssids);
+
+ /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
+ * Becasue of this, driver is assuming that this is not wildcard scan and so
+ * is not aging out the scan results.
+ */
+ if ('\0' == request->ssids->ssid[0])
+ {
+ request->n_ssids = 0;
+ }
+
+ if (0 < request->n_ssids)
+ {
+ tCsrSSIDInfo *SsidInfo;
+ int j;
+ scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
+ /* Allocate num_ssid tCsrSSIDInfo structure */
+ SsidInfo = scanRequest.SSIDs.SSIDList =
+ ( tCsrSSIDInfo *)vos_mem_malloc(
+ request->n_ssids*sizeof(tCsrSSIDInfo));
+
+ if(NULL == scanRequest.SSIDs.SSIDList)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "memory alloc failed SSIDInfo buffer");
+ return -ENOMEM;
+ }
+
+ /* copy all the ssid's and their length */
+ for(j = 0; j < request->n_ssids; j++, SsidInfo++)
+ {
+ /* get the ssid length */
+ SsidInfo->SSID.length = request->ssids[j].ssid_len;
+ vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
+ SsidInfo->SSID.length);
+ SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
+ j, SsidInfo->SSID.ssId);
+ }
+ /* set the scan type to active */
+ scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ }
+ else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
+ {
+ /* set the scan type to active */
+ scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ }
+ else
+ {
+ /*Set the scan type to default type, in this case it is ACTIVE*/
+ scanRequest.scanType = pScanInfo->scan_mode;
+ }
+ scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
+ scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
+ }
+ else
+ {
+ /* set the scan type to active */
+ scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
+
+ /* set min and max channel time to zero */
+ scanRequest.minChnTime = 0;
+ scanRequest.maxChnTime = 0;
+ }
+
+ /* set BSSType to default type */
+ scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
+
+ /*TODO: scan the requested channels only*/
+
+ /*Right now scanning all the channels */
+ if( request )
+ {
+ if( request->n_channels )
+ {
+ channelList = vos_mem_malloc( request->n_channels );
+ if( NULL == channelList )
+ {
+ status = -ENOMEM;
+ goto free_mem;
+ }
+
+ for( i = 0 ; i < request->n_channels ; i++ )
+ channelList[i] = request->channels[i]->hw_value;
+ }
+
+ scanRequest.ChannelInfo.numOfChannels = request->n_channels;
+ scanRequest.ChannelInfo.ChannelList = channelList;
+
+ /* set requestType to full scan */
+ scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
+
+ if( request->ie_len )
+ {
+ /* save this for future association (join requires this) */
+ memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
+ memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
+ pScanInfo->scanAddIE.length = request->ie_len;
+
+ if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
+ (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
+ )
+ {
+ pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
+ pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
+ }
+
+ scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
+ scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
+
+#ifdef WLAN_FEATURE_P2P
+ pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
+ request->ie_len);
+ if (pP2pIe != NULL)
+ {
+ if ( (request->n_ssids == 1) &&
+ (request->ssids[0].ssid_len == P2P_WILDCARD_SSID_LEN) &&
+ !memcmp(request->ssids[0].ssid, P2P_WILDCARD_SSID,
+ P2P_WILDCARD_SSID_LEN ))
+ {
+ tANI_U8 sessionId = pAdapter->sessionId;
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: This is a P2P Search", __func__);
+ scanRequest.p2pSearch = 1;
+ pScanInfo->p2pSearch = 1;
+
+ /* set requestType to P2P Discovery */
+ scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
+ {
+ sessionId = pAdapter->p2pSessionId;
+ }
+ sme_ScanFlushResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ sessionId );
+ }
+ }
+#endif
+ }
+ }
+
+ INIT_COMPLETION(pScanInfo->scan_req_completion_event);
+
+ if ((pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated) &&
+ (scanRequest.p2pSearch))
+ {
+ status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->p2pSessionId, &scanRequest, &scanId,
+ &hdd_cfg80211_scan_done_callback, dev );
+ }
+ else
+ {
+ status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, &scanRequest, &scanId,
+ &hdd_cfg80211_scan_done_callback, dev );
+ }
+
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_ScanRequest returned error %d", __func__, status);
+ complete(&pScanInfo->scan_req_completion_event);
+ status = -EIO;
+ goto free_mem;
+ }
+
+ pScanInfo->mScanPending = TRUE;
+ pAdapter->request = request;
+ pScanInfo->scanId = scanId;
+
+ complete(&pScanInfo->scan_req_completion_event);
+
+free_mem:
+ if( scanRequest.SSIDs.SSIDList )
+ {
+ vos_mem_free(scanRequest.SSIDs.SSIDList);
+ }
+
+ if( channelList )
+ vos_mem_free( channelList );
+
+ EXIT();
+
+ return status;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_connect_start
+ * This function is used to start the association process
+ */
+int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
+ const u8 *ssid, size_t ssid_len, const u8 *bssid)
+{
+ int status = 0;
+ hdd_wext_state_t *pWextState;
+ v_U32_t roamId;
+ tCsrRoamProfile *pRoamProfile;
+ eMib_dot11DesiredBssType connectedBssType;
+ eCsrAuthType RSNAuthType;
+
+ ENTER();
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
+ return -EINVAL;
+ }
+
+ pRoamProfile = &pWextState->roamProfile;
+
+ if (pRoamProfile)
+ {
+ if (hdd_connGetConnectedBssType(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
+ &connectedBssType ) || ( eMib_dot11DesiredBssType_independent ==
+ connectedBssType))
+ {
+ /* Issue disconnect to CSR */
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+ if( eHAL_STATUS_SUCCESS ==
+ sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
+ {
+ wait_for_completion_interruptible_timeout(
+ &pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+ }
+ }
+
+ if (HDD_WMM_USER_MODE_NO_QOS ==
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
+ {
+ /*QoS not enabled in cfg file*/
+ pRoamProfile->uapsd_mask = 0;
+ }
+ else
+ {
+ /*QoS enabled, update uapsd mask from cfg file*/
+ pRoamProfile->uapsd_mask =
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
+ }
+
+ pRoamProfile->SSIDs.numOfSSIDs = 1;
+ pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
+ vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
+ sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
+ vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
+ ssid, ssid_len);
+
+ if (bssid)
+ {
+ pRoamProfile->BSSIDs.numOfBSSIDs = 1;
+ vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
+ WNI_CFG_BSSID_LEN);
+ /* Save BSSID in seperate variable as well, as RoamProfile
+ BSSID is getting zeroed out in the association process. And in
+ case of join failure we should send valid BSSID to supplicant
+ */
+ vos_mem_copy((void *)(pWextState->req_bssId), bssid,
+ WNI_CFG_BSSID_LEN);
+ }
+
+ if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
+ (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
+ {
+ /*set gen ie*/
+ hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
+ /*set auth*/
+ hdd_set_csr_auth_type(pAdapter, RSNAuthType);
+ }
+ else if ( (pWextState->roamProfile.AuthType.authType[0] ==
+ eCSR_AUTH_TYPE_OPEN_SYSTEM)
+ && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
+ eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
+ || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
+ eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
+ )
+ {
+ /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
+ * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
+ * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
+ eCSR_AUTH_TYPE_AUTOSWITCH;
+ pWextState->roamProfile.AuthType.authType[0] =
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
+ }
+#ifdef FEATURE_WLAN_WAPI
+ if (pAdapter->wapi_info.nWapiMode)
+ {
+ hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __FUNCTION__);
+ switch (pAdapter->wapi_info.wapiAuthMode)
+ {
+ case WAPI_AUTH_MODE_PSK:
+ {
+ hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __FUNCTION__,
+ pAdapter->wapi_info.wapiAuthMode);
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
+ break;
+ }
+ case WAPI_AUTH_MODE_CERT:
+ {
+ hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __FUNCTION__,
+ pAdapter->wapi_info.wapiAuthMode);
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
+ break;
+ }
+ } // End of switch
+ if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
+ pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
+ {
+ hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __FUNCTION__);
+ pRoamProfile->AuthType.numEntries = 1;
+ pRoamProfile->EncryptionType.numEntries = 1;
+ pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
+ pRoamProfile->mcEncryptionType.numEntries = 1;
+ pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
+ }
+ }
+#endif /* FEATURE_WLAN_WAPI */
+ pRoamProfile->csrPersona = pAdapter->device_mode;
+
+ status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, pRoamProfile, &roamId);
+
+ pRoamProfile->ChannelInfo.ChannelList = NULL;
+ pRoamProfile->ChannelInfo.numOfChannels = 0;
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
+ return -EINVAL;
+ }
+ EXIT();
+ return status;
+}
+
+/*
+ * FUNCTION: wlan_hdd_set_cfg80211_auth_type
+ * This function is used to set the authentication type (OPEN/SHARED).
+ *
+ */
+static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
+ enum nl80211_auth_type auth_type)
+{
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ ENTER();
+
+ /*set authentication type*/
+ switch (auth_type)
+ {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ case NL80211_AUTHTYPE_AUTOMATIC:
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: set authentication type to OPEN", __func__);
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+ break;
+
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: set authentication type to SHARED", __func__);
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
+ break;
+#ifdef FEATURE_WLAN_CCX
+ case NL80211_AUTHTYPE_NETWORK_EAP:
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: set authentication type to CCKM WPA", __func__);
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
+ break;
+#endif
+
+
+ default:
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Unsupported authentication type %d", __func__,
+ auth_type);
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
+ return -EINVAL;
+ }
+
+ pWextState->roamProfile.AuthType.authType[0] =
+ pHddStaCtx->conn_info.authType;
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_set_akm_suite
+ * This function is used to set the key mgmt type(PSK/8021x).
+ *
+ */
+static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
+ u32 key_mgmt
+ )
+{
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ ENTER();
+
+ /*set key mgmt type*/
+ switch(key_mgmt)
+ {
+ case WLAN_AKM_SUITE_PSK:
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
+ __func__);
+ pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
+ break;
+
+ case WLAN_AKM_SUITE_8021X:
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
+ __func__);
+ pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
+ break;
+#ifdef FEATURE_WLAN_CCX
+#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
+#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
+ case WLAN_AKM_SUITE_CCKM:
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
+ __func__);
+ pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
+ break;
+#endif
+
+ default:
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
+ __func__, key_mgmt);
+ return -EINVAL;
+
+ }
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_set_cipher
+ * This function is used to set the encryption type
+ * (NONE/WEP40/WEP104/TKIP/CCMP).
+ */
+static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
+ u32 cipher,
+ bool ucast
+ )
+{
+ eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ ENTER();
+
+ if (!cipher)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
+ __func__, cipher);
+ encryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ }
+ else
+ {
+
+ /*set encryption method*/
+ switch (cipher)
+ {
+ case IW_AUTH_CIPHER_NONE:
+ encryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ break;
+
+ case WLAN_CIPHER_SUITE_WEP40:
+ if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
+ (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
+ encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
+ else
+ encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ break;
+
+ case WLAN_CIPHER_SUITE_WEP104:
+ if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
+ (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
+ encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
+ else
+ encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
+ break;
+
+ case WLAN_CIPHER_SUITE_TKIP:
+ encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
+ break;
+
+ case WLAN_CIPHER_SUITE_CCMP:
+ encryptionType = eCSR_ENCRYPT_TYPE_AES;
+ break;
+#ifdef FEATURE_WLAN_WAPI
+ case WLAN_CIPHER_SUITE_SMS4:
+ encryptionType = eCSR_ENCRYPT_TYPE_WPI;
+ break;
+#endif
+
+#ifdef FEATURE_WLAN_CCX
+ case WLAN_CIPHER_SUITE_KRK:
+ encryptionType = eCSR_ENCRYPT_TYPE_KRK;
+ break;
+#endif
+ default:
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
+ __func__, cipher);
+ return -EOPNOTSUPP;
+ }
+ }
+
+ if (ucast)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
+ __func__, encryptionType);
+ pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
+ pWextState->roamProfile.EncryptionType.numEntries = 1;
+ pWextState->roamProfile.EncryptionType.encryptionType[0] =
+ encryptionType;
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
+ __func__, encryptionType);
+ pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
+ pWextState->roamProfile.mcEncryptionType.numEntries = 1;
+ pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
+ }
+
+ return 0;
+}
+
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_set_ie
+ * This function is used to parse WPA/RSN IE's.
+ */
+int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
+ u8 *ie,
+ size_t ie_len
+ )
+{
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ u8 *genie = ie;
+ v_U16_t remLen = ie_len;
+#ifdef FEATURE_WLAN_WAPI
+ v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
+ u16 *tmp;
+ v_U16_t akmsuiteCount;
+ int *akmlist;
+#endif
+ ENTER();
+
+ /* clear previous assocAddIE */
+ pWextState->assocAddIE.length = 0;
+ pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
+
+ while (remLen >= 2)
+ {
+ v_U16_t eLen = 0;
+ v_U8_t elementId;
+ elementId = *genie++;
+ eLen = *genie++;
+ remLen -= 2;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
+ __func__, elementId, eLen);
+
+ switch ( elementId )
+ {
+ case DOT11F_EID_WPA:
+ if ((2+4) > eLen) /* should have at least OUI */
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid WPA IE", __func__);
+ return -EINVAL;
+ }
+ else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
+ {
+ v_U16_t curAddIELen = pWextState->assocAddIE.length;
+ hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
+ __func__, eLen + 2);
+
+ if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE. "
+ "Need bigger buffer space\n");
+ VOS_ASSERT(0);
+ return -ENOMEM;
+ }
+ // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
+ memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
+ pWextState->assocAddIE.length += eLen + 2;
+
+ pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
+ pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
+ pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
+ }
+ else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
+ {
+ hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
+ memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
+ memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
+ pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
+ pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
+ }
+#ifdef WLAN_FEATURE_P2P
+ else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
+ P2P_OUI_TYPE_SIZE))
+ /*Consider P2P IE, only for P2P Client */
+ && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
+ {
+ v_U16_t curAddIELen = pWextState->assocAddIE.length;
+ hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
+ __func__, eLen + 2);
+
+ if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
+ "Need bigger buffer space\n");
+ VOS_ASSERT(0);
+ return -ENOMEM;
+ }
+ // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
+ memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
+ pWextState->assocAddIE.length += eLen + 2;
+
+ pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
+ pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
+ }
+#endif
+#ifdef WLAN_FEATURE_WFD
+ else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
+ WFD_OUI_TYPE_SIZE))
+ /*Consider WFD IE, only for P2P Client */
+ && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
+ {
+ v_U16_t curAddIELen = pWextState->assocAddIE.length;
+ hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
+ __func__, eLen + 2);
+
+ if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
+ "Need bigger buffer space\n");
+ VOS_ASSERT(0);
+ return -ENOMEM;
+ }
+ // WFD IE is saved to Additional IE ; it should be accumulated to handle
+ // WPS IE + P2P IE + WFD IE
+ memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
+ pWextState->assocAddIE.length += eLen + 2;
+
+ pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
+ pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
+ }
+#endif
+ break;
+ case DOT11F_EID_RSN:
+ hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
+ memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
+ memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
+ pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
+ pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
+ break;
+#ifdef FEATURE_WLAN_WAPI
+ case WLAN_EID_WAPI:
+ pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
+ hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
+ pAdapter->wapi_info.nWapiMode);
+ tmp = (u16 *)ie;
+ tmp = tmp + 2; // Skip element Id and Len, Version
+ akmsuiteCount = WPA_GET_LE16(tmp);
+ tmp = tmp + 1;
+ akmlist = (int *)(tmp);
+ if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
+ {
+ memcpy(akmsuite, akmlist, (4*akmsuiteCount));
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
+ VOS_ASSERT(0);
+ return -EINVAL;
+ }
+
+ if (WAPI_PSK_AKM_SUITE == akmsuite[0])
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
+ __FUNCTION__);
+ pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
+ }
+ if (WAPI_CERT_AKM_SUITE == akmsuite[0])
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
+ __FUNCTION__);
+ pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
+ }
+ break;
+#endif
+ default:
+ hddLog (VOS_TRACE_LEVEL_ERROR,
+ "%s Set UNKNOWN IE %X", __func__, elementId);
+ return 0;
+ }
+ genie += eLen;
+ remLen -= eLen;
+ }
+ EXIT();
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_set_privacy
+ * This function is used to initialize the security
+ * parameters during connect operation.
+ */
+int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
+ struct cfg80211_connect_params *req
+ )
+{
+ int status = 0;
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ ENTER();
+
+ /*set wpa version*/
+ pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
+
+ if (req->crypto.wpa_versions)
+ {
+ if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
+ && ( (req->ie_len)
+ && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
+ // Make sure that it is including a WPA IE.
+ /* Currently NL is putting WPA version 1 even for open,
+ * since p2p ie is also put in same buffer.
+ * */
+ {
+ pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
+ }
+ else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
+ {
+ pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
+ }
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
+ pWextState->wpaVersion);
+
+ /*set authentication type*/
+ status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
+
+ if (0 > status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: failed to set authentication type ", __func__);
+ return status;
+ }
+
+ /*set key mgmt type*/
+ if (req->crypto.n_akm_suites)
+ {
+ status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
+ if (0 > status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
+ __func__);
+ return status;
+ }
+ }
+
+ /*set pairwise cipher type*/
+ if (req->crypto.n_ciphers_pairwise)
+ {
+ status = wlan_hdd_cfg80211_set_cipher(pAdapter,
+ req->crypto.ciphers_pairwise[0], true);
+ if (0 > status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: failed to set unicast cipher type", __func__);
+ return status;
+ }
+ }
+ else
+ {
+ /*Reset previous cipher suite to none*/
+ status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
+ if (0 > status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: failed to set unicast cipher type", __func__);
+ return status;
+ }
+ }
+
+ /*set group cipher type*/
+ status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
+ false);
+
+ if (0 > status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
+ __func__);
+ return status;
+ }
+
+ /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
+ if (req->ie_len)
+ {
+ status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
+ if ( 0 > status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
+ __func__);
+ return status;
+ }
+ }
+
+ /*incase of WEP set default key information*/
+ if (req->key && req->key_len)
+ {
+ if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
+ || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
+ )
+ {
+ if ( IW_AUTH_KEY_MGMT_802_1X
+ == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
+ __func__);
+ return -EOPNOTSUPP;
+ }
+ else
+ {
+ u8 key_len = req->key_len;
+ u8 key_idx = req->key_idx;
+
+ if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
+ && (CSR_MAX_NUM_KEY > key_idx)
+ )
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: setting default wep key, key_idx = %hu key_len %hu",
+ __func__, key_idx, key_len);
+ vos_mem_copy(
+ &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
+ req->key, key_len);
+ pWextState->roamProfile.Keys.KeyLength[key_idx] =
+ (u8)key_len;
+ pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
+ }
+ }
+ }
+ }
+
+ return status;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_set_privacy
+ * This function is used to initialize the security
+ * parameters during connect operation.
+ */
+static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
+ struct net_device *ndev,
+ struct cfg80211_connect_params *req
+ )
+{
+ int status = 0;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
+ VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
+ hdd_context_t *pHddCtx = NULL;
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
+
+ if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s:LOGP in Progress. Ignore!!!", __func__);
+ return -EAGAIN;
+ }
+
+#ifdef WLAN_BTAMP_FEATURE
+ //Infra connect not supported when AMP traffic is on.
+ if( VOS_TRUE == WLANBAP_AmpSessionOn() )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: No connection when AMP is on", __func__);
+ return -1;
+ }
+#endif
+ /*initialise security parameters*/
+ status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
+
+ if ( 0 > status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
+ __func__);
+ return status;
+ }
+
+ //If Device Mode is Station Concurrent Sessions Exit BMps
+ //P2P Mode will be taken care in Open/close adaptor
+ if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
+ (vos_concurrent_sessions_running()))
+ {
+ v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
+
+ if (NULL != pVosContext)
+ {
+ pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
+ if(NULL != pHddCtx)
+ {
+ exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
+ }
+ }
+ }
+
+ status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
+ req->ssid_len, req->bssid);
+
+ if (0 > status)
+ {
+ //ReEnable BMPS if disabled
+ if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
+ (NULL != pHddCtx))
+ {
+ //ReEnable Bmps and Imps back
+ hdd_enable_bmps_imps(pHddCtx);
+ }
+
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
+ return status;
+ }
+ (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
+ EXIT();
+ return status;
+}
+
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_disconnect
+ * This function is used to issue a disconnect request to SME
+ */
+static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
+ struct net_device *dev,
+ u16 reason
+ )
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
+ tCsrRoamProfile *pRoamProfile =
+ &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
+ int status = 0;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
+ __func__,pAdapter->device_mode);
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
+ __func__, reason);
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return -EAGAIN;
+ }
+ if (NULL != pRoamProfile)
+ {
+ /*issue disconnect request to SME, if station is in connected state*/
+ if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
+ {
+ eCsrRoamDisconnectReason reasonCode =
+ eCSR_DISCONNECT_REASON_UNSPECIFIED;
+ switch(reason)
+ {
+ case WLAN_REASON_MIC_FAILURE:
+ reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
+ break;
+
+ case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
+ case WLAN_REASON_DISASSOC_AP_BUSY:
+ case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
+ reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
+ break;
+
+ case WLAN_REASON_PREV_AUTH_NOT_VALID:
+ case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
+ reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
+ break;
+
+ case WLAN_REASON_DEAUTH_LEAVING:
+ default:
+ reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
+ break;
+ }
+ pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
+ (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+
+ /*issue disconnect*/
+ status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, reasonCode);
+
+ if ( 0 != status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s csrRoamDisconnect failure, returned %d \n",
+ __func__, (int)status );
+ return -EINVAL;
+ }
+
+ wait_for_completion_interruptible_timeout(
+ &pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+
+
+ /*stop tx queues*/
+ netif_tx_disable(dev);
+ netif_carrier_off(dev);
+ }
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
+ }
+
+ return status;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
+ * This function is used to initialize the security
+ * settings in IBSS mode.
+ */
+static int wlan_hdd_cfg80211_set_privacy_ibss(
+ hdd_adapter_t *pAdapter,
+ struct cfg80211_ibss_params *params
+ )
+{
+ int status = 0;
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ ENTER();
+
+ pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
+
+ if (params->ie_len && ( NULL != params->ie) )
+ {
+ if (WLAN_EID_RSN == params->ie[0])
+ {
+ pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
+ encryptionType = eCSR_ENCRYPT_TYPE_AES;
+ }
+ else
+ {
+ pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
+ encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
+ }
+ status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
+
+ if (0 > status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
+ __func__);
+ return status;
+ }
+ }
+
+ pWextState->roamProfile.AuthType.authType[0] =
+ pHddStaCtx->conn_info.authType =
+ eCSR_AUTH_TYPE_OPEN_SYSTEM;
+
+ if (params->privacy)
+ {
+ /* Security enabled IBSS, At this time there is no information available
+ * about the security paramters, so initialise the encryption type to
+ * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
+ * The correct security parameters will be updated later in
+ * wlan_hdd_cfg80211_add_key */
+ /* Hal expects encryption type to be set inorder
+ *enable privacy bit in beacons */
+
+ encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ }
+
+ pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
+ pWextState->roamProfile.EncryptionType.numEntries = 1;
+ pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
+
+ return status;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_join_ibss
+ * This function is used to create/join an IBSS
+ */
+static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_ibss_params *params
+ )
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrRoamProfile *pRoamProfile;
+ int status;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
+
+ if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s:LOGP in Progress. Ignore!!!", __func__);
+ return -EAGAIN;
+ }
+
+ if (NULL == pWextState)
+ {
+ hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
+ __func__);
+ return -EIO;
+ }
+
+ pRoamProfile = &pWextState->roamProfile;
+
+ if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
+ {
+ hddLog (VOS_TRACE_LEVEL_ERROR,
+ "%s Interface type is not set to IBSS \n", __func__);
+ return -EINVAL;
+ }
+
+ /* Set Channel */
+ if (NULL != params->channel)
+ {
+ u8 channelNum;
+ if (IEEE80211_BAND_5GHZ == params->channel->band)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: IBSS join is called with unsupported band %d",
+ __func__, params->channel->band);
+ return -EOPNOTSUPP;
+ }
+
+ /* Get channel number */
+ channelNum =
+ ieee80211_frequency_to_channel(params->channel->center_freq);
+
+ /*TODO: use macro*/
+ if (14 >= channelNum)
+ {
+ v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+ v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ int indx;
+
+ if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
+ validChan, &numChans))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
+ __func__);
+ return -EOPNOTSUPP;
+ }
+
+ for (indx = 0; indx < numChans; indx++)
+ {
+ if (channelNum == validChan[indx])
+ {
+ break;
+ }
+ }
+ if (indx >= numChans)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
+ __func__, channelNum);
+ return -EINVAL;
+ }
+ /* Set the Operational Channel */
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
+ channelNum);
+ pRoamProfile->ChannelInfo.numOfChannels = 1;
+ pHddStaCtx->conn_info.operationChannel = channelNum;
+ pRoamProfile->ChannelInfo.ChannelList =
+ &pHddStaCtx->conn_info.operationChannel;
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
+ __func__, channelNum);
+ return -EINVAL;
+ }
+ }
+
+ /* Initialize security parameters */
+ status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
+ if (status < 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
+ __func__);
+ return status;
+ }
+
+ /* Issue connect start */
+ status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
+ params->ssid_len, params->bssid);
+
+ if (0 > status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
+ return status;
+ }
+
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_leave_ibss
+ * This function is used to leave an IBSS
+ */
+static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
+ struct net_device *dev
+ )
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrRoamProfile *pRoamProfile;
+
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
+ if (NULL == pWextState)
+ {
+ hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
+ __func__);
+ return -EIO;
+ }
+
+ pRoamProfile = &pWextState->roamProfile;
+
+ /* Issue disconnect only if interface type is set to IBSS */
+ if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
+ {
+ hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Issue Disconnect request */
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+ sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
+ eCSR_DISCONNECT_REASON_IBSS_LEAVE);
+
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
+ * This function is used to set the phy parameters
+ * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
+ */
+static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
+ u32 changed)
+{
+ hdd_context_t *pHddCtx = wiphy_priv(wiphy);
+ tHalHandle hHal = pHddCtx->hHal;
+
+ ENTER();
+
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD)
+ {
+ u16 rts_threshold = (wiphy->rts_threshold == -1) ?
+ WNI_CFG_RTS_THRESHOLD_STAMAX :
+ wiphy->rts_threshold;
+
+ if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
+ (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid RTS Threshold value %hu",
+ __func__, rts_threshold);
+ return -EINVAL;
+ }
+
+ if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
+ rts_threshold, ccmCfgSetCallback,
+ eANI_BOOLEAN_TRUE))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: ccmCfgSetInt failed for rts_threshold value %hu",
+ __func__, rts_threshold);
+ return -EIO;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
+ rts_threshold);
+ }
+
+ if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
+ {
+ u16 frag_threshold = (wiphy->frag_threshold == -1) ?
+ WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
+ wiphy->frag_threshold;
+
+ if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
+ (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid frag_threshold value %hu", __func__,
+ frag_threshold);
+ return -EINVAL;
+ }
+
+ if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
+ frag_threshold, ccmCfgSetCallback,
+ eANI_BOOLEAN_TRUE))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: ccmCfgSetInt failed for frag_threshold value %hu",
+ __func__, frag_threshold);
+ return -EIO;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
+ frag_threshold);
+ }
+
+ if ((changed & WIPHY_PARAM_RETRY_SHORT)
+ || (changed & WIPHY_PARAM_RETRY_LONG))
+ {
+ u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
+ wiphy->retry_short :
+ wiphy->retry_long;
+
+ if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
+ (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
+ __func__, retry_value);
+ return -EINVAL;
+ }
+
+ if (changed & WIPHY_PARAM_RETRY_SHORT)
+ {
+ if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
+ retry_value, ccmCfgSetCallback,
+ eANI_BOOLEAN_TRUE))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: ccmCfgSetInt failed for long retry count %hu",
+ __func__, retry_value);
+ return -EIO;
+ }
+ hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
+ __func__, retry_value);
+ }
+ else if (changed & WIPHY_PARAM_RETRY_SHORT)
+ {
+ if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
+ retry_value, ccmCfgSetCallback,
+ eANI_BOOLEAN_TRUE))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: ccmCfgSetInt failed for short retry count %hu",
+ __func__, retry_value);
+ return -EIO;
+ }
+ hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
+ __func__, retry_value);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_set_txpower
+ * This function is used to set the txpower
+ */
+static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
+ enum tx_power_setting type,
+#else
+ enum nl80211_tx_power_setting type,
+#endif
+ int dbm)
+{
+ hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
+ tHalHandle hHal = pHddCtx->hHal;
+ tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+ tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+
+ ENTER();
+
+ if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
+ dbm, ccmCfgSetCallback,
+ eANI_BOOLEAN_TRUE))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
+ return -EIO;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
+ dbm);
+
+ switch(type)
+ {
+ case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
+ /* Fall through */
+ case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
+ if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
+ __func__);
+ return -EIO;
+ }
+ break;
+ case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
+ __func__);
+ return -EOPNOTSUPP;
+ break;
+ default:
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
+ __func__, type);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/*
+ * FUNCTION: wlan_hdd_cfg80211_get_txpower
+ * This function is used to read the txpower
+ */
+static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
+{
+
+ hdd_adapter_t *pAdapter;
+ hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
+
+ if (NULL == pHddCtx)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
+ *dbm = 0;
+ return -ENOENT;
+ }
+
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
+ return -ENOENT;
+ }
+
+ wlan_hdd_get_classAstats(pAdapter);
+ *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
+
+ return 0;
+}
+
+static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+ u8* mac, struct station_info *sinfo)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
+ tANI_U8 rate_flags;
+
+ hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
+ hdd_config_t *pCfg = pHddCtx->cfg_ini;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+
+ tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
+ tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
+ tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
+ tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
+ tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
+ tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
+ tANI_U16 maxRate = 0;
+ tANI_U16 myRate;
+ tANI_U16 currentRate = 0;
+ tANI_U8 maxSpeedMCS = 0;
+ tANI_U8 maxMCSIdx = 0;
+ tANI_U8 rateFlag = 1;
+ tANI_U8 i, j, rssidx;
+
+ if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
+ (0 == ssidlen))
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
+ " Invalid ssidlen, %d", __func__, ssidlen);
+ /*To keep GUI happy*/
+ return 0;
+ }
+
+ wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
+ sinfo->filled |= STATION_INFO_SIGNAL;
+
+ wlan_hdd_get_classAstats(pAdapter);
+ rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
+
+ //convert to the UI units of 100kbps
+ myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
+
+#ifdef LINKSPEED_DEBUG_ENABLED
+ pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi low %d\n",
+ sinfo->signal,
+ pCfg->reportMaxLinkSpeed,
+ myRate,
+ (int) pCfg->linkSpeedRssiHigh,
+ (int) pCfg->linkSpeedRssiLow);
+#endif //LINKSPEED_DEBUG_ENABLED
+
+ if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
+ {
+ // we do not want to necessarily report the current speed
+ if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
+ {
+ // report the max possible speed
+ rssidx = 0;
+ }
+ else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
+ {
+ // report the max possible speed with RSSI scaling
+ if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
+ {
+ // report the max possible speed
+ rssidx = 0;
+ }
+ else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
+ {
+ // report middle speed
+ rssidx = 1;
+ }
+ else
+ {
+ // report actual speed
+ rssidx = 2;
+ }
+ }
+ else
+ {
+ // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid value for reportMaxLinkSpeed: %u",
+ __func__, pCfg->reportMaxLinkSpeed);
+ rssidx = 0;
+ }
+
+ maxRate = 0;
+
+ /* Get Basic Rate Set */
+ ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
+ for (i = 0; i < ORLeng; i++)
+ {
+ for (j = 0; j < sizeof(supported_data_rate); j ++)
+ {
+ /* Validate Rate Set */
+ if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
+ {
+ currentRate = supported_data_rate[j].supported_rate[rssidx];
+ break;
+ }
+ }
+ /* Update MAX rate */
+ maxRate = (currentRate > maxRate)?currentRate:maxRate;
+ }
+
+ /* Get Extended Rate Set */
+ ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
+ for (i = 0; i < ERLeng; i++)
+ {
+ for (j = 0; j < sizeof(supported_data_rate); j ++)
+ {
+ if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
+ {
+ currentRate = supported_data_rate[j].supported_rate[rssidx];
+ break;
+ }
+ }
+ /* Update MAX rate */
+ maxRate = (currentRate > maxRate)?currentRate:maxRate;
+ }
+
+ /* Get MCS Rate Set -- but only if we are connected at MCS
+ rates or if we are always reporting max speed or if we have
+ good rssi */
+ if ((0 == rssidx) || !(rate_flags & eHAL_TX_RATE_LEGACY))
+ {
+ ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
+ rateFlag = 0;
+ if (rate_flags & eHAL_TX_RATE_HT40)
+ {
+ rateFlag |= 1;
+ }
+ if (rate_flags & eHAL_TX_RATE_SGI)
+ {
+ rateFlag |= 2;
+ }
+
+ for (i = 0; i < MCSLeng; i++)
+ {
+ for (j = 0; j < sizeof(supported_mcs_rate); j++)
+ {
+ if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
+ {
+ currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
+ break;
+ }
+ }
+ if (currentRate > maxRate)
+ {
+ maxRate = currentRate;
+ maxSpeedMCS = 1;
+ maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
+ }
+ }
+ }
+
+ // make sure we report a value at least as big as our current rate
+ if (maxRate < myRate)
+ {
+ maxRate = myRate;
+ if (rate_flags & eHAL_TX_RATE_LEGACY)
+ {
+ maxSpeedMCS = 0;
+ }
+ else
+ {
+ maxSpeedMCS = 1;
+ maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
+ }
+ }
+
+ if (!maxSpeedMCS)
+ {
+ sinfo->txrate.legacy = maxRate;
+#ifdef LINKSPEED_DEBUG_ENABLED
+ pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
+#endif //LINKSPEED_DEBUG_ENABLED
+ }
+ else
+ {
+ sinfo->txrate.mcs = maxMCSIdx;
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+ if (rate_flags & eHAL_TX_RATE_SGI)
+ {
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ }
+ if (rate_flags & eHAL_TX_RATE_HT40)
+ {
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ }
+#ifdef LINKSPEED_DEBUG_ENABLED
+ pr_info("Reporting MCS rate %d flags %x\n",
+ sinfo->txrate.mcs,
+ sinfo->txrate.flags );
+#endif //LINKSPEED_DEBUG_ENABLED
+ }
+ }
+ else
+ {
+ // report current rate instead of max rate
+
+ if (rate_flags & eHAL_TX_RATE_LEGACY)
+ {
+ //provide to the UI in units of 100kbps
+ sinfo->txrate.legacy = myRate;
+#ifdef LINKSPEED_DEBUG_ENABLED
+ pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
+#endif //LINKSPEED_DEBUG_ENABLED
+ }
+ else
+ {
+ //must be MCS
+ sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+ if (rate_flags & eHAL_TX_RATE_SGI)
+ {
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ }
+ if (rate_flags & eHAL_TX_RATE_HT40)
+ {
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ }
+#ifdef LINKSPEED_DEBUG_ENABLED
+ pr_info("Reporting actual MCS rate %d flags %x\n",
+ sinfo->txrate.mcs,
+ sinfo->txrate.flags );
+#endif //LINKSPEED_DEBUG_ENABLED
+ }
+ }
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+
+ return 0;
+}
+
+static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+ struct net_device *dev, bool mode, v_SINT_t timeout)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ VOS_STATUS vos_status;
+
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
+ return -ENODEV;
+ }
+
+ /**The get power cmd from the supplicant gets updated by the nl only
+ *on successful execution of the function call
+ *we are oppositely mapped w.r.t mode in the driver
+ **/
+ vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
+
+ if (VOS_STATUS_E_FAILURE == vos_status)
+ {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
+ struct net_device *netdev,
+ u8 key_index)
+{
+ return 0;
+}
+#endif //LINUX_VERSION_CODE
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
+static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_txq_params *params)
+{
+ return 0;
+}
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
+ struct ieee80211_txq_params *params)
+{
+ return 0;
+}
+#endif //LINUX_VERSION_CODE
+
+static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
+ struct net_device *dev, u8 *mac)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
+ return -EINVAL;
+ }
+
+ if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
+ {
+ hddLog( LOGE,
+ "%s: Wlan Load/Unload is in progress", __func__);
+ return -EBUSY;
+ }
+
+ if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
+#ifdef WLAN_FEATURE_P2P
+ || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
+#endif
+ )
+ {
+ if( NULL == mac )
+ {
+ v_U16_t i;
+ for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
+ {
+ if(pAdapter->aStaInfo[i].isUsed)
+ {
+ u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: Delete STA with MAC::"
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ __func__,
+ macAddr[0], macAddr[1], macAddr[2],
+ macAddr[3], macAddr[4], macAddr[5]);
+ hdd_softap_sta_deauth(pAdapter, macAddr);
+ }
+ }
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: Delete STA with MAC::"
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ __func__,
+ mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+ hdd_softap_sta_deauth(pAdapter, mac);
+ }
+ }
+
+ EXIT();
+
+ return 0;
+}
+
+static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
+ struct net_device *dev, u8 *mac, struct station_parameters *params)
+{
+ // TODO: Implement this later.
+ return 0;
+}
+
+/* cfg80211_ops */
+static struct cfg80211_ops wlan_hdd_cfg80211_ops =
+{
+ .add_virtual_intf = wlan_hdd_add_virtual_intf,
+ .del_virtual_intf = wlan_hdd_del_virtual_intf,
+ .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
+ .change_station = wlan_hdd_change_station,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+ .add_beacon = wlan_hdd_cfg80211_add_beacon,
+ .del_beacon = wlan_hdd_cfg80211_del_beacon,
+ .set_beacon = wlan_hdd_cfg80211_set_beacon,
+#endif
+ .change_bss = wlan_hdd_cfg80211_change_bss,
+ .add_key = wlan_hdd_cfg80211_add_key,
+ .get_key = wlan_hdd_cfg80211_get_key,
+ .del_key = wlan_hdd_cfg80211_del_key,
+ .set_default_key = wlan_hdd_cfg80211_set_default_key,
+ .set_channel = wlan_hdd_cfg80211_set_channel,
+ .scan = wlan_hdd_cfg80211_scan,
+ .connect = wlan_hdd_cfg80211_connect,
+ .disconnect = wlan_hdd_cfg80211_disconnect,
+ .join_ibss = wlan_hdd_cfg80211_join_ibss,
+ .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
+ .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
+ .set_tx_power = wlan_hdd_cfg80211_set_txpower,
+ .get_tx_power = wlan_hdd_cfg80211_get_txpower,
+#ifdef WLAN_FEATURE_P2P
+ .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
+ .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
+ .mgmt_tx = wlan_hdd_action,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
+ .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
+ .set_txq_params = wlan_hdd_set_txq_params,
+#endif
+#endif
+ .get_station = wlan_hdd_cfg80211_get_station,
+ .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
+ .del_station = wlan_hdd_cfg80211_del_station,
+ .add_station = wlan_hdd_cfg80211_add_station
+};
+
+#endif // CONFIG_CFG80211
diff --git a/CORE/HDD/src/wlan_hdd_dev_pwr.c b/CORE/HDD/src/wlan_hdd_dev_pwr.c
new file mode 100644
index 0000000..db68ac9
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_dev_pwr.c
@@ -0,0 +1,545 @@
+/*
+ * 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.
+ */
+
+/**=========================================================================
+
+ EDIT HISTORY FOR FILE
+
+
+ This section contains comments describing changes made to the module.
+ Notice that changes are listed in reverse chronological order.
+
+
+ $Header:$ $DateTime: $ $Author: $
+
+
+ when who what, where, why
+ -------- --- --------------------------------------------------------
+ 03/29/11 tbh Created module.
+
+ ==========================================================================*/
+
+/*----------------------------------------------------------------------------
+ * Include Files
+ * -------------------------------------------------------------------------*/
+#include <wlan_hdd_dev_pwr.h>
+#ifdef ANI_BUS_TYPE_PLATFORM
+#include <linux/wcnss_wlan.h>
+#else
+#include <wcnss_wlan.h>
+#endif // ANI_BUS_TYP_PLATFORM
+
+/*----------------------------------------------------------------------------
+ * Preprocessor Definitions and Constants
+ * -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Type Declarations
+ * -------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------
+ * Global variables.
+ *-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------
+ * Local variables.
+ *-------------------------------------------------------------------------*/
+/* Reference VoIP, 100msec delay make disconnect.
+ * So TX sleep must be less than 100msec
+ * Every 20msec TX frame will goes out.
+ * 10 frame means 2seconds TX operation */
+static const hdd_tmLevelAction_t thermalMigrationAction[WLAN_HDD_TM_LEVEL_MAX] =
+{
+ /* TM Level 0, Do nothing, just normal operaton */
+ {1, 0, 0, 0, 0xFFFFF},
+ /* Tm Level 1, disable TX AMPDU */
+ {0, 0, 0, 0, 0xFFFFF},
+ /* TM Level 2, disable AMDPU,
+ * TX sleep 100msec if TX frame count is larger than 16 during 300msec */
+ {0, 0, 100, 300, 16},
+ /* TM Level 3, disable AMDPU,
+ * TX sleep 500msec if TX frame count is larger than 11 during 500msec */
+ {0, 0, 500, 500, 11},
+ /* TM Level 4, MAX TM level, enter IMPS */
+ {0, 1, 1000, 500, 10}
+};
+
+
+/*----------------------------------------------------------------------------
+
+ @brief Function to suspend the wlan driver.
+
+ @param hdd_context_t pHddCtx
+ Global hdd context
+
+
+ @return None
+
+----------------------------------------------------------------------------*/
+static int wlan_suspend(hdd_context_t* pHddCtx)
+{
+ int rc = 0;
+
+ pVosSchedContext vosSchedContext = NULL;
+
+ /* Get the global VOSS context */
+ vosSchedContext = get_vos_sched_ctxt();
+
+ if(!vosSchedContext) {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: Global VOS_SCHED context is Null",__func__);
+ return 0;
+ }
+ if(!vos_is_apps_power_collapse_allowed(pHddCtx))
+ {
+ /* Fail this suspend */
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Fail wlan suspend: not in IMPS/BMPS", __func__);
+ return -1;
+ }
+
+ /* Set the Station state as Suspended */
+ pHddCtx->isWlanSuspended = TRUE;
+
+ /*
+ Suspending MC Thread, Rx Thread and Tx Thread as the platform driver is going to Suspend.
+ */
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Suspending Mc, Rx and Tx Threads",__func__);
+
+ init_completion(&pHddCtx->tx_sus_event_var);
+
+ /* Indicate Tx Thread to Suspend */
+ set_bit(TX_SUSPEND_EVENT_MASK, &vosSchedContext->txEventFlag);
+
+ wake_up_interruptible(&vosSchedContext->txWaitQueue);
+
+ /* Wait for Suspend Confirmation from Tx Thread */
+ rc = wait_for_completion_interruptible_timeout(&pHddCtx->tx_sus_event_var, msecs_to_jiffies(200));
+
+ if(!rc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: Not able to suspend TX thread timeout happened", __func__);
+ clear_bit(TX_SUSPEND_EVENT_MASK, &vosSchedContext->txEventFlag);
+
+ return -1;
+ }
+ /* Set the Tx Thread as Suspended */
+ pHddCtx->isTxThreadSuspended = TRUE;
+
+ init_completion(&pHddCtx->rx_sus_event_var);
+
+ /* Indicate Rx Thread to Suspend */
+ set_bit(RX_SUSPEND_EVENT_MASK, &vosSchedContext->rxEventFlag);
+
+ wake_up_interruptible(&vosSchedContext->rxWaitQueue);
+
+ /* Wait for Suspend Confirmation from Rx Thread */
+ rc = wait_for_completion_interruptible_timeout(&pHddCtx->rx_sus_event_var, msecs_to_jiffies(200));
+
+ if(!rc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: Not able to suspend Rx thread timeout happened", __func__);
+
+ clear_bit(RX_SUSPEND_EVENT_MASK, &vosSchedContext->rxEventFlag);
+
+ /* Indicate Tx Thread to Resume */
+ complete(&vosSchedContext->ResumeTxEvent);
+
+ /* Set the Tx Thread as Resumed */
+ pHddCtx->isTxThreadSuspended = FALSE;
+
+ return -1;
+ }
+
+ /* Set the Rx Thread as Suspended */
+ pHddCtx->isRxThreadSuspended = TRUE;
+
+ init_completion(&pHddCtx->mc_sus_event_var);
+
+ /* Indicate MC Thread to Suspend */
+ set_bit(MC_SUSPEND_EVENT_MASK, &vosSchedContext->mcEventFlag);
+
+ wake_up_interruptible(&vosSchedContext->mcWaitQueue);
+
+ /* Wait for Suspend Confirmation from MC Thread */
+ rc = wait_for_completion_interruptible_timeout(&pHddCtx->mc_sus_event_var, msecs_to_jiffies(200));
+
+ if(!rc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: Not able to suspend MC thread timeout happened", __func__);
+
+ clear_bit(MC_SUSPEND_EVENT_MASK, &vosSchedContext->mcEventFlag);
+
+ /* Indicate Rx Thread to Resume */
+ complete(&vosSchedContext->ResumeRxEvent);
+
+ /* Set the Rx Thread as Resumed */
+ pHddCtx->isRxThreadSuspended = FALSE;
+
+ /* Indicate Tx Thread to Resume */
+ complete(&vosSchedContext->ResumeTxEvent);
+
+ /* Set the Tx Thread as Resumed */
+ pHddCtx->isTxThreadSuspended = FALSE;
+
+ return -1;
+ }
+
+ /* Set the Mc Thread as Suspended */
+ pHddCtx->isMcThreadSuspended = TRUE;
+
+ /* Set the Station state as Suspended */
+ pHddCtx->isWlanSuspended = TRUE;
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+
+ @brief Function to resume the wlan driver.
+
+ @param hdd_context_t pHddCtx
+ Global hdd context
+
+
+ @return None
+
+----------------------------------------------------------------------------*/
+static void wlan_resume(hdd_context_t* pHddCtx)
+{
+ pVosSchedContext vosSchedContext = NULL;
+
+ //Get the global VOSS context.
+ vosSchedContext = get_vos_sched_ctxt();
+
+ if(!vosSchedContext) {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: Global VOS_SCHED context is Null",__func__);
+ return;
+ }
+
+ /*
+ Resuming Mc, Rx and Tx Thread as platform Driver is resuming.
+ */
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Resuming Mc, Rx and Tx Thread",__func__);
+
+ /* Indicate MC Thread to Resume */
+ complete(&vosSchedContext->ResumeMcEvent);
+
+ /* Set the Mc Thread as Resumed */
+ pHddCtx->isMcThreadSuspended = FALSE;
+
+ /* Indicate Rx Thread to Resume */
+ complete(&vosSchedContext->ResumeRxEvent);
+
+ /* Set the Rx Thread as Resumed */
+ pHddCtx->isRxThreadSuspended = FALSE;
+
+ /* Indicate Tx Thread to Resume */
+ complete(&vosSchedContext->ResumeTxEvent);
+
+ /* Set the Tx Thread as Resumed */
+ pHddCtx->isTxThreadSuspended = FALSE;
+
+ /* Set the Station state as Suspended */
+ pHddCtx->isWlanSuspended = FALSE;
+}
+
+/*----------------------------------------------------------------------------
+
+ @brief Function to suspend the wlan driver.
+ This function will get called by platform driver Suspend on System Suspend
+
+ @param dev platform_func_device
+
+
+ @return None
+
+----------------------------------------------------------------------------*/
+int hddDevSuspendHdlr(struct device *dev)
+{
+ int ret = 0;
+ hdd_context_t* pHddCtx = NULL;
+
+ pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: WLAN suspended by platform driver",__func__);
+
+ /* Get the HDD context */
+ if(!pHddCtx) {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
+ return 0;
+ }
+
+ if(pHddCtx->isWlanSuspended == TRUE)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: WLAN is already in suspended state",__func__);
+ return 0;
+ }
+
+ /* Suspend the wlan driver */
+ ret = wlan_suspend(pHddCtx);
+ if(ret != 0)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: Not able to suspend wlan",__func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+
+ @brief Function to resume the wlan driver.
+ This function will get called by platform driver Resume on System Resume
+
+ @param dev platform_func_device
+
+
+ @return None
+
+----------------------------------------------------------------------------*/
+int hddDevResumeHdlr(struct device *dev)
+{
+ hdd_context_t* pHddCtx = NULL;
+
+ pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
+
+ if(pHddCtx->isWlanSuspended != TRUE)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: WLAN is already in resumed state",__func__);
+ return 0;
+ }
+
+ /* Resume the wlan driver */
+ wlan_resume(pHddCtx);
+
+ return 0;
+}
+
+static const struct dev_pm_ops pm_ops = {
+ .suspend = hddDevSuspendHdlr,
+ .resume = hddDevResumeHdlr,
+};
+
+/*----------------------------------------------------------------------------
+ *
+
+ @brief Registration function.
+ Register suspend, resume callback functions with platform driver.
+
+ @param hdd_context_t pHddCtx
+ Global hdd context
+
+ @return General status code
+ VOS_STATUS_SUCCESS Registration Success
+ VOS_STATUS_E_FAILURE Registration Fail
+
+----------------------------------------------------------------------------*/
+VOS_STATUS hddRegisterPmOps(hdd_context_t *pHddCtx)
+{
+ wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
+#ifndef FEATURE_R33D
+ wcnss_wlan_register_pm_ops(pHddCtx->parent_dev, &pm_ops);
+#endif /* FEATURE_R33D */
+ return VOS_STATUS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+
+ @brief De-registration function.
+ Deregister the suspend, resume callback functions with platform driver
+
+ @param hdd_context_t pHddCtx
+ Global hdd context
+
+ @return General status code
+ VOS_STATUS_SUCCESS De-Registration Success
+ VOS_STATUS_E_FAILURE De-Registration Fail
+
+----------------------------------------------------------------------------*/
+VOS_STATUS hddDeregisterPmOps(hdd_context_t *pHddCtx)
+{
+#ifndef FEATURE_R33D
+ wcnss_wlan_unregister_pm_ops(pHddCtx->parent_dev, &pm_ops);
+#endif /* FEATURE_R33D */
+ return VOS_STATUS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+
+ @brief TX frame block timeout handler
+ Resume TX, and reset TX frame count
+
+ @param hdd_context_t pHddCtx
+ Global hdd context
+
+ @return NONE
+
+----------------------------------------------------------------------------*/
+void hddDevTmTxBlockTimeoutHandler(void *usrData)
+{
+ hdd_context_t *pHddCtx = (hdd_context_t *)usrData;
+ hdd_adapter_t *staAdapater;
+ /* Sanity, This should not happen */
+ if(NULL == pHddCtx)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
+ "%s: NULL Context", __func__);
+ VOS_ASSERT(0);
+ return;
+ }
+
+ staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
+ if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
+ "%s: Aquire lock fail", __func__);
+ return;
+ }
+ pHddCtx->tmInfo.txFrameCount = 0;
+
+ /* Resume TX flow */
+ netif_tx_start_all_queues(staAdapater->dev);
+ mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
+
+ return;
+}
+
+/*----------------------------------------------------------------------------
+
+ @brief TM Level Change handler
+ Received Tm Level changed notification
+
+ @param dev : Device context
+ changedTmLevel : Changed new TM level
+
+ @return
+
+----------------------------------------------------------------------------*/
+void hddDevTmLevelChangedHandler(struct device *dev, int changedTmLevel)
+{
+ hdd_context_t *pHddCtx = NULL;
+ WLAN_TmLevelEnumType newTmLevel = changedTmLevel;
+ hdd_adapter_t *staAdapater;
+
+ pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
+
+ if((pHddCtx->tmInfo.currentTmLevel == newTmLevel) ||
+ (!pHddCtx->cfg_ini->thermalMitigationEnable))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_WARN,
+ "%s: TM Not enabled %d or Level does not changed %d",
+ __func__, pHddCtx->cfg_ini->thermalMitigationEnable, newTmLevel);
+ /* TM Level does not changed,
+ * Or feature does not enabled
+ * do nothing */
+ return;
+ }
+
+ sme_SetTmLevel(pHddCtx->hHal, changedTmLevel, 0);
+
+ if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
+ "%s: Aquire lock fail", __func__);
+ return;
+ }
+
+ pHddCtx->tmInfo.currentTmLevel = changedTmLevel;
+ pHddCtx->tmInfo.txFrameCount = 0;
+ vos_mem_copy(&pHddCtx->tmInfo.tmAction,
+ &thermalMigrationAction[newTmLevel],
+ sizeof(hdd_tmLevelAction_t));
+
+
+ if(pHddCtx->tmInfo.tmAction.enterImps)
+ {
+ staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
+ if(staAdapater)
+ {
+ if(hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(staAdapater)))
+ {
+ sme_RoamDisconnect(pHddCtx->hHal,
+ staAdapater->sessionId,
+ eCSR_DISCONNECT_REASON_UNSPECIFIED);
+ }
+ }
+ }
+
+ mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
+
+ return;
+}
+
+/*----------------------------------------------------------------------------
+
+ @brief Register function
+ Register Thermal Mitigation Level Changed handle callback function
+
+ @param hdd_context_t pHddCtx
+ Global hdd context
+
+ @return General status code
+ VOS_STATUS_SUCCESS Registration Success
+ VOS_STATUS_E_FAILURE Registration Fail
+
+----------------------------------------------------------------------------*/
+VOS_STATUS hddDevTmRegisterNotifyCallback(hdd_context_t *pHddCtx)
+{
+ VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
+ "%s: Register TM Handler", __func__);
+
+ wcnss_register_thermal_mitigation(pHddCtx->parent_dev ,hddDevTmLevelChangedHandler);
+
+ /* Set Default TM Level as Lowest, do nothing */
+ pHddCtx->tmInfo.currentTmLevel = WLAN_HDD_TM_LEVEL_0;
+ vos_mem_zero(&pHddCtx->tmInfo.tmAction, sizeof(hdd_tmLevelAction_t));
+ vos_timer_init(&pHddCtx->tmInfo.txSleepTimer,
+ VOS_TIMER_TYPE_SW,
+ hddDevTmTxBlockTimeoutHandler,
+ (void *)pHddCtx);
+ mutex_init(&pHddCtx->tmInfo.tmOperationLock);
+ pHddCtx->tmInfo.txFrameCount = 0;
+ pHddCtx->tmInfo.blockedQueue = NULL;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+
+ @brief Un-Register function
+ Un-Register Thermal Mitigation Level Changed handle callback function
+
+ @param hdd_context_t pHddCtx
+ Global hdd context
+
+ @return General status code
+ VOS_STATUS_SUCCESS Un-Registration Success
+ VOS_STATUS_E_FAILURE Un-Registration Fail
+
+----------------------------------------------------------------------------*/
+VOS_STATUS hddDevTmUnregisterNotifyCallback(hdd_context_t *pHddCtx)
+{
+ wcnss_unregister_thermal_mitigation(hddDevTmLevelChangedHandler);
+ return VOS_STATUS_SUCCESS;
+}
+
diff --git a/CORE/HDD/src/wlan_hdd_dp_utils.c b/CORE/HDD/src/wlan_hdd_dp_utils.c
new file mode 100644
index 0000000..c7ee744
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_dp_utils.c
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ */
+
+/**=============================================================================
+ wlan_hdd_dp_utils.c
+
+ \brief Utility functions for data path module
+
+ Description...
+ Copyright 2008 (c) Qualcomm, Incorporated.
+ All Rights Reserved.
+ Qualcomm Confidential and Proprietary.
+
+ ==============================================================================**/
+/* $HEADER$ */
+
+/**-----------------------------------------------------------------------------
+ Include files
+ ----------------------------------------------------------------------------*/
+#include <wlan_hdd_dp_utils.h>
+
+/**-----------------------------------------------------------------------------
+ Preprocessor definitions and constants
+ ----------------------------------------------------------------------------*/
+
+/**-----------------------------------------------------------------------------
+ Type declarations
+ ----------------------------------------------------------------------------*/
+
+/**-----------------------------------------------------------------------------
+ Function declarations and documenation
+ ----------------------------------------------------------------------------*/
+
+
+VOS_STATUS hdd_list_insert_front( hdd_list_t *pList, hdd_list_node_t *pNode )
+{
+ list_add( pNode, &pList->anchor );
+ pList->count++;
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_list_insert_back( hdd_list_t *pList, hdd_list_node_t *pNode )
+{
+ list_add_tail( pNode, &pList->anchor );
+ pList->count++;
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_list_insert_back_size( hdd_list_t *pList, hdd_list_node_t *pNode, v_SIZE_t *pSize )
+{
+ list_add_tail( pNode, &pList->anchor );
+ pList->count++;
+ *pSize = pList->count;
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_list_remove_front( hdd_list_t *pList, hdd_list_node_t **ppNode )
+{
+ struct list_head * listptr;
+
+ if ( list_empty( &pList->anchor ) )
+ {
+ return VOS_STATUS_E_EMPTY;
+ }
+
+ listptr = pList->anchor.next;
+ *ppNode = listptr;
+ list_del(pList->anchor.next);
+ pList->count--;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_list_remove_back( hdd_list_t *pList, hdd_list_node_t **ppNode )
+{
+ struct list_head * listptr;
+
+ if ( list_empty( &pList->anchor ) )
+ {
+ return VOS_STATUS_E_EMPTY;
+ }
+
+ listptr = pList->anchor.prev;
+ *ppNode = listptr;
+ list_del(pList->anchor.prev);
+ pList->count--;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_list_remove_node( hdd_list_t *pList,
+ hdd_list_node_t *pNodeToRemove )
+{
+ hdd_list_node_t *tmp;
+ int found = 0;
+
+ if ( list_empty( &pList->anchor ) )
+ {
+ return VOS_STATUS_E_EMPTY;
+ }
+
+ // verify that pNodeToRemove is indeed part of list pList
+ list_for_each(tmp, &pList->anchor)
+ {
+ if (tmp == pNodeToRemove)
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (found == 0)
+ return VOS_STATUS_E_INVAL;
+
+ list_del(pNodeToRemove);
+ pList->count--;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_list_peek_front( hdd_list_t *pList,
+ hdd_list_node_t **ppNode )
+{
+ struct list_head * listptr;
+ if ( list_empty( &pList->anchor ) )
+ {
+ return VOS_STATUS_E_EMPTY;
+ }
+
+ listptr = pList->anchor.next;
+ *ppNode = listptr;
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_list_peek_next( hdd_list_t *pList, hdd_list_node_t *pNode,
+ hdd_list_node_t **ppNode )
+{
+ struct list_head * listptr;
+ int found = 0;
+ hdd_list_node_t *tmp;
+
+ if ( ( pList == NULL) || ( pNode == NULL) || (ppNode == NULL))
+ {
+ return VOS_STATUS_E_FAULT;
+ }
+
+ if ( list_empty(&pList->anchor) )
+ {
+ return VOS_STATUS_E_EMPTY;
+ }
+
+ // verify that pNode is indeed part of list pList
+ list_for_each(tmp, &pList->anchor)
+ {
+ if (tmp == pNode)
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found == 0)
+ {
+ return VOS_STATUS_E_INVAL;
+ }
+
+ listptr = pNode->next;
+ if (listptr == &pList->anchor)
+ {
+ return VOS_STATUS_E_EMPTY;
+ }
+
+ *ppNode = listptr;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_string_to_hex( char *pSrcMac, int length, char *pDescMac )
+{
+ int i;
+ int k;
+ char temp[3] = {0};
+
+ //18 is MAC Address length plus the colons
+ if ( !pSrcMac && (length > 18 || length < 18) )
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+ i = k = 0;
+ while ( i < length )
+ {
+ memcpy(temp, pSrcMac+i, 2);
+ pDescMac[k++] = (char)simple_strtoul (temp, NULL, 16);
+ i += 3;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
diff --git a/CORE/HDD/src/wlan_hdd_early_suspend.c b/CORE/HDD/src/wlan_hdd_early_suspend.c
new file mode 100644
index 0000000..762aa59
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_early_suspend.c
@@ -0,0 +1,2211 @@
+/*
+ * 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.
+ */
+
+/**=============================================================================
+* wlan_hdd_early_suspend.c
+*
+* \brief power management functions
+*
+* Description
+* Copyright 2009 (c) Qualcomm, Incorporated.
+* All Rights Reserved.
+* Qualcomm Confidential and Proprietary.
+*
+==============================================================================**/
+/* $HEADER$ */
+
+/**-----------------------------------------------------------------------------
+* Include files
+* ----------------------------------------------------------------------------*/
+#ifdef CONFIG_HAS_EARLYSUSPEND
+
+#include <linux/pm.h>
+#include <linux/wait.h>
+#include <linux/earlysuspend.h>
+#include <linux/wcnss_wlan.h>
+#include <wlan_hdd_includes.h>
+#include <wlan_qct_driver.h>
+#include <linux/wakelock.h>
+#endif
+
+#include "halTypes.h"
+#include "sme_Api.h"
+#include <vos_api.h>
+#include "vos_power.h"
+#include <vos_sched.h>
+#include <macInitApi.h>
+#ifdef ANI_BUS_TYPE_SDIO
+#include <wlan_qct_sal.h>
+#include <wlan_qct_bal.h>
+#endif
+#include <wlan_qct_sys.h>
+#include <wlan_btc_svc.h>
+#include <wlan_nlink_common.h>
+#include <wlan_hdd_main.h>
+#include <wlan_hdd_assoc.h>
+#include <wlan_hdd_dev_pwr.h>
+#ifdef ANI_BUS_TYPE_SDIO
+#include <wlan_sal_misc.h>
+#include <libra_sdioif.h>
+#endif
+#include <wlan_nlink_srv.h>
+#include <wlan_hdd_misc.h>
+
+#ifdef WLAN_SOFTAP_FEATURE
+#include <linux/semaphore.h>
+#include <wlan_hdd_hostapd.h>
+#endif
+#include "cfgApi.h"
+
+#ifdef WLAN_BTAMP_FEATURE
+#include "bapApi.h"
+#include "bap_hdd_main.h"
+#include "bap_hdd_misc.h"
+#endif
+
+#include <linux/inetdevice.h>
+#include <wlan_hdd_cfg.h>
+/**-----------------------------------------------------------------------------
+* Preprocessor definitions and constants
+* ----------------------------------------------------------------------------*/
+
+/**-----------------------------------------------------------------------------
+* Type declarations
+* ----------------------------------------------------------------------------*/
+
+/**-----------------------------------------------------------------------------
+* Function and variables declarations
+* ----------------------------------------------------------------------------*/
+#include "wlan_hdd_power.h"
+#include "wlan_hdd_packet_filtering.h"
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct early_suspend wlan_early_suspend;
+#endif
+
+static eHalStatus g_full_pwr_status;
+static eHalStatus g_standby_status;
+
+extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
+extern VOS_STATUS vos_chipExitDeepSleepVREGHandler(
+ vos_call_status_type* status,
+ vos_power_cb_type callback,
+ v_PVOID_t user_data);
+extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
+void unregister_wlan_suspend(void);
+
+extern struct notifier_block hdd_netdev_notifier;
+#ifdef WLAN_SOFTAP_FEATURE
+extern tVOS_CON_MODE hdd_get_conparam ( void );
+#endif
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+extern void wlan_hdd_set_mc_addr_list(hdd_context_t *pHddCtx, v_U8_t set);
+#endif
+
+//Callback invoked by PMC to report status of standby request
+void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
+{
+ hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
+ g_standby_status = status;
+
+ if(eHAL_STATUS_SUCCESS == status)
+ {
+ pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
+ }
+
+ complete(&pHddCtx->standby_comp_var);
+}
+
+//Callback invoked by PMC to report status of full power request
+void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
+{
+ hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
+ g_full_pwr_status = status;
+
+ if(eHAL_STATUS_SUCCESS == status)
+ {
+ pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
+ }
+
+ complete(&pHddCtx->full_pwr_comp_var);
+}
+
+eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
+{
+ eHalStatus status = VOS_STATUS_SUCCESS;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
+ INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
+
+ g_full_pwr_status = eHAL_STATUS_FAILURE;
+ status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
+ eSME_FULL_PWR_NEEDED_BY_HDD);
+
+ if(status == eHAL_STATUS_PMC_PENDING)
+ {
+ //Block on a completion variable. Can't wait forever though
+ wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
+ status = g_full_pwr_status;
+ if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
+ VOS_ASSERT(0);
+ goto failure;
+ }
+ }
+ else if(status != eHAL_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
+ __func__, status);
+ VOS_ASSERT(0);
+ goto failure;
+ }
+ else
+ pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
+
+failure:
+ //No blocking to reduce latency. No other device should be depending on WLAN
+ //to finish resume and WLAN won't be instantly on after resume
+ return status;
+}
+
+
+//Helper routine to put the chip into standby
+VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
+{
+ eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+
+ //Disable IMPS/BMPS as we do not want the device to enter any power
+ //save mode on its own during suspend sequence
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+
+ //Note we do not disable queues unnecessarily. Queues should already be disabled
+ //if STA is disconnected or the queue will be disabled as and when disconnect
+ //happens because of standby procedure.
+
+ //Ensure that device is in full power first. There is scope for optimization
+ //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
+ //Core s/w needs to be optimized to handle this. Until then we request full
+ //power before issuing request for standby.
+ INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
+ g_full_pwr_status = eHAL_STATUS_FAILURE;
+ halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
+ pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
+
+ if(halStatus == eHAL_STATUS_PMC_PENDING)
+ {
+ //Block on a completion variable. Can't wait forever though
+ wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
+ if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
+ VOS_ASSERT(0);
+ vosStatus = VOS_STATUS_E_FAILURE;
+ goto failure;
+ }
+ }
+ else if(halStatus != eHAL_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
+ __func__, halStatus);
+ VOS_ASSERT(0);
+ vosStatus = VOS_STATUS_E_FAILURE;
+ goto failure;
+ }
+
+ if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
+ hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
+ pHddCtx->hdd_mcastbcast_filter_set = FALSE;
+ }
+
+ //Request standby. Standby will cause the STA to disassociate first. TX queues
+ //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
+ //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
+ //will send this failure code in case of concurrent sessions. Power Save cannot be supported
+ //when there are concurrent sessions.
+ INIT_COMPLETION(pHddCtx->standby_comp_var);
+ g_standby_status = eHAL_STATUS_FAILURE;
+ halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
+
+ if (halStatus == eHAL_STATUS_PMC_PENDING)
+ {
+ //Wait till WLAN device enters standby mode
+ wait_for_completion_timeout(&pHddCtx->standby_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
+ if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
+ VOS_ASSERT(0);
+ vosStatus = VOS_STATUS_E_FAILURE;
+ goto failure;
+ }
+ }
+ else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
+ __func__, halStatus);
+ VOS_ASSERT(0);
+ vosStatus = VOS_STATUS_E_FAILURE;
+ goto failure;
+ }
+ else
+ pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
+
+failure:
+ //Restore IMPS config
+ if(pHddCtx->cfg_ini->fIsImpsEnabled)
+ sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+
+ //Restore BMPS config
+ if(pHddCtx->cfg_ini->fIsBmpsEnabled)
+ sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+
+ return vosStatus;
+}
+
+
+//Helper routine for Deep sleep entry
+VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
+{
+ eHalStatus halStatus;
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ vos_call_status_type callType;
+#ifdef ANI_BUS_TYPE_SDIO
+ struct sdio_func *sdio_func_dev_current = NULL;
+ int attempts = 0;
+#endif
+ //Stop the Interface TX queue.
+ netif_tx_disable(pAdapter->dev);
+ netif_carrier_off(pAdapter->dev);
+
+ //Disable IMPS,BMPS as we do not want the device to enter any power
+ //save mode on it own during suspend sequence
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+
+ //Ensure that device is in full power as we will touch H/W during vos_Stop
+ INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
+ g_full_pwr_status = eHAL_STATUS_FAILURE;
+ halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
+ pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
+
+ if(halStatus == eHAL_STATUS_PMC_PENDING)
+ {
+ //Block on a completion variable. Can't wait forever though
+ wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
+ if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
+ VOS_ASSERT(0);
+ }
+ }
+ else if(halStatus != eHAL_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
+ VOS_ASSERT(0);
+ }
+
+ //Issue a disconnect. This is required to inform the supplicant that
+ //STA is getting disassociated and for GUI to be updated properly
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+ halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
+
+ //Success implies disconnect command got queued up successfully
+ if(halStatus == eHAL_STATUS_SUCCESS)
+ {
+ //Block on a completion variable. Can't wait forever though.
+ wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+ }
+
+
+ //None of the steps should fail after this. Continue even in case of failure
+ vosStatus = vos_stop( pHddCtx->pvosContext );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+#ifdef ANI_BUS_TYPE_SDIO
+ vosStatus = WLANBAL_Stop( pHddCtx->pvosContext );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+ vosStatus = WLANBAL_SuspendChip( pHddCtx->pvosContext );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+ vosStatus = WLANSAL_Stop(pHddCtx->pvosContext);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+#endif
+
+ vosStatus = vos_chipAssertDeepSleep( &callType, NULL, NULL );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+ //Vote off any PMIC voltage supplies
+ vosStatus = vos_chipPowerDown(NULL, NULL, NULL);
+
+#ifdef ANI_BUS_TYPE_SDIO
+ //Get the Current SDIO Func
+ sdio_func_dev_current = libra_getsdio_funcdev();
+ if(NULL != sdio_func_dev_current) {
+ libra_detect_card_change();
+ do {
+ msleep(100);
+ //Get the SDIO func device
+ sdio_func_dev_current = libra_getsdio_funcdev();
+ if(NULL == sdio_func_dev_current) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Card Removed Successfully",__func__);
+ break;
+ }
+ else {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Trying Again",__func__);
+ attempts++;
+ }
+ } while (attempts < LIBRA_CARD_REMOVE_DETECT_MAX_COUNT);
+
+ if(LIBRA_CARD_REMOVE_DETECT_MAX_COUNT == attempts) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Fatal",__func__);
+ goto err_fail;
+ }
+ }
+#endif
+
+ pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
+
+ //Restore IMPS config
+ if(pHddCtx->cfg_ini->fIsImpsEnabled)
+ sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+
+ //Restore BMPS config
+ if(pHddCtx->cfg_ini->fIsBmpsEnabled)
+ sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+
+#ifdef ANI_BUS_TYPE_SDIO
+err_fail:
+#endif
+ return vosStatus;
+}
+
+VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
+{
+ VOS_STATUS vosStatus;
+ eHalStatus halStatus;
+#ifdef ANI_BUS_TYPE_SDIO
+ int attempts = 0;
+ struct sdio_func *sdio_func_dev = NULL;
+#endif
+
+ //Power Up Libra WLAN card first if not already powered up
+ vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
+ "exiting", __func__);
+ goto err_deep_sleep;
+ }
+
+#ifdef ANI_BUS_TYPE_SDIO
+ libra_detect_card_change();
+
+ do {
+ sdio_func_dev = libra_getsdio_funcdev();
+ if (NULL == sdio_func_dev) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
+ attempts++;
+ }
+ else {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
+ break;
+ }
+
+ if(LIBRA_CARD_INSERT_DETECT_MAX_COUNT == attempts)
+ break;
+
+ msleep(250);
+
+ }while (attempts < LIBRA_CARD_INSERT_DETECT_MAX_COUNT);
+
+ //Retry to detect the card again by Powering Down the chip and Power up the chip
+ //again. This retry is done to recover from CRC Error
+ if (NULL == sdio_func_dev) {
+
+ attempts = 0;
+
+ //Vote off any PMIC voltage supplies
+ vos_chipPowerDown(NULL, NULL, NULL);
+
+ msleep(1000);
+
+ //Power Up Libra WLAN card first if not already powered up
+ vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
+ "exiting", __func__);
+ goto err_deep_sleep;
+ }
+
+ do {
+ sdio_func_dev = libra_getsdio_funcdev();
+ if (NULL == sdio_func_dev) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
+ attempts++;
+ }
+ else {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
+ break;
+ }
+
+ if(attempts == 2)
+ break;
+
+ msleep(1000);
+
+ }while (attempts < 3);
+
+ }
+
+ if (NULL == sdio_func_dev) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not found!!",__func__);
+ goto err_deep_sleep;
+ }
+
+ SET_NETDEV_DEV(pAdapter->dev, &sdio_func_dev->dev);
+ libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
+ atomic_set(&pHddCtx->sdio_claim_count, 0);
+ pHddCtx->parent_dev = &sdio_func_dev->dev;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: calling WLANSAL_Start",__func__);
+ vosStatus = WLANSAL_Start(pHddCtx->pvosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start SAL",__func__);
+ goto err_deep_sleep;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: calling WLANBAL_ResumeChip",__func__);
+ vosStatus = WLANBAL_ResumeChip( pHddCtx->pvosContext );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed in WLANBAL_ResumeChip",__func__);
+ goto err_sal_stop;
+ }
+
+ vosStatus = WLANBAL_Start(pHddCtx->pvosContext);
+
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to start BAL",__func__);
+ goto err_sal_stop;
+ }
+#endif
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: calling hdd_set_sme_config",__func__);
+ vosStatus = hdd_set_sme_config( pHddCtx );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed in hdd_set_sme_config",__func__);
+#ifdef ANI_BUS_TYPE_SDIO
+ goto err_bal_stop;
+#else
+ goto err_deep_sleep;
+#endif
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: calling vos_start",__func__);
+ vosStatus = vos_start( pHddCtx->pvosContext );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed in vos_start",__func__);
+#ifdef ANI_BUS_TYPE_SDIO
+ goto err_bal_stop;
+#else
+ goto err_deep_sleep;
+#endif
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: calling hdd_post_voss_start_config",__func__);
+ vosStatus = hdd_post_voss_start_config( pHddCtx );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed in hdd_post_voss_start_config",__func__);
+ goto err_voss_stop;
+ }
+
+
+ //Open a SME session for future operation
+ halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
+ (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
+ if ( !HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08lx]",
+ halStatus, halStatus );
+ goto err_voss_stop;
+
+ }
+
+ pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
+
+ //Trigger the initial scan
+ hdd_wlan_initial_scan(pHddCtx);
+
+ return VOS_STATUS_SUCCESS;
+
+err_voss_stop:
+ vos_stop(pHddCtx->pvosContext);
+#ifdef ANI_BUS_TYPE_SDIO
+err_bal_stop:
+ WLANBAL_Stop(pHddCtx->pvosContext);
+err_sal_stop:
+ WLANSAL_Stop(pHddCtx->pvosContext);
+#endif
+err_deep_sleep:
+ return VOS_STATUS_E_FAILURE;
+
+}
+
+VOS_STATUS hdd_conf_hostarpoffload(hdd_context_t* pHddCtx, v_BOOL_t fenable)
+{
+ struct in_ifaddr **ifap = NULL;
+ struct in_ifaddr *ifa = NULL;
+ struct in_device *in_dev;
+ int i = 0;
+ hdd_adapter_t *pAdapter = NULL;
+ tSirHostOffloadReq offLoadRequest;
+
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: \n", __func__);
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ if (pHddCtx->cfg_ini->isMcAddrListFilter)
+ {
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
+ if (pAdapter != NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Can't set multicast addr filtering in P2P-GO HDD", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
+ if (pAdapter == NULL)
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
+
+ if(pAdapter == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ else
+ {
+#endif
+ pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
+ if(pAdapter == NULL)
+ {
+ pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_P2P_CLIENT);
+ if(pAdapter == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ }
+#endif
+ if(fenable)
+ {
+ if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
+ {
+ for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
+ ifap = &ifa->ifa_next)
+ {
+ if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
+ {
+ break; /* found */
+ }
+ }
+ }
+
+ if(ifa && ifa->ifa_local)
+ {
+ offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
+ offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
+
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Enabled \n", __func__);
+
+ if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
+ pHddCtx->cfg_ini->mcastBcastFilterSetting )
+ || (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
+ pHddCtx->cfg_ini->mcastBcastFilterSetting))
+ {
+ //MCAST filter is set by hdd_conf_mcastbcast_filter fn call
+ offLoadRequest.enableOrDisable =
+ SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
+ }
+
+ //converting u32 to IPV4 address
+ for(i = 0 ; i < 4; i++)
+ {
+ offLoadRequest.params.hostIpv4Addr[i] =
+ (ifa->ifa_local >> (i*8) ) & 0xFF ;
+ }
+ hddLog(VOS_TRACE_LEVEL_WARN, " Enable SME HostOffload: %d.%d.%d.%d",
+ offLoadRequest.params.hostIpv4Addr[0],
+ offLoadRequest.params.hostIpv4Addr[1],
+ offLoadRequest.params.hostIpv4Addr[2],
+ offLoadRequest.params.hostIpv4Addr[3]);
+
+ if (eHAL_STATUS_SUCCESS !=
+ sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter) , &offLoadRequest))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
+ "feature\n", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s:IP Address is not assigned \n", __func__);
+ return VOS_STATUS_E_AGAIN;
+ }
+ }
+ else
+ {
+ vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
+ offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
+ offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
+
+ if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), &offLoadRequest))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
+ "offload feature\n", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+ }
+}
+
+void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
+{
+ eHalStatus halStatus = eHAL_STATUS_FAILURE;
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ tpAniSirGlobal pMac = (tpAniSirGlobal) vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext);
+#else
+ tpSirWlanSetRxpFilters wlanRxpFilterParam =
+ vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
+ if(NULL == wlanRxpFilterParam)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: vos_mem_alloc failed ", __func__);
+ return;
+ }
+#endif
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ if ( pMac )
+ {
+ halStatus = halRxp_configureRxpFilterMcstBcst( pMac, setfilter);
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pMac is initialised to NULL",__func__ );
+ }
+#else
+ wlanRxpFilterParam->setMcstBcstFilter = setfilter;
+ wlanRxpFilterParam->configuredMcstBcstFilterSetting =
+ pHddCtx->cfg_ini->mcastBcastFilterSetting;
+ halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
+#endif
+ if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
+ pHddCtx->hdd_mcastbcast_filter_set = TRUE;
+}
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
+ hdd_adapter_t *pAdapter)
+{
+ eHalStatus halStatus = eHAL_STATUS_FAILURE;
+ tpSirWlanSuspendParam wlanSuspendParam =
+ vos_mem_malloc(sizeof(tSirWlanSuspendParam));
+
+ if(NULL == wlanSuspendParam)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: vos_mem_alloc failed ", __func__);
+ return;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: send wlan suspend indication", __func__);
+
+ if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
+ {
+ if((pHddCtx->cfg_ini->fhostArpOffload) &&
+ (eConnectionState_Associated ==
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
+ {
+ halStatus = hdd_conf_hostarpoffload(pHddCtx, TRUE);
+ if (!VOS_IS_STATUS_SUCCESS(halStatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s:Failed to enable ARPOFFLOAD Feature %d\n",
+ __func__, halStatus);
+ }
+ }
+
+ if(pHddCtx->dynamic_mcbc_filter.enableCfg)
+ {
+ wlanSuspendParam->configuredMcstBcstFilterSetting =
+ pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
+ pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
+ pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend =
+ wlanSuspendParam->configuredMcstBcstFilterSetting;
+ }
+ else
+ {
+ pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE;
+ wlanSuspendParam->configuredMcstBcstFilterSetting =
+ pHddCtx->cfg_ini->mcastBcastFilterSetting;
+ }
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ if (pHddCtx->cfg_ini->isMcAddrListFilter)
+ {
+ /*Multicast addr list filter is enabled during suspend*/
+ if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
+ (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
+ && pHddCtx->mc_addr_list.mc_cnt
+ && (eConnectionState_Associated ==
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
+ {
+ /*set the filter*/
+ wlan_hdd_set_mc_addr_list(pHddCtx, TRUE);
+ }
+ }
+#endif
+ }
+
+ halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
+ if(eHAL_STATUS_SUCCESS == halStatus)
+ {
+ pHddCtx->hdd_mcastbcast_filter_set = TRUE;
+ }
+}
+
+static void hdd_conf_resume_ind(hdd_context_t* pHddCtx)
+{
+ eHalStatus halStatus = eHAL_STATUS_FAILURE;
+ tpSirWlanResumeParam wlanResumeParam =
+ vos_mem_malloc(sizeof(tSirWlanResumeParam));
+
+ if(NULL == wlanResumeParam)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: vos_mem_alloc failed ", __func__);
+ return;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: send wlan resume indication", __func__);
+
+ if(pHddCtx->cfg_ini->fhostArpOffload)
+ {
+ halStatus = hdd_conf_hostarpoffload(pHddCtx, FALSE);
+ if (!VOS_IS_STATUS_SUCCESS(halStatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s:Failed to disable ARPOFFLOAD "
+ "Feature %d\n", __func__, halStatus);
+ }
+ }
+ if (pHddCtx->dynamic_mcbc_filter.enableSuspend)
+ {
+ wlanResumeParam->configuredMcstBcstFilterSetting =
+ pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend;
+ }
+ else
+ {
+ wlanResumeParam->configuredMcstBcstFilterSetting =
+ pHddCtx->cfg_ini->mcastBcastFilterSetting;
+ }
+ sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ if (pHddCtx->cfg_ini->isMcAddrListFilter)
+ {
+ /*Mutlicast addr filtering is enabled*/
+ if(pHddCtx->mc_addr_list.isFilterApplied)
+ {
+ /*Filter applied during suspend mode*/
+ /*Clear it here*/
+ wlan_hdd_set_mc_addr_list(pHddCtx, FALSE);
+ }
+ }
+#endif
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+//Suspend routine registered with Android OS
+void hdd_suspend_wlan(struct early_suspend *wlan_suspend)
+{
+ hdd_context_t *pHddCtx = NULL;
+ v_CONTEXT_t pVosContext = NULL;
+
+ hdd_adapter_t *pAdapter = NULL;
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ VOS_STATUS status;
+#ifdef ANI_BUS_TYPE_SDIO
+ struct sdio_func *sdio_func_dev = NULL;
+#endif
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
+
+ //Get the global VOSS context.
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ if(!pVosContext) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return;
+ }
+
+ //Get the HDD context.
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+
+ if(!pHddCtx) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
+ return;
+ }
+
+ if (pHddCtx->isLogpInProgress) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Ignore suspend wlan, LOGP in progress!", __func__);
+ return;
+ }
+
+#ifdef ANI_BUS_TYPE_SDIO
+ sdio_func_dev = libra_getsdio_funcdev();
+
+ if(sdio_func_dev == NULL)
+ {
+ /* Our card got removed */
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
+ return;
+ }
+
+ if(!sd_is_drvdata_available(sdio_func_dev))
+ {
+ /* Our card got removed */
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD context is not available in sdio_func_dev!",__func__);
+ return;
+ }
+
+ sd_claim_host(sdio_func_dev);
+
+ // Prevent touching the pMac while LOGP reset in progress, we should never get here
+ // as the wake lock is already acquired and it would prevent from entering suspend
+ if (pHddCtx->isLogpInProgress) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Ignore suspend wlan, LOGP in progress!", __func__);
+ sd_release_host(sdio_func_dev);
+ return;
+ }
+#endif
+
+ /*loop through all adapters. TBD fix for Concurrency */
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+ if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
+ && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
+
+ { //just do for station interface
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ continue;
+ }
+
+#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
+ if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
+ {
+ //stop the interface before putting the chip to standby
+ netif_tx_disable(pAdapter->dev);
+ netif_carrier_off(pAdapter->dev);
+ }
+ else if (pHddCtx->cfg_ini->nEnableSuspend ==
+ WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
+ {
+ //Execute deep sleep procedure
+ hdd_enter_deep_sleep(pHddCtx, pAdapter);
+ }
+#endif
+
+ if((pHddCtx->cfg_ini->enableDynamicDTIM ||
+ pHddCtx->cfg_ini->enableModulatedDTIM) &&
+ (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
+ (eConnectionState_Associated ==
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
+ (pHddCtx->cfg_ini->fIsBmpsEnabled))
+ {
+ tSirSetPowerParamsReq powerRequest = { 0 };
+
+ powerRequest.uIgnoreDTIM = 1;
+
+ /*Back up the actual values from CFG */
+ wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM,
+ &pHddCtx->hdd_actual_ignore_DTIM_value);
+ wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL,
+ &pHddCtx->hdd_actual_LI_value);
+
+ if(pHddCtx->cfg_ini->enableModulatedDTIM)
+ {
+ powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
+ powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
+ }
+ else
+ {
+ powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
+ }
+
+ /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
+ *specified during Enter/Exit BMPS when LCD off*/
+ ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
+ NULL, eANI_BOOLEAN_FALSE);
+ ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
+ NULL, eANI_BOOLEAN_FALSE);
+
+ /* switch to the DTIM specified in cfg.ini */
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Switch to DTIM%d \n", powerRequest.uListenInterval);
+ sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
+
+ if (BMPS == pmcGetPmcState(pHddCtx->hHal))
+ {
+ /* put the device into full power */
+ wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
+
+ /* put the device back into BMPS */
+ wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
+
+ pHddCtx->hdd_ignore_dtim_enabled = TRUE;
+ }
+ }
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ /*Suspend notification sent down to driver*/
+ hdd_conf_suspend_ind(pHddCtx, pAdapter);
+#else
+ if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER) {
+ if(eConnectionState_Associated ==
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) {
+ hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
+ halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
+ pHddCtx->pvosContext), FALSE);
+ }
+ }
+#endif
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+ pHddCtx->hdd_wlan_suspended = TRUE;
+
+#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
+ if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
+ {
+ hdd_enter_standby(pHddCtx);
+ }
+#endif
+#ifdef ANI_BUS_TYPE_SDIO
+ sd_release_host(sdio_func_dev);
+#endif
+
+ return;
+}
+
+static void hdd_PowerStateChangedCB
+(
+ v_PVOID_t callbackContext,
+ tPmcState newState
+)
+{
+ hdd_context_t *pHddCtx = callbackContext;
+
+ /* if the driver was not in BMPS during early suspend,
+ * the dynamic DTIM is now updated at Riva */
+ if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
+ && pHddCtx->cfg_ini->enableDynamicDTIM
+ && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
+ {
+ pHddCtx->hdd_ignore_dtim_enabled = TRUE;
+ }
+ spin_lock(&pHddCtx->filter_lock);
+ if((newState == BMPS) && pHddCtx->hdd_wlan_suspended
+ && (pHddCtx->hdd_mcastbcast_filter_set != TRUE)) {
+ spin_unlock(&pHddCtx->filter_lock);
+ hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext), FALSE);
+#endif
+ if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
+ }
+ else
+ spin_unlock(&pHddCtx->filter_lock);
+}
+
+
+
+void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
+{
+ v_CONTEXT_t pVosContext;
+ tHalHandle smeContext;
+
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ if (NULL == pVosContext)
+ {
+ hddLog(LOGE, "%s: Invalid pContext", __FUNCTION__);
+ return;
+ }
+ smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
+ if (NULL == smeContext)
+ {
+ hddLog(LOGE, "%s: Invalid smeContext", __FUNCTION__);
+ return;
+ }
+
+ spin_lock_init(&pHddCtx->filter_lock);
+ if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
+ pHddCtx->cfg_ini->nEnableSuspend)
+ {
+ pmcRegisterDeviceStateUpdateInd(smeContext,
+ hdd_PowerStateChangedCB, pHddCtx);
+ }
+}
+
+void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
+{
+ v_CONTEXT_t pVosContext;
+ tHalHandle smeContext;
+
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ if (NULL == pVosContext)
+ {
+ hddLog(LOGE, "%s: Invalid pContext", __FUNCTION__);
+ return;
+ }
+ smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
+ if (NULL == smeContext)
+ {
+ hddLog(LOGE, "%s: Invalid smeContext", __FUNCTION__);
+ return;
+ }
+
+ if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
+ pHddCtx->cfg_ini->nEnableSuspend)
+ {
+ pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
+ }
+}
+
+void hdd_resume_wlan(struct early_suspend *wlan_suspend)
+{
+ hdd_context_t *pHddCtx = NULL;
+ hdd_adapter_t *pAdapter = NULL;
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ VOS_STATUS status;
+ v_CONTEXT_t pVosContext = NULL;
+#ifdef ANI_BUS_TYPE_SDIO
+ struct sdio_func *sdio_func_dev = NULL;
+#endif
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
+
+ //Get the global VOSS context.
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ if(!pVosContext) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return;
+ }
+
+ //Get the HDD context.
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+
+ if(!pHddCtx) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
+ return;
+ }
+
+ if (pHddCtx->isLogpInProgress) {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: Ignore resume wlan, LOGP in progress!", __func__);
+ return;
+ }
+
+#ifdef ANI_BUS_TYPE_SDIO
+ sdio_func_dev = libra_getsdio_funcdev();
+
+ if(sdio_func_dev == NULL)
+ {
+ /* Our card got removed */
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
+ return;
+ }
+
+ if(!sd_is_drvdata_available(sdio_func_dev))
+ {
+ /* Our card got removed */
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is not available "
+ "in sdio_func_dev!",__func__);
+ return;
+ }
+
+ sd_claim_host(sdio_func_dev);
+
+ // Prevent touching the pMac while LOGP reset in progress,
+ if (pHddCtx->isLogpInProgress) {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Ignore resume wlan, LOGP in progress!", __func__);
+ sd_release_host(sdio_func_dev);
+ return;
+ }
+#endif
+ pHddCtx->hdd_wlan_suspended = FALSE;
+ /*loop through all adapters. Concurrency */
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+ if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
+ && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
+ { //just do for station interface
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ continue;
+ }
+#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
+ if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
+ hdd_exit_deep_sleep(pAdapter);
+ }
+#endif
+
+ if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
+ {
+ /*Switch back to DTIM 1*/
+ tSirSetPowerParamsReq powerRequest = { 0 };
+
+ powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
+ powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
+
+ /*Disabled ModulatedDTIM if enabled on suspend*/
+ if(pHddCtx->cfg_ini->enableModulatedDTIM)
+ powerRequest.uDTIMPeriod = 0;
+
+ /* Update ignoreDTIM and ListedInterval in CFG with default values */
+ ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
+ NULL, eANI_BOOLEAN_FALSE);
+ ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
+ NULL, eANI_BOOLEAN_FALSE);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Switch to DTIM%d \n",powerRequest.uListenInterval);
+ sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
+
+ /* put the device into full power */
+ wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
+
+ /* put the device back into BMPS */
+ wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
+
+ pHddCtx->hdd_ignore_dtim_enabled = FALSE;
+ }
+
+ if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ hdd_conf_resume_ind(pHddCtx);
+#else
+ hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
+ pHddCtx->hdd_mcastbcast_filter_set = FALSE;
+ halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
+ pHddCtx->pvosContext), TRUE);
+#endif
+ pHddCtx->hdd_mcastbcast_filter_set = FALSE;
+ }
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+
+#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
+ if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
+ {
+ hdd_exit_standby(pHddCtx);
+ }
+#endif
+
+#ifdef ANI_BUS_TYPE_SDIO
+ sd_release_host(sdio_func_dev);
+#endif
+ return;
+}
+
+VOS_STATUS hdd_wlan_reset(void)
+{
+ VOS_STATUS vosStatus;
+ hdd_context_t *pHddCtx = NULL;
+ v_CONTEXT_t pVosContext = NULL;
+ pVosSchedContext vosSchedContext = NULL;
+#ifdef ANI_BUS_TYPE_SDIO
+ struct sdio_func *sdio_func_dev_new = NULL;
+ struct sdio_func *sdio_func_dev_current = NULL;
+ unsigned int attempts = 0;
+#endif
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
+
+ //Get the global VOSS context.
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ if(!pVosContext) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Get the HDD context.
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
+ if(!pHddCtx) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+#ifdef ANI_BUS_TYPE_SDIO
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SAL Stop",__func__);
+ //Invoke SAL stop
+ vosStatus = WLANSAL_Stop( pVosContext );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to stop SAL",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+#endif
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Asserting Deep Sleep",__func__);
+ //Assert Deep sleep signal now to put Libra HW in lowest power state
+ vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Power Down Chip",__func__);
+ //Vote off any PMIC voltage supplies
+ vos_chipPowerDown(NULL, NULL, NULL);
+
+
+ /**
+ EVM issue is observed with 1.6Mhz freq for 1.3V supply in wlan standalone case.
+ During concurrent operation (e.g. WLAN and WCDMA) this issue is not observed.
+ To workaround, wlan will vote for 3.2Mhz during startup and will vote for 1.6Mhz
+ during exit.
+ */
+ if (vos_chipVoteFreqFor1p3VSupply(NULL, NULL, NULL, VOS_NV_FREQUENCY_FOR_1_3V_SUPPLY_1P6MH) != VOS_STATUS_SUCCESS)
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to set the freq to 1.6Mhz for 1.3V Supply",__func__ );
+
+ //Disable IMPS/BMPS as we do not want the device to enter any power
+ //save mode on its own during reset sequence
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
+
+ //Kill all the threads first. We do not want any messages
+ //to be a processed any more and the best way to ensure that
+ //is to terminate the threads gracefully.
+ vosSchedContext = get_vos_sched_ctxt();
+
+ /* Wakeup Mc Thread if Suspended */
+ if(TRUE == pHddCtx->isMcThreadSuspended){
+ complete(&vosSchedContext->ResumeMcEvent);
+ pHddCtx->isMcThreadSuspended= FALSE;
+ }
+ /* Wakeup Tx Thread if Suspended */
+ if(TRUE == pHddCtx->isTxThreadSuspended){
+ complete(&vosSchedContext->ResumeTxEvent);
+ pHddCtx->isTxThreadSuspended= FALSE;
+ }
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ /* Wakeup Rx Thread if Suspended */
+ if(TRUE == pHddCtx->isRxThreadSuspended){
+ complete(&vosSchedContext->ResumeRxEvent);
+ pHddCtx->isRxThreadSuspended= FALSE;
+ }
+#endif
+
+ /* Reset the Suspend Variable */
+ pHddCtx->isWlanSuspended = FALSE;
+
+ //Wait for MC to exit
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
+ set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
+ set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
+ wake_up_interruptible(&vosSchedContext->mcWaitQueue);
+ wait_for_completion_interruptible(&vosSchedContext->McShutdown);
+
+ //Wait for TX to exit
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
+ set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
+ set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
+ wake_up_interruptible(&vosSchedContext->txWaitQueue);
+ wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ //Wait for RX to exit
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
+ set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
+ set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
+ wake_up_interruptible(&vosSchedContext->rxWaitQueue);
+ wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
+#endif
+
+ /* Cancel the vote for XO Core ON in LOGP since we are reinitializing our driver
+ * This is done here to ensure there is no race condition since MC and TX thread have
+ * exited at this point
+ */
+ hddLog(VOS_TRACE_LEVEL_WARN, "In LOGP: Cancel XO Core ON vote\n");
+ if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
+ "Power consumed will be high\n");
+ }
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
+ //Stop SME - Cannot invoke vos_stop as vos_stop relies
+ //on threads being running to process the SYS Stop
+ vosStatus = sme_Stop( pHddCtx->hHal, TRUE );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
+ //Stop MAC (PE and HAL)
+ vosStatus = macStop( pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
+ //Stop TL
+ vosStatus = WLANTL_Stop( pVosContext );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+#ifdef ANI_BUS_TYPE_SDIO
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL STOP",__func__);
+ vosStatus = WLANBAL_Stop( pVosContext );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to stop BAL",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ hdd_unregister_mcast_bcast_filter(pHddCtx);
+#endif
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Flush Queues",__func__);
+ //Clean up message queues of TX and MC thread
+ vos_sched_flush_mc_mqs(vosSchedContext);
+ vos_sched_flush_tx_mqs(vosSchedContext);
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ vos_sched_flush_rx_mqs(vosSchedContext);
+#endif
+
+ //Deinit all the TX and MC queues
+ vos_sched_deinit_mqs(vosSchedContext);
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing VOS Close",__func__);
+
+ //Close VOSS
+ vos_close(pVosContext);
+
+#ifdef ANI_BUS_TYPE_SDIO
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL Close",__func__);
+ vosStatus = WLANBAL_Close(pVosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to close BAL",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+ //Get the Current SDIO Func
+ sdio_func_dev_current = libra_getsdio_funcdev();
+
+ if(NULL != sdio_func_dev_current) {
+ libra_detect_card_change();
+ attempts = 0;
+ do {
+ msleep(100);
+ //Get the SDIO func device
+ sdio_func_dev_current = libra_getsdio_funcdev();
+ if(NULL == sdio_func_dev_current) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Card Removed Successfully",__func__);
+ break;
+ }
+ else {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Trying Again",__func__);
+ attempts++;
+ }
+ } while (attempts < LIBRA_CARD_REMOVE_DETECT_MAX_COUNT);
+
+ if(LIBRA_CARD_REMOVE_DETECT_MAX_COUNT == attempts) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Fatal",__func__);
+ goto err_fail;
+ }
+ }
+#endif
+
+#ifdef TIMER_MANAGER
+ vos_timer_exit();
+#endif
+
+#ifdef MEMORY_DEBUG
+ vos_mem_clean();
+#endif
+#ifdef ANI_BUS_TYPE_SDIO
+ //Reinitialize the variable
+ attempts = 0;
+#endif
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Powering Up chip Again",__func__);
+ //Power Up Libra WLAN card first if not already powered up
+ vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
+ "exiting", __func__);
+ goto err_pwr_fail;
+ }
+
+#ifdef ANI_BUS_TYPE_SDIO
+ // Trigger card detect
+ libra_detect_card_change();
+
+ //Reinitialize the variable
+ attempts = 0;
+
+ do {
+ msleep(500);
+
+ //Get the SDIO func device
+ sdio_func_dev_new = libra_getsdio_funcdev();
+ if(sdio_func_dev_new != NULL)
+ {
+ //Not needed but in case it causes probs then put a loop and set for each adapter
+ //SET_NETDEV_DEV(pAdapter->dev, &sdio_func_dev_new->dev);
+ libra_sdio_setprivdata (sdio_func_dev_new, pHddCtx);
+ atomic_set(&pHddCtx->sdio_claim_count, 0);
+ pHddCtx->parent_dev = &sdio_func_dev_new->dev;
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: Card Detected Successfully %p",__func__,
+ sdio_func_dev_new);
+ break;
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to detect card change %p",__func__,
+ sdio_func_dev_new);
+ attempts++;
+ }
+ }while (attempts < LIBRA_CARD_INSERT_DETECT_MAX_COUNT);
+
+ if(LIBRA_CARD_INSERT_DETECT_MAX_COUNT == attempts){
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN fail to detect in reset, "
+ "exiting", __func__);
+ goto err_fail;
+ }
+ //Get the SDIO func device
+ sdio_func_dev_new = libra_getsdio_funcdev();
+ if(sdio_func_dev_new != NULL)
+ {
+ sd_claim_host(sdio_func_dev_new);
+ /* Enable IRQ capabilities in host controller */
+ libra_disable_sdio_irq_capability(sdio_func_dev_new, 0);
+ libra_enable_sdio_irq(sdio_func_dev_new, 1);
+ sd_release_host(sdio_func_dev_new);
+ }
+ else
+ {
+ /* Our card got removed before LOGP. */
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
+ goto err_fail;
+ }
+
+ vosStatus = WLANBAL_Open(pVosContext);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to open BAL",__func__);
+ goto err_fail;
+ }
+
+ vosStatus = WLANSAL_Start(pVosContext);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
+ goto err_balclose;
+ }
+
+ /* Chip is reset so allow Lower MAC to start accessing WLAN registers. Note HDD is still blocked */
+ vos_set_logp_in_progress(VOS_MODULE_ID_HDD, FALSE);
+
+ /* Start BAL */
+ vosStatus = WLANBAL_Start(pVosContext);
+
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start BAL",__func__);
+ goto err_salstop;
+ }
+#endif
+ // Open VOSS
+ vosStatus = vos_open( &pVosContext, 0);
+
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
+#ifdef ANI_BUS_TYPE_SDIO
+ goto err_balstop;
+#else
+ goto err_pwr_fail;
+#endif
+ }
+
+ /* Save the hal context in Adapter */
+ pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
+
+ if ( NULL == pHddCtx->hHal )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
+ goto err_vosclose;
+ }
+ // Set the SME configuration parameters...
+ vosStatus = hdd_set_sme_config(pHddCtx);
+
+ if ( VOS_STATUS_SUCCESS != vosStatus )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
+ goto err_vosclose;
+ }
+
+ //Initialize the WMM module
+ vosStatus = hdd_wmm_init(pHddCtx);
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __FUNCTION__);
+ goto err_vosclose;
+ }
+
+ /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
+ Note: Firmware image will be read and downloaded inside vos_start API */
+ vosStatus = vos_start( pVosContext );
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
+ goto err_vosclose;
+ }
+
+ vosStatus = hdd_post_voss_start_config( pHddCtx );
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
+ __func__);
+ goto err_vosstop;
+ }
+
+ /* Restart all adapters */
+ hdd_start_all_adapters(pHddCtx);
+ pHddCtx->isLogpInProgress = FALSE;
+ pHddCtx->hdd_mcastbcast_filter_set = FALSE;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ hdd_register_mcast_bcast_filter(pHddCtx);
+#endif
+
+ // Allow the phone to go to sleep
+ hdd_allow_suspend();
+
+ goto success;
+
+err_vosstop:
+ vos_stop(pVosContext);
+
+err_vosclose:
+ vos_close(pVosContext );
+ vos_sched_close(pVosContext);
+
+#ifdef ANI_BUS_TYPE_SDIO
+err_balstop:
+#ifndef ANI_MANF_DIAG
+ wlan_hdd_enable_deepsleep(pVosContext);
+#endif
+ WLANBAL_Stop(pVosContext);
+ WLANBAL_SuspendChip(pVosContext);
+
+err_salstop:
+ WLANSAL_Stop(pVosContext);
+
+err_balclose:
+ WLANBAL_Close(pVosContext);
+
+err_fail:
+ //Assert Deep sleep signal now to put Libra HW in lowest power state
+ vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
+
+ //Vote off any PMIC voltage supplies
+ vos_chipPowerDown(NULL, NULL, NULL);
+#endif
+
+err_pwr_fail:
+ vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
+
+ // Allow the phone to go to sleep
+ hdd_allow_suspend();
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ // unregister suspend/resume callbacks
+ if(pHddCtx->cfg_ini->nEnableSuspend)
+ unregister_wlan_suspend();
+#endif
+
+ // Unregister the Net Device Notifier
+ unregister_netdevice_notifier(&hdd_netdev_notifier);
+
+ //Clean up HDD Nlink Service
+ send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
+ nl_srv_exit();
+
+ hdd_close_all_adapters(pHddCtx);
+ //Free up dynamically allocated members inside HDD Adapter
+ kfree(pHddCtx->cfg_ini);
+ pHddCtx->cfg_ini= NULL;
+
+#ifdef CONFIG_CFG80211
+ wiphy_unregister(pHddCtx->wiphy);
+ wiphy_free(pHddCtx->wiphy);
+#else
+ vos_mem_free(pHddCtx);
+#endif
+
+#ifdef ANI_BUS_TYPE_SDIO
+ WLANSAL_Close(pVosContext);
+#endif
+ vos_preClose(&pVosContext);
+
+#ifdef MEMORY_DEBUG
+ vos_mem_exit();
+#endif
+
+ return -1;
+
+success:
+ //Trigger replay of BTC events
+ send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
+ return VOS_STATUS_SUCCESS;
+
+}
+
+
+
+VOS_STATUS hdd_wlan_reset_initialization(void)
+{
+#ifdef ANI_BUS_TYPE_SDIO
+ struct sdio_func *sdio_func_dev = NULL;
+ v_U8_t regValue = 0;
+ int err_ret = 0;
+#endif
+ v_CONTEXT_t pVosContext = NULL;
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
+
+ //Get the global VOSS context.
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ if(!pVosContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
+
+ // Prevent the phone from going to sleep
+ hdd_prevent_suspend();
+
+#ifdef ANI_BUS_TYPE_SDIO
+ /* Clear pending interrupt and disable Interrupts. Use only CMD52 */
+ VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
+ "%s LOGP in progress. Disabling Interrupt", __func__);
+
+ sdio_func_dev = libra_getsdio_funcdev();
+
+ if(sdio_func_dev == NULL)
+ {
+ /* Our card got removed before LOGP. Continue with reset anyways */
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
+ return VOS_STATUS_SUCCESS;
+ }
+
+ sd_claim_host(sdio_func_dev);
+
+ regValue = 0;
+ libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_SIF_INT_EN_REG,
+ ®Value, 1, &err_ret);
+
+ VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
+ "%s LOGP Cleared SIF_SIF_INT_EN_REG status:%d", __func__,err_ret);
+
+ regValue = 0;
+ libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_PEND_REG,
+ ®Value, 1, &err_ret);
+
+ VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
+ "%s LOGP Cleared SIF_BAR4_INT_PEND_REG status :%d", __func__,err_ret);
+
+ regValue = 0;
+ libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_ENABLE_REG,
+ ®Value, 1, &err_ret);
+
+ VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
+ "%s LOGP Cleared SIF_BAR4_INT_ENABLE_REG: Status:%d", __func__,err_ret);
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing Suspend Chip",__func__);
+
+ //Put the chip is standby before asserting deep sleep
+ WLANBAL_SuspendChip_NoLock( pVosContext );
+
+ sd_release_host(sdio_func_dev);
+#endif
+
+ return VOS_STATUS_SUCCESS;
+}
+
+
+void register_wlan_suspend(void)
+{
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Register WLAN suspend/resume "
+ "callbacks",__func__);
+ wlan_early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
+ wlan_early_suspend.suspend = hdd_suspend_wlan;
+ wlan_early_suspend.resume = hdd_resume_wlan;
+ register_early_suspend(&wlan_early_suspend);
+}
+
+void unregister_wlan_suspend(void)
+{
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Unregister WLAN suspend/resume "
+ "callbacks",__func__);
+ unregister_early_suspend(&wlan_early_suspend);
+}
+#endif
+
+/* the HDD interface to WLAN driver shutdown,
+ * the primary shutdown function in SSR
+ */
+VOS_STATUS hdd_wlan_shutdown(void)
+{
+ VOS_STATUS vosStatus;
+ v_CONTEXT_t pVosContext = NULL;
+ hdd_context_t *pHddCtx = NULL;
+ pVosSchedContext vosSchedContext = NULL;
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
+
+ /* Get the global VOSS context. */
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ if(!pVosContext) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ /* Get the HDD context. */
+ pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
+ if(!pHddCtx) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ hdd_reset_all_adapters(pHddCtx);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ /* unregister suspend/resume callbacks */
+ if(pHddCtx->cfg_ini->nEnableSuspend)
+ {
+ unregister_wlan_suspend();
+ }
+#endif
+ /* DeRegister with platform driver as client for Suspend/Resume */
+ vosStatus = hddDeregisterPmOps(pHddCtx);
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
+ }
+
+ vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
+ }
+
+ /* Disable IMPS/BMPS as we do not want the device to enter any power
+ * save mode on its own during reset sequence
+ */
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
+
+ vosSchedContext = get_vos_sched_ctxt();
+
+ /* Wakeup all driver threads */
+ if(TRUE == pHddCtx->isMcThreadSuspended){
+ complete(&vosSchedContext->ResumeMcEvent);
+ pHddCtx->isMcThreadSuspended= FALSE;
+ }
+ if(TRUE == pHddCtx->isTxThreadSuspended){
+ complete(&vosSchedContext->ResumeTxEvent);
+ pHddCtx->isTxThreadSuspended= FALSE;
+ }
+ if(TRUE == pHddCtx->isRxThreadSuspended){
+ complete(&vosSchedContext->ResumeRxEvent);
+ pHddCtx->isRxThreadSuspended= FALSE;
+ }
+ /* Reset the Suspend Variable */
+ pHddCtx->isWlanSuspended = FALSE;
+
+ /* Stop all the threads; we do not want any messages to be a processed,
+ * any more and the best way to ensure that is to terminate the threads
+ * gracefully.
+ */
+ /* Wait for MC to exit */
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
+ set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
+ set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
+ wake_up_interruptible(&vosSchedContext->mcWaitQueue);
+ wait_for_completion_interruptible(&vosSchedContext->McShutdown);
+
+ /* Wait for TX to exit */
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
+ set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
+ set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
+ wake_up_interruptible(&vosSchedContext->txWaitQueue);
+ wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
+
+ /* Wait for RX to exit */
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
+ set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
+ set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
+ wake_up_interruptible(&vosSchedContext->rxWaitQueue);
+ wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
+
+#ifdef WLAN_BTAMP_FEATURE
+ vosStatus = WLANBAP_Stop(pVosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to stop BAP",__func__);
+ }
+#endif //WLAN_BTAMP_FEATURE
+ vosStatus = vos_wda_shutdown(pVosContext);
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
+ /* Stop SME - Cannot invoke vos_stop as vos_stop relies
+ * on threads being running to process the SYS Stop
+ */
+ vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
+ /* Stop MAC (PE and HAL) */
+ vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
+ /* Stop TL */
+ vosStatus = WLANTL_Stop(pVosContext);
+ VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ hdd_unregister_mcast_bcast_filter(pHddCtx);
+#endif
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
+ /* Clean up message queues of TX and MC thread */
+ vos_sched_flush_mc_mqs(vosSchedContext);
+ vos_sched_flush_tx_mqs(vosSchedContext);
+ vos_sched_flush_rx_mqs(vosSchedContext);
+
+ /* Deinit all the TX and MC queues */
+ vos_sched_deinit_mqs(vosSchedContext);
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
+
+ /* shutdown VOSS */
+ vos_shutdown(pVosContext);
+ if (free_riva_power_on_lock("wlan"))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
+ __func__);
+ }
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
+ ,__func__);
+ return VOS_STATUS_SUCCESS;
+}
+
+
+
+/* the HDD interface to WLAN driver re-init.
+ * This is called to initialize/start WLAN driver after a shutdown.
+ */
+VOS_STATUS hdd_wlan_re_init(void)
+{
+ VOS_STATUS vosStatus;
+ v_CONTEXT_t pVosContext = NULL;
+ hdd_context_t *pHddCtx = NULL;
+ eHalStatus halStatus;
+#ifdef WLAN_BTAMP_FEATURE
+ hdd_config_t *pConfig = NULL;
+ WLANBAP_ConfigType btAmpConfig;
+#endif
+
+ hdd_prevent_suspend();
+ /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
+ vosStatus = vos_open(&pVosContext, 0);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
+ goto err_re_init;
+ }
+
+ /* Get the HDD context. */
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
+ if(!pHddCtx)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
+ goto err_vosclose;
+ }
+
+ /* Save the hal context in Adapter */
+ pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
+ if ( NULL == pHddCtx->hHal )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
+ goto err_vosclose;
+ }
+
+ /* Set the SME configuration parameters. */
+ vosStatus = hdd_set_sme_config(pHddCtx);
+ if ( VOS_STATUS_SUCCESS != vosStatus )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
+ goto err_vosclose;
+ }
+
+ /* Initialize the WMM module */
+ vosStatus = hdd_wmm_init(pHddCtx);
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __FUNCTION__);
+ goto err_vosclose;
+ }
+
+ vosStatus = vos_preStart( pHddCtx->pvosContext );
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
+ goto err_vosclose;
+ }
+
+ /* In the integrated architecture we update the configuration from
+ the INI file and from NV before vOSS has been started so that
+ the final contents are available to send down to the cCPU */
+ /* Apply the cfg.ini to cfg.dat */
+ if (FALSE == hdd_update_config_dat(pHddCtx))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
+ goto err_vosclose;
+ }
+
+ /* Set the MAC Address, currently this is used by HAL to add self sta.
+ * Remove this once self sta is added as part of session open. */
+ halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
+ (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
+ sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
+ if (!HAL_STATUS_SUCCESS(halStatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
+ "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
+ goto err_vosclose;
+ }
+
+ /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
+ Note: Firmware image will be read and downloaded inside vos_start API */
+ vosStatus = vos_start( pVosContext );
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
+ goto err_vosclose;
+ }
+
+ vosStatus = hdd_post_voss_start_config( pHddCtx );
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
+ __func__);
+ goto err_vosstop;
+ }
+
+#ifdef WLAN_BTAMP_FEATURE
+ vosStatus = WLANBAP_Open(pVosContext);
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to open BAP",__func__);
+ goto err_vosstop;
+ }
+ vosStatus = BSL_Init(pVosContext);
+ if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to Init BSL",__func__);
+ goto err_bap_close;
+ }
+ vosStatus = WLANBAP_Start(pVosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start TL",__func__);
+ goto err_bap_close;
+ }
+ pConfig = pHddCtx->cfg_ini;
+ btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
+ vosStatus = WLANBAP_SetConfig(&btAmpConfig);
+#endif //WLAN_BTAMP_FEATURE
+
+ /* Restart all adapters */
+ hdd_start_all_adapters(pHddCtx);
+ pHddCtx->isLogpInProgress = FALSE;
+ pHddCtx->hdd_mcastbcast_filter_set = FALSE;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ hdd_register_mcast_bcast_filter(pHddCtx);
+#endif
+
+ /* Register with platform driver as client for Suspend/Resume */
+ vosStatus = hddRegisterPmOps(pHddCtx);
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
+ goto err_bap_stop;
+ }
+ // Register suspend/resume callbacks
+ if(pHddCtx->cfg_ini->nEnableSuspend)
+ {
+ register_wlan_suspend();
+ }
+ /* Allow the phone to go to sleep */
+ hdd_allow_suspend();
+ /* register for riva power on lock */
+ if (req_riva_power_on_lock("wlan"))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
+ __func__);
+ goto err_unregister_pmops;
+ }
+ goto success;
+
+err_unregister_pmops:
+ hddDeregisterPmOps(pHddCtx);
+
+err_bap_stop:
+#ifdef WLAN_BTAMP_FEATURE
+ WLANBAP_Stop(pVosContext);
+#endif
+
+#ifdef WLAN_BTAMP_FEATURE
+err_bap_close:
+ WLANBAP_Close(pVosContext);
+#endif
+
+err_vosstop:
+ vos_stop(pVosContext);
+
+err_vosclose:
+ vos_close(pVosContext);
+ vos_sched_close(pVosContext);
+ if (pHddCtx)
+ {
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ /* unregister suspend/resume callbacks */
+ if (pHddCtx->cfg_ini->nEnableSuspend)
+ unregister_wlan_suspend();
+#endif
+ /* Unregister the Net Device Notifier */
+ unregister_netdevice_notifier(&hdd_netdev_notifier);
+ /* Clean up HDD Nlink Service */
+ send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
+ nl_srv_exit();
+ hdd_close_all_adapters(pHddCtx);
+ /* Free up dynamically allocated members inside HDD Adapter */
+ kfree(pHddCtx->cfg_ini);
+ pHddCtx->cfg_ini= NULL;
+
+#ifdef CONFIG_CFG80211
+ wiphy_unregister(pHddCtx->wiphy);
+ wiphy_free(pHddCtx->wiphy);
+#else
+ vos_mem_free(pHddCtx);
+#endif
+ }
+ vos_preClose(&pVosContext);
+
+#ifdef MEMORY_DEBUG
+ vos_mem_exit();
+#endif
+
+err_re_init:
+ /* Allow the phone to go to sleep */
+ hdd_allow_suspend();
+ return -1;
+
+success:
+ /* Trigger replay of BTC events */
+ send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
+ return VOS_STATUS_SUCCESS;
+}
diff --git a/CORE/HDD/src/wlan_hdd_ftm.c b/CORE/HDD/src/wlan_hdd_ftm.c
new file mode 100644
index 0000000..f3122db
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_ftm.c
@@ -0,0 +1,4736 @@
+/*
+ * 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 wlan_hdd_ftm.c
+
+ \brief This file contains the WLAN factory test mode implementation
+
+ 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.
+
+
+ $Header:$ $DateTime: $ $Author: $
+
+
+ when who what, where, why
+ -------- --- --------------------------------------------------------
+ 04/20/11 Leo/Henri Convergence for Prima and Volans. Single image
+ for FTM and mission mode
+ 04/5/09 Shailender Created module.
+
+ ==========================================================================*/
+#include <vos_mq.h>
+#include "vos_sched.h"
+#include <vos_api.h>
+#include "sirTypes.h"
+#include "halTypes.h"
+#include "sirApi.h"
+#include "sirMacProtDef.h"
+#include "sme_Api.h"
+#include "macInitApi.h"
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+#include "wlan_qct_sal.h"
+#include "wlan_qct_bal.h"
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+#include "wlan_qct_sys.h"
+#include "wlan_qct_tl.h"
+#include "wlan_hdd_misc.h"
+#include "i_vos_packet.h"
+#include "vos_nvitem.h"
+#include "wlan_hdd_main.h"
+#include "vos_power.h"
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+#include "ani_assert.h"
+#include "sys_api.h"
+#include "pttModuleApi.h"
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+#include "qwlan_version.h"
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include "wlan_nv.h"
+#include "wlan_qct_wda.h"
+#include "cfgApi.h"
+#include "pttMsgApi.h"
+#include "wlan_qct_pal_device.h"
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+#ifdef ANI_MANF_DIAG
+#define RXMODE_DISABLE_ALL 0
+#define RXMODE_ENABLE_ALL 1
+#define RXMODE_ENABLE_11GN 2
+#define RXMODE_ENABLE_11B 3
+
+#define FTM_CHAIN_SEL_NO_RX_TX 0
+#define FTM_CHAIN_SEL_R0_ON 1
+#define FTM_CHAIN_SEL_T0_ON 2
+#define FTM_CHAIN_SEL_R0_T0_ON 3
+#define FTM_CHAIN_SEL_MAX 3
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#ifndef QWLAN_PHYDBG_BASE
+#define QWLAN_PHYDBG_BASE 0x03004000
+#endif /* QWLAN_PHYDBG_BASE */
+
+#ifndef QWLAN_PHYDBG_TXPKT_CNT_REG
+#define QWLAN_PHYDBG_TXPKT_CNT_REG QWLAN_PHYDBG_BASE + 0x6C
+#define QWLAN_PHYDBG_TXPKT_CNT_CNT_MASK 0xFFFF
+#endif
+
+#ifndef QWLAN_AGC_BASE
+#define QWLAN_AGC_BASE 0x03013C00
+#endif /* QWLAN_AGC_BASE */
+
+#ifndef QWLAN_AGC_CHANNEL_FREQ_REG
+#define QWLAN_AGC_CHANNEL_FREQ_REG QWLAN_AGC_BASE + 0x34
+#define QWLAN_AGC_CHANNEL_FREQ_FREQ_MASK 0x1FFF
+#endif /* QWLAN_AGC_CHANNEL_FREQ_REG */
+
+#ifndef QWLAN_AGC_SUBBAND_CONFIG_REG
+#define QWLAN_AGC_SUBBAND_CONFIG_REG QWLAN_AGC_BASE + 0x30
+#define QWLAN_AGC_SUBBAND_CONFIG_STG2_SUBBAND_MASK 0x03
+#endif /* QWLAN_AGC_SUBBAND_CONFIG_REG */
+
+#ifndef QWLAN_RFAPB_BASE
+#define QWLAN_RFAPB_BASE 0x0E02F800
+#endif /* QWLAN_RFAPB_BASE */
+
+#ifndef QWLAN_RFAPB_REV_ID_REG
+#define QWLAN_RFAPB_REV_ID_REG QWLAN_RFAPB_BASE + 0x00
+#endif /* QWLAN_RFAPB_REV_ID_REG */
+
+#ifndef QWLAN_TXCTL_BASE
+#define QWLAN_TXCTL_BASE 0x03012000
+#endif /* QWLAN_TXCTL_BASE */
+
+#ifndef QWLAN_TXCTL_FSHIFT_REG
+#define QWLAN_TXCTL_FSHIFT_REG QWLAN_TXCTL_BASE + 0x20
+#define QWLAN_TXCTL_FSHIFT_BW14_OFFSET 0x02
+#define QWLAN_TXCTL_FSHIFT_BW14_MASK 0x1C
+#define QWLAN_TXCTL_FSHIFT_BW12_OFFSET 0x00
+#define QWLAN_TXCTL_FSHIFT_BW12_MASK 0x03
+#endif /* QWLAN_TXCTL_FSHIFT_REG */
+
+/* To set 4MAC addresses from given first MAC address,
+ * Last byte value within given MAC address must less than 0xFF - 3 */
+#define QWLAN_MAX_MAC_LAST_BYTE_VALUE 0xFC
+
+typedef struct {
+ tANI_U32 tableSize; /* Whole NV Table Size */
+ tANI_U32 chunkSize; /* Current Chunk Size < 2K */
+ eNvTable nvTable;
+ tANI_U8 tableData; /* Filled by host driver */
+} pttGetNvTable;
+
+typedef struct {
+ tANI_U32 tableSize; /* Whole NV Table Size */
+ tANI_U32 chunkSize; /* Current Chunk Size < 2K */
+ eNvTable nvTable;
+ tANI_U8 tableData;
+} pttSetNvTable;
+
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+extern const sHalNv nvDefaults;
+static int wlan_ftm_register_wext(hdd_adapter_t *pAdapter);
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+static v_VOID_t ftm_vos_sys_probe_thread_cback( v_VOID_t *pUserData );
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+/* for PRIMA: all the available frequency, channal pair i the table are defined for channel frequency @ RF center frequency
+ Since it is associated to agc.channel_freq register for mapping.
+ For channel bonding, the channel number is +2 or -2 for CB with primary high, or with primary low respectively.
+*/
+static const freq_chan_t freq_chan_tbl[] = {
+ {2412, 1}, {2417, 2},{2422, 3}, {2427, 4}, {2432, 5}, {2437, 6}, {2442, 7},
+ {2447, 8}, {2452, 9},{2457, 10},{2462, 11},{2467 ,12},{2472, 13},{2484, 14}
+};
+
+static rateStr2rateIndex_t rateName_rateIndex_tbl[] =
+{
+ { HAL_PHY_RATE_11B_LONG_1_MBPS, "11B_LONG_1_MBPS"},
+ { HAL_PHY_RATE_11B_LONG_2_MBPS, "11B_LONG_2_MBPS"},
+ { HAL_PHY_RATE_11B_LONG_5_5_MBPS, "11B_LONG_5_5_MBPS"},
+ { HAL_PHY_RATE_11B_LONG_11_MBPS, "11B_LONG_11_MBPS"},
+ { HAL_PHY_RATE_11B_SHORT_2_MBPS, "11B_SHORT_2_MBPS"},
+ { HAL_PHY_RATE_11B_SHORT_5_5_MBPS, "11B_SHORT_5_5_MBPS"},
+ { HAL_PHY_RATE_11B_SHORT_11_MBPS, "11B_SHORT_11_MBPS"},
+ //Spica_Virgo 11A 20MHz Rates
+ { HAL_PHY_RATE_11A_6_MBPS, "11A_6_MBPS"},
+ { HAL_PHY_RATE_11A_9_MBPS, "11A_9_MBPS"},
+ { HAL_PHY_RATE_11A_12_MBPS, "11A_12_MBPS"},
+ { HAL_PHY_RATE_11A_18_MBPS, "11A_18_MBPS"},
+ { HAL_PHY_RATE_11A_24_MBPS, "11A_24_MBPS"},
+ { HAL_PHY_RATE_11A_36_MBPS, "11A_36_MBPS"},
+ { HAL_PHY_RATE_11A_48_MBPS, "11A_48_MBPS"},
+ { HAL_PHY_RATE_11A_54_MBPS, "11A_54_MBPS"},
+
+//MCS Index #0-15 (20MHz)
+ { HAL_PHY_RATE_MCS_1NSS_6_5_MBPS, "MCS_6_5_MBPS"},
+ { HAL_PHY_RATE_MCS_1NSS_13_MBPS, "MCS_13_MBPS"},
+ { HAL_PHY_RATE_MCS_1NSS_19_5_MBPS, "MCS_19_5_MBPS"},
+ { HAL_PHY_RATE_MCS_1NSS_26_MBPS, "MCS_26_MBPS"},
+ { HAL_PHY_RATE_MCS_1NSS_39_MBPS, "MCS_39_MBPS"},
+ { HAL_PHY_RATE_MCS_1NSS_52_MBPS, "MCS_52_MBPS"},
+ { HAL_PHY_RATE_MCS_1NSS_58_5_MBPS, "MCS_58_5_MBPS"},
+ { HAL_PHY_RATE_MCS_1NSS_65_MBPS, "MCS_65_MBPS"},
+ { HAL_PHY_RATE_MCS_1NSS_MM_SG_72_2_MBPS, "MCS_72_2_MBPS"}
+};
+
+static rateIndex2Preamble_t rate_index_2_preamble_table[] =
+{
+
+ { HAL_PHY_RATE_11B_LONG_1_MBPS, PHYDBG_PREAMBLE_LONGB},
+ { HAL_PHY_RATE_11B_LONG_2_MBPS, PHYDBG_PREAMBLE_LONGB},
+ { HAL_PHY_RATE_11B_LONG_5_5_MBPS, PHYDBG_PREAMBLE_LONGB},
+ { HAL_PHY_RATE_11B_LONG_11_MBPS, PHYDBG_PREAMBLE_LONGB},
+ { HAL_PHY_RATE_11B_SHORT_2_MBPS, PHYDBG_PREAMBLE_SHORTB},
+ { HAL_PHY_RATE_11B_SHORT_5_5_MBPS, PHYDBG_PREAMBLE_SHORTB},
+ { HAL_PHY_RATE_11B_SHORT_11_MBPS, PHYDBG_PREAMBLE_SHORTB},
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ //SLR Rates
+ { HAL_PHY_RATE_SLR_0_25_MBPS, PHYDBG_PREAMBLE_NOT_SUPPORTED},
+ { HAL_PHY_RATE_SLR_0_5_MBPS, PHYDBG_PREAMBLE_NOT_SUPPORTED},
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+ //Spica_Virgo 11A 20MHz Rates
+ { HAL_PHY_RATE_11A_6_MBPS, PHYDBG_PREAMBLE_OFDM},
+ { HAL_PHY_RATE_11A_9_MBPS, PHYDBG_PREAMBLE_OFDM},
+ { HAL_PHY_RATE_11A_12_MBPS, PHYDBG_PREAMBLE_OFDM},
+ { HAL_PHY_RATE_11A_18_MBPS, PHYDBG_PREAMBLE_OFDM},
+ { HAL_PHY_RATE_11A_24_MBPS, PHYDBG_PREAMBLE_OFDM},
+ { HAL_PHY_RATE_11A_36_MBPS, PHYDBG_PREAMBLE_OFDM},
+ { HAL_PHY_RATE_11A_48_MBPS, PHYDBG_PREAMBLE_OFDM},
+ { HAL_PHY_RATE_11A_54_MBPS, PHYDBG_PREAMBLE_OFDM},
+
+ //MCS Index #0-15 (20MHz)
+ { HAL_PHY_RATE_MCS_1NSS_6_5_MBPS, PHYDBG_PREAMBLE_MIXED},
+ { HAL_PHY_RATE_MCS_1NSS_13_MBPS, PHYDBG_PREAMBLE_MIXED},
+ { HAL_PHY_RATE_MCS_1NSS_19_5_MBPS, PHYDBG_PREAMBLE_MIXED},
+ { HAL_PHY_RATE_MCS_1NSS_26_MBPS, PHYDBG_PREAMBLE_MIXED},
+ { HAL_PHY_RATE_MCS_1NSS_39_MBPS, PHYDBG_PREAMBLE_MIXED},
+ { HAL_PHY_RATE_MCS_1NSS_52_MBPS, PHYDBG_PREAMBLE_MIXED},
+ { HAL_PHY_RATE_MCS_1NSS_58_5_MBPS, PHYDBG_PREAMBLE_MIXED},
+ { HAL_PHY_RATE_MCS_1NSS_65_MBPS, PHYDBG_PREAMBLE_MIXED},
+ { HAL_PHY_RATE_MCS_1NSS_MM_SG_7_2_MBPS, PHYDBG_PREAMBLE_NOT_SUPPORTED},
+ { HAL_PHY_RATE_MCS_1NSS_MM_SG_14_4_MBPS,PHYDBG_PREAMBLE_NOT_SUPPORTED},
+ { HAL_PHY_RATE_MCS_1NSS_MM_SG_21_7_MBPS,PHYDBG_PREAMBLE_NOT_SUPPORTED},
+ { HAL_PHY_RATE_MCS_1NSS_MM_SG_28_9_MBPS,PHYDBG_PREAMBLE_NOT_SUPPORTED},
+ { HAL_PHY_RATE_MCS_1NSS_MM_SG_43_3_MBPS,PHYDBG_PREAMBLE_NOT_SUPPORTED},
+ { HAL_PHY_RATE_MCS_1NSS_MM_SG_57_8_MBPS,PHYDBG_PREAMBLE_NOT_SUPPORTED},
+ { HAL_PHY_RATE_MCS_1NSS_MM_SG_65_MBPS, PHYDBG_PREAMBLE_NOT_SUPPORTED},
+ { HAL_PHY_RATE_MCS_1NSS_MM_SG_72_2_MBPS, PHYDBG_PREAMBLE_MIXED},
+};
+
+typedef struct
+{
+ tANI_BOOLEAN frameGenEnabled;
+ tANI_BOOLEAN wfmEnabled;
+ sPttFrameGenParams frameParams;
+ v_U16_t txpower;
+ v_U16_t rxmode;
+ v_U16_t chainSelect;
+
+} FTM_STATUS ;
+static FTM_STATUS ftm_status;
+
+//tpAniSirGlobal pMac;
+
+static void _ftm_status_init(void)
+{
+ tANI_U8 addr1[ANI_MAC_ADDR_SIZE] = { 0x00, 0x11, 0x11, 0x11, 0x11, 0x11 }; //dest
+ tANI_U8 addr2[ANI_MAC_ADDR_SIZE] = { 0x00, 0x22, 0x22, 0x22, 0x22, 0x22 }; //sour
+ tANI_U8 addr3[ANI_MAC_ADDR_SIZE] = { 0x00, 0x33, 0x33, 0x33, 0x33, 0x33 }; //bssId
+
+ ftm_status.wfmEnabled = eANI_BOOLEAN_FALSE;
+ ftm_status.frameGenEnabled = eANI_BOOLEAN_FALSE;
+ ftm_status.frameParams.numTestPackets = 0; //Continuous
+ ftm_status.frameParams.interFrameSpace = 10;
+ ftm_status.frameParams.rate = HAL_PHY_RATE_11A_6_MBPS;
+ ftm_status.frameParams.payloadContents = TEST_PAYLOAD_RANDOM;
+ ftm_status.frameParams.payloadLength = 2000;
+ ftm_status.frameParams.payloadFillByte = 0xA5;
+ ftm_status.frameParams.pktAutoSeqNum = eANI_BOOLEAN_FALSE;
+ ftm_status.frameParams.tx_mode = 0;
+ ftm_status.frameParams.crc = 0;
+ ftm_status.frameParams.preamble = PHYDBG_PREAMBLE_OFDM;
+ memcpy(&ftm_status.frameParams.addr1[0], addr1, ANI_MAC_ADDR_SIZE);
+ memcpy(&ftm_status.frameParams.addr2[0], addr2, ANI_MAC_ADDR_SIZE);
+ memcpy(&ftm_status.frameParams.addr3[0], addr3, ANI_MAC_ADDR_SIZE);
+ ftm_status.txpower = 2 ;
+ ftm_status.rxmode = RXMODE_ENABLE_ALL; /* macStart() enables all receive pkt types */
+ ftm_status.chainSelect = FTM_CHAIN_SEL_R0_T0_ON;
+
+ return;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_postmsg() -
+
+ The function used for sending the command to the halphy.
+
+ \param - cmd_ptr - Pointer command buffer.
+
+ \param - cmd_len - Command length.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static v_U32_t wlan_ftm_postmsg(v_U8_t *cmd_ptr, v_U16_t cmd_len)
+{
+ vos_msg_t *ftmReqMsg;
+ vos_msg_t ftmMsg;
+ ENTER();
+
+ ftmReqMsg = (vos_msg_t *) cmd_ptr;
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ ftmMsg.type = WDA_FTM_CMD_REQ;
+#else
+ ftmMsg.type = ftmReqMsg->type;
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+ ftmMsg.reserved = 0;
+ ftmMsg.bodyptr = (v_U8_t*)cmd_ptr;
+ ftmMsg.bodyval = 0;
+
+ /* Use Vos messaging mechanism to send the command to halPhy */
+ /*
+ Note that VOS_MODULE_ID_HAL corresponds to VOS_MODULE_ID_WDA
+ for INTEGRATED_SOC. SO this code is left as it is.
+ */
+ if (VOS_STATUS_SUCCESS != vos_mq_post_message(
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ VOS_MODULE_ID_HAL,
+#else
+ VOS_MODULE_ID_WDA,
+#endif
+ (vos_msg_t *)&ftmMsg)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL\n",__func__);
+
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ EXIT();
+ return VOS_STATUS_SUCCESS;
+}
+
+/*---------------------------------------------------------------------------
+
+ \brief wlan_ftm_vos_open() - Open the vOSS Module
+
+ The \a wlan_ftm_vos_open() function opens the vOSS Scheduler
+ Upon successful initialization:
+
+ - All VOS submodules should have been initialized
+
+ - The VOS scheduler should have opened
+
+ - All the WLAN SW components should have been opened. This include
+ MAC.
+
+
+ \param hddContextSize: Size of the HDD context to allocate.
+
+
+ \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and
+ is ready to be used.
+
+ VOS_STATUS_E_RESOURCES - System resources (other than memory)
+ are unavailable to initialize the scheduler
+
+
+ VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/
+
+ \sa wlan_ftm_vos_open()
+
+---------------------------------------------------------------------------*/
+static VOS_STATUS wlan_ftm_vos_open( v_CONTEXT_t pVosContext, v_SIZE_t hddContextSize )
+{
+ VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
+ int iter = 0;
+ tSirRetStatus sirStatus = eSIR_SUCCESS;
+ tMacOpenParameters macOpenParms;
+ pVosContextType gpVosContext = (pVosContextType)pVosContext;
+
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: Opening VOSS", __func__);
+
+ if (NULL == gpVosContext)
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Trying to open VOSS without a PreOpen",__func__);
+ VOS_ASSERT(0);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* Initialize the probe event */
+ if (vos_event_init(&gpVosContext->ProbeEvent) != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to init probeEvent",__func__);
+ VOS_ASSERT(0);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ if(vos_event_init(&(gpVosContext->wdaCompleteEvent)) != VOS_STATUS_SUCCESS )
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to init wdaCompleteEvent",__func__);
+ VOS_ASSERT(0);
+
+ goto err_probe_event;
+ }
+#endif /*FEATURE_WLAN_INTEGRATED_SOC */
+
+ /* Initialize the free message queue */
+ vStatus = vos_mq_init(&gpVosContext->freeVosMq);
+ if (! VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+
+ /* Critical Error ... Cannot proceed further */
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to initialize VOS free message queue",__func__);
+ VOS_ASSERT(0);
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ goto err_wda_complete_event;
+#else
+ goto err_probe_event;
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+ }
+
+ for (iter = 0; iter < VOS_CORE_MAX_MESSAGES; iter++)
+ {
+ (gpVosContext->aMsgWrappers[iter]).pVosMsg =
+ &(gpVosContext->aMsgBuffers[iter]);
+ INIT_LIST_HEAD(&gpVosContext->aMsgWrappers[iter].msgNode);
+ vos_mq_put(&gpVosContext->freeVosMq, &(gpVosContext->aMsgWrappers[iter]));
+ }
+
+ /* Now Open the VOS Scheduler */
+ vStatus= vos_sched_open(gpVosContext, &gpVosContext->vosSched,
+ sizeof(VosSchedContext));
+
+ if (!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ /* Critical Error ... Cannot proceed further */
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to open VOS Scheduler", __func__);
+ VOS_ASSERT(0);
+ goto err_msg_queue;
+ }
+
+ /* Open the SYS module */
+ vStatus = sysOpen(gpVosContext);
+
+ if (!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ /* Critical Error ... Cannot proceed further */
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to open SYS module",__func__);
+ VOS_ASSERT(0);
+ goto err_sched_close;
+ }
+
+ #ifdef FEATURE_WLAN_INTEGRATED_SOC
+ /*Open the WDA module */
+ vos_mem_set(&macOpenParms, sizeof(macOpenParms), 0);
+ macOpenParms.driverType = eDRIVER_TYPE_MFG;
+ vStatus = WDA_open(gpVosContext, gpVosContext->pHDDContext, &macOpenParms);
+ if (!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ /* Critical Error ... Cannot proceed further */
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to open WDA module",__func__);
+ VOS_ASSERT(0);
+ goto err_sys_close;
+ }
+#endif
+
+ /* initialize the NV module */
+ vStatus = vos_nv_open();
+ if (!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ // NV module cannot be initialized, however the driver is allowed
+ // to proceed
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to initialize the NV module", __func__);
+ goto err_wda_close;
+ }
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ /* Probe the MC thread */
+ sysMcThreadProbe(gpVosContext,
+ &ftm_vos_sys_probe_thread_cback,
+ gpVosContext);
+
+
+ if (vos_wait_single_event(&gpVosContext->ProbeEvent, 0)!= VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to probe MC Thread", __func__);
+ VOS_ASSERT(0);
+ goto err_nv_close;
+ }
+#endif
+ /* If we arrive here, both threads dispacthing messages correctly */
+
+ /* Now proceed to open the MAC */
+
+ /* UMA is supported in hardware for performing the
+ frame translation 802.11 <-> 802.3 */
+ macOpenParms.frameTransRequired = 1;
+ sirStatus = macOpen(&(gpVosContext->pMACContext), gpVosContext->pHDDContext,
+ &macOpenParms);
+
+ if (eSIR_SUCCESS != sirStatus)
+ {
+ /* Critical Error ... Cannot proceed further */
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to open MAC", __func__);
+ VOS_ASSERT(0);
+ goto err_nv_close;
+ }
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ vStatus = WLANBAL_Open(gpVosContext);
+ if(!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to open BAL",__func__);
+ goto err_mac_close;
+ }
+#else
+ /* Now proceed to open the SME */
+ vStatus = sme_Open(gpVosContext->pMACContext);
+ if (!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ /* Critical Error ... Cannot proceed further */
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to open SME",__func__);
+ goto err_mac_close;
+ }
+ return VOS_STATUS_SUCCESS;
+
+#endif
+
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: VOSS successfully Opened",__func__);
+
+ return VOS_STATUS_SUCCESS;
+err_mac_close:
+ macClose(gpVosContext->pMACContext);
+
+err_nv_close:
+ vos_nv_close();
+
+err_wda_close:
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ WDA_close(gpVosContext);
+
+err_sys_close:
+#endif
+ sysClose(gpVosContext);
+
+err_sched_close:
+ vos_sched_close(gpVosContext);
+err_msg_queue:
+ vos_mq_deinit(&gpVosContext->freeVosMq);
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+err_wda_complete_event:
+ vos_event_destroy(&gpVosContext->wdaCompleteEvent);
+#endif
+
+err_probe_event:
+ vos_event_destroy(&gpVosContext->ProbeEvent);
+
+ return VOS_STATUS_E_FAILURE;
+
+} /* wlan_ftm_vos_open() */
+
+/*---------------------------------------------------------------------------
+
+ \brief wlan_ftm_vos_close() - Close the vOSS Module
+
+ The \a wlan_ftm_vos_close() function closes the vOSS Module
+
+ \param vosContext context of vos
+
+ \return VOS_STATUS_SUCCESS - successfully closed
+
+ \sa wlan_ftm_vos_close()
+
+---------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_vos_close( v_CONTEXT_t vosContext )
+{
+ VOS_STATUS vosStatus;
+ pVosContextType gpVosContext = (pVosContextType)vosContext;
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ vosStatus = WLANBAL_Close(vosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to close BAL",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+#else
+ vosStatus = sme_Close(((pVosContextType)vosContext)->pMACContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to close BAL",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+#endif
+
+ vosStatus = macClose( ((pVosContextType)vosContext)->pMACContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to close MAC",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+ ((pVosContextType)vosContext)->pMACContext = NULL;
+
+ vosStatus = vos_nv_close();
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to close NV",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+
+ vosStatus = sysClose( vosContext );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to close SYS",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ vosStatus = WDA_close( vosContext );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to close WDA",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+ vos_mq_deinit(&((pVosContextType)vosContext)->freeVosMq);
+
+ vosStatus = vos_event_destroy(&gpVosContext->ProbeEvent);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to destroy ProbeEvent",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ vosStatus = vos_event_destroy(&gpVosContext->wdaCompleteEvent);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to destroy wdaCompleteEvent",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+#endif
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_set_txifs() -
+
+ This function is used for
+
+ \param - pAdapter - Pointer HDD Context.
+ - ifs
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+
+
+static VOS_STATUS wlan_ftm_priv_set_txifs(hdd_adapter_t *pAdapter,v_U32_t ifs)
+{
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* do not allow to change setting when tx pktgen is enabled */
+ if (ftm_status.frameGenEnabled)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:cannot set txifs when pktgen is enabled.",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if (ifs > 100000) //max = (MSK_24 / ONE_MICROSECOND)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:ifs value is invalid ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ftm_status.frameParams.interFrameSpace = ifs;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_set_txpktcnt() -
+
+ This function is used for
+
+ \param - pAdapter - Pointer HDD Context.
+ - ifs
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_set_txpktcnt(hdd_adapter_t *pAdapter,v_U32_t cnt)
+{
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* do not allow to change setting when tx pktgen is enabled */
+ if (ftm_status.frameGenEnabled)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:cannot set txpktcnt when pktgen is enabled.",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if (cnt > QWLAN_PHYDBG_TXPKT_CNT_CNT_MASK) //0xFFFF
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pktcnt value is invalid",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ftm_status.frameParams.numTestPackets = cnt;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+static VOS_STATUS wlan_ftm_priv_set_txpktlen(hdd_adapter_t *pAdapter,v_U32_t len)
+{
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* do not allow to change setting when tx pktgen is enabled */
+ if (ftm_status.frameGenEnabled)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:cannot set txpktcnt when pktgen is enabled.",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if (len > 4095) //4096
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:payload len is invalid",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ftm_status.frameParams.payloadLength = (tANI_U16)len;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_enable_chain(hdd_adapter_t *pAdapter,v_U16_t chainSelect)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ v_U16_t chainSelect_save = chainSelect;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if (chainSelect > FTM_CHAIN_SEL_MAX)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Invalid chain",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* do not allow to change setting when tx pktgen is enabled */
+ if (ftm_status.frameGenEnabled)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:cannot select chain when pktgen is enabled.",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ switch (chainSelect)
+ {
+ case FTM_CHAIN_SEL_NO_RX_TX:
+ chainSelect = PHY_CHAIN_SEL_NO_RX_TX;
+ break;
+
+ case FTM_CHAIN_SEL_R0_ON:
+ chainSelect = PHY_CHAIN_SEL_R0_ON;
+ break;
+
+ case FTM_CHAIN_SEL_T0_ON:
+ chainSelect = PHY_CHAIN_SEL_T0_ON;
+ break;
+ }
+
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_ENABLE_CHAINS;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttEnableChains) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->EnableChains.chainSelect = chainSelect;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ ftm_status.chainSelect = chainSelect_save;
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+ --------------------------------------------------------------------------*/
+static VOS_STATUS wlan_ftm_priv_get_status(hdd_adapter_t *pAdapter,char *buf)
+{
+ int ii;
+ int lenBuf = WE_FTM_MAX_STR_LEN;
+ int lenRes = 0;
+ char *chain[] = {
+ "None",
+ "R0,R1",
+ "R0",
+ "R1",
+ "T0",
+ "R0,R1,T0"
+ };
+ char *rx[] = {
+ "disable",
+ "11b/g/n",
+ "11g/n",
+ "11b"
+ };
+ char *tx[] = {
+ "stopped",
+ "started",
+ };
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ lenRes = snprintf(buf, lenBuf, "\n chainSelect: %s\n rxmode: %s\n "
+ "txpktgen: %s\n txifs: %ld\n txrate: ",
+ chain[ftm_status.chainSelect], rx[ftm_status.rxmode],
+ tx[ftm_status.frameGenEnabled],
+ ftm_status.frameParams.interFrameSpace);
+ if ((lenRes < 0) || (lenRes >= lenBuf))
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ buf += lenRes;
+ lenBuf -= lenRes;
+
+ for (ii = 0; ii < SIZE_OF_TABLE(rateName_rateIndex_tbl); ii++)
+ {
+ if (rateName_rateIndex_tbl[ii].rate_index == ftm_status.frameParams.rate)
+ break;
+ }
+
+ if (ii < SIZE_OF_TABLE(rateName_rateIndex_tbl))
+ {
+ lenRes = strlcpy(buf, rateName_rateIndex_tbl[ii].rate_str, lenBuf);
+ }
+ else
+ {
+ lenRes = strlcpy(buf, "invalid", lenBuf);
+ }
+ if ((lenRes < 0) || (lenRes >= lenBuf))
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ buf += lenRes;
+ lenBuf -= lenRes;
+
+ lenRes = snprintf(buf, lenBuf, "\n txpower: %d\n txpktcnt: %ld\n "
+ "txpktlen: %d\n", ftm_status.txpower,
+ ftm_status.frameParams.numTestPackets,
+ ftm_status.frameParams.payloadLength);
+
+ if ((lenRes < 0) || (lenRes >= lenBuf))
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+v_VOID_t
+static ftm_vos_sys_probe_thread_cback
+(
+ v_VOID_t *pUserData
+)
+{
+ pVosContextType pVosContext= (pVosContextType)pUserData;
+ if (vos_event_set(&pVosContext->ProbeEvent)!= VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: vos_event_set failed", __FUNCTION__);
+ return;
+ }
+} /* vos_sys_probe_thread_cback() */
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+void HEXDUMP(char *s0, char *s1, int len)
+{
+ int tmp;
+ printk(KERN_EMERG "%s\n :", s0);
+
+ for (tmp = 0; tmp< len; tmp++) {
+ printk(KERN_EMERG "%02x ", *s1++);
+ }
+ printk("\n");
+}
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+/*---------------------------------------------------------------------------
+
+ \brief vos_ftm_preStart() -
+
+ The \a vos_ftm_preStart() function to download CFG.
+ including:
+ - ccmStart
+
+ - WDA: triggers the CFG download
+
+
+ \param pVosContext: The VOS context
+
+
+ \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and
+ is ready to be used.
+
+ VOS_STATUS_E_RESOURCES - System resources (other than memory)
+ are unavailable to initialize the scheduler
+
+
+ VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/
+
+ \sa vos_start
+
+---------------------------------------------------------------------------*/
+VOS_STATUS vos_ftm_preStart( v_CONTEXT_t vosContext )
+{
+ VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
+ pVosContextType pVosContext = (pVosContextType)vosContext;
+
+ VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO,
+ "vos prestart");
+
+
+ VOS_ASSERT( NULL != pVosContext->pWDAContext);
+
+ /* call macPreStart */
+ vStatus = macPreStart(pVosContext->pMACContext);
+ if ( !VOS_IS_STATUS_SUCCESS(vStatus) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR,
+ "Failed at macPreStart ");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* call ccmStart */
+ ccmStart(pVosContext->pMACContext);
+
+ /* Reset wda wait event */
+ vos_event_reset(&pVosContext->wdaCompleteEvent);
+
+
+ /*call WDA pre start*/
+ vStatus = WDA_preStart(pVosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR,
+ "Failed to WDA prestart ");
+ macStop(pVosContext->pMACContext, HAL_STOP_TYPE_SYS_DEEP_SLEEP);
+ ccmStop(pVosContext->pMACContext);
+ VOS_ASSERT(0);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* Need to update time out of complete */
+ vStatus = vos_wait_single_event( &pVosContext->wdaCompleteEvent, 1000);
+ if ( vStatus != VOS_STATUS_SUCCESS )
+ {
+ if ( vStatus == VOS_STATUS_E_TIMEOUT )
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Timeout occurred before WDA complete\n",__func__);
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: WDA_preStart reporting other error \n",__func__);
+ }
+ VOS_ASSERT( 0 );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+#endif
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_open() -
+
+ The function hdd_wlan_startup calls this function to initialize the FTM specific modules.
+
+ \param - pAdapter - Pointer HDD Context.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+int wlan_hdd_ftm_open(hdd_context_t *pHddCtx)
+{
+ VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
+ pVosContextType pVosContext= NULL;
+ hdd_adapter_t *pAdapter;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: Opening VOSS", __func__);
+
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+
+ if (NULL == pVosContext)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Trying to open VOSS without a PreOpen",__func__);
+ VOS_ASSERT(0);
+ goto err_vos_status_failure;
+ }
+
+ // Open VOSS
+ vStatus = wlan_ftm_vos_open( pVosContext, 0);
+
+ if ( !VOS_IS_STATUS_SUCCESS( vStatus ))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
+ goto err_vos_status_failure;
+ }
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ /* Start SAL now */
+ vStatus = WLANSAL_Start(pVosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start SAL",__func__);
+ goto err_vos_open_failure;
+ }
+
+ /* Save the hal context in Adapter */
+ pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_HAL, pVosContext );
+#else
+ /*
+ For Integrated SOC, only needed to start WDA, whihc happens in wlan_hdd_ftm_start()
+ */
+ /* Save the hal context in Adapter */
+ pHddCtx->hHal = (tHalHandle)vos_get_context(VOS_MODULE_ID_SME, pVosContext );
+#endif
+
+ if ( NULL == pHddCtx->hHal )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: HAL context is null",__func__);
+ goto err_sal_close;
+ }
+
+ pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_FTM, "wlan%d",
+ wlan_hdd_get_intf_addr(pHddCtx), FALSE);
+ if( NULL == pAdapter )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
+ goto err_adapter_open_failure;
+ }
+
+ if( wlan_ftm_register_wext(pAdapter)!= 0 )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%S: hdd_register_wext failed",__func__);
+ goto err_sal_close;
+ }
+
+ //Initialize the nlink service
+ if(nl_srv_init() != 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%S: nl_srv_init failed",__func__);
+ goto err_ftm_register_wext_close;
+ }
+
+#ifdef PTT_SOCK_SVC_ENABLE
+ //Initialize the PTT service
+ if(ptt_sock_activate_svc(pHddCtx) != 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: ptt_sock_activate_svc failed",__func__);
+ goto err_nl_srv_init;
+ }
+#endif
+ if (!VOS_IS_STATUS_SUCCESS(vos_chipVoteOnXOBuffer(NULL, NULL, NULL)))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
+ goto err_nl_srv_init;
+ }
+#ifdef HDD_SESSIONIZE
+ //Turn off carrier state
+ netif_carrier_off(pAdapter->dev);
+
+ //Stop the Interface TX queue. Just being safe
+ netif_tx_disable(pAdapter->dev);
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ pHddCtx->ftm.processingNVTable = NV_MAX_TABLE;
+ pHddCtx->ftm.targetNVTableSize = 0;
+ pHddCtx->ftm.targetNVTablePointer = NULL;
+ pHddCtx->ftm.processedNVTableSize = 0;
+ pHddCtx->ftm.tempNVTableBuffer = (v_U8_t *)vos_mem_malloc(MAX_NV_TABLE_SIZE);
+ if(NULL == pHddCtx->ftm.tempNVTableBuffer)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: NV Table Buffer Alloc Fail",__func__);
+ VOS_ASSERT(0);
+ goto err_nl_srv_init;
+ }
+ vos_mem_zero((v_VOID_t *)pHddCtx->ftm.tempNVTableBuffer, MAX_NV_TABLE_SIZE);
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+ _ftm_status_init();
+ /* Initialize the ftm vos event */
+ if (vos_event_init(&pHddCtx->ftm.ftm_vos_event) != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to init probeEvent",__func__);
+ VOS_ASSERT(0);
+ vos_mem_free(pHddCtx->ftm.tempNVTableBuffer);
+ goto err_nl_srv_init;
+ }
+
+ pHddCtx->ftm.ftm_state = WLAN_FTM_INITIALIZED;
+
+ return VOS_STATUS_SUCCESS;
+
+err_nl_srv_init:
+nl_srv_exit();
+
+err_ftm_register_wext_close:
+hdd_UnregisterWext(pAdapter->dev);
+
+err_adapter_open_failure:
+hdd_close_all_adapters( pHddCtx );
+
+err_sal_close:
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+WLANSAL_Stop(pVosContext);
+
+err_vos_open_failure:
+wlan_ftm_vos_close(pVosContext);
+#endif
+
+err_vos_status_failure:
+
+ return VOS_STATUS_E_FAILURE;
+}
+
+
+
+int wlan_hdd_ftm_close(hdd_context_t *pHddCtx)
+{
+ VOS_STATUS vosStatus;
+ v_CONTEXT_t vosContext = pHddCtx->pvosContext;
+
+ hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_FTM);
+ ENTER();
+ if(pAdapter == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ vosStatus = WLANBAL_SuspendChip( pHddCtx->pvosContext );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+ vosStatus = WLANSAL_Stop(pHddCtx->pvosContext);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+ //Assert Deep sleep signal now to put Libra HW in lowest power state
+ vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+ //Vote off any PMIC voltage supplies
+ vos_chipPowerDown(NULL, NULL, NULL);
+
+ vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
+
+ nl_srv_exit();
+
+ //TODO----------
+ //Deregister the device with the kernel
+ hdd_UnregisterWext(pAdapter->dev);
+
+ hdd_close_all_adapters( pHddCtx );
+#if 0
+ if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags))
+ {
+ unregister_netdev(pAdapter->dev);
+ clear_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
+ }
+#endif
+ //-----------------
+
+ vosStatus = vos_sched_close( vosContext );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to close VOSS Scheduler",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+ //Close VOSS
+ wlan_ftm_vos_close(vosContext);
+
+
+ vosStatus = vos_event_destroy(&pHddCtx->ftm.ftm_vos_event);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to destroy ftm_vos Event",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ vos_mem_free(pHddCtx->ftm.tempNVTableBuffer);
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+ //Free up dynamically allocated members inside HDD Adapter
+ kfree(pHddCtx->cfg_ini);
+ pHddCtx->cfg_ini= NULL;
+
+ return 0;
+
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_send_response() -
+
+ The function sends the response to the ptt socket application running in user space.
+
+ \param - pAdapter - Pointer HDD Context.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_send_response(hdd_context_t *pHddCtx){
+
+ if( ptt_sock_send_msg_to_app(&pHddCtx->ftm.wnl->wmsg, 0, ANI_NL_MSG_PUMAC, pHddCtx->ftm.wnl->nlh.nlmsg_pid) < 0) {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("Ptt Socket error sending message to the app!!\n"));
+ return VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_start() -
+
+ This function gets called when the FTM start commands received from the ptt socket application and
+ it starts the following modules.
+ 1) SAL Start.
+ 2) BAL Start.
+ 3) MAC Start to download the firmware.
+
+
+ \param - pAdapter - Pointer HDD Context.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static int wlan_hdd_ftm_start(hdd_context_t *pHddCtx)
+{
+ VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
+ tSirRetStatus sirStatus = eSIR_SUCCESS;
+ pVosContextType pVosContext = (pVosContextType)(pHddCtx->pvosContext);
+ tHalMacStartParameters halStartParams;
+
+ if (WLAN_FTM_STARTED == pHddCtx->ftm.ftm_state)
+ {
+ return VOS_STATUS_SUCCESS;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Starting Libra SW", __func__);
+
+ /* We support only one instance for now ...*/
+ if (pVosContext == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: mismatch in context",__FUNCTION__);
+ goto err_status_failure;
+ }
+
+ #ifndef FEATURE_WLAN_INTEGRATED_SOC
+ if (pVosContext->pBALContext == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: BAL NULL context",__FUNCTION__);
+ goto err_status_failure;
+ }
+#endif
+
+ if (pVosContext->pMACContext == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: MAC NULL context",__FUNCTION__);
+ goto err_status_failure;
+ }
+
+ #ifndef FEATURE_WLAN_INTEGRATED_SOC
+ /* Start BAL */
+ vStatus = WLANBAL_Start(pVosContext);
+
+ if (!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start BAL",__func__);
+ goto err_sal_stop;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: BAL correctly started",__func__);
+#else
+ /*
+ Prima needs to start the WDA correctly instead of BAL and SAL
+ */
+
+ /* Vos preStart is calling */
+ if ( !VOS_IS_STATUS_SUCCESS(vos_ftm_preStart(pHddCtx->pvosContext) ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
+ goto err_status_failure;
+ }
+
+
+ vStatus = WDA_NVDownload_Start(pVosContext);
+
+ if ( vStatus != VOS_STATUS_SUCCESS )
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start NV Download",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ vStatus = vos_wait_single_event(&(pVosContext->wdaCompleteEvent), 1000);
+
+ if ( vStatus != VOS_STATUS_SUCCESS )
+ {
+ if ( vStatus == VOS_STATUS_E_TIMEOUT )
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Timeout occurred before WDA_NVDownload_Start complete\n",__func__);
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: WDA_NVDownload_Start reporting other error \n",__func__);
+ }
+ VOS_ASSERT(0);
+ goto err_wda_stop;
+ }
+
+ vStatus = WDA_start(pVosContext);
+ if (vStatus != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start WDA",__func__);
+ goto err_status_failure;
+ }
+#endif
+
+
+ /* Start the MAC */
+ vos_mem_zero((v_PVOID_t)&halStartParams, sizeof(tHalMacStartParameters));
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ /* Attempt to get the firmware binary through VOS. We need to pass this
+ to the MAC when starting. */
+ vStatus = hdd_request_firmware(WLAN_FW_FILE, pHddCtx,
+ (v_VOID_t **)&halStartParams.FW.pImage,
+ (v_SIZE_t *)&halStartParams.FW.cbImage);
+
+ if ( !VOS_IS_STATUS_SUCCESS( vStatus ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to get firmware binary",__func__);
+ goto err_bal_stop;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Firmware binary file found",__func__);
+#endif
+
+ halStartParams.driverType = eDRIVER_TYPE_MFG;
+
+ /* Start the MAC */
+ sirStatus = macStart(pVosContext->pMACContext,(v_PVOID_t)&halStartParams);
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ /* Free uo the FW image no matter what */
+ if( NULL != halStartParams.FW.pImage )
+ {
+ hdd_release_firmware(WLAN_FW_FILE, pVosContext->pHDDContext);
+ halStartParams.FW.pImage = NULL;
+ halStartParams.FW.cbImage = 0;
+ }
+#endif
+
+ if (eSIR_SUCCESS != sirStatus)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start MAC", __func__);
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ goto err_bal_stop;
+#else
+ goto err_wda_stop;
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: MAC correctly started",__func__);
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+
+ /**
+ EVM issue is observed with 1.6Mhz freq for 1.3V RF supply in wlan standalone case.
+ During concurrent operation (e.g. WLAN and WCDMA) this issue is not observed.
+ To workaround, wlan will vote for 3.2Mhz during startup and will vote for 1.6Mhz
+ during exit.
+ Since using 3.2Mhz has a side effect on power (extra 200ua), this is left configurable.
+ If customers do their design right, they should not see the EVM issue and in that case they
+ can decide to keep 1.6Mhz by setting an NV.
+ If NV item is not present, use the default 3.2Mhz
+ vos_stop is also invoked if wlan startup seq fails (after vos_start, where 3.2Mhz is voted.)
+ */
+ {
+ sFreqFor1p3VSupply freq;
+ vStatus = vos_nv_read( NV_TABLE_FREQUENCY_FOR_1_3V_SUPPLY, &freq, NULL,
+ sizeof(freq) );
+ if (VOS_STATUS_SUCCESS != vStatus)
+ freq.freqFor1p3VSupply = VOS_NV_FREQUENCY_FOR_1_3V_SUPPLY_3P2MH;
+
+ if (vos_chipVoteFreqFor1p3VSupply(NULL, NULL, NULL, freq.freqFor1p3VSupply) != VOS_STATUS_SUCCESS)
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to set the freq %d for 1.3V Supply",__func__,freq.freqFor1p3VSupply );
+ }
+
+
+ /* START SYS. This will trigger the CFG download */
+ sysMcStart(pVosContext, ftm_vos_sys_probe_thread_cback, pVosContext);
+#endif
+
+ pHddCtx->ftm.ftm_state = WLAN_FTM_STARTED;
+
+ return VOS_STATUS_SUCCESS;
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+err_bal_stop:
+WLANBAL_Stop(pVosContext);
+
+err_sal_stop:
+WLANSAL_Stop(pVosContext);
+
+#else
+err_wda_stop:
+ vos_event_reset(&(pVosContext->wdaCompleteEvent));
+ WDA_stop(pVosContext, HAL_STOP_TYPE_RF_KILL);
+ vStatus = vos_wait_single_event(&(pVosContext->wdaCompleteEvent), 1000);
+ if(vStatus != VOS_STATUS_SUCCESS)
+ {
+ if(vStatus == VOS_STATUS_E_TIMEOUT)
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Timeout occurred before WDA_stop complete\n",__func__);
+
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: WDA_stop reporting other error \n",__func__);
+ }
+ VOS_ASSERT(0);
+ }
+#endif
+
+err_status_failure:
+
+ return VOS_STATUS_E_FAILURE;
+
+}
+
+
+static int wlan_ftm_stop(hdd_context_t *pHddCtx)
+{
+ VOS_STATUS vosStatus;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //if(pHddCtx->ftm.cmd_iwpriv == TRUE)
+ {
+ /* STOP MAC only */
+ v_VOID_t *hHal;
+ hHal = vos_get_context( VOS_MODULE_ID_SME, pHddCtx->pvosContext );
+ if (NULL == hHal)
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: NULL hHal", __func__);
+ }
+ else
+ {
+ vosStatus = macStop(hHal, HAL_STOP_TYPE_SYS_DEEP_SLEEP );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to stop SYS", __func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+ }
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ vosStatus = WLANBAL_Stop( pHddCtx->pvosContext );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to stop BAL",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+ /**
+ EVM issue is observed with 1.6Mhz freq for 1.3V supply in wlan standalone case.
+ During concurrent operation (e.g. WLAN and WCDMA) this issue is not observed.
+ To workaround, wlan will vote for 3.2Mhz during startup and will vote for 1.6Mhz
+ during exit.
+ vos_stop is also invoked if wlan startup seq fails (after vos_start, where 3.2Mhz is voted.)
+ */
+ if (vos_chipVoteFreqFor1p3VSupply(NULL, NULL, NULL, VOS_NV_FREQUENCY_FOR_1_3V_SUPPLY_1P6MH) != VOS_STATUS_SUCCESS)
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to set the freq to 1.6Mhz for 1.3V Supply",__func__ );
+
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ WDA_stop(pHddCtx->pvosContext, HAL_STOP_TYPE_RF_KILL);
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+ }
+ return WLAN_FTM_SUCCESS;
+}
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_get_nv_table() -
+ Get Specific NV table
+
+ \param - ftmCmd - Pointer FTM Commad Buffer
+
+ \return - int
+ -1, Process Host command fail, vail out
+ 1, Process Host command success
+
+ --------------------------------------------------------------------------*/
+int wlan_hdd_ftm_get_nv_table
+(
+ hdd_context_t *pHddCtx,
+ tPttMsgbuffer *ftmCmd
+)
+{
+ VOS_STATUS nvStatus = VOS_STATUS_SUCCESS;
+ pttGetNvTable *nvTable = (pttGetNvTable *)&ftmCmd->msgBody.GetNvTable;
+ v_SIZE_t nvSize;
+ sHalNv *nvContents = NULL;
+
+ if (NULL == pHddCtx)
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "Not valid driver context");
+ return -1;
+ }
+
+ /* Test first chunk of NV table */
+ if ((NV_MAX_TABLE == pHddCtx->ftm.processingNVTable) ||
+ (0 == pHddCtx->ftm.processedNVTableSize))
+ {
+ nvStatus = vos_nv_getNVBuffer((void **)&nvContents, &nvSize);
+ if ((VOS_STATUS_SUCCESS != nvStatus) || (NULL == nvContents))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "Fail to get cached NV value Status %d", nvStatus);
+ return -1;
+ }
+
+ switch (nvTable->nvTable)
+ {
+ case NV_TABLE_RATE_POWER_SETTINGS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.pwrOptimum);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.pwrOptimum;
+ break;
+
+ case NV_TABLE_REGULATORY_DOMAINS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.regDomains);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.regDomains;
+ break;
+
+ case NV_TABLE_DEFAULT_COUNTRY:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.defaultCountryTable);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.defaultCountryTable;
+ break;
+
+ case NV_TABLE_TPC_POWER_TABLE:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.plutCharacterized);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.plutCharacterized[0];
+ break;
+
+ case NV_TABLE_TPC_PDADC_OFFSETS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.plutPdadcOffset);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.plutPdadcOffset[0];
+ break;
+
+ case NV_TABLE_VIRTUAL_RATE:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.pwrOptimum_virtualRate);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.pwrOptimum_virtualRate[0];
+ break;
+
+ case NV_TABLE_RSSI_CHANNEL_OFFSETS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.rssiChanOffsets);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.rssiChanOffsets[0];
+ break;
+
+ case NV_TABLE_RF_CAL_VALUES:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.rFCalValues);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.rFCalValues;
+ break;
+
+ case NV_TABLE_ANTENNA_PATH_LOSS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.antennaPathLoss);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.antennaPathLoss[0];
+ break;
+
+ case NV_TABLE_PACKET_TYPE_POWER_LIMITS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.pktTypePwrLimits);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.pktTypePwrLimits[0][0];
+ break;
+
+ default:
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "Not Valid NV Table %d", nvTable->nvTable);
+ return -1;
+ break;
+ }
+
+ if (pHddCtx->ftm.targetNVTableSize != nvTable->tableSize)
+ {
+ /* Invalid table size, discard and initialize data */
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "Invalid Table Size %d", nvTable->tableSize);
+ pHddCtx->ftm.processingNVTable = NV_MAX_TABLE;
+ pHddCtx->ftm.targetNVTableSize = 0;
+ pHddCtx->ftm.processedNVTableSize = 0;
+ vos_mem_zero(pHddCtx->ftm.tempNVTableBuffer, MAX_NV_TABLE_SIZE);
+ return -1;
+ }
+
+ /* Set Current Processing NV table type */
+ pHddCtx->ftm.processingNVTable = nvTable->nvTable;
+ /* Copy target NV table value into temp context buffer */
+ vos_mem_copy(pHddCtx->ftm.tempNVTableBuffer,
+ pHddCtx->ftm.targetNVTablePointer,
+ pHddCtx->ftm.targetNVTableSize);
+
+ }
+
+ if (pHddCtx->ftm.processingNVTable != nvTable->nvTable)
+ {
+ /* Invalid table type */
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "Invalid NV Table, now Processing %d, not %d",
+ pHddCtx->ftm.processingNVTable, nvTable->nvTable);
+ pHddCtx->ftm.processingNVTable = NV_MAX_TABLE;
+ pHddCtx->ftm.targetNVTableSize = 0;
+ pHddCtx->ftm.processedNVTableSize = 0;
+ vos_mem_zero(pHddCtx->ftm.tempNVTableBuffer, MAX_NV_TABLE_SIZE);
+
+ return -1;
+ }
+
+ /* Copy next chunk of NV table value into response buffer */
+ vos_mem_copy(&nvTable->tableData,
+ pHddCtx->ftm.tempNVTableBuffer + pHddCtx->ftm.processedNVTableSize,
+ nvTable->chunkSize);
+ /* Update processed pointer to prepare next chunk copy */
+ pHddCtx->ftm.processedNVTableSize += nvTable->chunkSize;
+
+ if (pHddCtx->ftm.targetNVTableSize == pHddCtx->ftm.processedNVTableSize)
+ {
+ /* Finished to process last chunk of data, initialize buffer */
+ pHddCtx->ftm.processingNVTable = NV_MAX_TABLE;
+ pHddCtx->ftm.targetNVTableSize = 0;
+ pHddCtx->ftm.processedNVTableSize = 0;
+ vos_mem_zero(pHddCtx->ftm.tempNVTableBuffer, MAX_NV_TABLE_SIZE);
+ }
+
+ return 1;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_set_nv_table() -
+ Set Specific NV table as given
+
+ \param - ftmCmd - Pointer FTM Commad Buffer
+
+ \return - int
+ -1, Process Host command fail, vail out
+ 1, Process Host command success
+
+ --------------------------------------------------------------------------*/
+int wlan_hdd_ftm_set_nv_table
+(
+ hdd_context_t *pHddCtx,
+ tPttMsgbuffer *ftmCmd
+)
+{
+ VOS_STATUS nvStatus = VOS_STATUS_SUCCESS;
+ pttSetNvTable *nvTable = (pttSetNvTable *)&ftmCmd->msgBody.SetNvTable;
+ v_SIZE_t nvSize;
+ sHalNv *nvContents = NULL;
+
+ if (NULL == pHddCtx)
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "Not valid driver context");
+ return -1;
+ }
+
+ /* Test first chunk of NV table */
+ if ((NV_MAX_TABLE == pHddCtx->ftm.processingNVTable) ||
+ (0 == pHddCtx->ftm.processedNVTableSize))
+ {
+ nvStatus = vos_nv_getNVBuffer((void **)&nvContents, &nvSize);
+ if ((VOS_STATUS_SUCCESS != nvStatus) || (NULL == nvContents))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "Fail to get cached NV value Status %d", nvStatus);
+ return -1;
+ }
+
+ switch (nvTable->nvTable)
+ {
+ case NV_TABLE_RATE_POWER_SETTINGS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.pwrOptimum);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.pwrOptimum;
+ break;
+
+ case NV_TABLE_REGULATORY_DOMAINS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.regDomains);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.regDomains;
+ break;
+
+ case NV_TABLE_DEFAULT_COUNTRY:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.defaultCountryTable);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.defaultCountryTable;
+ break;
+
+ case NV_TABLE_TPC_POWER_TABLE:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.plutCharacterized);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.plutCharacterized[0];
+ break;
+
+ case NV_TABLE_TPC_PDADC_OFFSETS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.plutPdadcOffset);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.plutPdadcOffset[0];
+ break;
+
+ case NV_TABLE_VIRTUAL_RATE:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.pwrOptimum_virtualRate);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.pwrOptimum_virtualRate[0];
+ break;
+
+ case NV_TABLE_RSSI_CHANNEL_OFFSETS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.rssiChanOffsets);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.rssiChanOffsets[0];
+ break;
+
+ case NV_TABLE_RF_CAL_VALUES:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.rFCalValues);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.rFCalValues;
+ break;
+
+ case NV_TABLE_ANTENNA_PATH_LOSS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.antennaPathLoss);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.antennaPathLoss[0];
+ break;
+
+ case NV_TABLE_PACKET_TYPE_POWER_LIMITS:
+ pHddCtx->ftm.targetNVTableSize = sizeof(nvContents->tables.pktTypePwrLimits);
+ pHddCtx->ftm.targetNVTablePointer = (v_U8_t *)&nvContents->tables.pktTypePwrLimits[0][0];
+ break;
+
+ default:
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "Not Valid NV Table %d", nvTable->nvTable);
+ return -1;
+ break;
+ }
+
+ /* Set Current Processing NV table type */
+ pHddCtx->ftm.processingNVTable = nvTable->nvTable;
+ if (pHddCtx->ftm.targetNVTableSize != nvTable->tableSize)
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "Invalid Table Size %d", nvTable->tableSize);
+ pHddCtx->ftm.processingNVTable = NV_MAX_TABLE;
+ pHddCtx->ftm.targetNVTableSize = 0;
+ pHddCtx->ftm.processedNVTableSize = 0;
+ vos_mem_zero(pHddCtx->ftm.tempNVTableBuffer, MAX_NV_TABLE_SIZE);
+ return -1;
+ }
+ }
+
+ if (pHddCtx->ftm.processingNVTable != nvTable->nvTable)
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "Invalid NV Table, now Processing %d, not %d",
+ pHddCtx->ftm.processingNVTable, nvTable->nvTable);
+ pHddCtx->ftm.processingNVTable = NV_MAX_TABLE;
+ pHddCtx->ftm.targetNVTableSize = 0;
+ pHddCtx->ftm.processedNVTableSize = 0;
+ vos_mem_zero(pHddCtx->ftm.tempNVTableBuffer, MAX_NV_TABLE_SIZE);
+ return -1;
+ }
+ vos_mem_copy(pHddCtx->ftm.tempNVTableBuffer + pHddCtx->ftm.processedNVTableSize,
+ &nvTable->tableData,
+ nvTable->chunkSize);
+
+ pHddCtx->ftm.processedNVTableSize += nvTable->chunkSize;
+ if (pHddCtx->ftm.targetNVTableSize == pHddCtx->ftm.processedNVTableSize)
+ {
+ vos_mem_copy(pHddCtx->ftm.targetNVTablePointer,
+ pHddCtx->ftm.tempNVTableBuffer,
+ pHddCtx->ftm.targetNVTableSize);
+ pHddCtx->ftm.processingNVTable = NV_MAX_TABLE;
+ pHddCtx->ftm.targetNVTableSize = 0;
+ pHddCtx->ftm.processedNVTableSize = 0;
+ vos_mem_zero(pHddCtx->ftm.tempNVTableBuffer, MAX_NV_TABLE_SIZE);
+ }
+
+ return 1;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_blank_nv() -
+ Set all NV table value as default
+
+ \param - ftmCmd - Pointer FTM Commad Buffer
+
+ \return - int
+ -1, Process Host command fail, vail out
+ 0, Process Host command success
+
+ --------------------------------------------------------------------------*/
+int wlan_hdd_ftm_blank_nv_table
+(
+ tPttMsgbuffer *ftmCmd
+)
+{
+ VOS_STATUS nvStatus = VOS_STATUS_SUCCESS;
+ v_SIZE_t nvSize;
+ v_SIZE_t itemSize;
+ sHalNv *nvContents = NULL;
+
+ nvStatus = vos_nv_getNVBuffer((void **)&nvContents, &nvSize);
+ if((VOS_STATUS_SUCCESS != nvStatus) || (NULL == nvContents))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
+ "Fail to get cached NV value Status %d", nvStatus);
+ return -1;
+ }
+
+ itemSize = sizeof(nvContents->tables.pwrOptimum);
+ memcpy(&nvContents->tables.pwrOptimum,
+ &nvDefaults.tables.pwrOptimum,
+ itemSize);
+
+ itemSize = sizeof(nvContents->tables.regDomains);
+ memcpy(&nvContents->tables.regDomains,
+ &nvDefaults.tables.regDomains,
+ itemSize);
+
+ itemSize = sizeof(nvContents->tables.defaultCountryTable);
+ memcpy(&nvContents->tables.defaultCountryTable,
+ &nvDefaults.tables.defaultCountryTable,
+ itemSize);
+
+ itemSize = sizeof(nvContents->tables.plutCharacterized);
+ memcpy(&nvContents->tables.plutCharacterized[0],
+ &nvDefaults.tables.plutCharacterized[0],
+ itemSize);
+
+ itemSize = sizeof(nvContents->tables.plutPdadcOffset);
+ memcpy(&nvContents->tables.plutPdadcOffset[0],
+ &nvDefaults.tables.plutPdadcOffset[0],
+ itemSize);
+
+ itemSize = sizeof(nvContents->tables.pwrOptimum_virtualRate);
+ memcpy(&nvContents->tables.pwrOptimum_virtualRate[0],
+ &nvDefaults.tables.pwrOptimum_virtualRate[0],
+ itemSize);
+
+ itemSize = sizeof(nvContents->tables.rssiChanOffsets);
+ memcpy(&nvContents->tables.rssiChanOffsets[0],
+ &nvDefaults.tables.rssiChanOffsets[0],
+ itemSize);
+
+ itemSize = sizeof(nvContents->tables.rFCalValues);
+ memcpy(&nvContents->tables.rFCalValues,
+ &nvDefaults.tables.rFCalValues,
+ itemSize);
+
+ itemSize = sizeof(nvContents->tables.antennaPathLoss);
+ memcpy(&nvContents->tables.antennaPathLoss[0],
+ &nvDefaults.tables.antennaPathLoss[0],
+ itemSize);
+
+ itemSize = sizeof(nvContents->tables.pktTypePwrLimits);
+ memcpy(&nvContents->tables.pktTypePwrLimits[0][0],
+ &nvDefaults.tables.pktTypePwrLimits[0][0],
+ itemSize);
+
+ return 1;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_delete_nv_table() -
+ Delete Specific NV table
+
+ \param - ftmCmd - Pointer FTM Commad Buffer
+
+ \return - int
+ -1, Process Host command fail, vail out
+ 1, Process Host command success
+
+ --------------------------------------------------------------------------*/
+int wlan_hdd_ftm_delete_nv_table
+(
+ tPttMsgbuffer *ftmCmd
+)
+{
+ VOS_STATUS nvStatus = VOS_STATUS_SUCCESS;
+ tMsgPttDelNvTable *nvTable = (tMsgPttDelNvTable *)&ftmCmd->msgBody.DelNvTable;
+ v_SIZE_t nvSize;
+ v_SIZE_t itemSize;
+ sHalNv *nvContents = NULL;
+
+ nvStatus = vos_nv_getNVBuffer((void **)&nvContents, &nvSize);
+ if ((VOS_STATUS_SUCCESS != nvStatus) || (NULL == nvContents))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
+ "Fail to get cached NV value Status %d", nvStatus);
+ return -1;
+ }
+
+ switch (nvTable->nvTable)
+ {
+ case NV_TABLE_RATE_POWER_SETTINGS:
+ itemSize = sizeof(nvContents->tables.pwrOptimum);
+ memcpy(&nvContents->tables.pwrOptimum,
+ &nvDefaults.tables.pwrOptimum,
+ itemSize);
+ break;
+
+ case NV_TABLE_REGULATORY_DOMAINS:
+ itemSize = sizeof(nvContents->tables.regDomains);
+ memcpy(&nvContents->tables.regDomains,
+ &nvDefaults.tables.regDomains,
+ itemSize);
+ break;
+
+ case NV_TABLE_DEFAULT_COUNTRY:
+ itemSize = sizeof(nvContents->tables.defaultCountryTable);
+ memcpy(&nvContents->tables.defaultCountryTable,
+ &nvDefaults.tables.defaultCountryTable,
+ itemSize);
+ break;
+
+ case NV_TABLE_TPC_POWER_TABLE:
+ itemSize = sizeof(nvContents->tables.plutCharacterized);
+ memcpy(&nvContents->tables.plutCharacterized[0],
+ &nvDefaults.tables.plutCharacterized[0],
+ itemSize);
+ break;
+
+ case NV_TABLE_TPC_PDADC_OFFSETS:
+ itemSize = sizeof(nvContents->tables.plutPdadcOffset);
+ memcpy(&nvContents->tables.plutPdadcOffset[0],
+ &nvDefaults.tables.plutPdadcOffset[0],
+ itemSize);
+ break;
+
+ case NV_TABLE_VIRTUAL_RATE:
+ itemSize = sizeof(nvContents->tables.pwrOptimum_virtualRate);
+ memcpy(&nvContents->tables.pwrOptimum_virtualRate[0],
+ &nvDefaults.tables.pwrOptimum_virtualRate[0],
+ itemSize);
+ break;
+
+ case NV_TABLE_RSSI_CHANNEL_OFFSETS:
+ itemSize = sizeof(nvContents->tables.rssiChanOffsets);
+ memcpy(&nvContents->tables.rssiChanOffsets[0],
+ &nvDefaults.tables.rssiChanOffsets[0],
+ itemSize);
+ break;
+
+ case NV_TABLE_RF_CAL_VALUES:
+ itemSize = sizeof(nvContents->tables.rFCalValues);
+ memcpy(&nvContents->tables.rFCalValues,
+ &nvDefaults.tables.rFCalValues,
+ itemSize);
+ break;
+
+ case NV_TABLE_ANTENNA_PATH_LOSS:
+ itemSize = sizeof(nvContents->tables.antennaPathLoss);
+ memcpy(&nvContents->tables.antennaPathLoss[0],
+ &nvDefaults.tables.antennaPathLoss[0],
+ itemSize);
+ break;
+
+ case NV_TABLE_PACKET_TYPE_POWER_LIMITS:
+ itemSize = sizeof(nvContents->tables.pktTypePwrLimits);
+ memcpy(&nvContents->tables.pktTypePwrLimits[0][0],
+ &nvDefaults.tables.pktTypePwrLimits[0][0],
+ itemSize);
+ break;
+
+ default:
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "Not Valid NV Table %d", nvTable->nvTable);
+ return -1;
+ break;
+ }
+
+ return 1;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_get_nv_field() -
+ Get Specific NV field
+
+ \param - ftmCmd - Pointer FTM Commad Buffer
+
+ \return - int
+ -1, Process Host command fail, vail out
+ 1, Process Host command success
+
+ --------------------------------------------------------------------------*/
+int wlan_hdd_ftm_get_nv_field
+(
+ tPttMsgbuffer *ftmCmd
+)
+{
+ sNvFields nvFieldDataBuffer;
+ tMsgPttGetNvField *nvField = (tMsgPttGetNvField *)&ftmCmd->msgBody.GetNvField;
+ VOS_STATUS nvStatus = VOS_STATUS_SUCCESS;
+ sHalNv *nvContents = NULL;
+ v_SIZE_t nvSize;
+
+ nvStatus = vos_nv_getNVBuffer((void **)&nvContents, &nvSize);
+ if ((VOS_STATUS_SUCCESS != nvStatus) || (NULL == nvContents))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
+ "Fail to get cached NV value Status %d", nvStatus);
+ return -1;
+ }
+ memcpy(&nvFieldDataBuffer, &nvContents->fields, sizeof(sNvFields));
+
+ switch (nvField->nvField)
+ {
+ case NV_COMMON_PRODUCT_ID:
+ memcpy((void *)&nvField->fieldData,
+ &nvFieldDataBuffer.productId,
+ sizeof(nvFieldDataBuffer.productId));
+ break;
+
+ case NV_COMMON_PRODUCT_BANDS:
+ memcpy((void *)&nvField->fieldData,
+ &nvFieldDataBuffer.productBands,
+ sizeof(nvFieldDataBuffer.productBands));
+ break;
+
+ case NV_COMMON_NUM_OF_TX_CHAINS:
+ memcpy((void *)&nvField->fieldData,
+ &nvFieldDataBuffer.numOfTxChains,
+ sizeof(nvFieldDataBuffer.numOfTxChains));
+ break;
+
+ case NV_COMMON_NUM_OF_RX_CHAINS:
+ memcpy((void *)&nvField->fieldData,
+ &nvFieldDataBuffer.numOfRxChains,
+ sizeof(nvFieldDataBuffer.numOfRxChains));
+ break;
+
+ case NV_COMMON_MAC_ADDR:
+ memcpy((void *)&nvField->fieldData,
+ &nvFieldDataBuffer.macAddr[0],
+ NV_FIELD_MAC_ADDR_SIZE);
+ break;
+
+ case NV_COMMON_MFG_SERIAL_NUMBER:
+ memcpy((void *)&nvField->fieldData,
+ &nvFieldDataBuffer.mfgSN[0],
+ NV_FIELD_MFG_SN_SIZE);
+ break;
+
+ case NV_COMMON_COUPLER_TYPE:
+ memcpy((void *)&nvField->fieldData,
+ &nvFieldDataBuffer.couplerType,
+ sizeof(nvFieldDataBuffer.couplerType));
+ break;
+
+ default:
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "Not Valid NV field %d", nvField->nvField);
+ return -1;
+ break;
+ }
+
+ return 1;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_set_nv_field() -
+ Set Specific NV field
+
+ \param - ftmCmd - Pointer FTM Commad Buffer
+
+ \return - int
+ -1, Process Host command fail, vail out
+ 1, Process Host command success
+
+ --------------------------------------------------------------------------*/
+int wlan_hdd_ftm_set_nv_field
+(
+ tPttMsgbuffer *ftmCmd
+)
+{
+ tMsgPttSetNvField *nvField = (tMsgPttSetNvField *)&ftmCmd->msgBody.SetNvField;
+ VOS_STATUS nvStatus = VOS_STATUS_SUCCESS;
+ v_SIZE_t nvSize;
+ sHalNv *nvContents = NULL;
+ v_U8_t macLoop;
+ v_U8_t *pNVMac;
+ v_U8_t lastByteMAC;
+
+ nvStatus = vos_nv_getNVBuffer((void **)&nvContents, &nvSize);
+ if((VOS_STATUS_SUCCESS != nvStatus) || (NULL == nvContents))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
+ "Fail to get cached NV value Status %d", nvStatus);
+ return -1;
+ }
+
+ switch (nvField->nvField)
+ {
+ case NV_COMMON_PRODUCT_ID:
+ memcpy(&nvContents->fields.productId,
+ &nvField->fieldData,
+ sizeof(nvContents->fields.productId));
+ break;
+
+ case NV_COMMON_PRODUCT_BANDS:
+ memcpy(&nvContents->fields.productBands,
+ &nvField->fieldData,
+ sizeof(nvContents->fields.productBands));
+ break;
+
+ case NV_COMMON_NUM_OF_TX_CHAINS:
+ memcpy(&nvContents->fields.numOfTxChains,
+ &nvField->fieldData,
+ sizeof(nvContents->fields.numOfTxChains));
+ break;
+
+ case NV_COMMON_NUM_OF_RX_CHAINS:
+ memcpy(&nvContents->fields.numOfRxChains,
+ &nvField->fieldData,
+ sizeof(nvContents->fields.numOfRxChains));
+ break;
+
+ case NV_COMMON_MAC_ADDR:
+ /* If Last byte is larger than 252 (0xFC), return Error,
+ * Since 3MACs should be derived from first MAC */
+ if(QWLAN_MAX_MAC_LAST_BYTE_VALUE <
+ nvField->fieldData.macAddr[VOS_MAC_ADDRESS_LEN - 1])
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "Last Byte of the seed MAC is too large 0x%x",
+ nvField->fieldData.macAddr[VOS_MAC_ADDRESS_LEN - 1]);
+ return -1;
+ }
+
+ pNVMac = (v_U8_t *)nvContents->fields.macAddr;
+ lastByteMAC = nvField->fieldData.macAddr[VOS_MAC_ADDRESS_LEN - 1];
+ for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
+ {
+ nvField->fieldData.macAddr[VOS_MAC_ADDRESS_LEN - 1] =
+ lastByteMAC + macLoop;
+ vos_mem_copy(pNVMac + (macLoop * NV_FIELD_MAC_ADDR_SIZE),
+ &nvField->fieldData.macAddr[0],
+ NV_FIELD_MAC_ADDR_SIZE);
+ }
+ break;
+
+ case NV_COMMON_MFG_SERIAL_NUMBER:
+ memcpy(&nvContents->fields.mfgSN[0],
+ &nvField->fieldData,
+ NV_FIELD_MFG_SN_SIZE);
+ break;
+
+ case NV_COMMON_COUPLER_TYPE:
+ memcpy(&nvContents->fields.couplerType,
+ &nvField->fieldData,
+ sizeof(nvContents->fields.couplerType));
+ break;
+
+ default:
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "Not Valid NV field %d", nvField->nvField);
+ return -1;
+ break;
+ }
+
+ return 1;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_store_nv_table() -
+ Store Cached NV information into Flash Memory, file
+
+ \param - ftmCmd - Pointer FTM Commad Buffer
+
+ \return - int
+ -1, Process Host command fail, vail out
+ 0, Process Host command success
+
+ --------------------------------------------------------------------------*/
+int wlan_hdd_ftm_store_nv_table
+(
+ tPttMsgbuffer *ftmCmd
+)
+{
+ VOS_STATUS nvStatus = VOS_STATUS_SUCCESS;
+ v_SIZE_t nvSize;
+ sHalNv *nvContents = NULL;
+ tMsgPttStoreNvTable *nvTable = (tMsgPttStoreNvTable *)&ftmCmd->msgBody.StoreNvTable;
+ void *tablePtr = NULL;
+ unsigned int tableSize = 0;
+ VNV_TYPE tableVNVType = VNV_FIELD_IMAGE;
+
+ nvStatus = vos_nv_getNVBuffer((void **)&nvContents, &nvSize);
+ if((VOS_STATUS_SUCCESS != nvStatus) || (NULL == nvContents))
+ {
+ return -1;
+ }
+
+ /* Set Platform type as PRIMA */
+ nvContents->fields.wlanNvRevId = 2;
+
+ switch(nvTable->nvTable)
+ {
+ case NV_FIELDS_IMAGE:
+ tablePtr = (void *)&nvContents->fields;
+ tableSize = sizeof(nvContents->fields);
+ tableVNVType = VNV_FIELD_IMAGE;
+ break;
+
+ case NV_TABLE_RATE_POWER_SETTINGS:
+ tablePtr = (void *)&nvContents->tables.pwrOptimum[0];
+ tableSize = sizeof(nvContents->tables.pwrOptimum);
+ tableVNVType = VNV_RATE_TO_POWER_TABLE;
+ break;
+
+ case NV_TABLE_REGULATORY_DOMAINS:
+ tablePtr = (void *)&nvContents->tables.regDomains[0];
+ tableSize = sizeof(nvContents->tables.regDomains);
+ tableVNVType = VNV_REGULARTORY_DOMAIN_TABLE;
+ break;
+
+ case NV_TABLE_DEFAULT_COUNTRY:
+ tablePtr = (void *)&nvContents->tables.defaultCountryTable;
+ tableSize = sizeof(nvContents->tables.defaultCountryTable);
+ tableVNVType = VNV_DEFAULT_LOCATION;
+ break;
+
+ case NV_TABLE_TPC_POWER_TABLE:
+ tablePtr = (void *)&nvContents->tables.plutCharacterized[0];
+ tableSize = sizeof(nvContents->tables.plutCharacterized);
+ tableVNVType = VNV_TPC_POWER_TABLE;
+ break;
+
+ case NV_TABLE_TPC_PDADC_OFFSETS:
+ tablePtr = (void *)&nvContents->tables.plutPdadcOffset[0];
+ tableSize = sizeof(nvContents->tables.plutPdadcOffset);
+ tableVNVType = VNV_TPC_PDADC_OFFSETS;
+ break;
+
+ case NV_TABLE_VIRTUAL_RATE:
+ tablePtr = (void *)&nvContents->tables.pwrOptimum_virtualRate[0];
+ tableSize = sizeof(nvContents->tables.pwrOptimum_virtualRate);
+ tableVNVType = VNV_TABLE_VIRTUAL_RATE;
+ break;
+
+ case NV_TABLE_RSSI_CHANNEL_OFFSETS:
+ tablePtr = (void *)&nvContents->tables.rssiChanOffsets[0];
+ tableSize = sizeof(nvContents->tables.rssiChanOffsets);
+ tableVNVType = VNV_RSSI_CHANNEL_OFFSETS;
+ break;
+
+ case NV_TABLE_RF_CAL_VALUES:
+ tablePtr = (void *)&nvContents->tables.rFCalValues;
+ tableSize = sizeof(nvContents->tables.rFCalValues);
+ tableVNVType = VNV_RF_CAL_VALUES;
+ break;
+
+ case NV_TABLE_ANTENNA_PATH_LOSS:
+ tablePtr = (void *)&nvContents->tables.antennaPathLoss[0];
+ tableSize = sizeof(nvContents->tables.antennaPathLoss);
+ tableVNVType = VNV_ANTENNA_PATH_LOSS;
+ break;
+
+ case NV_TABLE_PACKET_TYPE_POWER_LIMITS:
+ tablePtr = (void *)&nvContents->tables.pktTypePwrLimits[0][0];
+ tableSize = sizeof(nvContents->tables.pktTypePwrLimits);
+ tableVNVType = VNV_PACKET_TYPE_POWER_LIMITS;
+ break;
+
+ default:
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "Not Supported Table Type %d", nvTable->nvTable);
+ return -1;
+ break;
+
+ }
+
+ nvStatus = vos_nv_write(tableVNVType,
+ tablePtr,
+ tableSize);
+ if(VOS_STATUS_SUCCESS != nvStatus)
+ {
+ return -1;
+ }
+
+ return 1;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_ftm_temp_get_rel_num() -
+ Get internal release number
+
+ \param - ftmCmd - Pointer FTM Commad Buffer
+
+ \return - int
+ -1, Process Host command fail, vail out
+ 0, Process Host command success
+
+ --------------------------------------------------------------------------*/
+int wlan_hdd_ftm_temp_get_rel_num
+(
+ tPttMsgbuffer *ftmCmd
+)
+{
+ tMsgPttGetBuildReleaseNumber *relNum = (tMsgPttGetBuildReleaseNumber *)&ftmCmd->msgBody.GetBuildReleaseNumber;
+
+ relNum->relParams.drvMjr = QWLAN_VERSION_MAJOR;
+ relNum->relParams.drvMnr = QWLAN_VERSION_MINOR;
+ relNum->relParams.drvPtch = QWLAN_VERSION_PATCH;
+ relNum->relParams.drvBld = QWLAN_VERSION_BUILD;
+ relNum->relParams.pttMax = 10;
+ relNum->relParams.pttMin = 1;
+
+ return 1;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_process_ftm_host_cmd() -
+ process any command should be handled within host.
+ decide any command should be send to HAL or not
+
+ \param - ftmCmd - Pointer FTM Commad Buffer
+
+ \return - int
+ -1, Process Host command fail, vail out
+ 0, Process Host command success, not need to send CMD to HAL
+ 1, Process Host command success, need to send CMD to HAL
+
+ --------------------------------------------------------------------------*/
+int wlan_hdd_process_ftm_host_cmd
+(
+ hdd_context_t *pHddCtx,
+ void *ftmCmd
+)
+{
+ tPttMsgbuffer *pFTMCmd = (tPttMsgbuffer *)ftmCmd;
+ int needToRouteHal = 1;
+ int hostState = 1;
+
+ switch(pFTMCmd->msgId)
+ {
+ case PTT_MSG_GET_NV_TABLE:
+ hostState = wlan_hdd_ftm_get_nv_table(pHddCtx, pFTMCmd);
+ needToRouteHal = 0;
+ break;
+
+ case PTT_MSG_SET_NV_TABLE:
+ hostState = wlan_hdd_ftm_set_nv_table(pHddCtx, pFTMCmd);
+ /* Temp NV Operation will be isolated to host
+ needToRouteHal = 1; */
+ needToRouteHal = 0;
+ break;
+
+ case PTT_MSG_BLANK_NV:
+ hostState = wlan_hdd_ftm_blank_nv_table(pFTMCmd);
+ needToRouteHal = 1;
+ break;
+
+ case PTT_MSG_DEL_NV_TABLE:
+ hostState = wlan_hdd_ftm_delete_nv_table(pFTMCmd);
+ needToRouteHal = 1;
+ break;
+
+ case PTT_MSG_GET_NV_FIELD:
+ hostState = wlan_hdd_ftm_get_nv_field(pFTMCmd);
+ needToRouteHal = 0;
+ break;
+
+ case PTT_MSG_SET_NV_FIELD:
+ hostState = wlan_hdd_ftm_set_nv_field(pFTMCmd);
+ needToRouteHal = 0;
+ break;
+
+ case PTT_MSG_STORE_NV_TABLE:
+ hostState = wlan_hdd_ftm_store_nv_table(pFTMCmd);
+ needToRouteHal = 0;
+ break;
+
+ case PTT_MSG_DBG_READ_REGISTER:
+ wpalReadRegister(pFTMCmd->msgBody.DbgReadRegister.regAddr,
+ &pFTMCmd->msgBody.DbgReadRegister.regValue);
+ needToRouteHal = 0;
+ break;
+
+ case PTT_MSG_DBG_WRITE_REGISTER:
+ wpalWriteRegister(pFTMCmd->msgBody.DbgWriteRegister.regAddr,
+ pFTMCmd->msgBody.DbgWriteRegister.regValue);
+ needToRouteHal = 0;
+ break;
+
+ case PTT_MSG_DBG_READ_MEMORY:
+ wpalReadDeviceMemory(pFTMCmd->msgBody.DbgReadMemory.memAddr,
+ (unsigned char *)pFTMCmd->msgBody.DbgReadMemory.pMemBuf,
+ pFTMCmd->msgBody.DbgReadMemory.nBytes);
+ needToRouteHal = 0;
+ break;
+
+ case PTT_MSG_DBG_WRITE_MEMORY:
+ wpalWriteDeviceMemory(pFTMCmd->msgBody.DbgWriteMemory.memAddr,
+ (unsigned char *)pFTMCmd->msgBody.DbgWriteMemory.pMemBuf,
+ pFTMCmd->msgBody.DbgWriteMemory.nBytes);
+ needToRouteHal = 0;
+ break;
+
+ case PTT_MSG_GET_BUILD_RELEASE_NUMBER:
+ wlan_hdd_ftm_temp_get_rel_num(pFTMCmd);
+ needToRouteHal = 0;
+ break;
+
+ default:
+ needToRouteHal = 1;
+ break;
+ }
+
+ if(-1 == hostState)
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "Host Command Handle Fail, Bailout");
+ return -1;
+ }
+
+ return needToRouteHal;
+}
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_hdd_process_ftm_cmd() -
+
+ This function process the commands received from the ptt socket application.
+
+ \param - pAdapter - Pointer HDD Context.
+
+ \param - wnl - Pointer to the ANI netlink header.
+
+ \return - none
+
+ --------------------------------------------------------------------------*/
+
+void wlan_hdd_process_ftm_cmd
+(
+ hdd_context_t *pHddCtx,
+ tAniNlHdr *wnl
+)
+{
+ wlan_hdd_ftm_request_t *pRequestBuf = (wlan_hdd_ftm_request_t*)(((v_U8_t*)(&wnl->wmsg))+sizeof(tAniHdr)) ;
+ v_U16_t cmd_len;
+ v_U8_t *pftm_data;
+ pVosContextType pVosContext = (pVosContextType)(pHddCtx->pvosContext);
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ int hostState;
+ tPttMsgbuffer *tempRspBuffer = NULL;
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+ ENTER();
+
+ if (!pRequestBuf) {
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: request buffer is null\n",__func__);
+ return ;
+ }
+ /*Save the received request*/
+ pHddCtx->ftm.pRequestBuf = pRequestBuf;
+
+ pHddCtx->ftm.pResponseBuf = (wlan_hdd_ftm_response_t*)pRequestBuf;
+ /*Save the received request netlink header used for sending the response*/
+ pHddCtx->ftm.wnl = wnl;
+ if (pRequestBuf->module_type != QUALCOMM_MODULE_TYPE) {
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Invalid Module Type =%d\n",__func__,pRequestBuf->module_type);
+
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_FAILURE;
+ wlan_ftm_send_response(pHddCtx);
+ return ;
+ }
+
+ switch (pRequestBuf->ftmpkt.ftm_cmd_type)
+ {
+ case WLAN_FTM_START:
+ if (pHddCtx->ftm.ftm_state == WLAN_FTM_STARTED) {
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: FTM has already started =%d\n",__func__,pRequestBuf->ftmpkt.ftm_cmd_type);
+ pHddCtx->ftm.pResponseBuf->ftm_hdr.data_len -= 1;
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_SUCCESS;
+ wlan_ftm_send_response(pHddCtx);
+ return;
+ }
+
+ if (wlan_hdd_ftm_start(pVosContext->pHDDContext) != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: : Failed to start WLAN FTM"
+ ,__func__);
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_FAILURE;
+ wlan_ftm_send_response(pHddCtx);
+ return;
+ }
+ /* Ptt application running on the host PC expects the length to be one byte less that what we have received*/
+ pHddCtx->ftm.pResponseBuf->ftm_hdr.data_len -= 1;
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_SUCCESS;
+ pHddCtx->ftm.pResponseBuf->ftmpkt.ftm_cmd_type = 0;
+
+ wlan_ftm_send_response(pHddCtx);
+
+ break;
+
+ case WLAN_FTM_STOP:
+ if (pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED) {
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s:: FTM has not started\n",__func__);
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_SUCCESS;
+ wlan_ftm_send_response(pHddCtx);
+ return;
+ }
+
+ if (VOS_STATUS_SUCCESS != wlan_ftm_stop(pHddCtx)) {
+
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_FAILURE;
+ wlan_ftm_send_response(pHddCtx);
+ return;
+ }
+
+ pHddCtx->ftm.ftm_state = WLAN_FTM_STOPPED;
+ /* This would send back the Command Success Status */
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_SUCCESS;
+
+ wlan_ftm_send_response(pHddCtx);
+
+ break;
+
+ case WLAN_FTM_CMD:
+ /* if it is regular FTM command, pass it to HAL PHY */
+ if(pHddCtx->ftm.IsCmdPending == TRUE) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s:: FTM command pending for process\n",__func__);
+ return;
+ }
+ if (pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED) {
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s:: FTM has not started\n",__func__);
+
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_FAILURE;
+ wlan_ftm_send_response(pHddCtx);
+ return;
+
+ }
+ vos_event_reset(&pHddCtx->ftm.ftm_vos_event);
+ cmd_len = pRequestBuf->ftm_hdr.data_len;
+ cmd_len -= (sizeof(wlan_hdd_ftm_request_t)- sizeof(pRequestBuf->ftmpkt.ftm_cmd_type));
+ pftm_data = pRequestBuf->ftmpkt.pFtmCmd;
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ hostState = wlan_hdd_process_ftm_host_cmd(pHddCtx, pftm_data);
+ if (0 == hostState)
+ {
+ tempRspBuffer = (tPttMsgbuffer *)vos_mem_malloc(((tPttMsgbuffer *)pftm_data)->msgBodyLength);
+ if (NULL == tempRspBuffer)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s:: temp Mem Alloc Fail\n",__func__);
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_FAILURE;
+ wlan_ftm_send_response(pHddCtx);
+ return;
+ }
+ memcpy(tempRspBuffer, pftm_data, ((tPttMsgbuffer *)pftm_data)->msgBodyLength);
+ tempRspBuffer->msgResponse = PTT_STATUS_SUCCESS;
+ memcpy((unsigned char *)&pHddCtx->ftm.pResponseBuf->ftmpkt,
+ (unsigned char *) tempRspBuffer,
+ tempRspBuffer->msgBodyLength);
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_SUCCESS;
+ wlan_ftm_send_response(pHddCtx);
+ vos_mem_free(tempRspBuffer);
+ return;
+ }
+ else if (-1 == hostState)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "*** Host Command Handle Fail ***");
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_FAILURE;
+ wlan_ftm_send_response(pHddCtx);
+ return;
+ }
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+ //HEXDUMP("Request:",(char*)pftm_data,cmd_len);
+
+ pHddCtx->ftm.IsCmdPending = TRUE;
+
+ /*Post the command to the HAL*/
+ if (wlan_ftm_postmsg(pftm_data, cmd_len) != VOS_STATUS_SUCCESS) {
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s:: FTM command failed\n",__func__);
+ return;
+
+ }
+ /*Wait here until you get the response from HAL*/
+ if (vos_wait_single_event(&pHddCtx->ftm.ftm_vos_event, FTM_VOS_EVENT_WAIT_TIME)!= VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: vos_wait_single_event failed",__func__);
+ return;
+ }
+
+ cmd_len = be16_to_cpu(pHddCtx->ftm.wnl->wmsg.length);
+
+ //HEXDUMP("Response to QXDM:", (char *)&pAdapter->ftm.wnl->wmsg, cmd_len);
+
+ wlan_ftm_send_response(pHddCtx);
+ pHddCtx->ftm.IsCmdPending = FALSE;
+ break;
+
+ default:
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s:: Command not supported \n",__func__);
+ return;
+ }
+
+ EXIT();
+ return;
+} /* wlan_adp_ftm_cmd() */
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_start_stop_ftm() -
+
+ This function is used for start/stop the ftm driver.
+
+ \param - pAdapter - Pointer HDD Context.
+ - start - 1/0 to start/stop ftm driver.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_start_stop_ftm(hdd_adapter_t *pAdapter,
+ v_U16_t start)
+{
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if (start)
+ {
+ pHddCtx->ftm.cmd_iwpriv = TRUE;
+ status = wlan_hdd_ftm_start(pHddCtx);
+
+ if (status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "FTM Start Failed");
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ else
+ {
+ status = wlan_ftm_stop(pHddCtx);
+
+ if (status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "FTM Stop Failed");
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_set_channel() -
+
+ This function is used for setting the channel to the halphy ptt module.
+
+ \param - pAdapter - Pointer HDD Context.
+ - channel - Channel Number 1-14.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_set_channel(hdd_adapter_t *pAdapter,v_U16_t channel)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if(!(channel >= 1 && channel <= 14))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Invalid Channel Number. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_SET_CHANNEL;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttSetChannel) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+
+ pMsgBody->SetChannel.chId = channel;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Channel =%d\n",pMsgBody->SetChannel.chId);
+ pMsgBody->SetChannel.cbState = PHY_SINGLE_CHANNEL_CENTERED;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+
+ }
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_set_txpower() -
+
+ This function is used for setting the txpower to the halphy ptt module.
+
+ \param - pAdapter - Pointer HDD Context.
+ - txpower - txpower Number 1-18.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_set_txpower(hdd_adapter_t *pAdapter,v_U16_t txpower)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* do not allow to change setting when tx pktgen is enabled, although halphy does allow changing tx power
+ * when tx pktgen is enabled
+ */
+ if (ftm_status.frameGenEnabled)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:cannot set txpower when pktgen is enabled.",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if(!(txpower >= 9 && txpower <= 24))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Invalid tx power. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_CLOSE_TPC_LOOP;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttCloseTpcLoop) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->CloseTpcLoop.tpcClose = TRUE;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_SET_TX_POWER;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttSetTxPower) + PTT_HEADER_LENGTH;
+
+ pMsgBody->SetTxPower.dbmPwr = txpower*100;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ ftm_status.txpower = txpower ;
+ done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+
+}
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_set_txrate() -
+
+ This function is used for setting the txrate to the halphy ptt module.
+ It converts the user input string for txrate to the tx rate index.
+
+ \param - pAdapter - Pointer HDD Context.
+ - txrate - Pointer to the tx rate string.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_set_txrate(hdd_adapter_t *pAdapter,char *txrate)
+{
+ int ii;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm.",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* do not allow to change setting when tx pktgen is enabled */
+ if (ftm_status.frameGenEnabled)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:cannot set txrate when pktgen is enabled.",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ for(ii = 0; ii < SIZE_OF_TABLE(rateName_rateIndex_tbl); ii++)
+ {
+ if(!strcmp(rateName_rateIndex_tbl[ii].rate_str,txrate))
+ break;
+ }
+ if(ii >= SIZE_OF_TABLE(rateName_rateIndex_tbl))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Invalid Rate String\n",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ftm_status.frameParams.rate = rateName_rateIndex_tbl[ii].rate_index;
+ ftm_status.frameParams.preamble = rate_index_2_preamble_table[rateName_rateIndex_tbl[ii].rate_index].Preamble;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_start_stop_tx_pktgen() -
+
+ This function is used for start/stop the tx packet generation.
+
+ \param - pAdapter - Pointer HDD Context.
+ - startStop - Value( 1/0) start/stop the tx packet generation.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_start_stop_tx_pktgen(hdd_adapter_t *pAdapter,v_U16_t startStop)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if(startStop != 1 && startStop != 0)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Tx value is invalid ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if ((ftm_status.frameGenEnabled && startStop == 1) ||
+ (!ftm_status.frameGenEnabled && startStop == 0))
+ {
+ return VOS_STATUS_SUCCESS ;
+ }
+
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ if (startStop == 1)
+ {
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_CONFIG_TX_PACKET_GEN;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttConfigTxPacketGen) + PTT_HEADER_LENGTH;
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->ConfigTxPacketGen.frameParams = ftm_status.frameParams ;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:posting PTT_MSG_CONFIG_TX_PACKET_GEN failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: PTT_MSG_CONFIG_TX_PACKET_GEN failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ }
+
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_START_STOP_TX_PACKET_GEN;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttStartStopTxPacketGen) + PTT_HEADER_LENGTH;
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->StartStopTxPacketGen.startStop = startStop;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ if (status == VOS_STATUS_SUCCESS)
+ {
+ if (startStop == 1)
+ {
+ ftm_status.frameGenEnabled = eANI_BOOLEAN_TRUE ;
+ }
+ else
+ {
+ ftm_status.frameGenEnabled = eANI_BOOLEAN_FALSE ;
+ }
+ }
+
+ return status;
+}
+
+
+static VOS_STATUS wlan_ftm_priv_set_rssi_offset(hdd_adapter_t *pAdapter,v_S15_t *phyRxChains)
+{
+#ifndef ANI_CHIPSET_VOLANS
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_SET_NV_TABLE;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttSetNvTable) + PTT_HEADER_LENGTH;
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->SetNvTable.nvTable= NV_TABLE_RSSI_OFFSETS;
+ memcpy(&pMsgBody->SetNvTable.tableData.rssiOffset[0], phyRxChains,sizeof(tANI_S16) * PHY_MAX_RX_CHAINS);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "rssiOffset[0]= %d rssiOffset[1]= %d\n",
+ pMsgBody->SetNvTable.tableData.rssiOffset[0],
+ pMsgBody->SetNvTable.tableData.rssiOffset[1]);
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_STORE_NV_TABLE;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttStoreNvTable) + PTT_HEADER_LENGTH;
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->StoreNvTable.nvTable= NV_TABLE_RSSI_OFFSETS;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+#else
+ return VOS_STATUS_E_FAILURE;
+#endif
+}
+
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_rx_mode() -
+
+ This function is used for start/stop the rx packet generation.
+
+ \param - pAdapter - Pointer HDD Context.
+ - rxmode - 0-disable RX.
+ - 1-rx ALL frames
+ - 2-rx 11 g/n frames
+ - 3-rx 11b frames
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_rx_mode(hdd_adapter_t *pAdapter,v_U16_t rxmode)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if(rxmode > 3)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Rx mode value is invalid ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+
+ pMsgBuf->msgId = PTT_MSG_SET_RX_DISABLE_MODE;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttSetRxDisableMode) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+
+ switch(rxmode)
+ {
+ case RXMODE_DISABLE_ALL:
+ pMsgBody->SetRxDisableMode.disabled.agPktsDisabled = VOS_TRUE;
+ pMsgBody->SetRxDisableMode.disabled.bPktsDisabled = VOS_TRUE;
+ pMsgBody->SetRxDisableMode.disabled.slrPktsDisabled= VOS_TRUE;
+ break;
+
+ case RXMODE_ENABLE_ALL:
+ pMsgBody->SetRxDisableMode.disabled.agPktsDisabled = VOS_FALSE;
+ pMsgBody->SetRxDisableMode.disabled.bPktsDisabled = VOS_FALSE;
+ pMsgBody->SetRxDisableMode.disabled.slrPktsDisabled= VOS_FALSE;
+ break;
+
+ case RXMODE_ENABLE_11GN:
+ pMsgBody->SetRxDisableMode.disabled.agPktsDisabled = VOS_FALSE;
+ pMsgBody->SetRxDisableMode.disabled.bPktsDisabled = VOS_TRUE;
+ pMsgBody->SetRxDisableMode.disabled.slrPktsDisabled= VOS_TRUE;
+ break;
+
+ case RXMODE_ENABLE_11B:
+ pMsgBody->SetRxDisableMode.disabled.agPktsDisabled = VOS_TRUE;
+ pMsgBody->SetRxDisableMode.disabled.bPktsDisabled = VOS_FALSE;
+ pMsgBody->SetRxDisableMode.disabled.slrPktsDisabled= VOS_TRUE;
+ break;
+
+ }
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ ftm_status.rxmode = rxmode ;
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_rx_pkt_clear() -
+
+ This function sets the rx pkt count to zero.
+
+ \param - pAdapter - Pointer HDD Context.
+ - rx_pkt_clear - rx_pkt_clear value.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_rx_pkt_clear(hdd_adapter_t *pAdapter,v_U16_t rx_pkt_clear)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if(rx_pkt_clear != 1)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Invalid rx_pkt_clear value ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_RESET_RX_PACKET_STATISTICS;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttResetRxPacketStatistics) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->ResetRxPacketStatistics.notUsed= rx_pkt_clear;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_get_channel() -
+
+ This function gets the channel number from the halphy ptt module and
+ returns the channel number to the application.
+
+ \param - pAdapter - Pointer HDD Context.
+ - pChannel - Poniter to get the Channel number.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_get_channel(hdd_adapter_t *pAdapter,v_U16_t *pChannel)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ v_U16_t freq;
+ v_U8_t indx=0;
+
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_DBG_READ_REGISTER;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttDbgReadRegister) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->DbgReadRegister.regAddr = QWLAN_AGC_CHANNEL_FREQ_REG;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ freq = ((v_U16_t)pMsgBody->DbgReadRegister.regValue & QWLAN_AGC_CHANNEL_FREQ_FREQ_MASK);
+
+ while ((indx < SIZE_OF_TABLE(freq_chan_tbl)) && (freq != freq_chan_tbl[indx].freq))
+ indx++;
+ if (indx >= SIZE_OF_TABLE(freq_chan_tbl))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Invalid Frequency!!!",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ *pChannel = freq_chan_tbl[indx].chan;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Channel = %d freq = %d\n",*pChannel, freq);
+ done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_get_txpower() -
+
+ This function gets the TX power from the halphy ptt module and
+ returns the TX power to the application.
+
+ \param - pAdapter - Pointer HDD Context.
+ - pTxPwr - Poniter to get the Tx power.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_get_txpower(hdd_adapter_t *pAdapter,v_U16_t *pTxPwr)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_GET_TX_POWER_REPORT;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttGetTxPowerReport) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: PTT_MSG_GET_TX_POWER_REPORT failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ *pTxPwr = ((((pMsgBody->GetTxPowerReport.pwrTemplateIndex & 0x1F) + 4)*50)/100);
+
+ done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_get_ftm_version() -
+
+ This function gets ftm driver and firmware version.
+
+ \param - pAdapter - Pointer HDD Context.
+ - pTxRate - Poniter to get the Tx rate.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+VOS_STATUS wlan_ftm_priv_get_ftm_version(hdd_adapter_t *pAdapter,char *pftmVer)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ v_U32_t reg_val;
+ char *buf = pftmVer;
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ FwVersionInfo *pFwVersion;
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+ int lenRes = 0;
+ int lenBuf = WE_FTM_MAX_STR_LEN;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_DBG_READ_REGISTER;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttDbgReadRegister) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->DbgReadRegister.regAddr = QWLAN_RFAPB_REV_ID_REG;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ reg_val = (v_U16_t)pMsgBody->DbgReadRegister.regValue;
+
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+
+ pMsgBuf->msgId = PTT_MSG_GET_BUILD_RELEASE_NUMBER;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttGetBuildReleaseNumber) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+
+ lenRes = snprintf(buf, lenBuf, "%s_",WLAN_CHIP_VERSION);
+ if(lenRes < 0 || lenRes >= lenBuf)
+ {
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ buf += lenRes;
+ lenBuf -= lenRes;
+
+ /*Read the RevID*/
+ lenRes = snprintf(buf, lenBuf, "%x.%x-",(v_U8_t)(reg_val >> 8), (v_U8_t)(reg_val &0x000000FF));
+ if(lenRes < 0 || lenRes >= lenBuf)
+ {
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ buf += lenRes;
+ lenBuf -= lenRes;
+
+ lenRes = snprintf(buf, lenBuf, "%s-", QWLAN_VERSIONSTR);
+ if(lenRes < 0 || lenRes >= lenBuf)
+ {
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ buf += lenRes;
+ lenBuf -= lenRes;
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ pFwVersion = &pMsgBody->GetBuildReleaseNumber.relParams.fwVer;
+ lenRes = snprintf(buf, lenBuf, "%ld.%ld.%ld.%ld", pFwVersion->uMj,pFwVersion->uMn,pFwVersion->uPatch,pFwVersion->uBuild ) ;
+ if(lenRes < 0 || lenRes >= lenBuf)
+ {
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ buf += lenRes;
+ lenBuf -= lenRes;
+
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_get_txrate() -
+
+ This function gets the TX rate from the halphy ptt module and
+ returns the TX rate to the application.
+
+ \param - pAdapter - Pointer HDD Context.
+ - pTxRate - Poniter to get the Tx rate.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_get_txrate(hdd_adapter_t *pAdapter,char *pTxRate)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ v_U16_t rate_index,ii;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_GET_TX_POWER_REPORT;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttGetTxPowerReport) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse == PTT_STATUS_SUCCESS) {
+
+ rate_index = pMsgBody->GetTxPowerReport.rate;
+ }
+ else {
+ /*Return the default rate*/
+ //rate_index = HAL_PHY_RATE_11A_6_MBPS;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: PTT_MSG_GET_TX_POWER_REPORT failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ for(ii = 0; ii < SIZE_OF_TABLE(rateName_rateIndex_tbl); ii++) {
+ if(rateName_rateIndex_tbl[ii].rate_index == rate_index)
+ break;
+ }
+ if(ii >= SIZE_OF_TABLE(rateName_rateIndex_tbl))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Invalid Rate Index\n",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ strlcpy(pTxRate,rateName_rateIndex_tbl[ii].rate_str, WE_FTM_MAX_STR_LEN);
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_get_rx_pkt_count() -
+
+ This function gets the rx pkt count from the halphy ptt module and
+ returns the rx pkt count to the application.
+
+ \param - pAdapter - Pointer HDD Context.
+ - pRxPktCnt - Poniter to get the rx pkt count.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_get_rx_pkt_count(hdd_adapter_t *pAdapter,v_U16_t *pRxPktCnt)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_GET_RX_PKT_COUNTS;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttGetRxPktCounts) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ *pRxPktCnt = pMsgBody->GetRxPktCounts.counters.totalRxPackets;
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_get_rx_rssi() -
+
+ This function gets the rx rssi from the halphy ptt module and
+ returns the rx rssi to the application.
+
+ \param - pAdapter - Pointer HDD Context.
+ - buf - Poniter to get rssi of Rx chains
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_get_rx_rssi(hdd_adapter_t *pAdapter,char *buf)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+ int ret;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_GET_RX_RSSI;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttGetRxRssi) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ ret = snprintf(buf, WE_FTM_MAX_STR_LEN, " R0:%d, R1:%d",
+ pMsgBody->GetRxRssi.rssi.rx[0],
+ pMsgBody->GetRxRssi.rssi.rx[1]);
+
+ if( ret < 0 || ret >= WE_FTM_MAX_STR_LEN )
+ {
+ status = VOS_STATUS_E_FAILURE;
+ }
+
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_get_mac_address() -
+
+ This function gets the mac address from the halphy ptt module and
+ returns the mac address to the application.
+
+ \param - pAdapter - Pointer HDD Context.
+ - buf - Poniter to get the mac address.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_get_mac_address(hdd_adapter_t *pAdapter,char *buf)
+{
+ v_BOOL_t itemIsValid = VOS_FALSE;
+ v_U8_t macAddr[VOS_MAC_ADDRESS_LEN] = {0, 0x0a, 0xf5, 4,5, 6};
+ int ret;
+
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ /*Check the NV FIELD is valid or not*/
+ if (vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid) == VOS_STATUS_SUCCESS)
+ {
+ if (itemIsValid == VOS_TRUE)
+ {
+ vos_nv_readMacAddress(macAddr);
+
+ ret = snprintf(buf, WE_FTM_MAX_STR_LEN,
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ MAC_ADDR_ARRAY(macAddr));
+ if( ret < 0 || ret >= WE_FTM_MAX_STR_LEN )
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ }
+ else
+ {
+ /*Return Hard coded mac address*/
+ ret = snprintf(buf, WE_FTM_MAX_STR_LEN,
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ MAC_ADDR_ARRAY(macAddr));
+
+ if( ret < 0 || ret >= WE_FTM_MAX_STR_LEN )
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief wlan_ftm_priv_set_mac_address() -
+
+ This function sets the mac address to the halphy ptt module and
+ sends the netlink message to the ptt socket application which writes
+ the macaddress to the qcom_wlan_nv.bin file
+
+ \param - pAdapter - Pointer HDD Context.
+ - buf - Poniter to the macaddress.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static VOS_STATUS wlan_ftm_priv_set_mac_address(hdd_adapter_t *pAdapter,char *buf)
+{
+ tPttMsgbuffer *pMsgBuf;
+ uPttMsgs *pMsgBody;
+ VOS_STATUS status;
+ int macAddr[VOS_MAC_ADDRESS_LEN];
+ v_U8_t *pMacAddress;
+ v_U8_t ii;
+ hdd_context_t *pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
+
+ if(pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ftm has not started. Please start the ftm. ",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ pMsgBuf = (tPttMsgbuffer *)vos_mem_malloc(sizeof(tPttMsgbuffer));
+ if(pMsgBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pMsgBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ pMsgBuf->msgId = PTT_MSG_SET_NV_FIELD;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttSetNvField) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+ pMsgBody->SetNvField.nvField = NV_COMMON_MAC_ADDR;
+
+ /*We get the mac address in string format "XX:XX:XX:XX:XX:XX" convert to hex*/
+ sscanf(buf,"%02x:%02x:%02x:%02x:%02x:%02x",&macAddr[0],(int*)&macAddr[1],(int*)&macAddr[2],(int*)&macAddr[3],(int*)&macAddr[4],(int*)&macAddr[5]);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "MacAddress = %02x:%02x:%02x:%02x:%02x:%02x",MAC_ADDR_ARRAY(macAddr));
+
+
+ pMacAddress = &pMsgBody->SetNvField.fieldData.macAddr[0];
+
+ for(ii = 0; ii < VOS_MAC_ADDRESS_LEN; ii++)
+ pMacAddress[ii] = (v_U8_t)macAddr[ii];
+
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "pMacAddress = %02x:%02x:%02x:%02x:%02x:%02x",MAC_ADDR_ARRAY(pMacAddress));
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed!!",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+
+ if(pMsgBuf->msgResponse != PTT_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Ptt response status failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "NV_COMMON_MAC_ADDR Success!!!\n");
+
+ init_completion(&pHddCtx->ftm.ftm_comp_var);
+ memset( pMsgBuf,0,sizeof(tPttMsgbuffer));
+
+ pMsgBuf->msgId = PTT_MSG_STORE_NV_TABLE;
+ pMsgBuf->msgBodyLength = sizeof(tMsgPttStoreNvTable) + PTT_HEADER_LENGTH;
+
+ pMsgBody = &pMsgBuf->msgBody;
+
+ pMsgBody->StoreNvTable.nvTable = NV_FIELDS_IMAGE;
+
+ status = wlan_ftm_postmsg((v_U8_t*)pMsgBuf,pMsgBuf->msgBodyLength);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:wlan_ftm_postmsg failed!!!!",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ goto done;
+ }
+
+ wait_for_completion_interruptible_timeout(&pHddCtx->ftm.ftm_comp_var, msecs_to_jiffies(WLAN_FTM_COMMAND_TIME_OUT));
+done:
+ vos_mem_free((v_VOID_t * )pMsgBuf);
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/* set param sub-ioctls */
+static int iw_ftm_setchar_getnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int sub_cmd = wrqu->data.flags;
+ int ret = 0; /* sucess */
+ VOS_STATUS status;
+ hdd_adapter_t *pAdapter = (netdev_priv(dev));
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received length %d", __FUNCTION__, wrqu->data.length);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received data %s", __FUNCTION__, (char*)wrqu->data.pointer);
+
+ switch(sub_cmd)
+ {
+ case WE_SET_MAC_ADDRESS:
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "SET MAC ADDRESS\n");
+
+ status = wlan_ftm_priv_set_mac_address(pAdapter,(char*)wrqu->data.pointer);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_set_mac_address Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+
+ }
+ break;
+ case WE_SET_TX_RATE:
+ {
+ status = wlan_ftm_priv_set_txrate(pAdapter,(char*)wrqu->data.pointer);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_set_txrate Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+
+ break;
+ }
+ default:
+ {
+ hddLog(LOGE, "%s: Invalid sub command %d\n",__FUNCTION__, sub_cmd);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int iw_ftm_setint_getnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = (netdev_priv(dev));
+ int *value = (int *)extra;
+ int sub_cmd = value[0];
+ int set_value = value[1];
+ int ret = 0; /* success */
+ VOS_STATUS status;
+
+ switch(sub_cmd)
+ {
+ case WE_FTM_ON_OFF:
+ {
+ status = wlan_ftm_priv_start_stop_ftm(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s Failed =%d\n",__FUNCTION__, status);
+ ret = -EINVAL;
+ }
+
+ break;
+ }
+
+ case WE_TX_PKT_GEN:
+ status = wlan_ftm_priv_start_stop_tx_pktgen(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_start_stop_tx_pktgen Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+
+ case WE_SET_TX_IFS:
+ status = wlan_ftm_priv_set_txifs(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_set_txifs Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+
+ case WE_SET_TX_PKT_CNT:
+ status = wlan_ftm_priv_set_txpktcnt(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_set_txpktcnt Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+
+ case WE_SET_TX_PKT_LEN:
+ status = wlan_ftm_priv_set_txpktlen(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_set_txpktlen Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+
+ case WE_SET_CHANNEL:
+ {
+ status = wlan_ftm_priv_set_channel(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_set_channel Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case WE_SET_TX_POWER:
+ {
+ status = wlan_ftm_priv_set_txpower(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_set_txpower Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case WE_CLEAR_RX_PKT_CNT:
+ {
+ status = wlan_ftm_priv_rx_pkt_clear(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_rx_pkt_clear Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case WE_RX:
+ {
+ status = wlan_ftm_priv_rx_mode(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_rx_mode Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case WE_ENABLE_CHAIN:
+ {
+ status = wlan_ftm_priv_enable_chain(pAdapter,set_value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_enable_chain Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+ }
+
+ default:
+ {
+ hddLog(LOGE, "Invalid IOCTL setvalue command %d value %d \n",
+ sub_cmd, set_value);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/* get param sub-ioctls */
+static int iw_ftm_setnone_getint(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = (netdev_priv(dev));
+ int *value = (int *)extra;
+ int ret = 0; /* sucess */
+ VOS_STATUS status;
+
+ switch (value[0])
+ {
+ case WE_GET_CHANNEL:
+ {
+ status = wlan_ftm_priv_get_channel(pAdapter,(v_U16_t*)value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_get_channel Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case WE_GET_TX_POWER:
+ {
+ status = wlan_ftm_priv_get_txpower(pAdapter,(v_U16_t*)value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_get_txpower Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case WE_GET_RX_PKT_CNT:
+ {
+ status = wlan_ftm_priv_get_rx_pkt_count(pAdapter,(v_U16_t*)value);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"wlan_ftm_priv_get_rx_pkt_count Failed =%d\n",status);
+ ret = -EINVAL;
+ }
+ break;
+ }
+ default:
+ {
+ hddLog(LOGE, "Invalid IOCTL get_value command %d ",value[0]);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int iw_ftm_get_char_setnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int sub_cmd = wrqu->data.flags;
+ VOS_STATUS status;
+ hdd_adapter_t *pAdapter = (netdev_priv(dev));
+
+ switch(sub_cmd)
+ {
+ case WE_GET_MAC_ADDRESS:
+ {
+ status = wlan_ftm_priv_get_mac_address(pAdapter, extra);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "wlan_ftm_priv_get_mac_address failed =%d\n",status);
+ return -EINVAL;
+ }
+ wrqu->data.length = strlen(extra)+1;
+ break;
+ }
+ case WE_GET_TX_RATE:
+ {
+ status = wlan_ftm_priv_get_txrate(pAdapter, extra);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "wlan_ftm_priv_get_txrate failed =%d\n",status);
+ return -EINVAL;
+ }
+
+ wrqu->data.length = strlen(extra)+1;
+ break;
+ }
+ case WE_GET_FTM_VERSION:
+ {
+ status = wlan_ftm_priv_get_ftm_version(pAdapter, extra);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "wlan_ftm_priv_get_mac_address failed =%d\n",status);
+ return -EINVAL;
+ }
+ wrqu->data.length = strlen(extra)+1;
+ break;
+ }
+ case WE_GET_FTM_STATUS:
+ {
+ status = wlan_ftm_priv_get_status(pAdapter, extra);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "wlan_ftm_priv_get_status failed =%d\n",status);
+ return -EINVAL;
+ }
+
+ wrqu->data.length = strlen(extra)+1;
+ break;
+ }
+ case WE_GET_RX_RSSI:
+ {
+ status = wlan_ftm_priv_get_rx_rssi(pAdapter, extra);
+
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "wlan_ftm_priv_get_rx_rssi failed =%d\n",status);
+ return -EINVAL;
+ }
+
+ wrqu->data.length = strlen(extra)+1;
+ break;
+ }
+ default:
+ {
+ hddLog(LOGE, "Invalid IOCTL command %d \n", sub_cmd );
+ break;
+ }
+ }
+
+ return 0;
+}
+#endif//ANI_MANF_DIAG
+
+VOS_STATUS wlan_write_to_efs (v_U8_t *pData, v_U16_t data_len)
+{
+#if defined(ANI_MANF_DIAG) && defined(MSM_PLATFORM)
+ tAniHdr *wmsg = NULL;
+ v_U8_t *pBuf;
+ hdd_context_t *pHddCtx = NULL;
+ v_CONTEXT_t pVosContext= NULL;
+
+ pBuf = (v_U8_t*)vos_mem_malloc(sizeof(tAniHdr) + sizeof(v_U32_t)+ data_len);
+ if(pBuf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pBuf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ wmsg = (tAniHdr*)pBuf;
+ wmsg->type = PTT_MSG_FTM_CMDS_TYPE;
+ wmsg->length = data_len + sizeof(tAniHdr)+ sizeof(v_U32_t);
+ wmsg->length = FTM_SWAP16(wmsg->length);
+ pBuf += sizeof(tAniHdr);
+
+ /*Get the global context */
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+
+ /*Get the Hdd Context */
+ //pAdapter = ((VosContextType*)(pVosContext))->pHDDContext;
+ pHddCtx = (hdd_context_t *)(((VosContextType*)(pVosContext))->pHDDContext);
+
+ /* EfS command Code */
+ *(v_U32_t*)pBuf = 0x000000EF;
+
+ pBuf += sizeof(v_U32_t);
+
+ memcpy(pBuf, pData,data_len);
+
+ if(pHddCtx->ftm.cmd_iwpriv == TRUE) {
+ if( ptt_sock_send_msg_to_app(wmsg, 0, ANI_NL_MSG_PUMAC, pHddCtx->ptt_pid) < 0) {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("Ptt Socket error sending message to the app!!\n"));
+ vos_mem_free((v_VOID_t*)wmsg);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ else {
+ if( ptt_sock_send_msg_to_app(wmsg, 0, ANI_NL_MSG_PUMAC, pHddCtx->ftm.wnl->nlh.nlmsg_pid) < 0) {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("Ptt Socket error sending message to the app!!\n"));
+ vos_mem_free((v_VOID_t*)wmsg);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+
+ vos_mem_free((v_VOID_t*)wmsg);
+#endif //FTM and ANDROID
+
+ return VOS_STATUS_SUCCESS;
+}
+
+#ifdef ANI_MANF_DIAG
+/* action sub-ioctls */
+static int iw_ftm_setnone_getnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int sub_cmd = wrqu->data.flags;
+ int ret = 0; /* sucess */
+
+ switch (sub_cmd)
+ {
+ case WE_SET_NV_DEFAULTS:
+ {
+ v_U8_t *pu8buf,*pTempBuf;
+ v_U16_t size;
+ size = sizeof(v_U32_t) + sizeof(sHalNv);
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HAL NV Size =%d\n",size);
+ pu8buf = vos_mem_malloc(size);
+ if(pu8buf == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pu8buf is NULL",__func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+ memset(pu8buf,0,size);
+ pTempBuf = pu8buf;
+ pTempBuf += sizeof(v_U32_t);
+ memcpy(pTempBuf,&nvDefaults,sizeof(sHalNv));
+
+ wlan_write_to_efs(pu8buf,size);
+ vos_mem_free(pu8buf);
+ }
+
+ default:
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: unknown ioctl %d", __FUNCTION__, sub_cmd);
+ hddLog(LOGE, "Invalid IOCTL action command %d ", sub_cmd);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int iw_ftm_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ hdd_adapter_t *pAdapter = (netdev_priv(dev));
+ int sub_cmd = wrqu->data.flags;
+ int *value = (int*)wrqu->data.pointer;
+ v_S15_t phyRxChains[MAX_FTM_VAR_ARGS] = {0};
+
+ if(wrqu->data.length != 2)
+ {
+ hddLog(LOGE, "Invalid number of Arguments %d \n", wrqu->data.length);
+ return -EINVAL;
+ }
+ switch (sub_cmd)
+ {
+ case WE_SET_RSSI_OFFSET:
+ {
+ phyRxChains[0] = *(v_S15_t*) value++;
+ phyRxChains[1] = *(v_S15_t*) value;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,"PhyRxchain0=%d PhyRxChain1=%d\n",phyRxChains[0],phyRxChains[1]);
+ wlan_ftm_priv_set_rssi_offset(pAdapter, &phyRxChains[0]);
+ }
+ break;
+
+ default:
+ {
+ hddLog(LOGE, "Invalid IOCTL command %d \n", sub_cmd );
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static const iw_handler we_ftm_private[] = {
+
+ [WLAN_FTM_PRIV_SET_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_ftm_setint_getnone, //set priv ioctl
+ [WLAN_FTM_PRIV_SET_NONE_GET_INT - SIOCIWFIRSTPRIV] = iw_ftm_setnone_getint, //get priv ioctl
+ [WLAN_FTM_PRIV_SET_CHAR_GET_NONE - SIOCIWFIRSTPRIV] = iw_ftm_setchar_getnone, //get priv ioctl
+ [WLAN_FTM_PRIV_GET_CHAR_SET_NONE - SIOCIWFIRSTPRIV] = iw_ftm_get_char_setnone,
+ [WLAN_FTM_PRIV_SET_NONE_GET_NONE - SIOCIWFIRSTPRIV] = iw_ftm_setnone_getnone, //action priv ioctl
+ [WLAN_FTM_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_ftm_set_var_ints_getnone,
+};
+
+/*Maximum command length can be only 15 */
+static const struct iw_priv_args we_ftm_private_args[] = {
+
+ /* handlers for main ioctl */
+ { WLAN_FTM_PRIV_SET_INT_GET_NONE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "" },
+
+ { WE_FTM_ON_OFF,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "ftm" },
+
+ { WE_TX_PKT_GEN,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "tx" },
+
+ { WE_SET_TX_IFS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_txifs" },
+
+ { WE_SET_TX_PKT_CNT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_txpktcnt" },
+
+ { WE_SET_TX_PKT_LEN,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_txpktlen" },
+
+ { WE_SET_CHANNEL,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_channel" },
+
+ { WE_SET_TX_POWER,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_txpower" },
+
+ { WE_CLEAR_RX_PKT_CNT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "clr_rxpktcnt" },
+
+ { WE_RX,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "rx" },
+
+ { WE_ENABLE_CHAIN,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "ena_chain" },
+
+ /* handlers for main ioctl */
+ { WLAN_FTM_PRIV_SET_NONE_GET_INT,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "" },
+
+ { WE_GET_CHANNEL,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_channel" },
+
+ { WE_GET_TX_POWER,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_txpower" },
+
+ { WE_GET_RX_PKT_CNT,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_rxpktcnt" },
+
+ /* handlers for main ioctl */
+ { WLAN_FTM_PRIV_SET_CHAR_GET_NONE,
+ IW_PRIV_TYPE_CHAR| 512,
+ 0,
+ "" },
+
+ { WE_SET_MAC_ADDRESS,
+ IW_PRIV_TYPE_CHAR| 512,
+ 0,
+ "set_mac_address" },
+
+ { WE_SET_TX_RATE,
+ IW_PRIV_TYPE_CHAR | 512,
+ 0,
+ "set_txrate" },
+
+ /* handlers for main ioctl */
+ { WLAN_FTM_PRIV_GET_CHAR_SET_NONE,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_FTM_MAX_STR_LEN,
+ "" },
+
+ { WE_GET_MAC_ADDRESS,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_FTM_MAX_STR_LEN,
+ "get_mac_address" },
+
+ { WE_GET_FTM_VERSION,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_FTM_MAX_STR_LEN,
+ "ftm_version" },
+
+ { WE_GET_TX_RATE,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_FTM_MAX_STR_LEN,
+ "get_txrate" },
+
+ { WE_GET_FTM_STATUS,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_FTM_MAX_STR_LEN,
+ "get_status" },
+
+ { WE_GET_RX_RSSI,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_FTM_MAX_STR_LEN,
+ "get_rx_rssi" },
+
+ { WLAN_FTM_PRIV_SET_VAR_INT_GET_NONE,
+ IW_PRIV_TYPE_INT | MAX_FTM_VAR_ARGS,
+ 0,
+ "" },
+
+ { WE_SET_RSSI_OFFSET,
+ IW_PRIV_TYPE_INT| MAX_FTM_VAR_ARGS,
+ 0,
+ "set_rssi_offset" },
+
+ /* handlers for main ioctl */
+ { WLAN_FTM_PRIV_SET_NONE_GET_NONE,
+ 0,
+ 0,
+ "" },
+
+ /* handlers for sub-ioctl */
+ { WE_SET_NV_DEFAULTS,
+ 0,
+ 0,
+ "set_nv_defaults" },
+
+};
+
+const struct iw_handler_def we_ftm_handler_def = {
+ .num_standard = 0,
+ .num_private = sizeof(we_ftm_private) / sizeof(we_ftm_private[0]),
+ .num_private_args = sizeof(we_ftm_private_args) / sizeof(we_ftm_private_args[0]),
+
+ .standard = (iw_handler *)NULL,
+ .private = (iw_handler *)we_ftm_private,
+ .private_args = we_ftm_private_args,
+ .get_wireless_stats = NULL,
+};
+
+static int wlan_ftm_register_wext(hdd_adapter_t *pAdapter)
+{
+
+ //hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ // Zero the memory. This zeros the profile structure.
+ //memset(pwextBuf, 0,sizeof(hdd_wext_state_t));
+
+ pAdapter->dev->wireless_handlers = (struct iw_handler_def *)&we_ftm_handler_def;
+
+ return 0;
+}
+
+#endif //ANI_MANF_DIAG
+
+VOS_STATUS WLANFTM_McProcessMsg (v_VOID_t *message)
+{
+#ifdef ANI_MANF_DIAG
+ ftm_rsp_msg_t *pFtmMsgRsp;
+
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ hdd_context_t *pHddCtx;
+ v_CONTEXT_t pVosContext= NULL;
+
+ ENTER();
+
+ pFtmMsgRsp = (ftm_rsp_msg_t *)message;
+
+ if (!message )
+ {
+ VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR,
+ "WLAN FTM:Invalid parameter sent on WLANFTM_ProcessMainMessage");
+ return VOS_STATUS_E_INVAL;
+ }
+ /*Get the global context */
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+
+ /*Get the Hdd Context */
+ pHddCtx = ((VosContextType*)(pVosContext))->pHDDContext;
+
+ if (pHddCtx->ftm.cmd_iwpriv == TRUE) {
+
+ complete(&pHddCtx->ftm.ftm_comp_var);
+ }
+ else {
+ /*Response length to Ptt App*/
+ pHddCtx->ftm.wnl->wmsg.length = sizeof(tAniHdr)+ SIZE_OF_FTM_DIAG_HEADER_LEN + pFtmMsgRsp->msgBodyLength;
+
+ /*Ptt App expects the response length in LE */
+ pHddCtx->ftm.wnl->wmsg.length = FTM_SWAP16(pHddCtx->ftm.wnl->wmsg.length);
+
+ /*Response expects the length to be in */
+ pHddCtx->ftm.pResponseBuf->ftm_hdr.data_len = pHddCtx->ftm.pRequestBuf->ftm_hdr.data_len -
+ sizeof(pHddCtx->ftm.pRequestBuf->ftm_hdr.data_len);
+
+ /*Copy the message*/
+ memcpy((char*)&pHddCtx->ftm.pResponseBuf->ftmpkt,(char*)message,pFtmMsgRsp->msgBodyLength);
+
+ /*Update the error code*/
+ pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_SUCCESS;
+
+ vos_status = vos_event_set(&pHddCtx->ftm.ftm_vos_event);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos_event_set failed!!\n"));
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ EXIT();
+#endif
+ return VOS_STATUS_SUCCESS;
+
+}
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
new file mode 100644
index 0000000..585dc9b
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -0,0 +1,2753 @@
+/*
+ * 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 wlan_hdd_hostapd.c
+ \brief WLAN Host Device Driver implementation
+
+ 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.
+
+ $Header:$ $DateTime: $ $Author: $
+
+
+ when who what, where, why
+ -------- --- --------------------------------------------------------
+ 04/5/09 Shailender Created module.
+ 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
+ ==========================================================================*/
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/wireless.h>
+#include <linux/semaphore.h>
+#include <vos_api.h>
+#include <vos_sched.h>
+#include <linux/etherdevice.h>
+#include <wlan_hdd_includes.h>
+#include <qc_sap_ioctl.h>
+#include <wlan_hdd_hostapd.h>
+#include <sapApi.h>
+#include <sapInternal.h>
+#include <wlan_qct_tl.h>
+#include <wlan_hdd_softap_tx_rx.h>
+#include <wlan_hdd_main.h>
+#include <linux/netdevice.h>
+#include <linux/mmc/sdio_func.h>
+#include "wlan_nlink_common.h"
+#include "wlan_btc_svc.h"
+#include <bap_hdd_main.h>
+#if defined CONFIG_CFG80211
+#include "wlan_hdd_p2p.h"
+#endif
+
+#define IS_UP(_dev) \
+ (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
+#define IS_UP_AUTO(_ic) \
+ (IS_UP((_ic)->ic_dev) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
+#define WE_WLAN_VERSION 1
+#define STATS_CONTEXT_MAGIC 0x53544154
+
+struct statsContext
+{
+ struct completion completion;
+ hdd_adapter_t *pAdapter;
+ unsigned int magic;
+};
+#define SAP_24GHZ_CH_COUNT (14)
+/*---------------------------------------------------------------------------
+ * Function definitions
+ *-------------------------------------------------------------------------*/
+/**---------------------------------------------------------------------------
+
+ \brief hdd_hostapd_open() - HDD Open function for hostapd interface
+
+ This is called in response to ifconfig up
+
+ \param - dev Pointer to net_device structure
+
+ \return - 0 for success non-zero for failure
+
+ --------------------------------------------------------------------------*/
+int hdd_hostapd_open (struct net_device *dev)
+{
+ ENTER();
+
+ //Turn ON carrier state
+ netif_carrier_on(dev);
+ //Enable all Tx queues
+ netif_tx_start_all_queues(dev);
+
+ EXIT();
+ return 0;
+}
+/**---------------------------------------------------------------------------
+
+ \brief hdd_hostapd_stop() - HDD stop function for hostapd interface
+
+ This is called in response to ifconfig down
+
+ \param - dev Pointer to net_device structure
+
+ \return - 0 for success non-zero for failure
+
+ --------------------------------------------------------------------------*/
+int hdd_hostapd_stop (struct net_device *dev)
+{
+ ENTER();
+
+ //Stop all tx queues
+ netif_tx_disable(dev);
+
+ //Turn OFF carrier state
+ netif_carrier_off(dev);
+
+ EXIT();
+ return 0;
+}
+/**---------------------------------------------------------------------------
+
+ \brief hdd_hostapd_uninit() - HDD uninit function
+
+ This is called during the netdev unregister to uninitialize all data
+associated with the device
+
+ \param - dev Pointer to net_device structure
+
+ \return - void
+
+ --------------------------------------------------------------------------*/
+static void hdd_hostapd_uninit (struct net_device *dev)
+{
+ hdd_adapter_t *pHostapdAdapter = netdev_priv(dev);
+
+ ENTER();
+
+ if (pHostapdAdapter && pHostapdAdapter->pHddCtx)
+ {
+ hdd_deinit_adapter(pHostapdAdapter->pHddCtx, pHostapdAdapter);
+
+ /* after uninit our adapter structure will no longer be valid */
+ pHostapdAdapter->dev = NULL;
+ }
+
+ EXIT();
+}
+
+
+/**============================================================================
+ @brief hdd_hostapd_hard_start_xmit() - Function registered with the Linux OS for
+ transmitting packets. There are 2 versions of this function. One that uses
+ locked queue and other that uses lockless queues. Both have been retained to
+ do some performance testing
+ @param skb : [in] pointer to OS packet (sk_buff)
+ @param dev : [in] pointer to Libra network device
+
+ @return : NET_XMIT_DROP if packets are dropped
+ : NET_XMIT_SUCCESS if packet is enqueued succesfully
+ ===========================================================================*/
+int hdd_hostapd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ return 0;
+}
+int hdd_hostapd_change_mtu(struct net_device *dev, int new_mtu)
+{
+ return 0;
+}
+
+int hdd_hostapd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_priv_data_t priv_data;
+ tANI_U8 *command = NULL;
+ int ret = 0;
+
+ if (NULL == pAdapter)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD adapter context is Null", __FUNCTION__);
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ if ((!ifr) && (!ifr->ifr_data))
+ {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
+ {
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ command = kmalloc(priv_data.total_len, GFP_KERNEL);
+ if (!command)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: failed to allocate memory\n", __FUNCTION__);
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ if (copy_from_user(command, priv_data.buf, priv_data.total_len))
+ {
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ if ((SIOCDEVPRIVATE + 1) == cmd)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "***HOSTAPD*** : Received %s cmd from Wi-Fi GUI***", command);
+
+#ifdef WLAN_FEATURE_P2P
+ if(strncmp(command, "P2P_SET_NOA", 11) == 0 )
+ {
+ hdd_setP2pNoa(dev, command);
+ }
+ else if( strncmp(command, "P2P_SET_PS", 10) == 0 )
+ {
+ hdd_setP2pOpps(dev, command);
+ }
+#endif
+ }
+exit:
+ if (command)
+ {
+ kfree(command);
+ }
+ return ret;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_hostapd_set_mac_address() -
+ This function sets the user specified mac address using
+ the command ifconfig wlanX hw ether <mac adress>.
+
+ \param - dev - Pointer to the net device.
+ - addr - Pointer to the sockaddr.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static int hdd_hostapd_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sockaddr *psta_mac_addr = addr;
+ ENTER();
+ memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
+ EXIT();
+ return 0;
+}
+void hdd_hostapd_inactivity_timer_cb(v_PVOID_t usrDataForCallback)
+{
+ struct net_device *dev = (struct net_device *)usrDataForCallback;
+ v_BYTE_t we_custom_event[64];
+ union iwreq_data wrqu;
+#ifdef DISABLE_CONCURRENCY_AUTOSAVE
+ VOS_STATUS vos_status;
+ hdd_adapter_t *pHostapdAdapter;
+ hdd_ap_ctx_t *pHddApCtx;
+#endif /*DISABLE_CONCURRENCY_AUTOSAVE */
+
+ /* event_name space-delimiter driver_module_name */
+ /* Format of the event is "AUTO-SHUT.indication" " " "module_name" */
+ char * autoShutEvent = "AUTO-SHUT.indication" " " KBUILD_MODNAME;
+ int event_len = strlen(autoShutEvent) + 1; /* For the NULL at the end */
+
+ ENTER();
+
+#ifdef DISABLE_CONCURRENCY_AUTOSAVE
+ if (vos_concurrent_sessions_running())
+ {
+ /*
+ This timer routine is going to be called only when AP
+ persona is up.
+ If there are concurrent sessions running we do not want
+ to shut down the Bss.Instead we run the timer again so
+ that if Autosave is enabled next time and other session
+ was down only then we bring down AP
+ */
+ pHostapdAdapter = netdev_priv(dev);
+ pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
+ vos_status = vos_timer_start(
+ &pHddApCtx->hdd_ap_inactivity_timer,
+ (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff
+ * 1000);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ hddLog(LOGE, FL("Failed to init AP inactivity timer"));
+ }
+ EXIT();
+ return;
+ }
+#endif /*DISABLE_CONCURRENCY_AUTOSAVE */
+ memset(&we_custom_event, '\0', sizeof(we_custom_event));
+ memcpy(&we_custom_event, autoShutEvent, event_len);
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = event_len;
+
+ hddLog(LOG1, FL("Shutting down AP interface due to inactivity"));
+ wireless_send_event(dev, IWEVCUSTOM, &wrqu, (char *)we_custom_event);
+
+ EXIT();
+}
+
+
+VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCallback)
+{
+ hdd_adapter_t *pHostapdAdapter;
+ hdd_ap_ctx_t *pHddApCtx;
+ hdd_hostapd_state_t *pHostapdState;
+ struct net_device *dev;
+ eSapHddEvent sapEvent;
+ union iwreq_data wrqu;
+ v_BYTE_t *we_custom_event_generic = NULL;
+ int we_event = 0;
+ int i = 0;
+ v_U8_t staId;
+ VOS_STATUS vos_status;
+ v_BOOL_t bWPSState;
+ v_BOOL_t bApActive = FALSE;
+ v_BOOL_t bAuthRequired = TRUE;
+ tpSap_AssocMacAddr pAssocStasArray = NULL;
+ char unknownSTAEvent[IW_CUSTOM_MAX+1];
+ char maxAssocExceededEvent[IW_CUSTOM_MAX+1];
+ v_BYTE_t we_custom_start_event[64];
+ char *startBssEvent;
+
+ dev = (struct net_device *)usrDataForCallback;
+ pHostapdAdapter = netdev_priv(dev);
+ pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
+ pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
+ sapEvent = pSapEvent->sapHddEventCode;
+ memset(&wrqu, '\0', sizeof(wrqu));
+
+ switch(sapEvent)
+ {
+ case eSAP_START_BSS_EVENT :
+ hddLog(LOG1, FL("BSS configured status = %s, channel = %lu, bc sta Id = %d\n"),
+ pSapEvent->sapevt.sapStartBssCompleteEvent.status ? "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS",
+ pSapEvent->sapevt.sapStartBssCompleteEvent.operatingChannel,
+ pSapEvent->sapevt.sapStartBssCompleteEvent.staId);
+
+ pHostapdState->vosStatus = pSapEvent->sapevt.sapStartBssCompleteEvent.status;
+ vos_status = vos_event_set(&pHostapdState->vosEvent);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_status) || pHostapdState->vosStatus)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: startbss event failed!!\n"));
+ goto stopbss;
+ }
+ else
+ {
+ pHddApCtx->uBCStaId = pSapEvent->sapevt.sapStartBssCompleteEvent.staId;
+ //@@@ need wep logic here to set privacy bit
+ hdd_softap_Register_BC_STA(pHostapdAdapter, pHddApCtx->uPrivacy);
+ }
+
+ if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff)
+ {
+ // AP Inactivity timer init and start
+ vos_status = vos_timer_init( &pHddApCtx->hdd_ap_inactivity_timer, VOS_TIMER_TYPE_SW,
+ hdd_hostapd_inactivity_timer_cb, (v_PVOID_t)dev );
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ hddLog(LOGE, FL("Failed to init AP inactivity timer\n"));
+
+ vos_status = vos_timer_start( &pHddApCtx->hdd_ap_inactivity_timer, (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff * 1000);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ hddLog(LOGE, FL("Failed to init AP inactivity timer\n"));
+
+ }
+ pHddApCtx->operatingChannel = pSapEvent->sapevt.sapStartBssCompleteEvent.operatingChannel;
+ pHostapdState->bssState = BSS_START;
+
+ // Send current operating channel of SoftAP to BTC-ES
+ send_btc_nlink_msg(WLAN_BTC_SOFTAP_BSS_START, 0);
+
+#ifdef CONFIG_CFG80211
+ //Check if there is any group key pending to set.
+ if( pHddApCtx->groupKey.keyLength )
+ {
+ if( eHAL_STATUS_SUCCESS != WLANSAP_SetKeySta(
+ (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext,
+ &pHddApCtx->groupKey ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WLANSAP_SetKeySta failed", __func__);
+ }
+ pHddApCtx->groupKey.keyLength = 0;
+ }
+ else if ( pHddApCtx->wepKey[0].keyLength )
+ {
+ int i=0;
+ for ( i = 0; i < CSR_MAX_NUM_KEY; i++ )
+ {
+ if( eHAL_STATUS_SUCCESS != WLANSAP_SetKeySta(
+ (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext,
+ &pHddApCtx->wepKey[i] ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WLANSAP_SetKeySta failed idx %d", __func__, i);
+ }
+ pHddApCtx->wepKey[i].keyLength = 0;
+ }
+ }
+#endif
+ //Fill the params for sending IWEVCUSTOM Event with SOFTAP.enabled
+ startBssEvent = "SOFTAP.enabled";
+ memset(&we_custom_start_event, '\0', sizeof(we_custom_start_event));
+ memcpy(&we_custom_start_event, startBssEvent, strlen(startBssEvent));
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlen(startBssEvent);
+ we_event = IWEVCUSTOM;
+ we_custom_event_generic = we_custom_start_event;
+
+ break; //Event will be sent after Switch-Case stmt
+
+ case eSAP_STOP_BSS_EVENT:
+ hddLog(LOG1, FL("BSS stop status = %s\n"),pSapEvent->sapevt.sapStopBssCompleteEvent.status ?
+ "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS");
+
+ pHddApCtx->operatingChannel = 0; //Invalidate the channel info.
+ vos_event_set(&pHostapdState->vosEvent);
+ goto stopbss;
+ case eSAP_STA_SET_KEY_EVENT:
+ //TODO: forward the message to hostapd once implementtation is done for now just print
+ hddLog(LOG1, FL("SET Key: configured status = %s\n"),pSapEvent->sapevt.sapStationSetKeyCompleteEvent.status ?
+ "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS");
+ return VOS_STATUS_SUCCESS;
+ case eSAP_STA_DEL_KEY_EVENT:
+ //TODO: forward the message to hostapd once implementtation is done for now just print
+ hddLog(LOG1, FL("Event received %s\n"),"eSAP_STA_DEL_KEY_EVENT");
+ return VOS_STATUS_SUCCESS;
+ case eSAP_STA_MIC_FAILURE_EVENT:
+ {
+ struct iw_michaelmicfailure msg;
+ memset(&msg, '\0', sizeof(msg));
+ msg.src_addr.sa_family = ARPHRD_ETHER;
+ memcpy(msg.src_addr.sa_data, &pSapEvent->sapevt.sapStationMICFailureEvent.staMac, sizeof(msg.src_addr.sa_data));
+ hddLog(LOG1, "MIC MAC "MAC_ADDRESS_STR"\n", MAC_ADDR_ARRAY(msg.src_addr.sa_data));
+ if(pSapEvent->sapevt.sapStationMICFailureEvent.multicast == eCSR_ROAM_RESULT_MIC_ERROR_GROUP)
+ msg.flags = IW_MICFAILURE_GROUP;
+ else
+ msg.flags = IW_MICFAILURE_PAIRWISE;
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = sizeof(msg);
+ we_event = IWEVMICHAELMICFAILURE;
+ we_custom_event_generic = (v_BYTE_t *)&msg;
+ }
+#ifdef CONFIG_CFG80211
+ /* inform mic failure to nl80211 */
+ cfg80211_michael_mic_failure(dev,
+ pSapEvent->sapevt.
+ sapStationMICFailureEvent.staMac.bytes,
+ ((pSapEvent->sapevt.sapStationMICFailureEvent.multicast == eSIR_TRUE) ?
+ NL80211_KEYTYPE_GROUP :
+ NL80211_KEYTYPE_PAIRWISE),
+ pSapEvent->sapevt.sapStationMICFailureEvent.keyId,
+ pSapEvent->sapevt.sapStationMICFailureEvent.TSC,
+ GFP_KERNEL);
+#endif
+ break;
+
+ case eSAP_STA_ASSOC_EVENT:
+ case eSAP_STA_REASSOC_EVENT:
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ memcpy(wrqu.addr.sa_data, &pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac,
+ sizeof(wrqu.addr.sa_data));
+ hddLog(LOG1, " associated "MAC_ADDRESS_STR"\n", MAC_ADDR_ARRAY(wrqu.addr.sa_data));
+ we_event = IWEVREGISTERED;
+
+ WLANSAP_Get_WPS_State((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, &bWPSState);
+
+ if ( (eCSR_ENCRYPT_TYPE_NONE == pHddApCtx->ucEncryptType) ||
+ ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pHddApCtx->ucEncryptType ) ||
+ ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pHddApCtx->ucEncryptType ) )
+ {
+ bAuthRequired = FALSE;
+ }
+
+ if (bAuthRequired || bWPSState == eANI_BOOLEAN_TRUE )
+ {
+ hdd_softap_RegisterSTA( pHostapdAdapter,
+ TRUE,
+ pHddApCtx->uPrivacy,
+ pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId,
+ 0,
+ 0,
+ (v_MACADDR_t *)wrqu.addr.sa_data,
+ pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.wmmEnabled);
+ }
+ else
+ {
+ hdd_softap_RegisterSTA( pHostapdAdapter,
+ FALSE,
+ pHddApCtx->uPrivacy,
+ pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId,
+ 0,
+ 0,
+ (v_MACADDR_t *)wrqu.addr.sa_data,
+ pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.wmmEnabled);
+ }
+
+ // Stop AP inactivity timer
+ if (pHddApCtx->hdd_ap_inactivity_timer.state == VOS_TIMER_STATE_RUNNING)
+ {
+ vos_status = vos_timer_stop(&pHddApCtx->hdd_ap_inactivity_timer);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ hddLog(LOGE, FL("Failed to start AP inactivity timer\n"));
+ }
+#ifdef CONFIG_CFG80211
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ {
+ struct station_info staInfo;
+ v_U16_t iesLen = pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.iesLen;
+
+ memset(&staInfo, 0, sizeof(staInfo));
+ if (iesLen <= MAX_ASSOC_IND_IE_LEN )
+ {
+ staInfo.assoc_req_ies =
+ (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.ies[0];
+ staInfo.assoc_req_ies_len = iesLen;
+ cfg80211_new_sta(dev,
+ (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac.bytes[0],
+ &staInfo, GFP_KERNEL);
+ }
+ else
+ {
+ hddLog(LOGE, FL(" Assoc Ie length is too long \n"));
+ }
+ }
+#endif
+#endif
+
+ break;
+ case eSAP_STA_DISASSOC_EVENT:
+ memcpy(wrqu.addr.sa_data, &pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac,
+ sizeof(wrqu.addr.sa_data));
+ hddLog(LOG1, " disassociated "MAC_ADDRESS_STR"\n", MAC_ADDR_ARRAY(wrqu.addr.sa_data));
+ if (pSapEvent->sapevt.sapStationDisassocCompleteEvent.reason == eSAP_USR_INITATED_DISASSOC)
+ hddLog(LOG1," User initiated disassociation");
+ else
+ hddLog(LOG1," MAC initiated disassociation");
+ we_event = IWEVEXPIRED;
+ vos_status = hdd_softap_GetStaId(pHostapdAdapter, &pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac, &staId);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD Failed to find sta id!!\n"));
+ return VOS_STATUS_E_FAILURE;
+ }
+ hdd_softap_DeregisterSTA(pHostapdAdapter, staId);
+
+ if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff)
+ {
+ spin_lock_bh( &pHostapdAdapter->staInfo_lock );
+ // Start AP inactivity timer if no stations associated with it
+ for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
+ {
+ if (pHostapdAdapter->aStaInfo[i].isUsed && i != (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uBCStaId)
+ {
+ bApActive = TRUE;
+ break;
+ }
+ }
+ spin_unlock_bh( &pHostapdAdapter->staInfo_lock );
+
+ if (bApActive == FALSE)
+ {
+ if (pHddApCtx->hdd_ap_inactivity_timer.state == VOS_TIMER_STATE_STOPPED)
+ {
+ vos_status = vos_timer_start(&pHddApCtx->hdd_ap_inactivity_timer, (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff * 1000);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ hddLog(LOGE, FL("Failed to init AP inactivity timer\n"));
+ }
+ else
+ VOS_ASSERT(vos_timer_getCurrentState(&pHddApCtx->hdd_ap_inactivity_timer) == VOS_TIMER_STATE_STOPPED);
+ }
+ }
+#ifdef CONFIG_CFG80211
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ cfg80211_del_sta(dev,
+ (const u8 *)&pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac.bytes[0],
+ GFP_KERNEL);
+#endif
+#endif
+ break;
+ case eSAP_WPS_PBC_PROBE_REQ_EVENT:
+ {
+ static const char * message ="MLMEWPSPBCPROBEREQ.indication";
+ union iwreq_data wreq;
+
+ down(&pHddApCtx->semWpsPBCOverlapInd);
+ pHddApCtx->WPSPBCProbeReq.probeReqIELen = pSapEvent->sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq.probeReqIELen;
+
+ vos_mem_copy(pHddApCtx->WPSPBCProbeReq.probeReqIE, pSapEvent->sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq.probeReqIE,
+ pHddApCtx->WPSPBCProbeReq.probeReqIELen);
+
+ vos_mem_copy(pHddApCtx->WPSPBCProbeReq.peerMacAddr, pSapEvent->sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq.peerMacAddr, sizeof(v_MACADDR_t));
+ hddLog(LOG1, "WPS PBC probe req "MAC_ADDRESS_STR"\n", MAC_ADDR_ARRAY(pHddApCtx->WPSPBCProbeReq.peerMacAddr));
+ memset(&wreq, 0, sizeof(wreq));
+ wreq.data.length = strlen(message); // This is length of message
+ wireless_send_event(dev, IWEVCUSTOM, &wreq, (char *)message);
+
+ return VOS_STATUS_SUCCESS;
+ }
+ case eSAP_ASSOC_STA_CALLBACK_EVENT:
+ pAssocStasArray = pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas;
+ if (pSapEvent->sapevt.sapAssocStaListEvent.noOfAssocSta != 0)
+ { // List of associated stations
+ for (i = 0; i < pSapEvent->sapevt.sapAssocStaListEvent.noOfAssocSta; i++)
+ {
+ hddLog(LOG1,"Associated Sta Num %d:assocId=%d, staId=%d, staMac="MAC_ADDRESS_STR,
+ i+1,
+ pAssocStasArray->assocId,
+ pAssocStasArray->staId,
+ MAC_ADDR_ARRAY(pAssocStasArray->staMac.bytes));
+ pAssocStasArray++;
+ }
+ }
+ vos_mem_free(pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas);// Release caller allocated memory here
+ return VOS_STATUS_SUCCESS;
+#ifdef WLAN_FEATURE_P2P
+ case eSAP_INDICATE_MGMT_FRAME:
+ hdd_indicateMgmtFrame( pHostapdAdapter,
+ pSapEvent->sapevt.sapManagementFrameInfo.nFrameLength,
+ pSapEvent->sapevt.sapManagementFrameInfo.pbFrames,
+ pSapEvent->sapevt.sapManagementFrameInfo.frameType,
+ pSapEvent->sapevt.sapManagementFrameInfo.rxChan);
+ return VOS_STATUS_SUCCESS;
+ case eSAP_REMAIN_CHAN_READY:
+ hdd_remainChanReadyHandler( pHostapdAdapter );
+ return VOS_STATUS_SUCCESS;
+ case eSAP_SEND_ACTION_CNF:
+ hdd_sendActionCnf( pHostapdAdapter,
+ ( eSAP_STATUS_SUCCESS ==
+ pSapEvent->sapevt.sapActionCnf.actionSendSuccess ) ?
+ TRUE : FALSE );
+ return VOS_STATUS_SUCCESS;
+#endif
+ case eSAP_UNKNOWN_STA_JOIN:
+ snprintf(unknownSTAEvent, IW_CUSTOM_MAX, "JOIN_UNKNOWN_STA-%02x:%02x:%02x:%02x:%02x:%02x",
+ pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[0],
+ pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[1],
+ pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[2],
+ pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[3],
+ pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[4],
+ pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[5]);
+ we_event = IWEVCUSTOM; /* Discovered a new node (AP mode). */
+ wrqu.data.pointer = unknownSTAEvent;
+ wrqu.data.length = strlen(unknownSTAEvent);
+ we_custom_event_generic = (v_BYTE_t *)unknownSTAEvent;
+ hddLog(LOG1,"%s\n", unknownSTAEvent);
+ break;
+
+ case eSAP_MAX_ASSOC_EXCEEDED:
+ snprintf(maxAssocExceededEvent, IW_CUSTOM_MAX, "Peer %02x:%02x:%02x:%02x:%02x:%02x denied"
+ " assoc due to Maximum Mobile Hotspot connections reached. Please disconnect"
+ " one or more devices to enable the new device connection",
+ pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[0],
+ pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[1],
+ pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[2],
+ pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[3],
+ pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[4],
+ pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[5]);
+ we_event = IWEVCUSTOM; /* Discovered a new node (AP mode). */
+ wrqu.data.pointer = maxAssocExceededEvent;
+ wrqu.data.length = strlen(maxAssocExceededEvent);
+ we_custom_event_generic = (v_BYTE_t *)maxAssocExceededEvent;
+ hddLog(LOG1,"%s\n", maxAssocExceededEvent);
+ break;
+ case eSAP_STA_ASSOC_IND:
+ return VOS_STATUS_SUCCESS;
+ default:
+ hddLog(LOG1,"SAP message is not handled\n");
+ goto stopbss;
+ return VOS_STATUS_SUCCESS;
+ }
+ wireless_send_event(dev, we_event, &wrqu, (char *)we_custom_event_generic);
+ return VOS_STATUS_SUCCESS;
+
+stopbss :
+ {
+ v_BYTE_t we_custom_event[64];
+ char *stopBssEvent = "STOP-BSS.response";//17
+ int event_len = strlen(stopBssEvent);
+
+ hddLog(LOG1, FL("BSS stop status = %s"),
+ pSapEvent->sapevt.sapStopBssCompleteEvent.status ?
+ "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS");
+
+ /* Change the BSS state now since, as we are shutting things down,
+ * we don't want interfaces to become re-enabled */
+ pHostapdState->bssState = BSS_STOP;
+
+ /* Stop the pkts from n/w stack as we are going to free all of
+ * the TX WMM queues for all STAID's */
+ hdd_hostapd_stop(dev);
+
+ /* reclaim all resources allocated to the BSS */
+ hdd_softap_stop_bss(pHostapdAdapter);
+
+ /* notify userspace that the BSS has stopped */
+ memset(&we_custom_event, '\0', sizeof(we_custom_event));
+ memcpy(&we_custom_event, stopBssEvent, event_len);
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = event_len;
+ we_event = IWEVCUSTOM;
+ we_custom_event_generic = we_custom_event;
+ wireless_send_event(dev, we_event, &wrqu, (char *)we_custom_event_generic);
+ }
+ return VOS_STATUS_SUCCESS;
+}
+int hdd_softap_unpackIE(
+ tHalHandle halHandle,
+ eCsrEncryptionType *pEncryptType,
+ eCsrEncryptionType *mcEncryptType,
+ eCsrAuthType *pAuthType,
+ u_int16_t gen_ie_len,
+ u_int8_t *gen_ie )
+{
+ tDot11fIERSN dot11RSNIE;
+ tDot11fIEWPA dot11WPAIE;
+
+ tANI_U8 *pRsnIe;
+ tANI_U16 RSNIeLen;
+
+ if (NULL == halHandle)
+ {
+ hddLog(LOGE, FL("Error haHandle returned NULL\n"));
+ return -EINVAL;
+ }
+
+ // Validity checks
+ if ((gen_ie_len < VOS_MIN(DOT11F_IE_RSN_MIN_LEN, DOT11F_IE_WPA_MIN_LEN)) ||
+ (gen_ie_len > VOS_MAX(DOT11F_IE_RSN_MAX_LEN, DOT11F_IE_WPA_MAX_LEN)) )
+ return -EINVAL;
+ // Type check
+ if ( gen_ie[0] == DOT11F_EID_RSN)
+ {
+ // Validity checks
+ if ((gen_ie_len < DOT11F_IE_RSN_MIN_LEN ) ||
+ (gen_ie_len > DOT11F_IE_RSN_MAX_LEN) )
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+ // Skip past the EID byte and length byte
+ pRsnIe = gen_ie + 2;
+ RSNIeLen = gen_ie_len - 2;
+ // Unpack the RSN IE
+ memset(&dot11RSNIE, 0, sizeof(tDot11fIERSN));
+ dot11fUnpackIeRSN((tpAniSirGlobal) halHandle,
+ pRsnIe,
+ RSNIeLen,
+ &dot11RSNIE);
+ // Copy out the encryption and authentication types
+ hddLog(LOG1, FL("%s: pairwise cipher suite count: %d\n"),
+ __FUNCTION__, dot11RSNIE.pwise_cipher_suite_count );
+ hddLog(LOG1, FL("%s: authentication suite count: %d\n"),
+ __FUNCTION__, dot11RSNIE.akm_suite_count);
+ /*Here we have followed the apple base code,
+ but probably I suspect we can do something different*/
+ //dot11RSNIE.akm_suite_count
+ // Just translate the FIRST one
+ *pAuthType = hdd_TranslateRSNToCsrAuthType(dot11RSNIE.akm_suites[0]);
+ //dot11RSNIE.pwise_cipher_suite_count
+ *pEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.pwise_cipher_suites[0]);
+ //dot11RSNIE.gp_cipher_suite_count
+ *mcEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.gp_cipher_suite);
+ // Set the PMKSA ID Cache for this interface
+
+ // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
+ } else
+ if (gen_ie[0] == DOT11F_EID_WPA)
+ {
+ // Validity checks
+ if ((gen_ie_len < DOT11F_IE_WPA_MIN_LEN ) ||
+ (gen_ie_len > DOT11F_IE_WPA_MAX_LEN))
+ {
+ return VOS_STATUS_E_FAILURE;
+ }
+ // Skip past the EID byte and length byte - and four byte WiFi OUI
+ pRsnIe = gen_ie + 2 + 4;
+ RSNIeLen = gen_ie_len - (2 + 4);
+ // Unpack the WPA IE
+ memset(&dot11WPAIE, 0, sizeof(tDot11fIEWPA));
+ dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
+ pRsnIe,
+ RSNIeLen,
+ &dot11WPAIE);
+ // Copy out the encryption and authentication types
+ hddLog(LOG1, FL("%s: WPA unicast cipher suite count: %d\n"),
+ __FUNCTION__, dot11WPAIE.unicast_cipher_count );
+ hddLog(LOG1, FL("%s: WPA authentication suite count: %d\n"),
+ __FUNCTION__, dot11WPAIE.auth_suite_count);
+ //dot11WPAIE.auth_suite_count
+ // Just translate the FIRST one
+ *pAuthType = hdd_TranslateWPAToCsrAuthType(dot11WPAIE.auth_suites[0]);
+ //dot11WPAIE.unicast_cipher_count
+ *pEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.unicast_ciphers[0]);
+ //dot11WPAIE.unicast_cipher_count
+ *mcEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
+ }
+ else
+ {
+ hddLog(LOGW, FL("%s: gen_ie[0]: %d\n"), __FUNCTION__, gen_ie[0]);
+ return VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+}
+int
+static iw_softap_setparam(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
+ int *value = (int *)extra;
+ int sub_cmd = value[0];
+ int set_value = value[1];
+ eHalStatus status;
+ int ret = 0; /* success */
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+
+ switch(sub_cmd)
+ {
+
+ case QCSAP_PARAM_CLR_ACL:
+ if ( eHAL_STATUS_SUCCESS != WLANSAP_ClearACL( pVosContext ))
+ {
+ ret = -EIO;
+ }
+ break;
+
+ case QCSAP_PARAM_ACL_MODE:
+ if ((eSAP_ALLOW_ALL < (eSapMacAddrACL)set_value) ||
+ (eSAP_ACCEPT_UNLESS_DENIED > (eSapMacAddrACL)set_value))
+ {
+ hddLog(LOGE, FL("Invalid ACL Mode value %d"), set_value);
+ ret = -EINVAL;
+ }
+ else
+ {
+ WLANSAP_SetMode(pVosContext, set_value);
+ }
+ break;
+ case QCSAP_PARAM_MAX_ASSOC:
+ if (WNI_CFG_ASSOC_STA_LIMIT_STAMIN > set_value)
+ {
+ hddLog(LOGE, FL("Invalid setMaxAssoc value %d"), set_value);
+ ret = -EINVAL;
+ }
+ else
+ {
+ if (WNI_CFG_ASSOC_STA_LIMIT_STAMAX < set_value)
+ {
+ hddLog(LOGW, FL("setMaxAssoc value %d higher than max allowed %d."
+ "Setting it to max allowed and continuing"),
+ set_value, WNI_CFG_ASSOC_STA_LIMIT_STAMAX);
+ set_value = WNI_CFG_ASSOC_STA_LIMIT_STAMAX;
+ }
+ status = ccmCfgSetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT,
+ set_value, NULL, eANI_BOOLEAN_FALSE);
+ if ( status != eHAL_STATUS_SUCCESS )
+ {
+ hddLog(LOGE, FL("setMaxAssoc failure, status %d"),
+ status);
+ ret = -EIO;
+ }
+ }
+ break;
+
+ case QCSAP_PARAM_HIDE_SSID:
+ {
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ status = sme_HideSSID(hHal, pHostapdAdapter->sessionId, set_value);
+ if(eHAL_STATUS_SUCCESS != status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: QCSAP_PARAM_HIDE_SSID failed",
+ __FUNCTION__);
+ return status;
+ }
+ break;
+ }
+
+ default:
+ hddLog(LOGE, FL("Invalid setparam command %d value %d"),
+ sub_cmd, set_value);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+
+int
+static iw_softap_getparam(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
+ int *value = (int *)extra;
+ int sub_cmd = value[0];
+ eHalStatus status;
+ int ret = 0; /* success */
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+
+ switch (sub_cmd)
+ {
+ case QCSAP_PARAM_MAX_ASSOC:
+ status = ccmCfgGetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, (tANI_U32 *)value);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ ret = -EIO;
+ }
+ break;
+
+ case QCSAP_PARAM_CLR_ACL:
+ if ( eHAL_STATUS_SUCCESS != WLANSAP_ClearACL( pVosContext ))
+ {
+ ret = -EIO;
+ }
+ *value = 0;
+ break;
+
+ case QCSAP_PARAM_MODULE_DOWN_IND:
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: sending WLAN_MODULE_DOWN_IND", __FUNCTION__);
+ send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
+#ifdef WLAN_BTAMP_FEATURE
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Take down AMP PAL", __FUNCTION__);
+ BSL_Deinit(vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
+#endif
+ *value = 0;
+ break;
+ }
+
+ default:
+ hddLog(LOGE, FL("Invalid getparam command %d"), sub_cmd);
+ ret = -EINVAL;
+ break;
+
+ }
+
+ return ret;
+}
+
+/* Usage:
+ BLACK_LIST = 0
+ WHITE_LIST = 1
+ ADD MAC = 0
+ REMOVE MAC = 1
+
+ mac addr will be accepted as a 6 octet mac address with each octet inputted in hex
+ for e.g. 00:0a:f5:11:22:33 will be represented as 0x00 0x0a 0xf5 0x11 0x22 0x33
+ while using this ioctl
+
+ Syntax:
+ iwpriv softap.0 modify_acl
+ <6 octet mac addr> <list type> <cmd type>
+
+ Examples:
+ eg 1. to add a mac addr 00:0a:f5:89:89:90 to the black list
+ iwpriv softap.0 modify_acl 0x00 0x0a 0xf5 0x89 0x89 0x90 0 0
+ eg 2. to delete a mac addr 00:0a:f5:89:89:90 from white list
+ iwpriv softap.0 modify_acl 0x00 0x0a 0xf5 0x89 0x89 0x90 1 1
+*/
+int iw_softap_modify_acl(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+ v_BYTE_t *value = (v_BYTE_t*)extra;
+ v_U8_t pPeerStaMac[VOS_MAC_ADDR_SIZE];
+ int listType, cmd, i;
+ int ret = 0; /* success */
+
+ ENTER();
+ for (i=0; i<VOS_MAC_ADDR_SIZE; i++)
+ {
+ pPeerStaMac[i] = *(value+i);
+ }
+ listType = (int)(*(value+i));
+ i++;
+ cmd = (int)(*(value+i));
+
+ hddLog(LOG1, "%s: SAP Modify ACL arg0 %02x:%02x:%02x:%02x:%02x:%02x arg1 %d arg2 %d\n",
+ __FUNCTION__, pPeerStaMac[0], pPeerStaMac[1], pPeerStaMac[2],
+ pPeerStaMac[3], pPeerStaMac[4], pPeerStaMac[5], listType, cmd);
+
+ if (WLANSAP_ModifyACL(pVosContext, pPeerStaMac,(eSapACLType)listType,(eSapACLCmdType)cmd)
+ != VOS_STATUS_SUCCESS)
+ {
+ hddLog(LOGE, FL("Modify ACL failed\n"));
+ ret = -EIO;
+ }
+ EXIT();
+ return ret;
+}
+
+int
+static iw_softap_getchannel(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+
+ *(v_U32_t *)(wrqu->data.pointer) = (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->operatingChannel;
+
+ wrqu->data.length = sizeof((WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->operatingChannel);
+
+ return 0;
+}
+
+#define IS_BROADCAST_MAC(x) (((x[0] & x[1] & x[2] & x[3] & x[4] & x[5]) == 0xff) ? 1 : 0)
+
+int
+static iw_softap_getassoc_stamacaddr(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ unsigned char *pmaclist;
+ hdd_station_info_t *pStaInfo = pHostapdAdapter->aStaInfo;
+ int cnt = 0, len;
+
+
+ pmaclist = wrqu->data.pointer + sizeof(unsigned long int);
+ len = wrqu->data.length;
+
+ spin_lock_bh( &pHostapdAdapter->staInfo_lock );
+ while((cnt < WLAN_MAX_STA_COUNT) && (len > (sizeof(v_MACADDR_t)+1))) {
+ if (TRUE == pStaInfo[cnt].isUsed) {
+
+ if(!IS_BROADCAST_MAC(pStaInfo[cnt].macAddrSTA.bytes)) {
+ memcpy((void *)pmaclist, (void *)&(pStaInfo[cnt].macAddrSTA), sizeof(v_MACADDR_t));
+ pmaclist += sizeof(v_MACADDR_t);
+ len -= sizeof(v_MACADDR_t);
+ }
+ }
+ cnt++;
+ }
+ spin_unlock_bh( &pHostapdAdapter->staInfo_lock );
+
+ *pmaclist = '\0';
+
+ wrqu->data.length -= len;
+
+ *(unsigned long int *)(wrqu->data.pointer) = wrqu->data.length;
+
+ return 0;
+}
+
+/* Usage:
+ mac addr will be accepted as a 6 octet mac address with each octet inputted in hex
+ for e.g. 00:0a:f5:11:22:33 will be represented as 0x00 0x0a 0xf5 0x11 0x22 0x33
+ while using this ioctl
+
+ Syntax:
+ iwpriv softap.0 disassoc_sta <6 octet mac address>
+
+ e.g.
+ disassociate sta with mac addr 00:0a:f5:11:22:33 from softap
+ iwpriv softap.0 disassoc_sta 0x00 0x0a 0xf5 0x11 0x22 0x33
+*/
+
+int
+static iw_softap_disassoc_sta(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ v_U8_t *peerMacAddr;
+
+ ENTER();
+ /* the comparison below is needed since if iwpriv tool is used for calling this ioctl
+ * data is passed in extra (less than 16 octets); however in android wifi framework
+ * data is placed in wrqu->data.pointer.
+ */
+ if ((v_U8_t*)wrqu == (v_U8_t*)extra)
+ peerMacAddr = (v_U8_t *)(extra);
+ else
+ peerMacAddr = (v_U8_t *)(wrqu->data.pointer);
+
+ hddLog(LOG1, "data %02x:%02x:%02x:%02x:%02x:%02x",
+ peerMacAddr[0], peerMacAddr[1], peerMacAddr[2],
+ peerMacAddr[3], peerMacAddr[4], peerMacAddr[5]);
+ hdd_softap_sta_disassoc(pHostapdAdapter, peerMacAddr);
+ EXIT();
+ return 0;
+}
+
+int
+static iw_softap_ap_stats(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ WLANTL_TRANSFER_STA_TYPE statBuffer;
+ char *pstatbuf;
+ int len = wrqu->data.length;
+ pstatbuf = wrqu->data.pointer;
+
+ WLANSAP_GetStatistics((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, &statBuffer, (v_BOOL_t)wrqu->data.flags);
+
+ len = snprintf(pstatbuf, len,
+ "RUF=%d RMF=%d RBF=%d "
+ "RUB=%d RMB=%d RBB=%d "
+ "TUF=%d TMF=%d TBF=%d "
+ "TUB=%d TMB=%d TBB=%d",
+ (int)statBuffer.rxUCFcnt, (int)statBuffer.rxMCFcnt, (int)statBuffer.rxBCFcnt,
+ (int)statBuffer.rxUCBcnt, (int)statBuffer.rxMCBcnt, (int)statBuffer.rxBCBcnt,
+ (int)statBuffer.txUCFcnt, (int)statBuffer.txMCFcnt, (int)statBuffer.txBCFcnt,
+ (int)statBuffer.txUCBcnt, (int)statBuffer.txMCBcnt, (int)statBuffer.txBCBcnt
+ );
+
+ wrqu->data.length -= len;
+ return 0;
+}
+
+int
+static iw_softap_commit(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ hdd_hostapd_state_t *pHostapdState;
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+ tpWLAN_SAPEventCB pSapEventCallback;
+ tsap_Config_t *pConfig;
+ s_CommitConfig_t *pCommitConfig;
+ struct qc_mac_acl_entry *acl_entry = NULL;
+ v_SINT_t i = 0, num_mac = 0;
+ v_U32_t status = 0;
+ eCsrAuthType RSNAuthType;
+ eCsrEncryptionType RSNEncryptType;
+ eCsrEncryptionType mcRSNEncryptType;
+
+ pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
+ pCommitConfig = (s_CommitConfig_t *)extra;
+
+ pConfig = kmalloc(sizeof(tsap_Config_t), GFP_KERNEL);
+ if(NULL == pConfig) {
+ hddLog(LOG1, "VOS unable to allocate memory\n");
+ return -ENOMEM;
+ }
+ pConfig->beacon_int = pCommitConfig->beacon_int;
+ pConfig->channel = pCommitConfig->channel;
+
+ /*Protection parameter to enable or disable*/
+ pConfig->protEnabled = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
+ pConfig->dtim_period = pCommitConfig->dtim_period;
+ switch(pCommitConfig->hw_mode )
+ {
+ case eQC_DOT11_MODE_11A:
+ pConfig->SapHw_mode = eSAP_DOT11_MODE_11a;
+ break;
+ case eQC_DOT11_MODE_11B:
+ pConfig->SapHw_mode = eSAP_DOT11_MODE_11b;
+ break;
+ case eQC_DOT11_MODE_11G:
+ pConfig->SapHw_mode = eSAP_DOT11_MODE_11g;
+ break;
+
+ case eQC_DOT11_MODE_11N:
+ pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
+ break;
+ case eQC_DOT11_MODE_11G_ONLY:
+ pConfig->SapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
+ break;
+ case eQC_DOT11_MODE_11N_ONLY:
+ pConfig->SapHw_mode = eSAP_DOT11_MODE_11n_ONLY;
+ break;
+ default:
+ pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
+ break;
+
+ }
+
+ pConfig->ieee80211d = pCommitConfig->qcsap80211d;
+ vos_mem_copy(pConfig->countryCode, pCommitConfig->countryCode, 3);
+ if(pCommitConfig->authType == eQC_AUTH_TYPE_SHARED_KEY)
+ pConfig->authType = eSAP_SHARED_KEY;
+ else if(pCommitConfig->authType == eQC_AUTH_TYPE_OPEN_SYSTEM)
+ pConfig->authType = eSAP_OPEN_SYSTEM;
+ else
+ pConfig->authType = eSAP_AUTO_SWITCH;
+
+ pConfig->privacy = pCommitConfig->privacy;
+ (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pCommitConfig->privacy;
+ pConfig->wps_state = pCommitConfig->wps_state;
+ pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
+ pConfig->RSNWPAReqIELength = pCommitConfig->RSNWPAReqIELength;
+ if(pConfig->RSNWPAReqIELength){
+ pConfig->pRSNWPAReqIE = &pCommitConfig->RSNWPAReqIE[0];
+ if ((pConfig->pRSNWPAReqIE[0] == DOT11F_EID_RSN) || (pConfig->pRSNWPAReqIE[0] == DOT11F_EID_WPA)){
+ // The actual processing may eventually be more extensive than this.
+ // Right now, just consume any PMKIDs that are sent in by the app.
+ status = hdd_softap_unpackIE(
+#if defined(FEATURE_WLAN_NON_INTEGRATED_SOC)
+ vos_get_context( VOS_MODULE_ID_HAL, pVosContext),
+#else
+ vos_get_context( VOS_MODULE_ID_PE, pVosContext),
+#endif
+ &RSNEncryptType,
+ &mcRSNEncryptType,
+ &RSNAuthType,
+ pConfig->pRSNWPAReqIE[1]+2,
+ pConfig->pRSNWPAReqIE );
+
+ if( VOS_STATUS_SUCCESS == status )
+ {
+ // Now copy over all the security attributes you have parsed out
+ //TODO: Need to handle mixed mode
+ pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
+ pConfig->mcRSNEncryptType = mcRSNEncryptType;
+ hddLog( LOG1, FL("%s: CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d\n"),
+ RSNAuthType, RSNEncryptType, mcRSNEncryptType);
+ }
+ }
+ }
+ else
+ {
+ /* If no RSNIE, set encrypt type to NONE*/
+ pConfig->RSNEncryptType = eCSR_ENCRYPT_TYPE_NONE;
+ pConfig->mcRSNEncryptType = eCSR_ENCRYPT_TYPE_NONE;
+ hddLog( LOG1, FL("EncryptionType = %d mcEncryptionType = %d\n"),
+ pConfig->RSNEncryptType, pConfig->mcRSNEncryptType);
+ }
+
+ pConfig->SSIDinfo.ssidHidden = pCommitConfig->SSIDinfo.ssidHidden;
+ pConfig->SSIDinfo.ssid.length = pCommitConfig->SSIDinfo.ssid.length;
+ vos_mem_copy(pConfig->SSIDinfo.ssid.ssId, pCommitConfig->SSIDinfo.ssid.ssId, pConfig->SSIDinfo.ssid.length);
+ vos_mem_copy(pConfig->self_macaddr.bytes, pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
+
+ pConfig->SapMacaddr_acl = pCommitConfig->qc_macaddr_acl;
+
+ // ht_capab is not what the name conveys,this is used for protection bitmap
+ pConfig->ht_capab = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
+
+ if (pCommitConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
+ num_mac = pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
+ else
+ num_mac = pConfig->num_accept_mac = pCommitConfig->num_accept_mac;
+ acl_entry = pCommitConfig->accept_mac;
+ for (i = 0; i < num_mac; i++)
+ {
+ vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(v_MACADDR_t));
+ acl_entry++;
+ }
+ if (pCommitConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
+ num_mac = pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
+ else
+ num_mac = pConfig->num_deny_mac = pCommitConfig->num_deny_mac;
+ acl_entry = pCommitConfig->deny_mac;
+ for (i = 0; i < num_mac; i++)
+ {
+ vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(v_MACADDR_t));
+ acl_entry++;
+ }
+ //Uapsd Enabled Bit
+ pConfig->UapsdEnable = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
+ //Enable OBSS protection
+ pConfig->obssProtEnabled = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
+ (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->apDisableIntraBssFwd = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apDisableIntraBssFwd;
+
+ hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"), MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
+ hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
+ hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int, (int)pConfig->channel);
+ hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
+ hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy, pConfig->authType);
+ hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
+ hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
+ hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),pConfig->protEnabled, pConfig->obssProtEnabled);
+ hddLog(LOGW,FL("DisableIntraBssFwd = %d\n"),(WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->apDisableIntraBssFwd);
+
+ pSapEventCallback = hdd_hostapd_SAPEventCB;
+ pConfig->persona = pHostapdAdapter->device_mode;
+ if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,(v_PVOID_t)dev) != VOS_STATUS_SUCCESS)
+ {
+ hddLog(LOGE,FL("SAP Start Bss fail\n"));
+ }
+
+ kfree(pConfig);
+
+ hddLog(LOG1, FL("Waiting for Scan to complete(auto mode) and BSS to start"));
+ vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos wait for single_event failed!!\n"));
+ VOS_ASSERT(0);
+ }
+
+ pHostapdState->bCommit = TRUE;
+ if(pHostapdState->vosStatus)
+ {
+ return -1;
+ }
+ else
+ {
+ set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
+ WLANSAP_Update_WpsIe ( pVosContext );
+ return 0;
+ }
+}
+static
+int iw_softap_setmlme(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct sQcSapreq_mlme *pmlme;
+ hdd_adapter_t *pHostapdAdapter = (hdd_adapter_t*)(netdev_priv(dev));
+ v_MACADDR_t destAddress;
+ pmlme = (struct sQcSapreq_mlme *)(wrqu->name);
+ /* NOTE: this address is not valid incase of TKIP failure, since not filled */
+ vos_mem_copy(&destAddress.bytes, pmlme->im_macaddr, sizeof(v_MACADDR_t));
+ switch(pmlme->im_op)
+ {
+ case QCSAP_MLME_AUTHORIZE:
+ hdd_softap_change_STA_state( pHostapdAdapter, &destAddress, WLANTL_STA_AUTHENTICATED);
+ break;
+ case QCSAP_MLME_ASSOC:
+ //TODO:inform to TL after associating (not needed as we do in sapCallback)
+ break;
+ case QCSAP_MLME_UNAUTHORIZE:
+ //TODO: send the disassoc to station
+ //hdd_softap_change_STA_state( pHostapdAdapter, pmlme->im_macaddr, WLANTL_STA_AUTHENTICATED);
+ break;
+ case QCSAP_MLME_DISASSOC:
+ hdd_softap_sta_disassoc(pHostapdAdapter,pmlme->im_macaddr);
+ break;
+ case QCSAP_MLME_DEAUTH:
+ hdd_softap_sta_deauth(pHostapdAdapter,pmlme->im_macaddr);
+ break;
+ case QCSAP_MLME_MICFAILURE:
+ hdd_softap_tkip_mic_fail_counter_measure(pHostapdAdapter,pmlme->im_reason);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int iw_softap_set_channel_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
+
+ int *value = (int *)extra;
+ int startChannel = value[0];
+ int endChannel = value[1];
+ int band = value[2];
+ eHalStatus status;
+ int ret = 0; /* success */
+
+ status = WLANSAP_SetChannelRange(hHal,startChannel,endChannel,band);
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog( LOGE, FL("iw_softap_set_channel_range: startChannel = %d, endChannel = %d band = %d\n"),
+ startChannel,endChannel, band);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+int iw_softap_get_channel_list(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ v_U32_t num_channels = 0;
+ v_U8_t i = 0;
+ v_U8_t bandStartChannel = RF_CHAN_1;
+ v_U8_t bandEndChannel = RF_CHAN_165;
+ v_U32_t temp_num_channels = 0;
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
+ v_REGDOMAIN_t domainIdCurrentSoftap;
+
+ tpChannelListInfo channel_list = (tpChannelListInfo) extra;
+ wrqu->data.length = sizeof(tChannelListInfo);
+ ENTER();
+
+ for( i = bandStartChannel; i <= bandEndChannel; i++ )
+ {
+ if( NV_CHANNEL_ENABLE == regChannels[i].enabled )
+ {
+ channel_list->channels[num_channels] = rfChannels[i].channelNum;
+ num_channels++;
+ }
+ }
+
+ /* remove indoor channels if the domain is FCC, channels 36 - 48 */
+
+ temp_num_channels = num_channels;
+
+ if(eHAL_STATUS_SUCCESS != sme_getSoftApDomain(hHal,(v_REGDOMAIN_t *) &domainIdCurrentSoftap))
+ {
+ hddLog(LOG1,FL("Failed to get Domain ID, %d \n"),domainIdCurrentSoftap);
+ return -1;
+ }
+
+ if(REGDOMAIN_FCC == domainIdCurrentSoftap)
+ {
+ for(i = 0; i < temp_num_channels; i++)
+ {
+
+ if((channel_list->channels[i] > 35) &&
+ (channel_list->channels[i] < 49))
+ {
+ vos_mem_move(&channel_list->channels[i],
+ &channel_list->channels[i+1],
+ temp_num_channels - (i-1));
+ num_channels--;
+ temp_num_channels--;
+ i--;
+ }
+ }
+ }
+
+ hddLog(LOG1,FL(" number of channels %d\n"), num_channels);
+
+ if (num_channels > IW_MAX_FREQUENCIES)
+ {
+ num_channels = IW_MAX_FREQUENCIES;
+ }
+
+ channel_list->num_channels = num_channels;
+ EXIT();
+
+ return 0;
+}
+
+static
+int iw_get_genie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+ eHalStatus status;
+ v_U32_t length = DOT11F_IE_RSN_MAX_LEN;
+ v_U8_t genIeBytes[DOT11F_IE_RSN_MAX_LEN];
+ ENTER();
+ hddLog(LOG1,FL("getGEN_IE ioctl\n"));
+ // Actually retrieve the RSN IE from CSR. (We previously sent it down in the CSR Roam Profile.)
+ status = WLANSap_getstationIE_information(pVosContext,
+ &length,
+ genIeBytes);
+ wrqu->data.length = VOS_MIN((u_int16_t) length, DOT11F_IE_RSN_MAX_LEN);
+ vos_mem_copy( wrqu->data.pointer, (v_VOID_t*)genIeBytes, wrqu->data.length);
+
+ hddLog(LOG1,FL(" RSN IE of %d bytes returned\n"), wrqu->data.length );
+
+
+ EXIT();
+ return 0;
+}
+static
+int iw_get_WPSPBCProbeReqIEs(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ sQcSapreq_WPSPBCProbeReqIES_t *pWPSPBCProbeReqIEs;
+ hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
+ ENTER();
+
+ hddLog(LOG1,FL("get_WPSPBCProbeReqIEs ioctl\n"));
+
+ pWPSPBCProbeReqIEs = (sQcSapreq_WPSPBCProbeReqIES_t *)(wrqu->data.pointer);
+ pWPSPBCProbeReqIEs->probeReqIELen = pHddApCtx->WPSPBCProbeReq.probeReqIELen;
+ vos_mem_copy(pWPSPBCProbeReqIEs->probeReqIE, pHddApCtx->WPSPBCProbeReq.probeReqIE, pWPSPBCProbeReqIEs->probeReqIELen);
+ vos_mem_copy(pWPSPBCProbeReqIEs->macaddr, pHddApCtx->WPSPBCProbeReq.peerMacAddr, sizeof(v_MACADDR_t));
+ wrqu->data.length = 12 + pWPSPBCProbeReqIEs->probeReqIELen;
+ hddLog(LOG1, FL("Macaddress : "MAC_ADDRESS_STR"\n"), MAC_ADDR_ARRAY(pWPSPBCProbeReqIEs->macaddr));
+ up(&pHddApCtx->semWpsPBCOverlapInd);
+ EXIT();
+ return 0;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief iw_set_auth_hostap() -
+ This function sets the auth type received from the wpa_supplicant.
+
+ \param - dev - Pointer to the net device.
+ - info - Pointer to the iw_request_info.
+ - wrqu - Pointer to the iwreq_data.
+ - extra - Pointer to the data.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+int iw_set_auth_hostap(struct net_device *dev,struct iw_request_info *info,
+ union iwreq_data *wrqu,char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ ENTER();
+ switch(wrqu->param.flags & IW_AUTH_INDEX)
+ {
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ {
+ if(wrqu->param.value) {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "Counter Measure started %d", wrqu->param.value);
+ pWextState->mTKIPCounterMeasures = TKIP_COUNTER_MEASURE_STARTED;
+ }
+ else {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "Counter Measure stopped=%d", wrqu->param.value);
+ pWextState->mTKIPCounterMeasures = TKIP_COUNTER_MEASURE_STOPED;
+ }
+
+ hdd_softap_tkip_mic_fail_counter_measure(pAdapter,
+ wrqu->param.value);
+ }
+ break;
+
+ default:
+
+ hddLog(LOGW, "%s called with unsupported auth type %d", __FUNCTION__,
+ wrqu->param.flags & IW_AUTH_INDEX);
+ break;
+ }
+
+ EXIT();
+ return 0;
+}
+
+static int iw_set_ap_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+ hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
+ eHalStatus halStatus= eHAL_STATUS_SUCCESS;
+ struct iw_encode_ext *ext = (struct iw_encode_ext*)extra;
+ v_U8_t groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+ int key_index;
+ struct iw_point *encoding = &wrqu->encoding;
+ tCsrRoamSetKey setKey;
+// tCsrRoamRemoveKey RemoveKey;
+ int i;
+ ENTER();
+
+ key_index = encoding->flags & IW_ENCODE_INDEX;
+
+ if(key_index > 0) {
+
+ /*Convert from 1-based to 0-based keying*/
+ key_index--;
+ }
+ if(!ext->key_len) {
+#if 0
+ /*Set the encrytion type to NONE*/
+#if 0
+ pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+#endif
+
+ RemoveKey.keyId = key_index;
+ if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ /*Key direction for group is RX only*/
+ vos_mem_copy(RemoveKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
+ }
+ else {
+ vos_mem_copy(RemoveKey.peerMac,ext->addr.sa_data,WNI_CFG_BSSID_LEN);
+ }
+ switch(ext->alg)
+ {
+ case IW_ENCODE_ALG_NONE:
+ RemoveKey.encType = eCSR_ENCRYPT_TYPE_NONE;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ RemoveKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104;
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ RemoveKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ RemoveKey.encType = eCSR_ENCRYPT_TYPE_AES;
+ break;
+ default:
+ RemoveKey.encType = eCSR_ENCRYPT_TYPE_NONE;
+ break;
+ }
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Remove key cipher_alg:%d key_len%d *pEncryptionType :%d \n",
+ __FUNCTION__,(int)ext->alg,(int)ext->key_len,RemoveKey.encType);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Peer Mac = "MAC_ADDRESS_STR"\n",
+ __FUNCTION__, MAC_ADDR_ARRAY(RemoveKey.peerMac));
+ );
+ halStatus = WLANSAP_DelKeySta( pVosContext, &RemoveKey);
+ if ( halStatus != eHAL_STATUS_SUCCESS )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "[%4d] WLANSAP_DeleteKeysSta returned ERROR status= %d",
+ __LINE__, halStatus );
+ }
+#endif
+ return halStatus;
+
+ }
+
+ vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
+
+ setKey.keyId = key_index;
+ setKey.keyLength = ext->key_len;
+
+ if(ext->key_len <= CSR_MAX_KEY_LEN) {
+ vos_mem_copy(&setKey.Key[0],ext->key,ext->key_len);
+ }
+
+ if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ /*Key direction for group is RX only*/
+ setKey.keyDirection = eSIR_RX_ONLY;
+ vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
+ }
+ else {
+
+ setKey.keyDirection = eSIR_TX_RX;
+ vos_mem_copy(setKey.peerMac,ext->addr.sa_data,WNI_CFG_BSSID_LEN);
+ }
+ if(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ {
+ setKey.keyDirection = eSIR_TX_DEFAULT;
+ vos_mem_copy(setKey.peerMac,ext->addr.sa_data,WNI_CFG_BSSID_LEN);
+ }
+
+ /*For supplicant pae role is zero*/
+ setKey.paeRole = 0;
+
+ switch(ext->alg)
+ {
+ case IW_ENCODE_ALG_NONE:
+ setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
+ break;
+
+ case IW_ENCODE_ALG_WEP:
+ setKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104;
+ pHddApCtx->uPrivacy = 1;
+ hddLog(LOG1, "(%s) uPrivacy=%d", __FUNCTION__, pHddApCtx->uPrivacy);
+ break;
+
+ case IW_ENCODE_ALG_TKIP:
+ {
+ v_U8_t *pKey = &setKey.Key[0];
+
+ setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
+
+ vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
+
+ /*Supplicant sends the 32bytes key in this order
+
+ |--------------|----------|----------|
+ | Tk1 |TX-MIC | RX Mic |
+ |--------------|----------|----------|
+ <---16bytes---><--8bytes--><--8bytes-->
+
+ */
+ /*Sme expects the 32 bytes key to be in the below order
+
+ |--------------|----------|----------|
+ | Tk1 |RX-MIC | TX Mic |
+ |--------------|----------|----------|
+ <---16bytes---><--8bytes--><--8bytes-->
+ */
+ /* Copy the Temporal Key 1 (TK1) */
+ vos_mem_copy(pKey,ext->key,16);
+
+ /*Copy the rx mic first*/
+ vos_mem_copy(&pKey[16],&ext->key[24],8);
+
+ /*Copy the tx mic */
+ vos_mem_copy(&pKey[24],&ext->key[16],8);
+
+ }
+ break;
+
+ case IW_ENCODE_ALG_CCMP:
+ setKey.encType = eCSR_ENCRYPT_TYPE_AES;
+ break;
+
+ default:
+ setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
+ break;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ ("%s:EncryptionType:%d key_len:%d, :%d, KeyId:%d \n"),__FUNCTION__, setKey.encType, setKey.keyLength,
+ setKey.keyId);
+ for(i=0; i< ext->key_len; i++)
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ ("%02x"), setKey.Key[i]);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ ("\n"));
+ halStatus = WLANSAP_SetKeySta( pVosContext, &setKey);
+
+ if ( halStatus != eHAL_STATUS_SUCCESS )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] WLANSAP_SetKeySta returned ERROR status= %d", __LINE__, halStatus );
+ }
+
+ return halStatus;
+}
+static int iw_set_ap_mlme(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+#if 0
+ hdd_adapter_t *pAdapter = (netdev_priv(dev));
+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
+
+ ENTER();
+
+ //reason_code is unused. By default it is set to eCSR_DISCONNECT_REASON_UNSPECIFIED
+ switch (mlme->cmd) {
+ case IW_MLME_DISASSOC:
+ case IW_MLME_DEAUTH:
+ hddLog(LOG1, "Station disassociate");
+ if( pAdapter->conn_info.connState == eConnectionState_Associated )
+ {
+ eCsrRoamDisconnectReason reason = eCSR_DISCONNECT_REASON_UNSPECIFIED;
+
+ if( mlme->reason_code == HDD_REASON_MICHAEL_MIC_FAILURE )
+ reason = eCSR_DISCONNECT_REASON_MIC_ERROR;
+
+ status = sme_RoamDisconnect( pAdapter->hHal,pAdapter->sessionId, reason);
+
+ //clear all the reason codes
+ if (status != 0)
+ {
+ hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate : csrRoamDisconnect failure returned %d \n", __FUNCTION__, (int)mlme->cmd, (int)status );
+ }
+
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+ }
+ else
+ {
+ hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate called but station is not in associated state \n", __FUNCTION__, (int)mlme->cmd );
+ }
+ default:
+ hddLog(LOGE,"%s %d Command should be Disassociate/Deauthenticate \n", __FUNCTION__, (int)mlme->cmd );
+ return -EINVAL;
+ }//end of switch
+ EXIT();
+#endif
+ return 0;
+// return status;
+}
+
+static int iw_get_ap_rts_threshold(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ v_U32_t status = 0;
+
+ status = hdd_wlan_get_rts_threshold(pHostapdAdapter, wrqu);
+
+ return status;
+}
+
+static int iw_get_ap_frag_threshold(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ v_U32_t status = 0;
+
+ status = hdd_wlan_get_frag_threshold(pHostapdAdapter, wrqu);
+
+ return status;
+}
+
+static int iw_get_ap_freq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *fwrq, char *extra)
+{
+ v_U32_t status = 0,channel,freq;
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ tHalHandle hHal;
+ hdd_hostapd_state_t *pHostapdState;
+ hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pHostapdAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return status;
+ }
+
+ pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
+ hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
+
+ if(pHostapdState->bssState == BSS_STOP )
+ {
+ if (ccmCfgGetInt(hHal, WNI_CFG_CURRENT_CHANNEL, &channel)
+ != eHAL_STATUS_SUCCESS)
+ {
+ return -EIO;
+ }
+ else
+ {
+ status = hdd_wlan_get_freq(channel, &freq);
+ fwrq->m = freq;
+ fwrq->e = 0;
+ }
+ }
+ else
+ {
+ channel = pHddApCtx->operatingChannel;
+ status = hdd_wlan_get_freq(channel, &freq);
+ fwrq->m = freq;
+ fwrq->e = 0;
+ }
+ return status;
+}
+
+static int iw_softap_setwpsie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+ hdd_hostapd_state_t *pHostapdState;
+ eHalStatus halStatus= eHAL_STATUS_SUCCESS;
+ u_int8_t *wps_genie = wrqu->data.pointer;
+ u_int8_t *pos;
+ tpSap_WPSIE pSap_WPSIe;
+ u_int8_t WPSIeType;
+ u_int16_t length;
+ ENTER();
+
+ if(!wrqu->data.length)
+ return 0;
+
+ pSap_WPSIe = vos_mem_malloc(sizeof(tSap_WPSIE));
+ if (NULL == pSap_WPSIe)
+ {
+ hddLog(LOGE, "VOS unable to allocate memory\n");
+ return -ENOMEM;
+ }
+ vos_mem_zero(pSap_WPSIe, sizeof(tSap_WPSIE));
+
+ hddLog(LOG1,"%s WPS IE type[0x%X] IE[0x%X], LEN[%d]\n", __FUNCTION__, wps_genie[0], wps_genie[1], wps_genie[2]);
+ WPSIeType = wps_genie[0];
+ if ( wps_genie[0] == eQC_WPS_BEACON_IE)
+ {
+ pSap_WPSIe->sapWPSIECode = eSAP_WPS_BEACON_IE;
+ wps_genie = wps_genie + 1;
+ switch ( wps_genie[0] )
+ {
+ case DOT11F_EID_WPA:
+ if (wps_genie[1] < 2 + 4)
+ {
+ vos_mem_free(pSap_WPSIe);
+ return -EINVAL;
+ }
+ else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0)
+ {
+ hddLog (LOG1, "%s Set WPS BEACON IE(len %d)",__FUNCTION__, wps_genie[1]+2);
+ pos = &wps_genie[6];
+ while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) )
+ {
+ switch((u_int16_t)(*pos<<8) | *(pos+1))
+ {
+ case HDD_WPS_ELEM_VERSION:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version = *pos;
+ hddLog(LOG1, "WPS version %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version);
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_VER_PRESENT;
+ pos += 1;
+ break;
+
+ case HDD_WPS_ELEM_WPS_STATE:
+ pos +=4;
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState = *pos;
+ hddLog(LOG1, "WPS State %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState);
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_STATE_PRESENT;
+ pos += 1;
+ break;
+ case HDD_WPS_ELEM_APSETUPLOCK:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked = *pos;
+ hddLog(LOG1, "AP setup lock %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked);
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_APSETUPLOCK_PRESENT;
+ pos += 1;
+ break;
+ case HDD_WPS_ELEM_SELECTEDREGISTRA:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra = *pos;
+ hddLog(LOG1, "Selected Registra %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra);
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRA_PRESENT;
+ pos += 1;
+ break;
+ case HDD_WPS_ELEM_DEVICE_PASSWORD_ID:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID = (*pos<<8) | *(pos+1);
+ hddLog(LOG1, "Password ID: %x\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID);
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_DEVICEPASSWORDID_PRESENT;
+ pos += 2;
+ break;
+ case HDD_WPS_ELEM_REGISTRA_CONF_METHODS:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1);
+ hddLog(LOG1, "Select Registra Config Methods: %x\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod);
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT;
+ pos += 2;
+ break;
+
+ case HDD_WPS_ELEM_UUID_E:
+ pos += 2;
+ length = *pos<<8 | *(pos+1);
+ pos += 2;
+ vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E, pos, length);
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_UUIDE_PRESENT;
+ pos += length;
+ break;
+ case HDD_WPS_ELEM_RF_BANDS:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand = *pos;
+ hddLog(LOG1, "RF band: %d\n", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand);
+ pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_RF_BANDS_PRESENT;
+ pos += 1;
+ break;
+
+ default:
+ hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)\n", (*pos<<8 | *(pos+1)));
+ vos_mem_free(pSap_WPSIe);
+ return -EINVAL;
+ }
+ }
+ }
+ else {
+ hddLog (LOGE, "%s WPS IE Mismatch %X",
+ __FUNCTION__, wps_genie[0]);
+ }
+ break;
+
+ default:
+ hddLog (LOGE, "%s Set UNKNOWN IE %X",__FUNCTION__, wps_genie[0]);
+ vos_mem_free(pSap_WPSIe);
+ return 0;
+ }
+ }
+ else if( wps_genie[0] == eQC_WPS_PROBE_RSP_IE)
+ {
+ pSap_WPSIe->sapWPSIECode = eSAP_WPS_PROBE_RSP_IE;
+ wps_genie = wps_genie + 1;
+ switch ( wps_genie[0] )
+ {
+ case DOT11F_EID_WPA:
+ if (wps_genie[1] < 2 + 4)
+ {
+ vos_mem_free(pSap_WPSIe);
+ return -EINVAL;
+ }
+ else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0)
+ {
+ hddLog (LOG1, "%s Set WPS PROBE RSP IE(len %d)",__FUNCTION__, wps_genie[1]+2);
+ pos = &wps_genie[6];
+ while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) )
+ {
+ switch((u_int16_t)(*pos<<8) | *(pos+1))
+ {
+ case HDD_WPS_ELEM_VERSION:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version = *pos;
+ hddLog(LOG1, "WPS version %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_VER_PRESENT;
+ pos += 1;
+ break;
+
+ case HDD_WPS_ELEM_WPS_STATE:
+ pos +=4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState = *pos;
+ hddLog(LOG1, "WPS State %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_STATE_PRESENT;
+ pos += 1;
+ break;
+ case HDD_WPS_ELEM_APSETUPLOCK:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked = *pos;
+ hddLog(LOG1, "AP setup lock %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_APSETUPLOCK_PRESENT;
+ pos += 1;
+ break;
+ case HDD_WPS_ELEM_SELECTEDREGISTRA:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra = *pos;
+ hddLog(LOG1, "Selected Registra %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRA_PRESENT;
+ pos += 1;
+ break;
+ case HDD_WPS_ELEM_DEVICE_PASSWORD_ID:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID = (*pos<<8) | *(pos+1);
+ hddLog(LOG1, "Password ID: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICEPASSWORDID_PRESENT;
+ pos += 2;
+ break;
+ case HDD_WPS_ELEM_REGISTRA_CONF_METHODS:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1);
+ hddLog(LOG1, "Select Registra Config Methods: %x\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT;
+ pos += 2;
+ break;
+ case HDD_WPS_ELEM_RSP_TYPE:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType = *pos;
+ hddLog(LOG1, "Config Methods: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RESPONSETYPE_PRESENT;
+ pos += 1;
+ break;
+ case HDD_WPS_ELEM_UUID_E:
+ pos += 2;
+ length = *pos<<8 | *(pos+1);
+ pos += 2;
+ vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E, pos, length);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_UUIDE_PRESENT;
+ pos += length;
+ break;
+
+ case HDD_WPS_ELEM_MANUFACTURER:
+ pos += 2;
+ length = *pos<<8 | *(pos+1);
+ pos += 2;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.num_name = length;
+ vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name, pos, length);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MANUFACTURE_PRESENT;
+ pos += length;
+ break;
+
+ case HDD_WPS_ELEM_MODEL_NAME:
+ pos += 2;
+ length = *pos<<8 | *(pos+1);
+ pos += 2;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.num_text = length;
+ vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text, pos, length);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNAME_PRESENT;
+ pos += length;
+ break;
+ case HDD_WPS_ELEM_MODEL_NUM:
+ pos += 2;
+ length = *pos<<8 | *(pos+1);
+ pos += 2;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.num_text = length;
+ vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text, pos, length);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNUMBER_PRESENT;
+ pos += length;
+ break;
+ case HDD_WPS_ELEM_SERIAL_NUM:
+ pos += 2;
+ length = *pos<<8 | *(pos+1);
+ pos += 2;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.num_text = length;
+ vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text, pos, length);
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SERIALNUMBER_PRESENT;
+ pos += length;
+ break;
+ case HDD_WPS_ELEM_PRIMARY_DEVICE_TYPE:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory = (*pos<<8 | *(pos+1));
+ hddLog(LOG1, "primary dev category: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory);
+ pos += 2;
+
+ vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceOUI, pos, HDD_WPS_DEVICE_OUI_LEN);
+ hddLog(LOG1, "primary dev oui: %02x, %02x, %02x, %02x\n", pos[0], pos[1], pos[2], pos[3]);
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory = (*pos<<8 | *(pos+1));
+ hddLog(LOG1, "primary dev sub category: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory);
+ pos += 2;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT;
+ break;
+ case HDD_WPS_ELEM_DEVICE_NAME:
+ pos += 2;
+ length = *pos<<8 | *(pos+1);
+ pos += 2;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.num_text = length;
+ vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text, pos, length);
+ pos += length;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICENAME_PRESENT;
+ break;
+ case HDD_WPS_ELEM_CONFIG_METHODS:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ConfigMethod = (*pos<<8) | *(pos+1);
+ hddLog(LOG1, "Config Methods: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod);
+ pos += 2;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_CONFIGMETHODS_PRESENT;
+ break;
+
+ case HDD_WPS_ELEM_RF_BANDS:
+ pos += 4;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand = *pos;
+ hddLog(LOG1, "RF band: %d\n", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand);
+ pos += 1;
+ pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RF_BANDS_PRESENT;
+ break;
+ } // switch
+ }
+ }
+ else
+ {
+ hddLog (LOGE, "%s WPS IE Mismatch %X",__FUNCTION__, wps_genie[0]);
+ }
+
+ } // switch
+ }
+ halStatus = WLANSAP_Set_WpsIe(pVosContext, pSap_WPSIe);
+ pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
+ if( pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE)
+ {
+ //hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ //v_CONTEXT_t pVosContext = pHostapdAdapter->pvosContext;
+ WLANSAP_Update_WpsIe ( pVosContext );
+ }
+
+ vos_mem_free(pSap_WPSIe);
+ EXIT();
+ return halStatus;
+}
+
+static int iw_softap_stopbss(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ ENTER();
+ if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
+ {
+ if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext) ) )
+ {
+ hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
+
+ status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
+
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ ("ERROR: HDD vos wait for single_event failed!!\n"));
+ VOS_ASSERT(0);
+ }
+ }
+ clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
+ }
+ EXIT();
+ return (status == VOS_STATUS_SUCCESS) ? 0 : -EBUSY;
+}
+
+static int iw_softap_version(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ VOS_STATUS status;
+ ENTER();
+ status = hdd_wlan_get_version(pHostapdAdapter, wrqu, extra);
+ if ( !VOS_IS_STATUS_SUCCESS( status ) ) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s Failed!!!\n",__func__);
+ return -EINVAL;
+ }
+ EXIT();
+#endif//TODO need to handle in prima
+ return 0;
+}
+static int iw_set_ap_genie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
+ eHalStatus halStatus= eHAL_STATUS_SUCCESS;
+ u_int8_t *genie = wrqu->data.pointer;
+
+ ENTER();
+
+ if(!wrqu->data.length)
+ {
+ EXIT();
+ return 0;
+ }
+
+ switch (genie[0])
+ {
+ case DOT11F_EID_WPA:
+ case DOT11F_EID_RSN:
+ if((WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy == 0)
+ {
+ hdd_softap_Deregister_BC_STA(pHostapdAdapter);
+ hdd_softap_Register_BC_STA(pHostapdAdapter, 1);
+ }
+ (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = 1;
+ halStatus = WLANSAP_Set_WPARSNIes(pVosContext, wrqu->data.pointer, wrqu->data.length);
+ break;
+
+ default:
+ hddLog (LOGE, "%s Set UNKNOWN IE %X",__FUNCTION__, genie[0]);
+ halStatus = 0;
+ }
+
+ EXIT();
+ return halStatus;
+}
+
+static VOS_STATUS wlan_hdd_get_classAstats_for_station(hdd_adapter_t *pAdapter, u8 staid)
+{
+ eHalStatus hstatus;
+ long lrc;
+ struct statsContext context;
+
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Padapter is NULL", __func__);
+ return VOS_STATUS_E_FAULT;
+ }
+
+ init_completion(&context.completion);
+ context.pAdapter = pAdapter;
+ context.magic = STATS_CONTEXT_MAGIC;
+ hstatus = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ eCSR_HDD,
+ SME_GLOBAL_CLASSA_STATS,
+ hdd_GetClassA_statisticsCB,
+ 0, // not periodic
+ FALSE, //non-cached results
+ staid,
+ &context);
+ if (eHAL_STATUS_SUCCESS != hstatus)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to retrieve statistics for link speed",
+ __FUNCTION__);
+ }
+ else
+ {
+ lrc = wait_for_completion_interruptible_timeout(&context.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
+ context.magic = 0;
+ if (lrc <= 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: SME %s while retrieving link speed",
+ __FUNCTION__, (0 == lrc) ? "timeout" : "interrupt");
+ msleep(50);
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+int iw_get_softap_linkspeed(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+
+{
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ char *pLinkSpeed = (char*)extra;
+ v_U16_t link_speed;
+ unsigned short staId;
+ int len = sizeof(v_U16_t)+1;
+ v_BYTE_t macAddress[VOS_MAC_ADDR_SIZE];
+ VOS_STATUS status;
+ int rc;
+
+ if ( hdd_string_to_hex ((char *)wrqu->data.pointer, wrqu->data.length, macAddress ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "ERROR: Command not found");
+ return -EINVAL;
+ }
+
+ status = hdd_softap_GetStaId(pHostapdAdapter, (v_MACADDR_t *)macAddress, (void *)(&staId));
+
+ if (!VOS_IS_STATUS_SUCCESS(status ))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD Failed to find sta id!!\n"));
+ link_speed = 0;
+ }
+ else
+ {
+ status = wlan_hdd_get_classAstats_for_station(pHostapdAdapter , staId);
+ if (!VOS_IS_STATUS_SUCCESS(status ))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve SME statistics", __FUNCTION__);
+ return -EINVAL;
+ }
+ link_speed =(int)pHostapdAdapter->hdd_stats.ClassA_stat.tx_rate/2;
+ }
+
+ wrqu->data.length = len;
+ rc = snprintf(pLinkSpeed, len, "%u", link_speed);
+ if ((rc < 0) || (rc >= len))
+ {
+ // encoding or length error?
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to encode link speed, got [%s]",
+ __FUNCTION__, pLinkSpeed);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static const iw_handler hostapd_handler[] =
+{
+ (iw_handler) NULL, /* SIOCSIWCOMMIT */
+ (iw_handler) NULL, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) NULL, /* SIOCSIWFREQ */
+ (iw_handler) iw_get_ap_freq, /* SIOCGIWFREQ */
+ (iw_handler) NULL, /* SIOCSIWMODE */
+ (iw_handler) NULL, /* SIOCGIWMODE */
+ (iw_handler) NULL, /* SIOCSIWSENS */
+ (iw_handler) NULL, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* SIOCSIWRANGE */
+ (iw_handler) NULL, /* SIOCGIWRANGE */
+ (iw_handler) NULL, /* SIOCSIWPRIV */
+ (iw_handler) NULL, /* SIOCGIWPRIV */
+ (iw_handler) NULL, /* SIOCSIWSTATS */
+ (iw_handler) NULL, /* SIOCGIWSTATS */
+ (iw_handler) NULL, /* SIOCSIWSPY */
+ (iw_handler) NULL, /* SIOCGIWSPY */
+ (iw_handler) NULL, /* SIOCSIWTHRSPY */
+ (iw_handler) NULL, /* SIOCGIWTHRSPY */
+ (iw_handler) NULL, /* SIOCSIWAP */
+ (iw_handler) NULL, /* SIOCGIWAP */
+ (iw_handler) iw_set_ap_mlme, /* SIOCSIWMLME */
+ (iw_handler) NULL, /* SIOCGIWAPLIST */
+ (iw_handler) NULL, /* SIOCSIWSCAN */
+ (iw_handler) NULL, /* SIOCGIWSCAN */
+ (iw_handler) NULL, /* SIOCSIWESSID */
+ (iw_handler) NULL, /* SIOCGIWESSID */
+ (iw_handler) NULL, /* SIOCSIWNICKN */
+ (iw_handler) NULL, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCSIWRATE */
+ (iw_handler) NULL, /* SIOCGIWRATE */
+ (iw_handler) NULL, /* SIOCSIWRTS */
+ (iw_handler) iw_get_ap_rts_threshold, /* SIOCGIWRTS */
+ (iw_handler) NULL, /* SIOCSIWFRAG */
+ (iw_handler) iw_get_ap_frag_threshold, /* SIOCGIWFRAG */
+ (iw_handler) NULL, /* SIOCSIWTXPOW */
+ (iw_handler) NULL, /* SIOCGIWTXPOW */
+ (iw_handler) NULL, /* SIOCSIWRETRY */
+ (iw_handler) NULL, /* SIOCGIWRETRY */
+ (iw_handler) NULL, /* SIOCSIWENCODE */
+ (iw_handler) NULL, /* SIOCGIWENCODE */
+ (iw_handler) NULL, /* SIOCSIWPOWER */
+ (iw_handler) NULL, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) iw_set_ap_genie, /* SIOCSIWGENIE */
+ (iw_handler) NULL, /* SIOCGIWGENIE */
+ (iw_handler) iw_set_auth_hostap, /* SIOCSIWAUTH */
+ (iw_handler) NULL, /* SIOCGIWAUTH */
+ (iw_handler) iw_set_ap_encodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCGIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCSIWPMKSA */
+};
+
+#define IW_PRIV_TYPE_OPTIE IW_PRIV_TYPE_BYTE | QCSAP_MAX_OPT_IE
+#define IW_PRIV_TYPE_MLME \
+ IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_mlme)
+
+static const struct iw_priv_args hostapd_private_args[] = {
+ { QCSAP_IOCTL_SETPARAM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setparam" },
+ { QCSAP_IOCTL_SETPARAM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" },
+ { QCSAP_PARAM_MAX_ASSOC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setMaxAssoc" },
+ { QCSAP_PARAM_HIDE_SSID,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hideSSID" },
+ { QCSAP_IOCTL_GETPARAM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam" },
+ { QCSAP_IOCTL_GETPARAM, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" },
+ { QCSAP_PARAM_MAX_ASSOC, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getMaxAssoc" },
+ { QCSAP_PARAM_MODULE_DOWN_IND, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "moduleDownInd" },
+ { QCSAP_PARAM_CLR_ACL, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "setClearAcl" },
+ { QCSAP_PARAM_ACL_MODE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setAclMode" },
+ { QCSAP_IOCTL_COMMIT,
+ IW_PRIV_TYPE_BYTE | sizeof(struct s_CommitConfig) | IW_PRIV_SIZE_FIXED, 0, "commit" },
+ { QCSAP_IOCTL_SETMLME,
+ IW_PRIV_TYPE_BYTE | sizeof(struct sQcSapreq_mlme)| IW_PRIV_SIZE_FIXED, 0, "setmlme" },
+ { QCSAP_IOCTL_GET_STAWPAIE,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "get_staWPAIE" },
+ { QCSAP_IOCTL_SETWPAIE,
+ IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE | IW_PRIV_SIZE_FIXED, 0, "setwpaie" },
+ { QCSAP_IOCTL_STOPBSS,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED, 0, "stopbss" },
+ { QCSAP_IOCTL_VERSION, 0,
+ IW_PRIV_TYPE_CHAR | QCSAP_MAX_WSC_IE, "version" },
+ { QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES,
+ IW_PRIV_TYPE_BYTE | sizeof(sQcSapreq_WPSPBCProbeReqIES_t) | IW_PRIV_SIZE_FIXED | 1, 0, "getProbeReqIEs" },
+ { QCSAP_IOCTL_GET_CHANNEL, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | sizeof(signed long int), "getchannel" },
+ { QCSAP_IOCTL_ASSOC_STA_MACADDR, 0,
+ IW_PRIV_TYPE_BYTE | /*((WLAN_MAX_STA_COUNT*6)+100)*/1 , "get_assoc_stamac" },
+ { QCSAP_IOCTL_DISASSOC_STA,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 6 , 0, "disassoc_sta" },
+ { QCSAP_IOCTL_AP_STATS,
+ IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE, 0, "ap_stats" },
+ { QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED,
+ IW_PRIV_TYPE_CHAR | 18,
+ IW_PRIV_TYPE_CHAR | 3, "getLinkSpeed" },
+
+ { QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "" },
+ /* handlers for sub-ioctl */
+ { WE_SET_WLAN_DBG,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ 0,
+ "setwlandbg" },
+
+ /* handlers for main ioctl */
+ { QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE,
+ IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
+ 0,
+ "" },
+
+ /* handlers for sub-ioctl */
+ { WE_LOG_DUMP_CMD,
+ IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
+ 0,
+ "dump" },
+#ifdef WLAN_FEATURE_P2P
+ { WE_P2P_NOA_CMD,
+ IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
+ 0,
+ "SetP2pPs" },
+#endif
+ /* handlers for main ioctl */
+ { QCSAP_IOCTL_MODIFY_ACL,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 8,
+ 0,
+ "modify_acl" },
+
+ /* handlers for main ioctl */
+ { QCSAP_IOCTL_GET_CHANNEL_LIST,
+ 0,
+ IW_PRIV_TYPE_BYTE | sizeof(tChannelListInfo),
+ "getChannelList" },
+
+};
+static const iw_handler hostapd_private[] = {
+ [QCSAP_IOCTL_SETPARAM - SIOCIWFIRSTPRIV] = iw_softap_setparam, //set priv ioctl
+ [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, //get priv ioctl
+ [QCSAP_IOCTL_COMMIT - SIOCIWFIRSTPRIV] = iw_softap_commit, //get priv ioctl
+ [QCSAP_IOCTL_SETMLME - SIOCIWFIRSTPRIV] = iw_softap_setmlme,
+ [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, //get station genIE
+ [QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie,
+ [QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, // stop bss
+ [QCSAP_IOCTL_VERSION - SIOCIWFIRSTPRIV] = iw_softap_version, // get driver version
+ [QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES - SIOCIWFIRSTPRIV] = iw_get_WPSPBCProbeReqIEs,
+ [QCSAP_IOCTL_GET_CHANNEL - SIOCIWFIRSTPRIV] = iw_softap_getchannel,
+ [QCSAP_IOCTL_ASSOC_STA_MACADDR - SIOCIWFIRSTPRIV] = iw_softap_getassoc_stamacaddr,
+ [QCSAP_IOCTL_DISASSOC_STA - SIOCIWFIRSTPRIV] = iw_softap_disassoc_sta,
+ [QCSAP_IOCTL_AP_STATS - SIOCIWFIRSTPRIV] = iw_softap_ap_stats,
+ [QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_three_ints_getnone,
+ [QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_var_ints_getnone,
+ [QCSAP_IOCTL_SET_CHANNEL_RANGE - SIOCIWFIRSTPRIV] = iw_softap_set_channel_range,
+ [QCSAP_IOCTL_MODIFY_ACL - SIOCIWFIRSTPRIV] = iw_softap_modify_acl,
+ [QCSAP_IOCTL_GET_CHANNEL_LIST - SIOCIWFIRSTPRIV] = iw_softap_get_channel_list,
+ [QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_softap_linkspeed
+};
+const struct iw_handler_def hostapd_handler_def = {
+ .num_standard = sizeof(hostapd_handler) / sizeof(hostapd_handler[0]),
+ .num_private = sizeof(hostapd_private) / sizeof(hostapd_private[0]),
+ .num_private_args = sizeof(hostapd_private_args) / sizeof(hostapd_private_args[0]),
+ .standard = (iw_handler *)hostapd_handler,
+ .private = (iw_handler *)hostapd_private,
+ .private_args = hostapd_private_args,
+ .get_wireless_stats = NULL,
+};
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
+struct net_device_ops net_ops_struct = {
+ .ndo_open = hdd_hostapd_open,
+ .ndo_stop = hdd_hostapd_stop,
+ .ndo_uninit = hdd_hostapd_uninit,
+ .ndo_start_xmit = hdd_softap_hard_start_xmit,
+ .ndo_tx_timeout = hdd_softap_tx_timeout,
+ .ndo_get_stats = hdd_softap_stats,
+ .ndo_set_mac_address = hdd_hostapd_set_mac_address,
+ .ndo_do_ioctl = hdd_hostapd_ioctl,
+ .ndo_change_mtu = hdd_hostapd_change_mtu,
+ .ndo_select_queue = hdd_hostapd_select_queue,
+ };
+#endif
+
+int hdd_set_hostapd(hdd_adapter_t *pAdapter)
+{
+ return VOS_STATUS_SUCCESS;
+}
+
+void hdd_set_ap_ops( struct net_device *pWlanHostapdDev )
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
+ pWlanHostapdDev->netdev_ops = &net_ops_struct;
+#else
+ pWlanHostapdDev->open = hdd_hostapd_open;
+ pWlanHostapdDev->stop = hdd_hostapd_stop;
+ pWlanHostapdDev->uninit = hdd_hostapd_uninit;
+ pWlanHostapdDev->hard_start_xmit = hdd_softap_hard_start_xmit;
+ pWlanHostapdDev->tx_timeout = hdd_softap_tx_timeout;
+ pWlanHostapdDev->get_stats = hdd_softap_stats;
+ pWlanHostapdDev->set_mac_address = hdd_hostapd_set_mac_address;
+ pWlanHostapdDev->do_ioctl = hdd_hostapd_ioctl;
+#endif
+}
+
+VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter )
+{
+ hdd_hostapd_state_t * phostapdBuf;
+ struct net_device *dev = pAdapter->dev;
+ VOS_STATUS status;
+ ENTER();
+ // Allocate the Wireless Extensions state structure
+ phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR( pAdapter );
+
+ // Zero the memory. This zeros the profile structure.
+ memset(phostapdBuf, 0,sizeof(hdd_hostapd_state_t));
+
+ // Set up the pointer to the Wireless Extensions state structure
+ // NOP
+ status = hdd_set_hostapd(pAdapter);
+ if(!VOS_IS_STATUS_SUCCESS(status)) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: hdd_set_hostapd failed!!\n"));
+ return status;
+ }
+
+ status = vos_event_init(&phostapdBuf->vosEvent);
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: Hostapd HDD vos event init failed!!\n"));
+ return status;
+ }
+
+ init_completion(&pAdapter->session_close_comp_var);
+ init_completion(&pAdapter->session_open_comp_var);
+
+ sema_init(&(WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->semWpsPBCOverlapInd, 1);
+
+ // Register as a wireless device
+ dev->wireless_handlers = (struct iw_handler_def *)& hostapd_handler_def;
+
+ //Initialize the data path module
+ status = hdd_softap_init_tx_rx(pAdapter);
+ if ( !VOS_IS_STATUS_SUCCESS( status ))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_softap_init_tx_rx failed", __FUNCTION__);
+ }
+
+#ifdef CONFIG_CFG80211
+ wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), pAdapter );
+#endif
+#ifdef WLAN_FEATURE_P2P
+ /* If administrative interface is enabled then one interface being
+ * created for p2p device address. This will take one HW STA and
+ * the max number of clients that can connect to softAP will be
+ * reduced by one. So as soon as SoftAP interface got created remove
+ * the session for p2p device address.
+ */
+ if ( VOS_IS_STATUS_SUCCESS( status ) &&
+ ( pAdapter->device_mode == WLAN_HDD_SOFTAP ) &&
+ ( !strncmp( pAdapter->dev->name, "wlan", 4 )) )
+ {
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
+ {
+ INIT_COMPLETION(pAdapter->session_close_comp_var);
+ if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
+ pAdapter->p2pSessionId,
+ hdd_smeCloseSessionCallback, pAdapter ) )
+ {
+ //Block on a completion variable. Can't wait forever though.
+ wait_for_completion_interruptible_timeout(
+ &pAdapter->session_close_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
+ }
+ }
+ }
+#endif
+ EXIT();
+ return status;
+}
+
+hdd_adapter_t* hdd_wlan_create_ap_dev( hdd_context_t *pHddCtx, tSirMacAddr macAddr, tANI_U8 *iface_name )
+{
+ struct net_device *pWlanHostapdDev = NULL;
+ hdd_adapter_t *pHostapdAdapter = NULL;
+ v_CONTEXT_t pVosContext= NULL;
+
+#ifdef CONFIG_CFG80211
+ pWlanHostapdDev = alloc_netdev_mq(sizeof(hdd_adapter_t), iface_name, ether_setup, NUM_TX_QUEUES);
+#else
+ pWlanHostapdDev = alloc_etherdev_mq(sizeof(hdd_adapter_t), NUM_TX_QUEUES);
+#endif
+
+ if (pWlanHostapdDev != NULL)
+ {
+ pHostapdAdapter = netdev_priv(pWlanHostapdDev);
+
+ //Init the net_device structure
+ ether_setup(pWlanHostapdDev);
+
+ //Initialize the adapter context to zeros.
+ vos_mem_zero(pHostapdAdapter, sizeof( hdd_adapter_t ));
+ pHostapdAdapter->dev = pWlanHostapdDev;
+ pHostapdAdapter->pHddCtx = pHddCtx;
+ pHostapdAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
+
+ //Get the Global VOSS context.
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ //Save the adapter context in global context for future.
+ ((VosContextType*)(pVosContext))->pHDDSoftAPContext = (v_VOID_t*)pHostapdAdapter;
+
+ //Init the net_device structure
+ strlcpy(pWlanHostapdDev->name, (const char *)iface_name, IFNAMSIZ);
+
+ hdd_set_ap_ops( pHostapdAdapter->dev );
+
+ pWlanHostapdDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
+ pWlanHostapdDev->watchdog_timeo = HDD_TX_TIMEOUT;
+ pWlanHostapdDev->mtu = HDD_DEFAULT_MTU;
+
+ vos_mem_copy(pWlanHostapdDev->dev_addr, (void *)macAddr,sizeof(tSirMacAddr));
+ vos_mem_copy(pHostapdAdapter->macAddressCurrent.bytes, (void *)macAddr, sizeof(tSirMacAddr));
+
+ pWlanHostapdDev->destructor = free_netdev;
+#ifdef CONFIG_CFG80211
+ pWlanHostapdDev->ieee80211_ptr = &pHostapdAdapter->wdev ;
+ pHostapdAdapter->wdev.wiphy = pHddCtx->wiphy;
+ pHostapdAdapter->wdev.netdev = pWlanHostapdDev;
+ init_completion(&pHostapdAdapter->tx_action_cnf_event);
+#endif
+ init_completion(&pHostapdAdapter->cancel_rem_on_chan_var);
+ init_completion(&pHostapdAdapter->rem_on_chan_ready_event);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ init_completion(&pHostapdAdapter->offchannel_tx_event);
+#endif
+
+ init_completion(&pHostapdAdapter->scan_info.scan_req_completion_event);
+
+ SET_NETDEV_DEV(pWlanHostapdDev, pHddCtx->parent_dev);
+ }
+ return pHostapdAdapter;
+}
+
+VOS_STATUS hdd_register_hostapd( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
+{
+ struct net_device *dev = pAdapter->dev;
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+
+ ENTER();
+
+ if( rtnl_lock_held )
+ {
+ if (strchr(dev->name, '%')) {
+ if( dev_alloc_name(dev, dev->name) < 0 )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s:Failed:dev_alloc_name", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ if (register_netdevice(dev))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s:Failed:register_netdevice", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ else
+ {
+ if (register_netdev(dev))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed:register_netdev", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
+
+ EXIT();
+ return status;
+}
+
+VOS_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter)
+{
+ ENTER();
+
+ hdd_softap_deinit_tx_rx(pAdapter);
+
+ /* if we are being called during driver unload, then the dev has already
+ been invalidated. if we are being called at other times, then we can
+ detatch the wireless device handlers */
+ if (pAdapter->dev)
+ {
+ pAdapter->dev->wireless_handlers = NULL;
+ }
+ EXIT();
+ return 0;
+}
diff --git a/CORE/HDD/src/wlan_hdd_innav.c b/CORE/HDD/src/wlan_hdd_innav.c
new file mode 100644
index 0000000..1e9b029
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_innav.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/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
new file mode 100644
index 0000000..53397a0
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -0,0 +1,4469 @@
+/*
+ * 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 wlan_hdd_main.c
+
+ \brief WLAN Host Device Driver implementation
+
+ 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.
+
+
+ $Header:$ $DateTime: $ $Author: $
+
+
+ when who what, where, why
+ -------- --- --------------------------------------------------------
+ 04/5/09 Shailender Created module.
+ 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
+ 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
+ ==========================================================================*/
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+//#include <wlan_qct_driver.h>
+#include <wlan_hdd_includes.h>
+#ifdef ANI_BUS_TYPE_SDIO
+#include <wlan_sal_misc.h>
+#endif // ANI_BUS_TYPE_SDIO
+#include <vos_api.h>
+#include <vos_sched.h>
+#include <vos_power.h>
+#include <linux/etherdevice.h>
+#include <linux/firmware.h>
+#ifdef ANI_BUS_TYPE_SDIO
+#include <linux/mmc/sdio_func.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32))
+// added in 2.6.32, need to define locally if using an earlier kernel
+#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
+#endif
+#endif // ANI_BUS_TYPE_SDIO
+#ifdef ANI_BUS_TYPE_PLATFORM
+#include <linux/wcnss_wlan.h>
+#endif //ANI_BUS_TYPE_PLATFORM
+#ifdef ANI_BUS_TYPE_PCI
+#include "wcnss_wlan.h"
+#endif /* ANI_BUS_TYPE_PCI */
+#include <wlan_hdd_tx_rx.h>
+#include <palTimer.h>
+#include <wniApi.h>
+#include <wlan_nlink_srv.h>
+#include <wlan_btc_svc.h>
+#include <wlan_hdd_cfg.h>
+#include <wlan_ptt_sock_svc.h>
+#include <wlan_hdd_wowl.h>
+#include <wlan_hdd_misc.h>
+#include <wlan_hdd_wext.h>
+#ifdef WLAN_BTAMP_FEATURE
+#include <bap_hdd_main.h>
+#include <bapInternal.h>
+#endif // WLAN_BTAMP_FEATURE
+
+#ifdef CONFIG_CFG80211
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+#include "wlan_hdd_cfg80211.h"
+#include "wlan_hdd_p2p.h"
+#endif
+#include <linux/rtnetlink.h>
+#ifdef ANI_MANF_DIAG
+int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
+#endif
+#ifdef WLAN_SOFTAP_FEATURE
+#include "sapApi.h"
+#include <linux/semaphore.h>
+#include <mach/subsystem_restart.h>
+#include <wlan_hdd_hostapd.h>
+#include <wlan_hdd_softap_tx_rx.h>
+#endif
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include "cfgApi.h"
+#endif
+#include "wlan_hdd_dev_pwr.h"
+#ifdef WLAN_BTAMP_FEATURE
+#include "bap_hdd_misc.h"
+#endif
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include "wlan_qct_pal_trace.h"
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+#include "qwlan_version.h"
+
+#ifdef MODULE
+#define WLAN_MODULE_NAME module_name(THIS_MODULE)
+#else
+#define WLAN_MODULE_NAME "wlan"
+#endif
+
+#ifdef TIMER_MANAGER
+#define TIMER_MANAGER_STR " +TIMER_MANAGER"
+#else
+#define TIMER_MANAGER_STR ""
+#endif
+
+#ifdef MEMORY_DEBUG
+#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
+#else
+#define MEMORY_DEBUG_STR ""
+#endif
+
+/* the Android framework expects this param even though we don't use it */
+#define BUF_LEN 20
+static char fwpath[BUF_LEN];
+module_param_string(fwpath, fwpath, BUF_LEN,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+static struct wake_lock wlan_wake_lock;
+/* set when SSR is needed after unload */
+static v_U8_t isSsrRequired;
+
+//internal function declaration
+v_U16_t hdd_select_queue(struct net_device *dev,
+ struct sk_buff *skb);
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+static void hdd_set_multicast_list(struct net_device *dev);
+#endif
+
+void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
+
+extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
+
+static int hdd_netdev_notifier_call(struct notifier_block * nb,
+ unsigned long state,
+ void *ndev)
+{
+ struct net_device *dev = ndev;
+ hdd_adapter_t *pAdapter = NULL;
+#ifdef WLAN_BTAMP_FEATURE
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx;
+#endif
+
+ //Make sure that this callback corresponds to our device.
+ if((strncmp( dev->name, "wlan", 4 )) &&
+ (strncmp( dev->name, "p2p-wlan", 8))
+ )
+ return NOTIFY_DONE;
+
+#ifdef CONFIG_CFG80211
+ if (!dev->ieee80211_ptr)
+ return NOTIFY_DONE;
+#endif
+
+ pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ if(NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adaptor Null Pointer", __func__);
+ VOS_ASSERT(0);
+ return NOTIFY_DONE;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO,"%s: New Net Device State = %lu", __func__, state);
+
+ switch (state) {
+ case NETDEV_REGISTER:
+ break;
+
+ case NETDEV_UNREGISTER:
+ break;
+
+ case NETDEV_UP:
+ break;
+
+ case NETDEV_DOWN:
+ break;
+
+ case NETDEV_CHANGE:
+ if(VOS_STA_MODE == hdd_get_conparam())
+ {
+ if(TRUE == pAdapter->isLinkUpSvcNeeded)
+ complete(&pAdapter->linkup_event_var);
+ }
+ break;
+
+ case NETDEV_GOING_DOWN:
+ if( pAdapter->scan_info.mScanPending != FALSE )
+ {
+ int result;
+ INIT_COMPLETION(pAdapter->abortscan_event_var);
+ hdd_abort_mac_scan(pAdapter->pHddCtx);
+ result = wait_for_completion_interruptible_timeout(
+ &pAdapter->abortscan_event_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
+ if(!result)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Timeout occured while waiting for abortscan" ,
+ __FUNCTION__);
+ }
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Scan is not Pending from user" , __FUNCTION__);
+ }
+#ifdef WLAN_BTAMP_FEATURE
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __FUNCTION__);
+ pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ status = WLANBAP_StopAmp();
+ if(VOS_STATUS_SUCCESS != status )
+ {
+ pHddCtx->isAmpAllowed = VOS_TRUE;
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to stop AMP", __func__);
+ }
+ else
+ {
+ //a state m/c implementation in PAL is TBD to avoid this delay
+ msleep(500);
+ pHddCtx->isAmpAllowed = VOS_FALSE;
+ WLANBAP_DeregisterFromHCI();
+ }
+#endif //WLAN_BTAMP_FEATURE
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+struct notifier_block hdd_netdev_notifier = {
+ .notifier_call = hdd_netdev_notifier_call,
+};
+
+/*---------------------------------------------------------------------------
+ * Function definitions
+ *-------------------------------------------------------------------------*/
+extern int isWDresetInProgress(void);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+extern void register_wlan_suspend(void);
+extern void unregister_wlan_suspend(void);
+void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
+void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
+#endif
+#ifdef WLAN_SOFTAP_FEATURE
+//variable to hold the insmod parameters
+static int con_mode = 0;
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+/**---------------------------------------------------------------------------
+
+ \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
+
+ Called immediately after the cfg.ini is read in order to configure
+ the desired trace levels in the WDI.
+
+ \param - moduleId - module whose trace level is being configured
+ \param - bitmask - bitmask of log levels to be enabled
+
+ \return - void
+
+ --------------------------------------------------------------------------*/
+static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
+{
+ wpt_tracelevel level;
+
+ /* if the bitmask is the default value, then a bitmask was not
+ specified in cfg.ini, so leave the logging level alone (it
+ will remain at the "compiled in" default value) */
+ if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
+ {
+ return;
+ }
+
+ /* a mask was specified. start by disabling all logging */
+ wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
+
+ /* now cycle through the bitmask until all "set" bits are serviced */
+ level = eWLAN_PAL_TRACE_LEVEL_FATAL;
+ while (0 != bitmask)
+ {
+ if (bitmask & 1)
+ {
+ wpalTraceSetLevel(moduleId, level, 1);
+ }
+ level++;
+ bitmask >>= 1;
+ }
+}
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_priv_data_t priv_data;
+ tANI_U8 *command = NULL;
+ int ret = 0;
+
+ if (NULL == pAdapter)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD adapter context is Null", __FUNCTION__);
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ if ((!ifr) && (!ifr->ifr_data))
+ {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
+ {
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ command = kmalloc(priv_data.total_len, GFP_KERNEL);
+ if (!command)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: failed to allocate memory\n", __FUNCTION__);
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ if (copy_from_user(command, priv_data.buf, priv_data.total_len))
+ {
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ if ((SIOCDEVPRIVATE + 1) == cmd)
+ {
+ hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "***Received %s cmd from Wi-Fi GUI***", command);
+
+ if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
+ {
+ if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
+ sizeof(tSirMacAddr)))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: failed to copy data to user buffer\n", __FUNCTION__);
+ ret = -EFAULT;
+ }
+ }
+ if(strncmp(priv_data.buf, "SETBAND", 7) == 0)
+ {
+ tANI_U8 *ptr = (tANI_U8*)priv_data.buf ;
+ int ret = 0 ;
+
+ /* Change band request received */
+
+ /* First 8 bytes will have "SETBAND " and
+ * 9 byte will have band setting value */
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: SetBandCommand Info comm %s UL %d, TL %d", __FUNCTION__, priv_data.buf, priv_data.used_len, priv_data.total_len);
+
+ /* Change band request received */
+ ret = hdd_setBand_helper(dev, ptr);
+ }
+ }
+exit:
+ if (command)
+ {
+ kfree(command);
+ }
+ return ret;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_open() - HDD Open function
+
+ This is called in response to ifconfig up
+
+ \param - dev Pointer to net_device structure
+
+ \return - 0 for success non-zero for failure
+
+ --------------------------------------------------------------------------*/
+int hdd_open (struct net_device *dev)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx;
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ VOS_STATUS status;
+ v_BOOL_t in_standby = TRUE;
+
+ if (NULL == pAdapter)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD adapter context is Null", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
+ if (NULL == pHddCtx)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD context is Null", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+ while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
+ {
+ if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
+ "standby", __func__, pAdapter->device_mode);
+ in_standby = FALSE;
+ break;
+ }
+ else
+ {
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+ }
+
+ if (TRUE == in_standby)
+ {
+ if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
+ "wlan out of power save", __func__);
+ return -EINVAL;
+ }
+ }
+
+ pAdapter->event_flags |= DEVICE_IFACE_OPENED;
+ if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Enabling Tx Queues", __FUNCTION__);
+ /* Enable TX queues only when we are connected */
+ netif_tx_start_all_queues(dev);
+ }
+
+ return 0;
+}
+
+int hdd_mon_open (struct net_device *dev)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ if(pAdapter == NULL) {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD adapter context is Null", __FUNCTION__);
+ return -1;
+ }
+
+ netif_start_queue(dev);
+
+ return 0;
+}
+/**---------------------------------------------------------------------------
+
+ \brief hdd_stop() - HDD stop function
+
+ This is called in response to ifconfig down
+
+ \param - dev Pointer to net_device structure
+
+ \return - 0 for success non-zero for failure
+
+ --------------------------------------------------------------------------*/
+
+int hdd_stop (struct net_device *dev)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx;
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ VOS_STATUS status;
+ v_BOOL_t enter_standby = TRUE;
+
+ ENTER();
+
+ if (NULL == pAdapter)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD adapter context is Null", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
+ if (NULL == pHddCtx)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD context is Null", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
+ netif_tx_disable(pAdapter->dev);
+ netif_carrier_off(pAdapter->dev);
+
+
+ /* SoftAP ifaces should never go in power save mode
+ making sure same here. */
+ if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
+ || (WLAN_HDD_MONITOR == pAdapter->device_mode )
+#ifdef WLAN_FEATURE_P2P
+ || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
+#endif
+ )
+ {
+ /* SoftAP mode, so return from here */
+ EXIT();
+ return 0;
+ }
+
+ /* Find if any iface is up then
+ if any iface is up then can't put device to sleep/ power save mode. */
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+ while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
+ {
+ if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
+ "put device to sleep", __func__, pAdapter->device_mode);
+ enter_standby = FALSE;
+ break;
+ }
+ else
+ {
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+ }
+
+ if (TRUE == enter_standby)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
+ "entering standby", __func__);
+ if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
+ {
+ /*log and return success*/
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
+ "wlan in power save", __func__);
+ }
+ }
+
+ EXIT();
+ return 0;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_uninit() - HDD uninit function
+
+ This is called during the netdev unregister to uninitialize all data
+associated with the device
+
+ \param - dev Pointer to net_device structure
+
+ \return - void
+
+ --------------------------------------------------------------------------*/
+static void hdd_uninit (struct net_device *dev)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ ENTER();
+
+ do
+ {
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: NULL pAdapter", __func__);
+ break;
+ }
+
+ if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Invalid magic", __func__);
+ break;
+ }
+
+ if (NULL == pAdapter->pHddCtx)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: NULL pHddCtx", __func__);
+ break;
+ }
+
+ if (dev != pAdapter->dev)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Invalid device reference", __func__);
+ /* we haven't validated all cases so let this go for now */
+ }
+
+ hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
+
+ /* after uninit our adapter structure will no longer be valid */
+ pAdapter->dev = NULL;
+ pAdapter->magic = 0;
+ } while (0);
+
+ EXIT();
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_release_firmware() -
+
+ This function calls the release firmware API to free the firmware buffer.
+
+ \param - pFileName Pointer to the File Name.
+ pCtx - Pointer to the adapter .
+
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
+ ENTER();
+
+
+ if (!strcmp(WLAN_FW_FILE, pFileName)) {
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
+
+ if(pHddCtx->fw) {
+ release_firmware(pHddCtx->fw);
+ pHddCtx->fw = NULL;
+ }
+ else
+ status = VOS_STATUS_E_FAILURE;
+ }
+ else if (!strcmp(WLAN_NV_FILE,pFileName)) {
+ if(pHddCtx->nv) {
+ release_firmware(pHddCtx->nv);
+ pHddCtx->nv = NULL;
+ }
+ else
+ status = VOS_STATUS_E_FAILURE;
+
+ }
+
+ EXIT();
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_request_firmware() -
+
+ This function reads the firmware file using the request firmware
+ API and returns the the firmware data and the firmware file size.
+
+ \param - pfileName - Pointer to the file name.
+ - pCtx - Pointer to the adapter .
+ - ppfw_data - Pointer to the pointer of the firmware data.
+ - pSize - Pointer to the file size.
+
+ \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
+
+ --------------------------------------------------------------------------*/
+
+
+VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
+{
+ int status;
+ VOS_STATUS retval = VOS_STATUS_SUCCESS;
+ hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
+ ENTER();
+
+ if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
+
+ status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
+
+ if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
+ __func__, pfileName);
+ retval = VOS_STATUS_E_FAILURE;
+ }
+
+ else {
+ *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
+ *pSize = pHddCtx->fw->size;
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
+ __func__, *pSize);
+ }
+ }
+ else if(!strcmp(WLAN_NV_FILE, pfileName)) {
+
+ status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
+
+ if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
+ __func__, pfileName);
+ retval = VOS_STATUS_E_FAILURE;
+ }
+
+ else {
+ *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
+ *pSize = pHddCtx->nv->size;
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
+ __func__, *pSize);
+ }
+ }
+
+ EXIT();
+ return retval;
+}
+/**---------------------------------------------------------------------------
+ \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
+
+ This is the function invoked by SME to inform the result of a full power
+ request issued by HDD
+
+ \param - callbackcontext - Pointer to cookie
+ status - result of request
+
+ \return - None
+
+--------------------------------------------------------------------------*/
+void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
+{
+ hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"HDD full Power callback status = %d", status);
+ if(&pHddCtx->full_pwr_comp_var)
+ {
+ complete(&pHddCtx->full_pwr_comp_var);
+ }
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
+
+ This is the function invoked by SME to inform the result of BMPS
+ request issued by HDD
+
+ \param - callbackcontext - Pointer to cookie
+ status - result of request
+
+ \return - None
+
+--------------------------------------------------------------------------*/
+void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
+{
+
+ struct completion *completion_var = (struct completion*) callbackContext;
+
+ hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
+ if(completion_var != NULL)
+ {
+ complete(completion_var);
+ }
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_get_cfg_file_size() -
+
+ This function reads the configuration file using the request firmware
+ API and returns the configuration file size.
+
+ \param - pCtx - Pointer to the adapter .
+ - pFileName - Pointer to the file name.
+ - pBufSize - Pointer to the buffer size.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
+{
+ int status;
+ hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
+
+ ENTER();
+
+ status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
+
+ if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
+ status = VOS_STATUS_E_FAILURE;
+ }
+ else {
+ *pBufSize = pHddCtx->fw->size;
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
+ release_firmware(pHddCtx->fw);
+ pHddCtx->fw = NULL;
+ }
+
+ EXIT();
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_read_cfg_file() -
+
+ This function reads the configuration file using the request firmware
+ API and returns the cfg data and the buffer size of the configuration file.
+
+ \param - pCtx - Pointer to the adapter .
+ - pFileName - Pointer to the file name.
+ - pBuffer - Pointer to the data buffer.
+ - pBufSize - Pointer to the buffer size.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
+ v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
+{
+ int status;
+ hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
+
+ ENTER();
+
+ status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
+
+ if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ else {
+ if(*pBufSize != pHddCtx->fw->size) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
+ "file size", __func__);
+ release_firmware(pHddCtx->fw);
+ pHddCtx->fw = NULL;
+ return VOS_STATUS_E_FAILURE;
+ }
+ else {
+ if(pBuffer) {
+ vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
+ }
+ release_firmware(pHddCtx->fw);
+ pHddCtx->fw = NULL;
+ }
+ }
+
+ EXIT();
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_set_mac_addr_cb() -
+
+ This function is the call back function for setting the station
+ mac adrress called by ccm module to indicate the
+ success/failure result.
+
+ \param - hHal - Pointer to the hal module.
+ - result - returns the result of the set mac address.
+
+ \return - void
+
+ --------------------------------------------------------------------------*/
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+static void hdd_set_mac_addr_cb( tHalHandle hHal, tANI_S32 result )
+{
+ // ignore the STA_ID response for now.
+
+ VOS_ASSERT( CCM_IS_RESULT_SUCCESS( result ) );
+}
+#endif
+
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_set_mac_address() -
+
+ This function sets the user specified mac address using
+ the command ifconfig wlanX hw ether <mac adress>.
+
+ \param - dev - Pointer to the net device.
+ - addr - Pointer to the sockaddr.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static int hdd_set_mac_address(struct net_device *dev, void *addr)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ struct sockaddr *psta_mac_addr = addr;
+ eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+
+ ENTER();
+
+ memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
+
+#ifdef HDD_SESSIONIZE
+ // set the MAC address though the STA ID CFG.
+ halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
+ (v_U8_t *)&pAdapter->macAddressCurrent,
+ sizeof( pAdapter->macAddressCurrent ),
+ hdd_set_mac_addr_cb, VOS_FALSE );
+#endif
+
+ memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
+
+ EXIT();
+ return halStatus;
+}
+
+tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
+{
+ int i;
+ for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
+ {
+ if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
+ break;
+ }
+
+ if( VOS_MAX_CONCURRENCY_PERSONA == i)
+ return NULL;
+
+ pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
+ return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
+}
+
+void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
+{
+ int i;
+ for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
+ {
+ if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
+ {
+ pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
+ break;
+ }
+ }
+ return;
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
+ static struct net_device_ops wlan_drv_ops = {
+ .ndo_open = hdd_open,
+ .ndo_stop = hdd_stop,
+ .ndo_uninit = hdd_uninit,
+ .ndo_start_xmit = hdd_hard_start_xmit,
+ .ndo_tx_timeout = hdd_tx_timeout,
+ .ndo_get_stats = hdd_stats,
+ .ndo_do_ioctl = hdd_ioctl,
+ .ndo_set_mac_address = hdd_set_mac_address,
+ .ndo_select_queue = hdd_select_queue,
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
+ .ndo_set_rx_mode = hdd_set_multicast_list,
+#else
+ .ndo_set_multicast_list = hdd_set_multicast_list,
+#endif //LINUX_VERSION_CODE
+#endif
+ };
+#ifdef CONFIG_CFG80211
+ static struct net_device_ops wlan_mon_drv_ops = {
+ .ndo_open = hdd_mon_open,
+ .ndo_stop = hdd_stop,
+ .ndo_uninit = hdd_uninit,
+ .ndo_start_xmit = hdd_mon_hard_start_xmit,
+ .ndo_tx_timeout = hdd_tx_timeout,
+ .ndo_get_stats = hdd_stats,
+ .ndo_do_ioctl = hdd_ioctl,
+ .ndo_set_mac_address = hdd_set_mac_address,
+ };
+#endif
+
+#endif
+
+void hdd_set_station_ops( struct net_device *pWlanDev )
+{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
+ pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
+ pWlanDev->netdev_ops = &wlan_drv_ops;
+#else
+ pWlanDev->open = hdd_open;
+ pWlanDev->stop = hdd_stop;
+ pWlanDev->uninit = hdd_uninit;
+ pWlanDev->hard_start_xmit = NULL;
+ pWlanDev->tx_timeout = hdd_tx_timeout;
+ pWlanDev->get_stats = hdd_stats;
+ pWlanDev->do_ioctl = hdd_ioctl;
+ pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
+ pWlanDev->set_mac_address = hdd_set_mac_address;
+#endif
+}
+
+hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, char* name )
+{
+ struct net_device *pWlanDev = NULL;
+ hdd_adapter_t *pAdapter = NULL;
+#ifdef CONFIG_CFG80211
+ /*
+ * cfg80211 initialization and registration....
+ */
+ pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
+
+#else
+ //Allocate the net_device and private data (station ctx)
+ pWlanDev = alloc_etherdev_mq(sizeof( hdd_adapter_t ), NUM_TX_QUEUES);
+
+#endif
+
+ if(pWlanDev != NULL)
+ {
+
+ //Save the pointer to the net_device in the HDD adapter
+ pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
+
+#ifndef CONFIG_CFG80211
+ //Init the net_device structure
+ ether_setup(pWlanDev);
+#endif
+
+ vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
+
+ pAdapter->dev = pWlanDev;
+ pAdapter->pHddCtx = pHddCtx;
+ pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
+
+ init_completion(&pAdapter->session_open_comp_var);
+ init_completion(&pAdapter->session_close_comp_var);
+ init_completion(&pAdapter->disconnect_comp_var);
+ init_completion(&pAdapter->linkup_event_var);
+ init_completion(&pAdapter->cancel_rem_on_chan_var);
+ init_completion(&pAdapter->rem_on_chan_ready_event);
+ init_completion(&pAdapter->abortscan_event_var);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ init_completion(&pAdapter->offchannel_tx_event);
+#endif
+#ifdef CONFIG_CFG80211
+ init_completion(&pAdapter->tx_action_cnf_event);
+#endif
+ init_completion(&pHddCtx->mc_sus_event_var);
+ init_completion(&pHddCtx->tx_sus_event_var);
+
+ init_completion(&pAdapter->scan_info.scan_req_completion_event);
+
+ pAdapter->isLinkUpSvcNeeded = FALSE;
+ pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
+ //Init the net_device structure
+ strlcpy(pWlanDev->name, name, IFNAMSIZ);
+
+ vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
+ vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
+ pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
+ pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
+
+ hdd_set_station_ops( pAdapter->dev );
+
+ pWlanDev->destructor = free_netdev;
+#ifdef CONFIG_CFG80211
+ pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
+ pAdapter->wdev.wiphy = pHddCtx->wiphy;
+ pAdapter->wdev.netdev = pWlanDev;
+#endif
+ /* set pWlanDev's parent to underlying device */
+ SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
+ }
+
+ return pAdapter;
+}
+
+VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
+{
+ struct net_device *pWlanDev = pAdapter->dev;
+ //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
+ //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+
+ if( rtnl_lock_held )
+ {
+ if (strchr(pWlanDev->name, '%')) {
+ if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ if (register_netdevice(pWlanDev))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ else
+ {
+ if(register_netdev(pWlanDev))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
+
+ return VOS_STATUS_SUCCESS;
+}
+
+eHalStatus hdd_smeCloseSessionCallback(void *pContext)
+{
+ if(pContext != NULL)
+ {
+ clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
+
+ /* need to make sure all of our scheduled work has completed.
+ * This callback is called from MC thread context, so it is safe to
+ * to call below flush workqueue API from here.
+ */
+ flush_scheduled_work();
+ complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
+ }
+ return eHAL_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
+{
+ struct net_device *pWlanDev = pAdapter->dev;
+ hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ int rc = 0;
+
+ INIT_COMPLETION(pAdapter->session_open_comp_var);
+ //Open a SME session for future operation
+ halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
+ (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
+ if ( !HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "sme_OpenSession() failed with status code %08d [x%08lx]",
+ halStatus, halStatus );
+ status = VOS_STATUS_E_FAILURE;
+ goto error_sme_open;
+ }
+
+ //Block on a completion variable. Can't wait forever though.
+ rc = wait_for_completion_interruptible_timeout(
+ &pAdapter->session_open_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
+ if (!rc)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "Session is not opened within timeout period code %08d", rc );
+ status = VOS_STATUS_E_FAILURE;
+ goto error_sme_open;
+ }
+
+ // Register wireless extensions
+ if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "hdd_register_wext() failed with status code %08d [x%08lx]",
+ halStatus, halStatus );
+ status = VOS_STATUS_E_FAILURE;
+ goto error_register_wext;
+ }
+ //Safe to register the hard_start_xmit function again
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
+ wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
+#else
+ pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
+#endif
+
+ //Set the Connection State to Not Connected
+ pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
+
+ //Set the default operation channel
+ pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
+
+ /* Make the default Auth Type as OPEN*/
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+
+ if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
+ status, status );
+ goto error_init_txrx;
+ }
+
+ set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
+
+ if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
+ status, status );
+ goto error_wmm_init;
+ }
+
+ set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
+
+ return VOS_STATUS_SUCCESS;
+
+error_wmm_init:
+ clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
+ hdd_deinit_tx_rx(pAdapter);
+error_init_txrx:
+ hdd_UnregisterWext(pWlanDev);
+error_register_wext:
+ if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
+ {
+ INIT_COMPLETION(pAdapter->session_close_comp_var);
+ if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
+ pAdapter->sessionId,
+ hdd_smeCloseSessionCallback, pAdapter ) )
+ {
+ //Block on a completion variable. Can't wait forever though.
+ wait_for_completion_interruptible_timeout(
+ &pAdapter->session_close_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
+ }
+}
+error_sme_open:
+ return status;
+}
+
+#ifdef WLAN_FEATURE_P2P
+/**
+ * hdd_init_p2p_device_mode
+ *
+ *FUNCTION:
+ * This function is called from hdd_wlan_startup function when wlan
+ * driver module is loaded.
+ *
+ *LOGIC:
+ * Open New SME session with P2P Device Mac Address which is different
+ * from STA Mac Address SME session. When driver receive any frame on STA Mac
+ * Address then we divert all the frame using P2P Device Mac Address instaed of
+ * STA Mac address.
+ *
+ *ASSUMPTIONS:
+ *
+ *
+ *NOTE:
+ *
+ * @param pAdapter Pointer to pAdapter structure
+ *
+ * @return None
+ */
+VOS_STATUS hdd_init_p2p_device_mode( hdd_adapter_t *pAdapter)
+{
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ int rc = 0;
+
+ INIT_COMPLETION(pAdapter->session_open_comp_var);
+ //Open a SME session for future operation
+ halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
+ (tANI_U8 *)&pHddCtx->p2pDeviceAddress, &pAdapter->p2pSessionId);
+ if ( !HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "sme_OpenSession() failed with status code %08d [x%08lx]",
+ halStatus, halStatus );
+ status = VOS_STATUS_E_FAILURE;
+ return status;
+ }
+
+ //Block on a completion variable. Can't wait forever though.
+ rc = wait_for_completion_interruptible_timeout(
+ &pAdapter->session_open_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
+ if (!rc)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "Session is not opened within timeout period code %08d", rc );
+ status = VOS_STATUS_E_FAILURE;
+ return status;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+#endif
+
+#ifdef CONFIG_CFG80211
+void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
+{
+ hdd_cfg80211_state_t *cfgState;
+
+ cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+
+ if( NULL != cfgState->buf )
+ {
+ int rc;
+ INIT_COMPLETION(pAdapter->tx_action_cnf_event);
+ rc = wait_for_completion_interruptible_timeout(
+ &pAdapter->tx_action_cnf_event,
+ msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
+ if(!rc)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
+ }
+ }
+ return;
+}
+#endif
+
+void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
+{
+ ENTER();
+ switch ( pAdapter->device_mode )
+ {
+ case WLAN_HDD_INFRA_STATION:
+ case WLAN_HDD_P2P_CLIENT:
+ {
+ if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
+ {
+ hdd_deinit_tx_rx( pAdapter );
+ clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
+ }
+
+ if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
+ {
+ hdd_wmm_adapter_close( pAdapter );
+ clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
+ }
+
+#ifdef CONFIG_CFG80211
+ hdd_cleanup_actionframe(pHddCtx, pAdapter);
+#endif
+
+ break;
+ }
+
+ case WLAN_HDD_SOFTAP:
+ case WLAN_HDD_P2P_GO:
+#ifdef WLAN_SOFTAP_FEATURE
+ {
+#ifdef CONFIG_CFG80211
+ hdd_cleanup_actionframe(pHddCtx, pAdapter);
+#endif
+
+ hdd_unregister_hostapd(pAdapter);
+ hdd_set_conparam( 0 );
+#ifdef CONFIG_CFG80211
+ wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
+#endif
+ break;
+ }
+
+ case WLAN_HDD_MONITOR:
+ {
+#ifdef CONFIG_CFG80211
+ hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
+#endif
+ if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
+ {
+ hdd_deinit_tx_rx( pAdapter );
+ clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
+ }
+#ifdef CONFIG_CFG80211
+ if(NULL != pAdapterforTx)
+ {
+ hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
+ }
+#endif
+#endif //WLAN_SOFTAP_FEATURE
+ break;
+ }
+
+
+ default:
+ break;
+ }
+
+ EXIT();
+}
+
+void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
+{
+ struct net_device *pWlanDev = pAdapter->dev;
+
+ if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
+ if( rtnl_held )
+ {
+ unregister_netdevice(pWlanDev);
+ }
+ else
+ {
+ unregister_netdev(pWlanDev);
+ }
+ // note that the pAdapter is no longer valid at this point
+ // since the memory has been reclaimed
+ }
+
+}
+
+VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+
+ if(pHddCtx->cfg_ini->fIsBmpsEnabled)
+ {
+ sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+ }
+
+ if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
+ {
+ sme_StartAutoBmpsTimer(pHddCtx->hHal);
+ }
+
+ if (pHddCtx->cfg_ini->fIsImpsEnabled)
+ {
+ sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ }
+
+ return status;
+}
+
+VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
+{
+ hdd_adapter_t *pAdapter = NULL;
+ eHalStatus halStatus;
+ VOS_STATUS status = VOS_STATUS_E_INVAL;
+ v_BOOL_t disableBmps = FALSE;
+ v_BOOL_t disableImps = FALSE;
+
+ switch(session_type)
+ {
+ case WLAN_HDD_INFRA_STATION:
+ case WLAN_HDD_SOFTAP:
+#ifdef WLAN_FEATURE_P2P
+ case WLAN_HDD_P2P_CLIENT:
+ case WLAN_HDD_P2P_GO:
+#endif
+ //Exit BMPS -> Is Sta/P2P Client is already connected
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
+ if((NULL != pAdapter)&&
+ hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
+ {
+ disableBmps = TRUE;
+ }
+
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
+ if((NULL != pAdapter)&&
+ hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
+ {
+ disableBmps = TRUE;
+ }
+
+ //Exit both Bmps and Imps incase of Go/SAP Mode
+ if((WLAN_HDD_SOFTAP == session_type) ||
+ (WLAN_HDD_P2P_GO == session_type))
+ {
+ disableBmps = TRUE;
+ disableImps = TRUE;
+ }
+
+ if(TRUE == disableImps)
+ {
+ if (pHddCtx->cfg_ini->fIsImpsEnabled)
+ {
+ sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ }
+ }
+
+ if(TRUE == disableBmps)
+ {
+ if(pHddCtx->cfg_ini->fIsBmpsEnabled)
+ {
+ halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+
+ if(eHAL_STATUS_SUCCESS != halStatus)
+ {
+ status = VOS_STATUS_E_FAILURE;
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
+ VOS_ASSERT(0);
+ return status;
+ }
+ }
+
+ if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
+ {
+ halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
+
+ if(eHAL_STATUS_SUCCESS != halStatus)
+ {
+ status = VOS_STATUS_E_FAILURE;
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
+ VOS_ASSERT(0);
+ return status;
+ }
+ }
+ }
+
+ if((TRUE == disableBmps) ||
+ (TRUE == disableImps))
+ {
+ /* Now, get the chip into Full Power now */
+ INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
+ halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
+ pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
+
+ if(halStatus != eHAL_STATUS_SUCCESS)
+ {
+ if(halStatus == eHAL_STATUS_PMC_PENDING)
+ {
+ //Block on a completion variable. Can't wait forever though
+ wait_for_completion_interruptible_timeout(
+ &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
+ }
+ else
+ {
+ status = VOS_STATUS_E_FAILURE;
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
+ VOS_ASSERT(0);
+ return status;
+ }
+ }
+
+ status = VOS_STATUS_SUCCESS;
+ }
+
+ break;
+ }
+ return status;
+}
+
+hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
+ char *iface_name, tSirMacAddr macAddr,
+ tANI_U8 rtnl_held )
+{
+ hdd_adapter_t *pAdapter = NULL;
+ hdd_adapter_list_node_t *pHddAdapterNode = NULL;
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ VOS_STATUS exitbmpsStatus;
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
+
+ //Disable BMPS incase of Concurrency
+ exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
+
+ if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
+ {
+ //Fail to Exit BMPS
+ VOS_ASSERT(0);
+ return NULL;
+ }
+
+ switch(session_type)
+ {
+ case WLAN_HDD_INFRA_STATION:
+#ifdef WLAN_FEATURE_P2P
+ case WLAN_HDD_P2P_CLIENT:
+#endif
+ {
+ pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
+
+ if( NULL == pAdapter )
+ return NULL;
+
+#ifdef CONFIG_CFG80211
+ pAdapter->wdev.iftype = (session_type == WLAN_HDD_INFRA_STATION) ?
+ NL80211_IFTYPE_STATION :
+ NL80211_IFTYPE_P2P_CLIENT;
+#endif
+
+
+ pAdapter->device_mode = session_type;
+
+ status = hdd_init_station_mode( pAdapter );
+ if( VOS_STATUS_SUCCESS != status )
+ goto err_free_netdev;
+
+ status = hdd_register_interface( pAdapter, rtnl_held );
+ if( VOS_STATUS_SUCCESS != status )
+ {
+ hdd_deinit_adapter(pHddCtx, pAdapter);
+ goto err_free_netdev;
+ }
+ //Stop the Interface TX queue.
+ netif_tx_disable(pAdapter->dev);
+ //netif_tx_disable(pWlanDev);
+ netif_carrier_off(pAdapter->dev);
+
+ break;
+ }
+
+#ifdef WLAN_FEATURE_P2P
+ case WLAN_HDD_P2P_GO:
+#endif
+ case WLAN_HDD_SOFTAP:
+ {
+ pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
+ if( NULL == pAdapter )
+ return NULL;
+
+#ifdef CONFIG_CFG80211
+ pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
+ NL80211_IFTYPE_AP:
+ NL80211_IFTYPE_P2P_GO;
+#endif
+ pAdapter->device_mode = session_type;
+
+ status = hdd_init_ap_mode(pAdapter);
+ if( VOS_STATUS_SUCCESS != status )
+ goto err_free_netdev;
+
+ status = hdd_register_hostapd( pAdapter, rtnl_held );
+ if( VOS_STATUS_SUCCESS != status )
+ {
+ hdd_deinit_adapter(pHddCtx, pAdapter);
+ goto err_free_netdev;
+ }
+
+ netif_tx_disable(pAdapter->dev);
+ netif_carrier_off(pAdapter->dev);
+
+ hdd_set_conparam( 1 );
+ break;
+ }
+ case WLAN_HDD_MONITOR:
+ {
+#ifdef CONFIG_CFG80211
+ pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
+ if( NULL == pAdapter )
+ return NULL;
+
+ pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
+ pAdapter->device_mode = session_type;
+ status = hdd_register_interface( pAdapter, rtnl_held );
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
+ pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
+#else
+ pAdapter->dev->open = hdd_mon_open;
+ pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
+#endif
+ hdd_init_tx_rx( pAdapter );
+ set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
+ //Set adapter to be used for data tx. It will use either GO or softap.
+ pAdapter->sessionCtx.monitor.pAdapterForTx =
+ hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
+#ifdef WLAN_FEATURE_P2P
+ if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
+ {
+ pAdapter->sessionCtx.monitor.pAdapterForTx =
+ hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
+ }
+#endif
+ /* This workqueue will be used to transmit management packet over
+ * monitor interface. */
+ INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
+ hdd_mon_tx_work_queue);
+#endif
+ }
+ break;
+#ifdef ANI_MANF_DIAG
+ case WLAN_HDD_FTM:
+ {
+ pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
+
+ if( NULL == pAdapter )
+ return NULL;
+ /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
+ * message while loading driver in FTM mode. */
+ pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
+ pAdapter->device_mode = session_type;
+ status = hdd_register_interface( pAdapter, rtnl_held );
+ }
+ break;
+#endif
+ default:
+ {
+ VOS_ASSERT(0);
+ return NULL;
+ }
+ }
+
+
+ if( VOS_STATUS_SUCCESS == status )
+ {
+ //Add it to the hdd's session list.
+ pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
+ if( NULL == pHddAdapterNode )
+ {
+ status = VOS_STATUS_E_NOMEM;
+ }
+ else
+ {
+ pHddAdapterNode->pAdapter = pAdapter;
+ status = hdd_add_adapter_back ( pHddCtx,
+ pHddAdapterNode );
+ }
+ }
+
+ if( VOS_STATUS_SUCCESS != status )
+ {
+ if( NULL != pAdapter )
+ {
+ hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
+ pAdapter = NULL;
+ }
+ if( NULL != pHddAdapterNode )
+ {
+ vos_mem_free( pHddAdapterNode );
+ }
+
+ goto resume_bmps;
+ }
+
+ if(VOS_STATUS_SUCCESS == status)
+ {
+ wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ /* If there are concurrent session enable SW frame translation
+ * for all registered STA
+ * This is not required in case of PRIMA as HW frame translation
+ * is disabled in PRIMA*/
+ if (vos_concurrent_sessions_running())
+ {
+ WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, TRUE);
+ }
+#endif
+ }
+
+ return pAdapter;
+
+err_free_netdev:
+ free_netdev(pAdapter->dev);
+ wlan_hdd_release_intf_addr( pHddCtx,
+ pAdapter->macAddressCurrent.bytes );
+
+resume_bmps:
+ //If bmps disabled enable it
+ if(VOS_STATUS_SUCCESS == exitbmpsStatus)
+ {
+ hdd_enable_bmps_imps(pHddCtx);
+ }
+ return NULL;
+}
+
+VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
+ tANI_U8 rtnl_held )
+{
+ hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
+ VOS_STATUS status;
+
+ status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
+ if( VOS_STATUS_SUCCESS != status )
+ return status;
+
+ while ( pCurrent->pAdapter != pAdapter )
+ {
+ status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
+ if( VOS_STATUS_SUCCESS != status )
+ break;
+
+ pCurrent = pNext;
+ }
+ pAdapterNode = pCurrent;
+ if( VOS_STATUS_SUCCESS == status )
+ {
+ wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
+ hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
+ hdd_remove_adapter( pHddCtx, pAdapterNode );
+ vos_mem_free( pAdapterNode );
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ /* If there is no concurrent session disable SW frame translation
+ * for all registered STA */
+ /* This is not required in case of PRIMA as HW frame translation
+ * is disabled in PRIMA*/
+ if (!vos_concurrent_sessions_running())
+ {
+ WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, FALSE);
+ }
+#endif
+
+ /* If there is a single session of STA/P2P client, re-enable BMPS */
+ if ((!vos_concurrent_sessions_running()) &&
+ ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
+ (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
+ {
+ hdd_enable_bmps_imps(pHddCtx);
+ }
+
+ return VOS_STATUS_SUCCESS;
+ }
+
+ return VOS_STATUS_E_FAILURE;
+}
+
+VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
+{
+ hdd_adapter_list_node_t *pHddAdapterNode;
+ VOS_STATUS status;
+
+ ENTER();
+
+ do
+ {
+ status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
+ if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
+ vos_mem_free( pHddAdapterNode );
+ }
+ }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
+
+ EXIT();
+
+ return VOS_STATUS_SUCCESS;
+}
+
+void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
+{
+ v_U8_t addIE[1] = {0};
+
+ if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
+ eANI_BOOLEAN_FALSE) )
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
+ }
+
+ if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
+ eANI_BOOLEAN_FALSE) )
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
+ }
+
+ if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
+ WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
+ eANI_BOOLEAN_FALSE) )
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
+ }
+}
+
+VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
+{
+ eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ union iwreq_data wrqu;
+
+ ENTER();
+
+ switch(pAdapter->device_mode)
+ {
+ case WLAN_HDD_INFRA_STATION:
+ case WLAN_HDD_P2P_CLIENT:
+ if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
+ {
+ if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
+ halStatus = sme_RoamDisconnect(pHddCtx->hHal,
+ pAdapter->sessionId,
+ eCSR_DISCONNECT_REASON_IBSS_LEAVE);
+ else
+ halStatus = sme_RoamDisconnect(pHddCtx->hHal,
+ pAdapter->sessionId,
+ eCSR_DISCONNECT_REASON_UNSPECIFIED);
+ //success implies disconnect command got queued up successfully
+ if(halStatus == eHAL_STATUS_SUCCESS)
+ {
+ wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+ }
+ memset(&wrqu, '\0', sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
+ wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
+ }
+ else
+ {
+ hdd_abort_mac_scan(pHddCtx);
+ }
+
+ if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
+ {
+ INIT_COMPLETION(pAdapter->session_close_comp_var);
+ if (eHAL_STATUS_SUCCESS ==
+ sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
+ hdd_smeCloseSessionCallback, pAdapter))
+ {
+ //Block on a completion variable. Can't wait forever though.
+ wait_for_completion_interruptible_timeout(
+ &pAdapter->session_close_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
+ }
+ }
+
+ break;
+
+ case WLAN_HDD_SOFTAP:
+ case WLAN_HDD_P2P_GO:
+ //Any softap specific cleanup here...
+ mutex_lock(&pHddCtx->sap_lock);
+ if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
+ {
+ VOS_STATUS status;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ //Stop Bss.
+ status = WLANSAP_StopBss(pHddCtx->pvosContext);
+ if (VOS_IS_STATUS_SUCCESS(status))
+ {
+ hdd_hostapd_state_t *pHostapdState =
+ WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
+
+ status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
+
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
+ __FUNCTION__);
+ }
+ }
+ else
+ {
+ hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __FUNCTION__);
+ }
+ clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
+
+ if (eHAL_STATUS_FAILURE ==
+ ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
+ 0, NULL, eANI_BOOLEAN_FALSE))
+ {
+ hddLog(LOGE,
+ "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
+ __FUNCTION__);
+ }
+
+ if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
+ WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
+ eANI_BOOLEAN_FALSE) )
+ {
+ hddLog(LOGE,
+ "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
+ }
+
+ // Reset WNI_CFG_PROBE_RSP Flags
+ wlan_hdd_reset_prob_rspies(pAdapter);
+ kfree(pAdapter->sessionCtx.ap.beacon);
+ pAdapter->sessionCtx.ap.beacon = NULL;
+ }
+ mutex_unlock(&pHddCtx->sap_lock);
+ break;
+ case WLAN_HDD_MONITOR:
+ break;
+ default:
+ break;
+ }
+
+ EXIT();
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
+{
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ VOS_STATUS status;
+ hdd_adapter_t *pAdapter;
+
+ ENTER();
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+ netif_tx_disable(pAdapter->dev);
+ netif_carrier_off(pAdapter->dev);
+
+ hdd_stop_adapter( pHddCtx, pAdapter );
+
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+
+ EXIT();
+
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
+{
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ VOS_STATUS status;
+ hdd_adapter_t *pAdapter;
+
+ ENTER();
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+ netif_tx_disable(pAdapter->dev);
+ netif_carrier_off(pAdapter->dev);
+
+ //Record whether STA is associated
+ pAdapter->sessionCtx.station.bSendDisconnect =
+ hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
+ VOS_TRUE : VOS_FALSE;
+
+ hdd_deinit_tx_rx(pAdapter);
+ hdd_wmm_adapter_close(pAdapter);
+
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+
+ EXIT();
+
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
+{
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ VOS_STATUS status;
+ hdd_adapter_t *pAdapter;
+ v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
+
+ ENTER();
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+
+ switch(pAdapter->device_mode)
+ {
+ case WLAN_HDD_INFRA_STATION:
+ case WLAN_HDD_P2P_CLIENT:
+ hdd_init_station_mode(pAdapter);
+ /* Open the gates for HDD to receive Wext commands */
+ pAdapter->isLinkUpSvcNeeded = FALSE;
+ pAdapter->scan_info.mScanPending = FALSE;
+ pAdapter->scan_info.waitScanResult = FALSE;
+
+ //Trigger the initial scan
+ hdd_wlan_initial_scan(pAdapter);
+
+ //Indicate disconnect event to supplicant if associated previously
+ if(pAdapter->sessionCtx.station.bSendDisconnect)
+ {
+ union iwreq_data wrqu;
+ memset(&wrqu, '\0', sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
+ wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
+ pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
+
+#ifdef CONFIG_CFG80211
+ /* indicate disconnected event to nl80211 */
+ cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
+ NULL, 0, GFP_KERNEL);
+#endif
+ }
+ break;
+
+ case WLAN_HDD_SOFTAP:
+ /* softAP can handle SSR */
+ break;
+
+ case WLAN_HDD_P2P_GO:
+#ifdef CONFIG_CFG80211
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
+ __func__);
+ /* event supplicant to restart */
+ cfg80211_del_sta(pAdapter->dev,
+ (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
+#endif
+ break;
+
+ case WLAN_HDD_MONITOR:
+ /* monitor interface start */
+ break;
+ default:
+ break;
+ }
+
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+
+ EXIT();
+
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
+{
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ hdd_adapter_t *pAdapter;
+ VOS_STATUS status;
+ v_U32_t roamId;
+
+ ENTER();
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+
+ if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
+ (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
+ {
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
+ init_completion(&pAdapter->disconnect_comp_var);
+ sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
+ eCSR_DISCONNECT_REASON_UNSPECIFIED);
+
+ wait_for_completion_interruptible_timeout(
+ &pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+
+ pWextState->roamProfile.csrPersona = pAdapter->device_mode;
+ pHddCtx->isAmpAllowed = VOS_FALSE;
+ sme_RoamConnect(pHddCtx->hHal,
+ pAdapter->sessionId, &(pWextState->roamProfile),
+ &roamId);
+ }
+
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+
+ EXIT();
+
+ return VOS_STATUS_SUCCESS;
+}
+
+v_U8_t hdd_is_ssr_required( void)
+{
+ return isSsrRequired;
+}
+
+void hdd_set_ssr_required( v_U8_t value)
+{
+ isSsrRequired = value;
+}
+
+VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
+ hdd_adapter_list_node_t** ppAdapterNode)
+{
+ VOS_STATUS status;
+ spin_lock(&pHddCtx->hddAdapters.lock);
+ status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
+ (hdd_list_node_t**) ppAdapterNode );
+ spin_unlock(&pHddCtx->hddAdapters.lock);
+ return status;
+}
+
+VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
+ hdd_adapter_list_node_t* pAdapterNode,
+ hdd_adapter_list_node_t** pNextAdapterNode)
+{
+ VOS_STATUS status;
+ spin_lock(&pHddCtx->hddAdapters.lock);
+ status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
+ (hdd_list_node_t*) pAdapterNode,
+ (hdd_list_node_t**)pNextAdapterNode );
+
+ spin_unlock(&pHddCtx->hddAdapters.lock);
+ return status;
+}
+
+VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
+ hdd_adapter_list_node_t* pAdapterNode)
+{
+ VOS_STATUS status;
+ spin_lock(&pHddCtx->hddAdapters.lock);
+ status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
+ &pAdapterNode->node );
+ spin_unlock(&pHddCtx->hddAdapters.lock);
+ return status;
+}
+
+VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
+ hdd_adapter_list_node_t** ppAdapterNode)
+{
+ VOS_STATUS status;
+ spin_lock(&pHddCtx->hddAdapters.lock);
+ status = hdd_list_remove_front( &pHddCtx->hddAdapters,
+ (hdd_list_node_t**) ppAdapterNode );
+ spin_unlock(&pHddCtx->hddAdapters.lock);
+ return status;
+}
+
+VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
+ hdd_adapter_list_node_t* pAdapterNode)
+{
+ VOS_STATUS status;
+ spin_lock(&pHddCtx->hddAdapters.lock);
+ status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
+ (hdd_list_node_t*) pAdapterNode );
+ spin_unlock(&pHddCtx->hddAdapters.lock);
+ return status;
+}
+
+VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
+ hdd_adapter_list_node_t* pAdapterNode)
+{
+ VOS_STATUS status;
+ spin_lock(&pHddCtx->hddAdapters.lock);
+ status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
+ (hdd_list_node_t*) pAdapterNode );
+ spin_unlock(&pHddCtx->hddAdapters.lock);
+ return status;
+}
+
+hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
+ tSirMacAddr macAddr )
+{
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ hdd_adapter_t *pAdapter;
+ VOS_STATUS status;
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+
+ if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
+ macAddr, sizeof(tSirMacAddr) ) )
+ {
+ return pAdapter;
+ }
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+
+ return NULL;
+
+}
+
+hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
+{
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ hdd_adapter_t *pAdapter;
+ VOS_STATUS status;
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+
+ if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
+ IFNAMSIZ ) )
+ {
+ return pAdapter;
+ }
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+
+ return NULL;
+
+}
+
+hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
+{
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ hdd_adapter_t *pAdapter;
+ VOS_STATUS status;
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+
+ if( pAdapter && (mode == pAdapter->device_mode) )
+ {
+ return pAdapter;
+ }
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+
+ return NULL;
+
+}
+
+//Remove this function later
+hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
+{
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ hdd_adapter_t *pAdapter;
+ VOS_STATUS status;
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+
+ if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
+ {
+ return pAdapter;
+ }
+
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+
+ return NULL;
+
+}
+
+#ifdef CONFIG_CFG80211
+/**---------------------------------------------------------------------------
+
+ \brief hdd_set_monitor_tx_adapter() -
+
+ This API initializes the adapter to be used while transmitting on monitor
+ adapter.
+
+ \param - pHddCtx - Pointer to the HDD context.
+ pAdapter - Adapter that will used for TX. This can be NULL.
+ \return - None.
+ --------------------------------------------------------------------------*/
+void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
+{
+ hdd_adapter_t *pMonAdapter;
+
+ pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
+
+ if( NULL != pMonAdapter )
+ {
+ pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
+ }
+}
+#endif
+/**---------------------------------------------------------------------------
+
+ \brief hdd_select_queue() -
+
+ This API returns the operating channel of the requested device mode
+
+ \param - pHddCtx - Pointer to the HDD context.
+ - mode - Device mode for which operating channel is required
+ suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
+ WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
+ \return - channel number. "0" id the requested device is not found OR it is not connected.
+ --------------------------------------------------------------------------*/
+v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
+{
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ VOS_STATUS status;
+ hdd_adapter_t *pAdapter;
+ v_U8_t operatingChannel = 0;
+
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+
+ if( mode == pAdapter->device_mode )
+ {
+ switch(pAdapter->device_mode)
+ {
+ case WLAN_HDD_INFRA_STATION:
+ case WLAN_HDD_P2P_CLIENT:
+ if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
+ operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
+ break;
+ case WLAN_HDD_SOFTAP:
+ case WLAN_HDD_P2P_GO:
+ /*softap connection info */
+ if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
+ operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
+ break;
+ default:
+ break;
+ }
+
+ break; //Found the device of interest. break the loop
+ }
+
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+ return operatingChannel;
+}
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+/**---------------------------------------------------------------------------
+
+ \brief hdd_set_multicast_list() -
+
+ This used to set the multicast address list.
+
+ \param - dev - Pointer to the WLAN device.
+ - skb - Pointer to OS packet (sk_buff).
+ \return - success/fail
+
+ --------------------------------------------------------------------------*/
+static void hdd_set_multicast_list(struct net_device *dev)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx;
+ int mc_count;
+ int i = 0;
+ struct netdev_hw_addr *ha;
+ pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
+ if (NULL == pHddCtx)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: HDD context is Null", __FUNCTION__);
+ return;
+ }
+
+ if (dev->flags & IFF_ALLMULTI)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: allow all multicast frames", __FUNCTION__);
+ pHddCtx->mc_addr_list.mc_cnt = 0;
+ }
+ else
+ {
+ mc_count = netdev_mc_count(dev);
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: mc_count = %u", __FUNCTION__, mc_count);
+ if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: No free filter available; allow all multicast frames", __FUNCTION__);
+ pHddCtx->mc_addr_list.mc_cnt = 0;
+ return;
+ }
+
+ pHddCtx->mc_addr_list.mc_cnt = mc_count;
+
+ netdev_for_each_mc_addr(ha, dev) {
+ if (i == mc_count)
+ break;
+ memset(&(pHddCtx->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
+ memcpy(&(pHddCtx->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
+ hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = %02x:%02x:%02x:%02x:%02x:%02x",
+ __func__, i,
+ pHddCtx->mc_addr_list.addr[i][0], pHddCtx->mc_addr_list.addr[i][1],
+ pHddCtx->mc_addr_list.addr[i][2], pHddCtx->mc_addr_list.addr[i][3],
+ pHddCtx->mc_addr_list.addr[i][4], pHddCtx->mc_addr_list.addr[i][5]);
+ i++;
+ }
+ }
+ return;
+}
+#endif
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_select_queue() -
+
+ This function is registered with the Linux OS for network
+ core to decide which queue to use first.
+
+ \param - dev - Pointer to the WLAN device.
+ - skb - Pointer to OS packet (sk_buff).
+ \return - ac, Queue Index/access category corresponding to UP in IP header
+
+ --------------------------------------------------------------------------*/
+v_U16_t hdd_select_queue(struct net_device *dev,
+ struct sk_buff *skb)
+{
+ return hdd_wmm_select_queue(dev, skb);
+}
+
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_wlan_initial_scan() -
+
+ This function triggers the initial scan
+
+ \param - pAdapter - Pointer to the HDD adapter.
+
+ --------------------------------------------------------------------------*/
+void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
+{
+ tCsrScanRequest scanReq;
+ tCsrChannelInfo channelInfo;
+ eHalStatus halStatus;
+ unsigned long scanId;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
+ vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
+ scanReq.BSSType = eCSR_BSS_TYPE_ANY;
+
+ if(sme_Is11dSupported(pHddCtx->hHal))
+ {
+ halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
+ if ( HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
+ if( !scanReq.ChannelInfo.ChannelList )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
+ vos_mem_free(channelInfo.ChannelList);
+ return;
+ }
+ vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
+ channelInfo.numOfChannels);
+ scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
+ vos_mem_free(channelInfo.ChannelList);
+ }
+
+ scanReq.scanType = eSIR_PASSIVE_SCAN;
+ scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
+ scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
+ scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
+ }
+ else
+ {
+ scanReq.scanType = eSIR_ACTIVE_SCAN;
+ scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
+ scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
+ scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
+ }
+
+ halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
+ if ( !HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
+ __func__, halStatus );
+ }
+
+ if(sme_Is11dSupported(pHddCtx->hHal))
+ vos_mem_free(scanReq.ChannelInfo.ChannelList);
+}
+
+struct fullPowerContext
+{
+ struct completion completion;
+ unsigned int magic;
+};
+#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_full_power_callback() - HDD full power callback function
+
+ This is the function invoked by SME to inform the result of a full power
+ request issued by HDD
+
+ \param - callbackcontext - Pointer to cookie
+ \param - status - result of request
+
+ \return - None
+
+ --------------------------------------------------------------------------*/
+static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
+{
+ struct fullPowerContext *pContext = callbackContext;
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: context = %p, status = %d", pContext, status);
+
+ if (NULL == callbackContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Bad param, context [%p]",
+ __FUNCTION__, callbackContext);
+ return;
+ }
+
+ /* there is a race condition that exists between this callback function
+ and the caller since the caller could time out either before or
+ while this code is executing. we'll assume the timeout hasn't
+ occurred, but we'll verify that right before we save our work */
+
+ if (POWER_CONTEXT_MAGIC != pContext->magic)
+ {
+ /* the caller presumably timed out so there is nothing we can do */
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ "%s: Invalid context, magic [%08x]",
+ __FUNCTION__, pContext->magic);
+ return;
+ }
+
+ /* the race is on. caller could have timed out immediately after
+ we verified the magic, but if so, caller will wait a short time
+ for us to notify the caller, so the context will stay valid */
+ complete(&pContext->completion);
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_wlan_exit() - HDD WLAN exit function
+
+ This is the driver exit point (invoked during rmmod)
+
+ \param - pHddCtx - Pointer to the HDD Context
+
+ \return - None
+
+ --------------------------------------------------------------------------*/
+void hdd_wlan_exit(hdd_context_t *pHddCtx)
+{
+ eHalStatus halStatus;
+ v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
+ VOS_STATUS vosStatus;
+#ifdef ANI_BUS_TYPE_SDIO
+ struct sdio_func *sdio_func_dev = NULL;
+#endif // ANI_BUS_TYPE_SDIO
+#ifdef CONFIG_CFG80211
+ struct wiphy *wiphy = pHddCtx->wiphy;
+#endif
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ hdd_adapter_t* pAdapter;
+#endif
+ struct fullPowerContext powerContext;
+ long lrc;
+
+ ENTER();
+
+#ifdef CONFIG_CFG80211
+#ifdef WLAN_SOFTAP_FEATURE
+ if (VOS_STA_SAP_MODE != hdd_get_conparam())
+#endif
+ {
+#ifdef ANI_MANF_DIAG
+ if (VOS_FTM_MODE != hdd_get_conparam())
+#endif /* ANI_MANF_DIAG */
+ {
+ hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
+ WLAN_HDD_INFRA_STATION);
+ if (pAdapter == NULL)
+ pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
+
+ if (pAdapter != NULL)
+ {
+ wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
+ hdd_UnregisterWext(pAdapter->dev);
+ }
+ }
+ }
+#endif
+
+#ifdef ANI_MANF_DIAG
+ if (VOS_FTM_MODE == hdd_get_conparam())
+ {
+ wlan_hdd_ftm_close(pHddCtx);
+ goto free_hdd_ctx;
+ }
+#endif
+ //Stop the Interface TX queue.
+ //netif_tx_disable(pWlanDev);
+ //netif_carrier_off(pWlanDev);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ // unregister suspend/resume callbacks
+ if(pHddCtx->cfg_ini->nEnableSuspend)
+ {
+ unregister_wlan_suspend();
+ }
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#ifdef WLAN_SOFTAP_FEATURE
+ if (VOS_STA_SAP_MODE == hdd_get_conparam())
+ {
+ pAdapter = hdd_get_adapter(pHddCtx,
+ WLAN_HDD_SOFTAP);
+ }
+ else
+ {
+#endif
+#ifdef ANI_MANF_DIAG
+ if (VOS_FTM_MODE != hdd_get_conparam())
+#endif /* ANI_MANF_DIAG */
+ {
+ pAdapter = hdd_get_adapter(pHddCtx,
+ WLAN_HDD_INFRA_STATION);
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ }
+#endif
+ /* DeRegister with platform driver as client for Suspend/Resume */
+ vosStatus = hddDeregisterPmOps(pHddCtx);
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
+ VOS_ASSERT(0);
+ }
+
+ vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
+ }
+#endif //FEATURE_WLAN_INTEGRATED_SOC
+
+ // Cancel any outstanding scan requests. We are about to close all
+ // of our adapters, but an adapter structure is what SME passes back
+ // to our callback function. Hence if there are any outstanding scan
+ // requests then there is a race condition between when the adapter
+ // is closed and when the callback is invoked. We try to resolve that
+ // race condition here by canceling any outstanding scans before we
+ // close the adapters.
+ // Note that the scans may be cancelled in an asynchronous manner, so
+ // ideally there needs to be some kind of synchronization. Rather than
+ // introduce a new synchronization here, we will utilize the fact that
+ // we are about to Request Full Power, and since that is synchronized,
+ // the expectation is that by the time Request Full Power has completed,
+ // all scans will be cancelled.
+ hdd_abort_mac_scan( pHddCtx );
+
+ //Disable IMPS/BMPS as we do not want the device to enter any power
+ //save mode during shutdown
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
+ sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
+
+ //Ensure that device is in full power as we will touch H/W during vos_Stop
+ init_completion(&powerContext.completion);
+ powerContext.magic = POWER_CONTEXT_MAGIC;
+
+ halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
+ &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
+
+ if (eHAL_STATUS_SUCCESS != halStatus)
+ {
+ if (eHAL_STATUS_PMC_PENDING == halStatus)
+ {
+ /* request was sent -- wait for the response */
+ lrc = wait_for_completion_interruptible_timeout(
+ &powerContext.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
+ /* either we have a response or we timed out
+ either way, first invalidate our magic */
+ powerContext.magic = 0;
+ if (lrc <= 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
+ __FUNCTION__, (0 == lrc) ? "timeout" : "interrupt");
+ /* there is a race condition such that the callback
+ function could be executing at the same time we are. of
+ primary concern is if the callback function had already
+ verified the "magic" but hasn't yet set the completion
+ variable. Since the completion variable is on our
+ stack, we'll delay just a bit to make sure the data is
+ still valid if that is the case */
+ msleep(50);
+ }
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Request for Full Power failed, status %d",
+ __FUNCTION__, halStatus);
+ VOS_ASSERT(0);
+ /* continue -- need to clean up as much as possible */
+ }
+ }
+
+ // Unregister the Net Device Notifier
+ unregister_netdevice_notifier(&hdd_netdev_notifier);
+
+#ifdef WLAN_FEATURE_P2P
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
+ {
+ hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
+ WLAN_HDD_INFRA_STATION);
+ if (pAdapter != NULL)
+ {
+ INIT_COMPLETION(pAdapter->session_close_comp_var);
+ if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
+ pAdapter->p2pSessionId,
+ hdd_smeCloseSessionCallback, pAdapter ) )
+ {
+ //Block on a completion variable. Can't wait forever though.
+ wait_for_completion_interruptible_timeout(
+ &pAdapter->session_close_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
+ }
+ }
+ }
+#endif
+ hdd_stop_all_adapters( pHddCtx );
+
+#ifdef ANI_BUS_TYPE_SDIO
+ sdio_func_dev = libra_getsdio_funcdev();
+
+ if(sdio_func_dev == NULL)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
+ VOS_ASSERT(0);
+ return;
+ }
+
+ sd_claim_host(sdio_func_dev);
+
+ /* Disable SDIO IRQ since we are exiting */
+ libra_enable_sdio_irq(sdio_func_dev, 0);
+
+ sd_release_host(sdio_func_dev);
+#endif // ANI_BUS_TYPE_SDIO
+
+#ifdef WLAN_BTAMP_FEATURE
+ vosStatus = WLANBAP_Stop(pVosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to stop BAP",__func__);
+ }
+#endif //WLAN_BTAMP_FEATURE
+
+ //Stop all the modules
+ vosStatus = vos_stop( pVosContext );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to stop VOSS",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+#ifdef ANI_BUS_TYPE_SDIO
+ vosStatus = WLANBAL_Stop( pVosContext );
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN BAL STOP\n");
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to stop BAL",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+ msleep(50);
+ //Put the chip is standby before asserting deep sleep
+ vosStatus = WLANBAL_SuspendChip( pVosContext );
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN Suspend Chip\n");
+
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to suspend chip ",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+ //Invoke SAL stop
+ vosStatus = WLANSAL_Stop( pVosContext );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to stop SAL",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+#endif // ANI_BUS_TYPE_SDIO
+
+ //Assert Deep sleep signal now to put Libra HW in lowest power state
+ vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+
+ //Vote off any PMIC voltage supplies
+ vos_chipPowerDown(NULL, NULL, NULL);
+
+ vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
+
+ //Clean up HDD Nlink Service
+ send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
+ nl_srv_exit();
+
+ //This requires pMac access, Call this before vos_close().
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ hdd_unregister_mcast_bcast_filter(pHddCtx);
+#endif
+
+ //Close the scheduler before calling vos_close to make sure no thread is
+ // scheduled after the each module close is called i.e after all the data
+ // structures are freed.
+ vosStatus = vos_sched_close( pVosContext );
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to close VOSS Scheduler",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+
+
+ //Close VOSS
+ //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
+ vos_close(pVosContext);
+
+#ifdef ANI_BUS_TYPE_SDIO
+ vosStatus = WLANBAL_Close(pVosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to close BAL",__func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+ }
+ hddLog(VOS_TRACE_LEVEL_ERROR,"Returned WLAN BAL CLOSE\n\n\n\n");
+#endif // ANI_BUS_TYPE_SDIO
+
+ //Close Watchdog
+ if(pHddCtx->cfg_ini->fIsLogpEnabled)
+ vos_watchdog_close(pVosContext);
+
+ /* Cancel the vote for XO Core ON.
+ * This is done here to ensure there is no race condition since MC, TX and WD threads have
+ * exited at this point
+ */
+ hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
+ " when WLAN is turned OFF\n");
+ if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
+ " Not returning failure."
+ " Power consumed will be high\n");
+ }
+
+ hdd_close_all_adapters( pHddCtx );
+
+
+ //Free up dynamically allocated members inside HDD Adapter
+ kfree(pHddCtx->cfg_ini);
+ pHddCtx->cfg_ini= NULL;
+
+ /* free the power on lock from platform driver */
+ if (free_riva_power_on_lock("wlan"))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
+ __func__);
+ }
+
+#ifdef ANI_MANF_DIAG
+free_hdd_ctx:
+#endif
+#ifdef CONFIG_CFG80211
+ wiphy_unregister(wiphy) ;
+ wiphy_free(wiphy) ;
+#else
+ vos_mem_free( pHddCtx );
+#endif
+ if (hdd_is_ssr_required())
+ {
+ /* WDI timeout had happened during unload, so SSR is needed here */
+ subsystem_restart("riva");
+ msleep(5000);
+ }
+ hdd_set_ssr_required (VOS_FALSE);
+}
+
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_update_config_from_nv() - Function to update the contents of
+ the running configuration with parameters taken from NV storage
+
+ \param - pHddCtx - Pointer to the HDD global context
+
+ \return - VOS_STATUS_SUCCESS if successful
+
+ --------------------------------------------------------------------------*/
+static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
+{
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+ eHalStatus halStatus;
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ v_BOOL_t itemIsValid = VOS_FALSE;
+ VOS_STATUS status;
+ v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
+ v_U8_t macLoop;
+
+ /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
+ status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if (itemIsValid == VOS_TRUE)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
+ status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
+ VOS_MAX_CONCURRENCY_PERSONA);
+ if(status != VOS_STATUS_SUCCESS)
+ {
+ /* Get MAC from NV fail, not update CFG info
+ * INI MAC value will be used for MAC setting */
+ hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* If first MAC is not valid, treat all others are not valid
+ * Then all MACs will be got from ini file */
+ if(vos_is_macaddr_zero(&macFromNV[0]))
+ {
+ /* MAC address in NV file is not configured yet */
+ hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
+ return VOS_STATUS_E_INVAL;
+ }
+
+ /* Get MAC address from NV, update CFG info */
+ for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
+ {
+ if(vos_is_macaddr_zero(&macFromNV[macLoop]))
+ {
+ printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
+ /* This MAC is not valid, skip it
+ * This MAC will be got from ini file */
+ }
+ else
+ {
+ vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
+ (v_U8_t *)&macFromNV[macLoop].bytes[0],
+ VOS_MAC_ADDR_SIZE);
+ }
+ }
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
+ return VOS_STATUS_E_FAILURE;
+ }
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+#ifndef FEATURE_WLAN_INTEGRATED_SOC
+#if 1 /* need to fix for concurrency */
+ // Set the MAC Address
+ // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
+ halStatus = ccmCfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
+ (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
+ sizeof( pHddCtx->cfg_ini->intfMacAddr[0]),
+ hdd_set_mac_addr_cb, VOS_FALSE );
+
+ if (!HAL_STATUS_SUCCESS( halStatus ))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
+ "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
+ return VOS_STATUS_E_FAILURE;
+ }
+#endif
+#endif
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_post_voss_start_config() - HDD post voss start config helper
+
+ \param - pAdapter - Pointer to the HDD
+
+ \return - None
+
+ --------------------------------------------------------------------------*/
+VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
+{
+ eHalStatus halStatus;
+ v_U32_t listenInterval;
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ /* In the non-integrated architecture we update the configuration from
+ the INI file and from NV after vOSS has been started
+ */
+
+ // Apply the cfg.ini to cfg.dat
+ if (FALSE == hdd_update_config_dat(pHddCtx))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ // Apply the NV to cfg.dat
+ if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: config update from NV failed", __func__ );
+ return VOS_STATUS_E_FAILURE;
+ }
+#endif // FEATURE_WLAN_NON_INTEGRATED_SOC
+
+ // Send ready indication to the HDD. This will kick off the MAC
+ // into a 'running' state and should kick off an initial scan.
+ halStatus = sme_HDDReadyInd( pHddCtx->hHal );
+ if ( !HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
+ "code %08d [x%08x]",__func__, halStatus, halStatus );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ // Set default LI into HDD context,
+ // otherwise under some race condition, HDD will set 0 LI value into RIVA,
+ // And RIVA will crash
+ wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
+ pHddCtx->hdd_actual_LI_value = listenInterval;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+#ifdef ANI_BUS_TYPE_SDIO
+
+#ifndef ANI_MANF_DIAG
+// Routine to initialize the PMU
+void wlan_hdd_enable_deepsleep(v_VOID_t * pVosContext)
+{
+/*-------------- Need to fix this correctly while doing Deepsleep testing
+ tANI_U32 regValue = 0;
+
+ regValue = QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_DEEP_SLEEP_EN_MASK |
+ QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_AON_MASK_MASK |
+ QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_SW_MASK_MASK |
+ QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_2P3_LPM_MASK_MASK;
+
+ WLANBAL_WriteRegister(pVosContext, QWLAN_PMU_LDO_CTRL_REG_REG, regValue);
+---------------------*/
+
+ return;
+}
+#endif
+#endif
+
+/* wake lock APIs for HDD */
+void hdd_prevent_suspend(void)
+{
+ wake_lock(&wlan_wake_lock);
+}
+
+void hdd_allow_suspend(void)
+{
+ wake_unlock(&wlan_wake_lock);
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_wlan_startup() - HDD init function
+
+ This is the driver startup code executed once a WLAN device has been detected
+
+ \param - dev - Pointer to the underlying device
+
+ \return - 0 for success -1 for failure
+
+ --------------------------------------------------------------------------*/
+
+int hdd_wlan_startup(struct device *dev )
+{
+ VOS_STATUS status;
+ hdd_adapter_t *pAdapter = NULL;
+ hdd_context_t *pHddCtx = NULL;
+ v_CONTEXT_t pVosContext= NULL;
+#ifdef WLAN_BTAMP_FEATURE
+ VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
+ WLANBAP_ConfigType btAmpConfig;
+ hdd_config_t *pConfig;
+#endif
+ int ret;
+#ifdef CONFIG_CFG80211
+ struct wiphy *wiphy;
+#endif
+#ifdef ANI_BUS_TYPE_SDIO
+ struct sdio_func *sdio_func_dev = dev_to_sdio_func(dev);
+#endif //ANI_BUS_TYPE_SDIO
+
+ ENTER();
+#ifdef CONFIG_CFG80211
+ /*
+ * cfg80211: wiphy allocation
+ */
+ wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
+
+ if(wiphy == NULL)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
+ return -1;
+ }
+
+ pHddCtx = wiphy_priv(wiphy);
+
+#else
+
+ pHddCtx = vos_mem_malloc ( sizeof( hdd_context_t ) );
+ if(pHddCtx == NULL)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
+ return -1;
+ }
+
+#endif
+ //Initialize the adapter context to zeros.
+ vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
+
+#ifdef CONFIG_CFG80211
+ pHddCtx->wiphy = wiphy;
+#endif
+ hdd_prevent_suspend();
+ pHddCtx->isLoadUnloadInProgress = TRUE;
+
+ vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
+
+ /*Get vos context here bcoz vos_open requires it*/
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+
+ //Save the Global VOSS context in adapter context for future.
+ pHddCtx->pvosContext = pVosContext;
+
+ //Save the adapter context in global context for future.
+ ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
+
+#ifdef ANI_BUS_TYPE_SDIO
+ // Set the private data for the device to our adapter.
+ libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
+ atomic_set(&pHddCtx->sdio_claim_count, 0);
+#endif // ANI_BUS_TYPE_SDIO
+
+ pHddCtx->parent_dev = dev;
+
+ init_completion(&pHddCtx->full_pwr_comp_var);
+ init_completion(&pHddCtx->standby_comp_var);
+ init_completion(&pHddCtx->req_bmps_comp_var);
+
+
+ hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
+
+ // Load all config first as TL config is needed during vos_open
+ pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
+ if(pHddCtx->cfg_ini == NULL)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
+ goto err_free_hdd_context;
+ }
+
+ vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
+
+ // Read and parse the qcom_cfg.ini file
+ status = hdd_parse_config_ini( pHddCtx );
+ if ( VOS_STATUS_SUCCESS != status )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
+ __func__, WLAN_INI_FILE);
+ goto err_config;
+ }
+
+#ifdef CONFIG_CFG80211
+ /*
+ * cfg80211: Initialization and registration ...
+ */
+ if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: wlan_hdd_cfg80211_register return failure", __func__);
+ goto err_wiphy_reg;
+ }
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ // Update WDI trace levels based upon the cfg.ini
+ hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
+ pHddCtx->cfg_ini->wdiTraceEnableDAL);
+ hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
+ pHddCtx->cfg_ini->wdiTraceEnableCTL);
+ hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
+ pHddCtx->cfg_ini->wdiTraceEnableDAT);
+ hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
+ pHddCtx->cfg_ini->wdiTraceEnablePAL);
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
+#ifdef ANI_MANF_DIAG
+ if(VOS_FTM_MODE == hdd_get_conparam())
+ {
+ if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
+ goto err_free_hdd_context;
+ }
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
+ return VOS_STATUS_SUCCESS;
+ }
+#endif
+
+ //Open watchdog module
+ if(pHddCtx->cfg_ini->fIsLogpEnabled)
+ {
+ status = vos_watchdog_open(pVosContext,
+ &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
+
+ if(!VOS_IS_STATUS_SUCCESS( status ))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
+#ifdef CONFIG_CFG80211
+ goto err_wiphy_reg;
+#else
+ goto err_config;
+#endif
+ }
+ }
+
+ pHddCtx->isLogpInProgress = FALSE;
+ vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
+
+#ifdef ANI_BUS_TYPE_SDIO
+ status = WLANBAL_Open(pHddCtx->pvosContext);
+ if(!VOS_IS_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to open BAL",__func__);
+ goto err_wdclose;
+ }
+#endif // ANI_BUS_TYPE_SDIO
+
+ status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
+ if(!VOS_IS_STATUS_SUCCESS(status))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
+#ifdef ANI_BUS_TYPE_SDIO
+ goto err_balclose;
+#else
+ goto err_wdclose;
+#endif
+ }
+
+
+#ifdef ANI_BUS_TYPE_SDIO
+ status = WLANSAL_Start(pHddCtx->pvosContext);
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
+ goto err_clkvote;
+ }
+
+ /* Start BAL */
+ status = WLANBAL_Start(pHddCtx->pvosContext);
+
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start BAL",__func__);
+ goto err_salstop;
+ }
+#endif // ANI_BUS_TYPE_SDIO
+
+#ifdef MSM_PLATFORM_7x30
+ /* FIXME: Volans 2.0 configuration. Reconfigure 1.3v SW supply to 1.3v. It will be configured to
+ * 1.4v in vos_ChipPowerup() routine above
+ */
+#endif
+
+ status = vos_open( &pVosContext, 0);
+ if ( !VOS_IS_STATUS_SUCCESS( status ))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
+ goto err_balstop;
+ }
+
+ /* Save the hal context in Adapter */
+ pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
+
+ if ( NULL == pHddCtx->hHal )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
+ goto err_vosclose;
+ }
+
+ // Set the SME configuration parameters...
+ status = hdd_set_sme_config( pHddCtx );
+
+ if ( VOS_STATUS_SUCCESS != status )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
+ goto err_vosclose;
+ }
+
+ //Initialize the WMM module
+ status = hdd_wmm_init(pHddCtx);
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __FUNCTION__);
+ goto err_vosclose;
+ }
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ /* Vos preStart is calling */
+ status = vos_preStart( pHddCtx->pvosContext );
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
+ goto err_vosclose;
+ }
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ /* In the integrated architecture we update the configuration from
+ the INI file and from NV before vOSS has been started so that
+ the final contents are available to send down to the cCPU */
+
+ // Apply the cfg.ini to cfg.dat
+ if (FALSE == hdd_update_config_dat(pHddCtx))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
+ goto err_vosclose;
+ }
+
+ // Apply the NV to cfg.dat
+ /* Prima Update MAC address only at here */
+ if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
+ {
+#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
+ /* There was not a valid set of MAC Addresses in NV. See if the
+ default addresses were modified by the cfg.ini settings. If so,
+ we'll use them, but if not, we'll autogenerate a set of MAC
+ addresses based upon the device serial number */
+
+ static const v_MACADDR_t default_address =
+ {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
+ unsigned int serialno;
+ int i;
+
+ serialno = wcnss_get_serial_number();
+ if ((0 != serialno) &&
+ (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
+ sizeof(default_address))))
+ {
+ /* cfg.ini has the default address, invoke autogen logic */
+
+ /* MAC address has 3 bytes of OUI so we have a maximum of 3
+ bytes of the serial number that can be used to generate
+ the other 3 bytes of the MAC address. Mask off all but
+ the lower 3 bytes (this will also make sure we don't
+ overflow in the next step) */
+ serialno &= 0x00FFFFFF;
+
+ /* we need a unique address for each session */
+ serialno *= VOS_MAX_CONCURRENCY_PERSONA;
+
+ /* autogen all addresses */
+ for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
+ {
+ /* start with the entire default address */
+ pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
+ /* then replace the lower 3 bytes */
+ pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
+ pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
+ pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
+
+ serialno++;
+ }
+
+ pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
+ MAC_ADDRESS_STR,
+ MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
+ }
+ else
+#endif //WLAN_AUTOGEN_MACADDR_FEATURE
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid MAC address in NV, using MAC from ini file "
+ MAC_ADDRESS_STR, __func__,
+ MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
+ }
+ }
+ {
+ eHalStatus halStatus;
+ // Set the MAC Address
+ // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
+ halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
+ (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
+ sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
+
+ if (!HAL_STATUS_SUCCESS( halStatus ))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
+ "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+#endif // FEATURE_WLAN_INTEGRATED_SOC
+
+ /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
+ Note: Firmware image will be read and downloaded inside vos_start API */
+ status = vos_start( pHddCtx->pvosContext );
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
+ goto err_vosclose;
+ }
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ /* retrieve and display WCNSS version information */
+ do {
+ tSirVersionType versionCompiled;
+ tSirVersionType versionReported;
+ tSirVersionString versionString;
+ tANI_U8 fwFeatCapsMsgSupported = 0;
+ VOS_STATUS vstatus;
+
+ vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
+ &versionCompiled);
+ if (!VOS_IS_STATUS_SUCCESS(vstatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: unable to retrieve WCNSS WLAN compiled version",
+ __FUNCTION__);
+ break;
+ }
+
+ vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
+ &versionReported);
+ if (!VOS_IS_STATUS_SUCCESS(vstatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: unable to retrieve WCNSS WLAN reported version",
+ __FUNCTION__);
+ break;
+ }
+
+ if ((versionCompiled.major != versionReported.major) ||
+ (versionCompiled.minor != versionReported.minor) ||
+ (versionCompiled.version != versionReported.version) ||
+ (versionCompiled.revision != versionReported.revision))
+ {
+ pr_err("%s: WCNSS WlAN Version %u.%u.%u.%u, "
+ "Host expected %u.%u.%u.%u\n",
+ WLAN_MODULE_NAME,
+ (int)versionReported.major,
+ (int)versionReported.minor,
+ (int)versionReported.version,
+ (int)versionReported.revision,
+ (int)versionCompiled.major,
+ (int)versionCompiled.minor,
+ (int)versionCompiled.version,
+ (int)versionCompiled.revision);
+ }
+ else
+ {
+ pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
+ WLAN_MODULE_NAME,
+ (int)versionReported.major,
+ (int)versionReported.minor,
+ (int)versionReported.version,
+ (int)versionReported.revision);
+ }
+
+ vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
+ versionString,
+ sizeof(versionString));
+ if (!VOS_IS_STATUS_SUCCESS(vstatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: unable to retrieve WCNSS software version string",
+ __FUNCTION__);
+ break;
+ }
+
+ pr_info("%s: WCNSS software version %s\n",
+ WLAN_MODULE_NAME, versionString);
+
+ vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
+ versionString,
+ sizeof(versionString));
+ if (!VOS_IS_STATUS_SUCCESS(vstatus))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: unable to retrieve WCNSS hardware version string",
+ __FUNCTION__);
+ break;
+ }
+
+ pr_info("%s: WCNSS hardware version %s\n",
+ WLAN_MODULE_NAME, versionString);
+
+ /* Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message */
+ if ((versionReported.major>0) || (versionReported.minor>1) || ((versionReported.minor>=1) && (versionReported.version>=1)))
+ fwFeatCapsMsgSupported = 1;
+ if (fwFeatCapsMsgSupported)
+ sme_featureCapsExchange(pHddCtx->hHal);
+ } while (0);
+
+#endif // FEATURE_WLAN_INTEGRATED_SOC
+
+ status = hdd_post_voss_start_config( pHddCtx );
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
+ __func__);
+ goto err_vosstop;
+ }
+
+#ifdef WLAN_SOFTAP_FEATURE
+ if (VOS_STA_SAP_MODE == hdd_get_conparam())
+ {
+ pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
+ wlan_hdd_get_intf_addr(pHddCtx), FALSE );
+ }
+ else
+ {
+#endif
+ pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
+ wlan_hdd_get_intf_addr(pHddCtx), FALSE );
+ if (pAdapter != NULL)
+ {
+#ifdef WLAN_FEATURE_P2P
+ vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
+ pHddCtx->cfg_ini->intfMacAddr[0].bytes,
+ sizeof(tSirMacAddr));
+ if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
+ {
+ /* Generate the P2P Device Address. This consists of the device's
+ * primary MAC address with the locally administered bit set.
+ */
+ pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
+ status = hdd_init_p2p_device_mode(pAdapter);
+ if ( VOS_STATUS_SUCCESS != status )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Init Session fail for P2P Device Address Mode ",
+ __FUNCTION__);
+ goto err_close_adapter;
+ }
+ }
+#endif
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ }
+#endif
+
+ if( pAdapter == NULL )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
+#ifdef ANI_BUS_TYPE_SDIO
+ goto err_balstop;
+#else
+ goto err_clkvote;
+#endif
+ }
+
+
+#ifdef WLAN_BTAMP_FEATURE
+ vStatus = WLANBAP_Open(pVosContext);
+ if(!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to open BAP",__func__);
+ goto err_p2psession_close;
+ }
+
+ vStatus = BSL_Init(pVosContext);
+ if(!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to Init BSL",__func__);
+ goto err_bap_close;
+ }
+ vStatus = WLANBAP_Start(pVosContext);
+ if (!VOS_IS_STATUS_SUCCESS(vStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to start TL",__func__);
+ goto err_bap_close;
+ }
+
+ pConfig = pHddCtx->cfg_ini;
+ btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
+ status = WLANBAP_SetConfig(&btAmpConfig);
+
+#endif //WLAN_BTAMP_FEATURE
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+ /*SME must send channel update configuration to RIVA*/
+ sme_UpdateChannelConfig(pHddCtx->hHal);
+#endif
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ /* Register with platform driver as client for Suspend/Resume */
+ status = hddRegisterPmOps(pHddCtx);
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
+#ifdef WLAN_BTAMP_FEATURE
+ goto err_bap_stop;
+#else
+ goto err_p2psession_close;
+#endif //WLAN_BTAMP_FEATURE
+ }
+
+ /* Register TM level change handler function to the platform */
+ status = hddDevTmRegisterNotifyCallback(pHddCtx);
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
+ goto err_unregister_pmops;
+ }
+#endif
+
+ /* register for riva power on lock to platform driver */
+ if (req_riva_power_on_lock("wlan"))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
+ __func__);
+ goto err_unregister_pmops;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ // Register suspend/resume callbacks
+ if(pHddCtx->cfg_ini->nEnableSuspend)
+ {
+ register_wlan_suspend();
+ }
+#endif
+
+ // register net device notifier for device change notification
+ ret = register_netdevice_notifier(&hdd_netdev_notifier);
+
+ if(ret < 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
+ goto err_free_power_on_lock;
+ }
+
+ //Initialize the nlink service
+ if(nl_srv_init() != 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
+ goto err_reg_netdev;
+ }
+
+ //Initialize the BTC service
+ if(btc_activate_service(pHddCtx) != 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
+ goto err_nl_srv;
+ }
+
+#ifdef PTT_SOCK_SVC_ENABLE
+ //Initialize the PTT service
+ if(ptt_sock_activate_svc(pHddCtx) != 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
+ goto err_nl_srv;
+ }
+#endif
+
+ //Initialize the WoWL service
+ if(!hdd_init_wowl(pHddCtx))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
+ goto err_nl_srv;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ hdd_register_mcast_bcast_filter(pHddCtx);
+#endif
+#ifdef CONFIG_CFG80211
+#ifdef WLAN_SOFTAP_FEATURE
+ if (VOS_STA_SAP_MODE != hdd_get_conparam())
+#endif
+ {
+ wlan_hdd_cfg80211_post_voss_start(pAdapter);
+ }
+#endif
+
+ mutex_init(&pHddCtx->sap_lock);
+
+ pHddCtx->isLoadUnloadInProgress = FALSE;
+
+ vos_event_init(&pAdapter->scan_info.scan_finished_event);
+ pAdapter->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
+
+ vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
+ hdd_allow_suspend();
+
+ goto success;
+
+err_nl_srv:
+ nl_srv_exit();
+
+err_reg_netdev:
+ unregister_netdevice_notifier(&hdd_netdev_notifier);
+
+err_free_power_on_lock:
+ free_riva_power_on_lock("wlan");
+
+err_unregister_pmops:
+ hddDevTmUnregisterNotifyCallback(pHddCtx);
+ hddDeregisterPmOps(pHddCtx);
+
+#ifdef WLAN_BTAMP_FEATURE
+err_bap_stop:
+ WLANBAP_Stop(pVosContext);
+#endif
+
+#ifdef WLAN_BTAMP_FEATURE
+err_bap_close:
+ WLANBAP_Close(pVosContext);
+#endif
+
+err_p2psession_close:
+#ifdef WLAN_FEATURE_P2P
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
+ {
+ hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
+ WLAN_HDD_INFRA_STATION);
+
+ if (pAdapter != NULL)
+ {
+ INIT_COMPLETION(pAdapter->session_close_comp_var);
+ if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
+ pAdapter->p2pSessionId,
+ hdd_smeCloseSessionCallback, pAdapter ) )
+ {
+ //Block on a completion variable. Can't wait forever though.
+ wait_for_completion_interruptible_timeout(
+ &pAdapter->session_close_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
+ }
+ }
+ }
+#endif
+
+err_close_adapter:
+ hdd_close_all_adapters( pHddCtx );
+
+err_vosstop:
+ vos_stop(pVosContext);
+
+err_vosclose:
+ status = vos_sched_close( pVosContext );
+ if (!VOS_IS_STATUS_SUCCESS(status)) {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to close VOSS Scheduler", __func__);
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
+ }
+ vos_close(pVosContext );
+
+err_balstop:
+#ifdef ANI_BUS_TYPE_SDIO
+#ifndef ANI_MANF_DIAG
+ wlan_hdd_enable_deepsleep(pHddCtx->pvosContext);
+#endif
+
+ WLANBAL_Stop(pHddCtx->pvosContext);
+ WLANBAL_SuspendChip(pHddCtx->pvosContext);
+#endif
+
+#ifdef ANI_BUS_TYPE_SDIO
+err_salstop:
+ WLANSAL_Stop(pHddCtx->pvosContext);
+
+#endif
+err_clkvote:
+ vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
+
+#ifdef ANI_BUS_TYPE_SDIO
+err_balclose:
+ WLANBAL_Close(pHddCtx->pvosContext);
+#endif // ANI_BUS_TYPE_SDIO
+
+err_wdclose:
+ if(pHddCtx->cfg_ini->fIsLogpEnabled)
+ vos_watchdog_close(pVosContext);
+
+#ifdef CONFIG_CFG80211
+err_wiphy_reg:
+ wiphy_unregister(wiphy) ;
+#endif
+
+err_config:
+ kfree(pHddCtx->cfg_ini);
+ pHddCtx->cfg_ini= NULL;
+
+err_free_hdd_context:
+ hdd_allow_suspend();
+#ifdef CONFIG_CFG80211
+ wiphy_free(wiphy) ;
+ //kfree(wdev) ;
+#else
+ vos_mem_free( pHddCtx );
+#endif
+ VOS_BUG(1);
+
+ return -1;
+
+success:
+ EXIT();
+ return 0;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_module_init() - Init Function
+
+ This is the driver entry point (invoked when module is loaded using insmod)
+
+ \param - None
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+static int __init hdd_module_init ( void)
+{
+ VOS_STATUS status;
+ v_CONTEXT_t pVosContext = NULL;
+#ifdef ANI_BUS_TYPE_SDIO
+ struct sdio_func *sdio_func_dev = NULL;
+ unsigned int attempts = 0;
+#endif // ANI_BUS_TYPE_SDIO
+ struct device *dev = NULL;
+ int ret_status = 0;
+
+ ENTER();
+
+ wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
+
+ pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
+ QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
+
+ //Power Up Libra WLAN card first if not already powered up
+ status = vos_chipPowerUp(NULL,NULL,NULL);
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
+ "exiting", __func__);
+ return -1;
+ }
+
+#ifdef ANI_BUS_TYPE_SDIO
+ //SDIO Polling should be turned on for card detection. When using Android Wi-Fi GUI
+ //users need not trigger SDIO polling explicitly. However when loading drivers via
+ //command line (Adb shell), users must turn on SDIO polling prior to loading WLAN.
+ do {
+ sdio_func_dev = libra_getsdio_funcdev();
+ if (NULL == sdio_func_dev) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
+ attempts++;
+ }
+ else {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
+ dev = &sdio_func_dev->dev;
+ break;
+ }
+
+ if(attempts == 7)
+ break;
+
+ msleep(250);
+
+ }while (attempts < 7);
+
+ //Retry to detect the card again by Powering Down the chip and Power up the chip
+ //again. This retry is done to recover from CRC Error
+ if (NULL == sdio_func_dev) {
+
+ attempts = 0;
+
+ //Vote off any PMIC voltage supplies
+ vos_chipPowerDown(NULL, NULL, NULL);
+
+ msleep(1000);
+
+ //Power Up Libra WLAN card first if not already powered up
+ status = vos_chipPowerUp(NULL,NULL,NULL);
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
+ "exiting", __func__);
+ return -1;
+ }
+
+ do {
+ sdio_func_dev = libra_getsdio_funcdev();
+ if (NULL == sdio_func_dev) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
+ attempts++;
+ }
+ else {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
+ dev = &sdio_func_dev->dev;
+ break;
+ }
+
+ if(attempts == 2)
+ break;
+
+ msleep(1000);
+
+ }while (attempts < 3);
+ }
+
+#endif // ANI_BUS_TYPE_SDIO
+
+#ifdef ANI_BUS_TYPE_PCI
+
+ dev = wcnss_wlan_get_device();
+
+#endif // ANI_BUS_TYPE_PCI
+
+#ifdef ANI_BUS_TYPE_PLATFORM
+ dev = wcnss_wlan_get_device();
+#endif // ANI_BUS_TYPE_PLATFORM
+
+
+ do {
+ if (NULL == dev) {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
+ ret_status = -1;
+ break;
+ }
+
+#ifdef MEMORY_DEBUG
+ vos_mem_init();
+#endif
+
+#ifdef TIMER_MANAGER
+ vos_timer_manager_init();
+#endif
+
+ /* Preopen VOSS so that it is ready to start at least SAL */
+ status = vos_preOpen(&pVosContext);
+
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
+ ret_status = -1;
+ break;
+ }
+
+#ifdef ANI_BUS_TYPE_SDIO
+ /* Now Open SAL */
+ status = WLANSAL_Open(pVosContext, 0);
+
+ if(!VOS_IS_STATUS_SUCCESS(status))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to open SAL", __func__);
+
+ /* If unable to open, cleanup and return failure */
+ vos_preClose( &pVosContext );
+ ret_status = -1;
+ break;
+ }
+#endif // ANI_BUS_TYPE_SDIO
+
+#if defined(FEATURE_WLAN_INTEGRATED_SOC) && defined(ANI_MANF_DIAG)
+ if(5 == con_mode)
+ {
+ hdd_set_conparam(VOS_FTM_MODE);
+ }
+#endif /* FEATURE_WLAN_INTEGRATED_SOC && ANI_MANF_DIAG */
+
+ // Call our main init function
+ if(hdd_wlan_startup(dev)) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
+ __func__);
+#ifdef ANI_BUS_TYPE_SDIO
+ WLANSAL_Close(pVosContext);
+#endif // ANI_BUS_TYPE_SDIO
+ vos_preClose( &pVosContext );
+ ret_status = -1;
+ break;
+ }
+
+ /* Cancel the vote for XO Core ON
+ * This is done here for safety purposes in case we re-initialize without turning
+ * it OFF in any error scenario.
+ */
+ hddLog(VOS_TRACE_LEVEL_ERROR, "In module init: Ensure Force XO Core is OFF"
+ " when WLAN is turned ON so Core toggles"
+ " unless we enter PS\n");
+ if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
+ " Power consumed will be high\n");
+ }
+ } while (0);
+
+ if (0 != ret_status)
+ {
+ //Assert Deep sleep signal now to put Libra HW in lowest power state
+ status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
+
+ //Vote off any PMIC voltage supplies
+ vos_chipPowerDown(NULL, NULL, NULL);
+#ifdef TIMER_MANAGER
+ vos_timer_exit();
+#endif
+#ifdef MEMORY_DEBUG
+ vos_mem_exit();
+#endif
+
+ wake_lock_destroy(&wlan_wake_lock);
+ pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
+ }
+ else
+ {
+ //Send WLAN UP indication to Nlink Service
+ send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
+
+ pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
+
+ }
+
+ EXIT();
+
+ return ret_status;
+}
+
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_module_exit() - Exit function
+
+ This is the driver exit point (invoked when module is unloaded using rmmod)
+
+ \param - None
+
+ \return - None
+
+ --------------------------------------------------------------------------*/
+static void __exit hdd_module_exit(void)
+{
+ hdd_context_t *pHddCtx = NULL;
+ v_CONTEXT_t pVosContext = NULL;
+ int attempts = 0;
+
+ pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
+
+ //Get the global vos context
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+
+ if(!pVosContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ goto done;
+ }
+
+ //Get the HDD context.
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+
+ if(!pHddCtx)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
+ }
+ else
+ {
+ while(isWDresetInProgress()){
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:Reset in Progress by LOGP. Block rmmod for 500ms!!!",__func__);
+ VOS_ASSERT(0);
+ msleep(500);
+ attempts++;
+ if(attempts==MAX_EXIT_ATTEMPTS_DURING_LOGP)
+ break;
+ }
+
+ pHddCtx->isLoadUnloadInProgress = TRUE;
+ vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
+
+ //Do all the cleanup before deregistering the driver
+ hdd_wlan_exit(pHddCtx);
+ }
+
+#ifdef ANI_BUS_TYPE_SDIO
+ WLANSAL_Close(pVosContext);
+#endif // ANI_BUS_TYPE_SDIO
+
+ vos_preClose( &pVosContext );
+
+#ifdef TIMER_MANAGER
+ vos_timer_exit();
+#endif
+#ifdef MEMORY_DEBUG
+ vos_mem_exit();
+#endif
+
+done:
+ wake_lock_destroy(&wlan_wake_lock);
+ pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
+}
+
+#if defined(WLAN_SOFTAP_FEATURE) || defined(ANI_MANF_DIAG)
+/**---------------------------------------------------------------------------
+
+ \brief hdd_get_conparam() -
+
+ This is the driver exit point (invoked when module is unloaded using rmmod)
+
+ \param - None
+
+ \return - tVOS_CON_MODE
+
+ --------------------------------------------------------------------------*/
+tVOS_CON_MODE hdd_get_conparam ( void )
+{
+ return (tVOS_CON_MODE)con_mode;
+
+}
+void hdd_set_conparam ( v_UINT_t newParam )
+{
+ con_mode = newParam;
+}
+/**---------------------------------------------------------------------------
+
+ \brief hdd_softap_sta_deauth() - function
+
+ This to take counter measure to handle deauth req from HDD
+
+ \param - pAdapter - Pointer to the HDD
+
+ \param - enable - boolean value
+
+ \return - None
+
+ --------------------------------------------------------------------------*/
+
+void hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
+{
+ v_U8_t STAId;
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ tHalHandle hHalHandle;
+#endif
+
+ ENTER();
+
+ hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
+
+ //Ignore request to deauth bcmc station
+ if( pDestMacAddress[0] & 0x1 )
+ return;
+
+ WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
+
+ /*Get the Station ID*/
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ hHalHandle = (tHalHandle ) vos_get_context(VOS_MODULE_ID_HAL, pVosContext);
+ if (eHAL_STATUS_SUCCESS ==
+ halTable_FindStaidByAddr(hHalHandle, (tANI_U8 *)pDestMacAddress,
+ &STAId))
+ {
+ hdd_softap_DeregisterSTA(pAdapter, STAId);
+ }
+#else
+ if (VOS_STATUS_SUCCESS ==
+ hdd_softap_GetStaId(pAdapter, (v_MACADDR_t *)pDestMacAddress,
+ &STAId))
+ {
+ hdd_softap_DeregisterSTA(pAdapter, STAId);
+ }
+#endif
+
+ EXIT();
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_softap_sta_disassoc() - function
+
+ This to take counter measure to handle deauth req from HDD
+
+ \param - pAdapter - Pointer to the HDD
+
+ \param - enable - boolean value
+
+ \return - None
+
+ --------------------------------------------------------------------------*/
+
+void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
+{
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
+
+ ENTER();
+
+ hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
+
+ //Ignore request to disassoc bcmc station
+ if( pDestMacAddress[0] & 0x1 )
+ return;
+
+ WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
+}
+
+void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
+{
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
+
+ ENTER();
+
+ hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
+
+ WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
+}
+
+#endif /* WLAN_SOFTAP_FEATURE */
+/**---------------------------------------------------------------------------
+ *
+ * \brief hdd_get__concurrency_mode() -
+ *
+ *
+ * \param - None
+ *
+ * \return - CONCURRENCY MODE
+ *
+ * --------------------------------------------------------------------------*/
+tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
+ hdd_context_t *pHddCtx;
+
+ if (NULL != pVosContext)
+ {
+ pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
+ if (NULL != pHddCtx)
+ {
+ return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
+ }
+ }
+
+ /* we are in an invalid state :( */
+ hddLog(LOGE, "%s: Invalid context", __FUNCTION__);
+ return VOS_STA;
+}
+
+/* Decide whether to allow/not the apps power collapse.
+ * Allow apps power collapse if we are in connected state.
+ * if not, allow only if we are in IMPS */
+v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
+{
+ tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
+ hdd_config_t *pConfig = pHddCtx->cfg_ini;
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ hdd_adapter_t *pAdapter = NULL;
+ VOS_STATUS status;
+
+#ifdef WLAN_SOFTAP_FEATURE
+ if (VOS_STA_SAP_MODE == hdd_get_conparam())
+ return TRUE;
+#endif
+
+ /*loop through all adapters. TBD fix for Concurrency */
+ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+ while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+ {
+ pAdapter = pAdapterNode->pAdapter;
+ if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
+ || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
+ {
+ if ((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
+ && (pmcState != IMPS && pmcState != BMPS
+ && pmcState != STOPPED && pmcState != STANDBY))
+ {
+ return FALSE;
+ }
+ }
+ status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+ pAdapterNode = pNext;
+ }
+ return TRUE;
+}
+
+void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
+{
+ switch(mode)
+ {
+ case WLAN_HDD_INFRA_STATION:
+#ifdef WLAN_FEATURE_P2P
+ case WLAN_HDD_P2P_CLIENT:
+ case WLAN_HDD_P2P_GO:
+#endif
+ case WLAN_HDD_SOFTAP:
+ pHddCtx->concurrency_mode |= (1 << mode);
+ pHddCtx->no_of_sessions[mode]++;
+ break;
+ default:
+ break;
+
+ }
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
+ __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
+}
+
+
+void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
+{
+ switch(mode)
+ {
+ case WLAN_HDD_INFRA_STATION:
+#ifdef WLAN_FEATURE_P2P
+ case WLAN_HDD_P2P_CLIENT:
+ case WLAN_HDD_P2P_GO:
+#endif
+ case WLAN_HDD_SOFTAP:
+ pHddCtx->no_of_sessions[mode]--;
+ if (!(pHddCtx->no_of_sessions[mode]))
+ pHddCtx->concurrency_mode &= (~(1 << mode));
+ break;
+ default:
+ break;
+ }
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
+ __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
+}
+
+//Register the module init/exit functions
+module_init(hdd_module_init);
+module_exit(hdd_module_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Qualcomm Atheros, Inc.");
+MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
+
+#if defined(WLAN_SOFTAP_FEATURE) || defined(ANI_MANF_DIAG)
+module_param(con_mode, int, 0);
+#endif
diff --git a/CORE/HDD/src/wlan_hdd_mib.c b/CORE/HDD/src/wlan_hdd_mib.c
new file mode 100644
index 0000000..f6dbab2
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_mib.c
@@ -0,0 +1,211 @@
+/*
+ * 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 "wlan_hdd_includes.h"
+
+
+static inline v_VOID_t mibGetDot11DesiredBssType( hdd_adapter_t *pAdapter, eMib_dot11DesiredBssType *pDot11DesiredBssType )
+{
+ *pDot11DesiredBssType = pAdapter->hdd_mib.mibDot11DesiredBssType;
+ return;
+}
+
+static inline VOS_STATUS mibSetDot11DesiredBssType( hdd_adapter_t *pAdapter, eMib_dot11DesiredBssType mibDot11DesiredBssType )
+{
+ pAdapter->hdd_mib.mibDot11DesiredBssType = mibDot11DesiredBssType;
+ return( VOS_STATUS_SUCCESS );
+}
+
+v_BOOL_t mibIsDot11DesiredBssTypeInfrastructure( hdd_adapter_t *pAdapter )
+{
+ eMib_dot11DesiredBssType mibDot11DesiredBssType;
+ mibGetDot11DesiredBssType( pAdapter, &mibDot11DesiredBssType );
+
+ return( eMib_dot11DesiredBssType_infrastructure == mibDot11DesiredBssType );
+}
+
+
+static inline v_BOOL_t mibIsDot11DesiredBssTypeIndependent( hdd_adapter_t *pAdapter )
+{
+ eMib_dot11DesiredBssType mibDot11DesiredBssType;
+ mibGetDot11DesiredBssType( pAdapter, &mibDot11DesiredBssType );
+
+ return( eMib_dot11DesiredBssType_independent == mibDot11DesiredBssType );
+}
+
+static inline v_VOID_t mibGetDot11IbssJoinOnly( hdd_adapter_t *pAdapter, v_BOOL_t *pdot11IbssJoinOnly )
+{
+ *pdot11IbssJoinOnly = pAdapter->hdd_mib.dot11IbssJoinOnly;
+ return;
+}
+
+static inline VOS_STATUS mibSetDot11IbssJoinOnly( hdd_adapter_t *pAdapter, v_BOOL_t dot11IbssJoinOnly )
+{
+ pAdapter->hdd_mib.dot11IbssJoinOnly = dot11IbssJoinOnly;
+ return( VOS_STATUS_SUCCESS );
+}
+
+static inline VOS_STATUS mibSetDot11NICPowerState( hdd_adapter_t *pAdapter, eMib_dot11NICPowerState *pMibDot11NICPowerState )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+
+ pAdapter->hdd_mib.mibDot11NICPowerState = *pMibDot11NICPowerState;
+
+ return( status );
+}
+
+static inline VOS_STATUS mibSetDot11NICPowerStateOff( hdd_adapter_t *pAdapter )
+{
+ eMib_dot11NICPowerState dot11NICPowerState = eMib_dot11NICPowerState_OFF;
+ return( mibSetDot11NICPowerState( pAdapter, &dot11NICPowerState ) );
+}
+
+static inline void mibGetDot11NICPowerState( hdd_adapter_t *pAdapter, eMib_dot11NICPowerState *pMibDot11NICPowerState )
+{
+ *pMibDot11NICPowerState = pAdapter->hdd_mib.mibDot11NICPowerState;
+
+ return;
+}
+
+static inline v_BOOL_t mibIsDot11NICPowerStateOn( hdd_adapter_t *pAdapter )
+{
+ eMib_dot11NICPowerState dot11NICPowerState;
+
+ mibGetDot11NICPowerState( pAdapter, &dot11NICPowerState );
+
+ return( eMib_dot11NICPowerState_ON == dot11NICPowerState );
+}
+
+static inline v_BOOL_t mibIsDot11NICPowerStateOff( hdd_adapter_t *pAdapter )
+{
+ return( !mibIsDot11NICPowerStateOn( pAdapter ) );
+}
+
+static inline VOS_STATUS mibSetDot11DesiredSsidList( hdd_adapter_t *pAdapter, sMib_dot11DesiredSsidList *pDot11DesiredSsidList )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+
+ if ( pDot11DesiredSsidList->cEntries > MIB_DOT11_DESIRED_SSID_LIST_MAX_COUNT )
+
+ pAdapter->hdd_mib.mibDot11DesiredSsidList = *pDot11DesiredSsidList ;
+
+ return( status );
+}
+
+static inline VOS_STATUS mibSetDot11DesiredBssidList( hdd_adapter_t *pAdapter, sMib_dot11DesiredBssidList *pDot11DesiredBssidList )
+{
+ pAdapter->hdd_mib.mibDot11DesiredBssidList = *pDot11DesiredBssidList;
+
+ return( VOS_STATUS_SUCCESS );
+}
+
+
+static inline v_VOID_t mibGetDot11DesiredBssidList( hdd_adapter_t *pAdapter, sMib_dot11DesiredBssidList *pMibDot11DesiredBssidList )
+{
+ *pMibDot11DesiredBssidList = pAdapter->hdd_mib.mibDot11DesiredBssidList;
+
+ return;
+}
+
+
+static inline v_VOID_t mibGetDot11DesiredSsidList( hdd_adapter_t *pAdapter, sMib_dot11DesiredSsidList *pMibDot11DesiredSsidList )
+{
+ *pMibDot11DesiredSsidList = pAdapter->hdd_mib.mibDot11DesiredSsidList;
+
+ return;
+}
+
+
+static inline VOS_STATUS mibSetDot11AutoConfigEnabled( hdd_adapter_t *pAdapter, eMib_dot11AutoConfigEnabled *pMibDot11AutoConfigEnabled )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+
+ pAdapter->hdd_mib.mibDot11AutoConfigEnabled = *pMibDot11AutoConfigEnabled;
+
+ return( status );
+}
+
+
+static inline v_VOID_t mibGetDot11AutoConfigEnabled( hdd_adapter_t *pAdapter, eMib_dot11AutoConfigEnabled *pMibDot11AutoConfigEnabled )
+{
+ *pMibDot11AutoConfigEnabled = pAdapter->hdd_mib.mibDot11AutoConfigEnabled;
+
+ return;
+}
+
+static inline VOS_STATUS mibSetDot11MacExcludeList( hdd_adapter_t *pAdapter, sMib_dot11MacExcludeList *pDot11MacExcludeList )
+{
+ pAdapter->hdd_mib.mibDot11MacExcludeList = *pDot11MacExcludeList;
+
+ return( VOS_STATUS_SUCCESS );
+}
+
+static inline VOS_STATUS mibGetDot11MacExcludeList( hdd_adapter_t *pAdapter, sMib_dot11MacExcludeList *pDot11MacExcludeList )
+{
+ *pDot11MacExcludeList = pAdapter->hdd_mib.mibDot11MacExcludeList;
+
+ return( VOS_STATUS_SUCCESS );
+}
+
+static inline void mibSetDefaultDot11MacExcludeList( hdd_adapter_t *pAdapter )
+{
+ pAdapter->hdd_mib.mibDot11MacExcludeList.cEntries = 0;
+}
+
+static inline VOS_STATUS mibSetDot11HardwarePHYState( hdd_adapter_t *pAdapter, eMib_dot11HardwarePHYState *pMibDot11HardwarePHYState )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+
+ pAdapter->hdd_mib.mibDot11HardwarePHYState = *pMibDot11HardwarePHYState;
+
+ return( status );
+}
+
+
+static inline void mibGetDot11HardwarePHYState( hdd_adapter_t *pAdapter, eMib_dot11HardwarePHYState *pMibDot11HardwarePHYState )
+{
+ *pMibDot11HardwarePHYState = pAdapter->hdd_mib.mibDot11HardwarePHYState;
+
+ return;
+}
+
+static inline void mibSetDefaultDot11PrivacyExemptionList( hdd_adapter_t *pAdapter )
+{
+ pAdapter->hdd_mib.mibDot11PrivacyExemptionList.cEntries = 0;
+}
+
+
+static inline void mibGetDot11PowerSavingLevel( hdd_adapter_t *pAdapter, eMib_dot11PowerSavingLevel *pMibDot11PowerSavingLevel )
+{
+ *pMibDot11PowerSavingLevel = pAdapter->hdd_mib.mibDot11PowerSavingLevel;
+
+ return;
+}
+
+
+static inline void mibGetDevicePowerState( hdd_adapter_t *pAdapter, eMib_DevicePowerState *pMibDevicePowerState )
+{
+ *pMibDevicePowerState = pAdapter->hdd_mib.mibDevicePowerState;
+
+ return;
+}
+
+
diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c
new file mode 100644
index 0000000..4ca922c
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_p2p.c
@@ -0,0 +1,1230 @@
+/*
+ * 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 wlan_hdd_p2p.c
+
+ \brief WLAN Host Device Driver implementation for P2P commands interface
+
+ Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
+
+ Qualcomm Confidential and Proprietary.
+
+ ========================================================================*/
+#ifdef CONFIG_CFG80211
+
+#include <wlan_hdd_includes.h>
+#include <wlan_hdd_hostapd.h>
+#include <net/cfg80211.h>
+#include "sme_Api.h"
+#include "wlan_hdd_p2p.h"
+#include "sapApi.h"
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <net/ieee80211_radiotap.h>
+
+extern struct net_device_ops net_ops_struct;
+
+static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
+ int rtap_len, int flag );
+
+static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
+ hdd_cfg80211_state_t* cfgState,
+ tANI_BOOLEAN actionSendSuccess );
+
+static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
+ tANI_U32 nFrameLength,
+ tANI_U8* pbFrames,
+ tANI_U8 frameType );
+
+#ifdef WLAN_FEATURE_P2P
+eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
+ eHalStatus status )
+{
+ hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+ hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
+
+ if( pRemainChanCtx == NULL )
+ {
+ hddLog( LOGW,
+ "%s: No Rem on channel pending for which Rsp is received", __func__);
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ hddLog( LOG1, "Received remain on channel rsp");
+
+ cfgState->remain_on_chan_ctx = NULL;
+
+ if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
+ {
+ if( cfgState->buf )
+ {
+ hddLog( LOGP,
+ "%s: We need to receive yet an ack from one of tx packet",
+ __func__);
+ }
+ cfg80211_remain_on_channel_expired( pRemainChanCtx->dev,
+ pRemainChanCtx->cookie,
+ &pRemainChanCtx->chan,
+ pRemainChanCtx->chan_type, GFP_KERNEL );
+ }
+
+ vos_mem_free( pRemainChanCtx );
+
+ if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
+ ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode )
+ )
+ {
+ tANI_U8 sessionId = pAdapter->sessionId;
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
+ {
+ if ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode )
+ sessionId = pAdapter->p2pSessionId;
+ }
+ sme_DeregisterMgmtFrame(
+ hHal, sessionId,
+ (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
+ NULL, 0 );
+ }
+ else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
+ ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
+ )
+ {
+ WLANSAP_DeRegisterMgmtFrame(
+ (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
+ NULL, 0 );
+ }
+
+ complete(&pAdapter->cancel_rem_on_chan_var);
+ return eHAL_STATUS_SUCCESS;
+}
+
+static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ unsigned int duration, u64 *cookie,
+ rem_on_channel_request_type_t request_type )
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ hdd_remain_on_chan_ctx_t *pRemainChanCtx;
+ hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+ int status = 0;
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
+ __func__,pAdapter->device_mode);
+
+ hddLog( LOG1,
+ "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d",
+ chan->hw_value, chan->center_freq, channel_type, duration );
+
+ if( cfgState->remain_on_chan_ctx != NULL)
+ {
+ /* Wait till remain on channel ready indication before issuing cancel
+ * remain on channel request, otherwise if remain on channel not
+ * received and if the driver issues cancel remain on channel then lim
+ * will be in unknown state.
+ */
+ status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
+ msecs_to_jiffies(WAIT_REM_CHAN_READY));
+ if (!status)
+ {
+ hddLog( LOGE,
+ "%s: timeout waiting for remain on channel ready indication",
+ __func__);
+ }
+
+ INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
+
+ /* Issue abort remain on chan request to sme.
+ * The remain on channel callback will make sure the remain_on_chan
+ * expired event is sent.
+ */
+ if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
+ ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode )
+ )
+ {
+ sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
+ pAdapter->sessionId );
+ }
+ else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
+ (WLAN_HDD_P2P_GO == pAdapter->device_mode)
+ )
+ {
+ WLANSAP_CancelRemainOnChannel(
+ (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
+ }
+
+ wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
+ msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
+ }
+
+ /* When P2P-GO and if we are trying to unload the driver then
+ * wlan driver is keep on receiving the remain on channel command
+ * and which is resulting in crash. So not allowing any remain on
+ * channel requets when Load/Unload is in progress*/
+ if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
+ {
+ hddLog( LOGE,
+ "%s: Wlan Load/Unload is in progress", __func__);
+ return -EBUSY;
+ }
+
+ pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
+ if( NULL == pRemainChanCtx )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Not able to allocate memory for Channel context",
+ __func__);
+ return -ENOMEM;
+ }
+
+ vos_mem_copy( &pRemainChanCtx->chan, chan,
+ sizeof(struct ieee80211_channel) );
+
+ pRemainChanCtx->chan_type = channel_type;
+ pRemainChanCtx->duration = duration;
+ pRemainChanCtx->dev = dev;
+ *cookie = (tANI_U32) pRemainChanCtx;
+ pRemainChanCtx->cookie = *cookie;
+ pRemainChanCtx->rem_on_chan_request = request_type;
+ cfgState->remain_on_chan_ctx = pRemainChanCtx;
+ cfgState->current_freq = chan->center_freq;
+
+ INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
+
+ //call sme API to start remain on channel.
+ if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
+ ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode )
+ )
+ {
+ tANI_U8 sessionId = pAdapter->sessionId;
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
+ {
+ if ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode )
+ sessionId = pAdapter->p2pSessionId;
+ }
+ //call sme API to start remain on channel.
+ sme_RemainOnChannel(
+ WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
+ chan->hw_value, duration,
+ wlan_hdd_remain_on_channel_callback, pAdapter );
+
+ sme_RegisterMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ sessionId, (SIR_MAC_MGMT_FRAME << 2) |
+ (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 );
+
+ }
+ else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
+ ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
+ )
+ {
+ //call sme API to start remain on channel.
+ if (eHAL_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
+ (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ chan->hw_value, duration,
+ wlan_hdd_remain_on_channel_callback, pAdapter ))
+
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WLANSAP_RemainOnChannel returned fail", __func__);
+ cfgState->remain_on_chan_ctx = NULL;
+ vos_mem_free (pRemainChanCtx);
+ return -EINVAL;
+ }
+
+
+ if (eHAL_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
+ (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
+ NULL, 0 ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
+ WLANSAP_CancelRemainOnChannel(
+ (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
+ return -EINVAL;
+ }
+
+ }
+ return 0;
+
+}
+
+int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ unsigned int duration, u64 *cookie )
+{
+ return wlan_hdd_request_remain_on_channel(wiphy, dev,
+ chan, channel_type, duration, cookie,
+ REMAIN_ON_CHANNEL_REQUEST);
+}
+
+void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
+{
+ hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+ hdd_remain_on_chan_ctx_t* pRemainChanCtx = cfgState->remain_on_chan_ctx;
+
+ hddLog( LOG1, "Ready on chan ind");
+
+ if( pRemainChanCtx != NULL )
+ {
+ if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
+ {
+ cfg80211_ready_on_channel( pAdapter->dev, (tANI_U32)pRemainChanCtx,
+ &pRemainChanCtx->chan, pRemainChanCtx->chan_type,
+ pRemainChanCtx->duration, GFP_KERNEL );
+ }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request )
+ {
+ complete(&pAdapter->offchannel_tx_event);
+ }
+#endif
+ complete(&pAdapter->rem_on_chan_ready_event);
+ }
+ else
+ {
+ hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
+ }
+ return;
+}
+
+int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
+ struct net_device *dev, u64 cookie )
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+ int status = 0;
+
+ hddLog( LOG1, "Cancel remain on channel req");
+
+ /* FIXME cancel currently running remain on chan.
+ * Need to check cookie and cancel accordingly
+ */
+ if( (cfgState->remain_on_chan_ctx == NULL) ||
+ (cfgState->remain_on_chan_ctx->cookie != cookie) )
+ {
+ hddLog( LOGE,
+ "%s: No Remain on channel pending with specified cookie value",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* wait until remain on channel ready event received
+ * for already issued remain on channel request */
+ status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
+ msecs_to_jiffies(WAIT_REM_CHAN_READY));
+ if (!status)
+ {
+ hddLog( LOGE,
+ "%s: timeout waiting for remain on channel ready indication",
+ __func__);
+ }
+ INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
+ /* Issue abort remain on chan request to sme.
+ * The remain on channel callback will make sure the remain_on_chan
+ * expired event is sent.
+ */
+ if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
+ ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode )
+ )
+ {
+ tANI_U8 sessionId = pAdapter->sessionId;
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
+ {
+ if ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode )
+ sessionId = pAdapter->p2pSessionId;
+ }
+ sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
+ sessionId );
+ }
+ else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
+ (WLAN_HDD_P2P_GO == pAdapter->device_mode)
+ )
+ {
+ WLANSAP_CancelRemainOnChannel(
+ (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
+ __func__, pAdapter->device_mode);
+ return -EIO;
+ }
+ wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
+ msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
+ return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan, bool offchan,
+ enum nl80211_channel_type channel_type,
+ bool channel_type_valid, unsigned int wait,
+ const u8 *buf, size_t len, bool no_cck,
+ bool dont_wait_for_ack, u64 *cookie )
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan, bool offchan,
+ enum nl80211_channel_type channel_type,
+ bool channel_type_valid, unsigned int wait,
+ const u8 *buf, size_t len, u64 *cookie )
+#else
+int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ bool channel_type_valid,
+ const u8 *buf, size_t len, u64 *cookie )
+#endif //LINUX_VERSION_CODE
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
+ hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ hdd_adapter_t *goAdapter;
+#endif
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
+ __func__,pAdapter->device_mode);
+
+ //Call sme API to send out a action frame.
+ // OR can we send it directly through data path??
+ // After tx completion send tx status back.
+ if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
+ ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
+ )
+ {
+ tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
+ tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
+ if (type == SIR_MAC_MGMT_FRAME)
+ {
+ if (subType == SIR_MAC_MGMT_PROBE_RSP)
+ {
+ /* Drop Probe response recieved from supplicant, as for GO and
+ SAP PE itself sends probe response
+ */
+ goto err_rem_channel;
+ }
+ else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
+ (subType == SIR_MAC_MGMT_DEAUTH))
+ {
+ /* Deauth/Disassoc received from supplicant, If we simply
+ * transmit the frame over air, driver doesn't come to know
+ * about the deauth/disassoc. Because of this reason the
+ * supplicant and driver will be out of sync.
+ * Drop the frame here and initiate the disassoc procedure
+ * from driver, the core stack will take care of sending
+ * disassoc frame and indicating corresponding events to supplicant.
+ */
+ tANI_U8 dstMac[ETH_ALEN] = {0};
+ memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: Deauth/Disassoc received for STA:"
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ __func__,
+ dstMac[0], dstMac[1], dstMac[2],
+ dstMac[3], dstMac[4], dstMac[5]);
+ hdd_softap_sta_disassoc(pAdapter, (v_U8_t *)&dstMac);
+ goto err_rem_channel;
+ }
+ }
+ }
+
+ if( NULL != cfgState->buf )
+ return -EBUSY;
+
+ hddLog( LOG1, "Action frame tx request");
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
+
+ //If GO adapter exists and operating on same frequency
+ //then we will not request remain on channel
+ if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
+ == goAdapter->sessionCtx.ap.operatingChannel ) )
+ {
+ goto send_frame;
+ }
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ if( offchan && wait)
+ {
+ int status;
+
+ // In case of P2P Client mode if we are already
+ // on the same channel then send the frame directly
+
+ if((cfgState->remain_on_chan_ctx != NULL) &&
+ (cfgState->current_freq == chan->center_freq)
+ )
+ {
+ goto send_frame;
+ }
+
+ INIT_COMPLETION(pAdapter->offchannel_tx_event);
+
+ status = wlan_hdd_request_remain_on_channel(wiphy, dev,
+ chan, channel_type, wait, cookie,
+ OFF_CHANNEL_ACTION_TX);
+
+ if(0 != status)
+ {
+ if( (-EBUSY == status) &&
+ (cfgState->current_freq == chan->center_freq) )
+ {
+ goto send_frame;
+ }
+ goto err_rem_channel;
+ }
+
+ /* Wait for driver to be ready on the requested channel */
+ status = wait_for_completion_interruptible_timeout(
+ &pAdapter->offchannel_tx_event,
+ msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
+ if(!status)
+ {
+ hddLog( LOGE, "Not able to complete remain on channel request"
+ " within timeout period");
+ goto err_rem_channel;
+ }
+ }
+ else if ( offchan )
+ {
+ /* Check before sending action frame
+ whether we already remain on channel */
+ if(NULL == cfgState->remain_on_chan_ctx)
+ {
+ goto err_rem_channel;
+ }
+ }
+ send_frame:
+#endif
+
+ cfgState->buf = vos_mem_malloc( len ); //buf;
+ if( cfgState->buf == NULL )
+ return -ENOMEM;
+
+ cfgState->len = len;
+
+ vos_mem_copy( cfgState->buf, buf, len);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ if( cfgState->remain_on_chan_ctx )
+ {
+ cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
+ *cookie = cfgState->action_cookie;
+ }
+ else
+ {
+#endif
+ *cookie = (tANI_U32) cfgState->buf;
+ cfgState->action_cookie = *cookie;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ }
+#endif
+
+ if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
+ (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
+ )
+ {
+ tANI_U8 sessionId = pAdapter->sessionId;
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
+ {
+ if ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode )
+ {
+ sessionId = pAdapter->p2pSessionId;
+ vos_mem_copy((void*) (&buf[10]),
+ (void*) (&pHddCtx->p2pDeviceAddress.bytes[0]),
+ sizeof(tSirMacAddr));
+ }
+ }
+ if (eHAL_STATUS_SUCCESS !=
+ sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ sessionId, buf, len) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_sendAction returned fail", __func__);
+ goto err;
+ }
+ }
+ else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
+ ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
+ )
+ {
+ if( eHAL_STATUS_SUCCESS !=
+ WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ buf, len ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WLANSAP_SendAction returned fail", __func__);
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ hdd_sendActionCnf( pAdapter, FALSE );
+ return 0;
+err_rem_channel:
+ *cookie = (tANI_U32)cfgState;
+ cfg80211_mgmt_tx_status( pAdapter->dev, *cookie, buf, len, FALSE, GFP_KERNEL );
+ return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
+ struct net_device *dev,
+ u64 cookie)
+{
+ return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
+}
+#endif
+
+void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
+{
+ hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+
+ hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
+ if( NULL == cfgState->buf )
+ {
+ VOS_ASSERT( cfgState->buf );
+ return;
+ }
+
+ /* If skb is NULL it means this packet was received on CFG80211 interface
+ * else it was received on Monitor interface */
+ if( cfgState->skb == NULL )
+ {
+ /*
+ * buf is the same pointer it passed us to send. Since we are sending
+ * it through control path, we use different buffers.
+ * In case of mac80211, they just push it to the skb and pass the same
+ * data while sending tx ack status.
+ * */
+ cfg80211_mgmt_tx_status( pAdapter->dev, cfgState->action_cookie,
+ cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
+ vos_mem_free( cfgState->buf );
+ cfgState->buf = NULL;
+ }
+ else
+ {
+ hdd_adapter_t* pMonAdapter =
+ hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
+ if( pMonAdapter == NULL )
+ {
+ hddLog( LOGE, "Not able to get Monitor Adapter");
+ cfgState->skb = NULL;
+ vos_mem_free( cfgState->buf );
+ cfgState->buf = NULL;
+ complete(&pAdapter->tx_action_cnf_event);
+ return;
+ }
+ /* Send TX completion feedback over monitor interface. */
+ hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
+ cfgState->skb = NULL;
+ vos_mem_free( cfgState->buf );
+ cfgState->buf = NULL;
+ /* Look for the next Mgmt packet to TX */
+ hdd_mon_tx_mgmt_pkt(pAdapter);
+ }
+ complete(&pAdapter->tx_action_cnf_event);
+}
+
+/**
+ * hdd_setP2pNoa
+ *
+ *FUNCTION:
+ * This function is called from hdd_hostapd_ioctl function when Driver
+ * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
+ *
+ *LOGIC:
+ * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
+ *
+ *ASSUMPTIONS:
+ *
+ *
+ *NOTE:
+ *
+ * @param dev Pointer to net device structure
+ * @param command Pointer to command
+ *
+ * @return Status
+ */
+
+int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tP2pPsConfig NoA;
+ int count, duration, interval;
+ char *param;
+
+ param = strchr(command, ' ');
+ if (param == NULL)
+ return -1;
+ param++;
+ sscanf(param, "%d %d %d", &count, &duration, &interval);
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d \n",
+ __func__, count, duration, interval);
+
+ /* PS Selection
+ * Periodic NoA (2)
+ * Single NOA (4)
+ */
+ NoA.opp_ps = 0;
+ NoA.ctWindow = 0;
+ if (count == 1)
+ {
+ NoA.duration = 0;
+ NoA.single_noa_duration = duration;
+ NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
+ }
+ else
+ {
+ NoA.duration = duration;
+ NoA.single_noa_duration = 0;
+ NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
+ }
+ NoA.interval = interval;
+ NoA.count = count;
+ NoA.sessionid = pAdapter->sessionId;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
+ "interval %d count %d single noa duration %d "
+ "PsSelection %x \n", __func__, NoA.opp_ps,
+ NoA.ctWindow, NoA.duration, NoA.interval,
+ NoA.count, NoA.single_noa_duration,
+ NoA.psSelection);
+
+ sme_p2pSetPs(hHal, &NoA);
+ return status;
+}
+
+/**
+ * hdd_setP2pOpps
+ *
+ *FUNCTION:
+ * This function is called from hdd_hostapd_ioctl function when Driver
+ * get P2P_SET_PS comand from wpa_supplicant using private ioctl
+ *
+ *LOGIC:
+ * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
+ *
+ *ASSUMPTIONS:
+ *
+ *
+ *NOTE:
+ *
+ * @param dev Pointer to net device structure
+ * @param command Pointer to command
+ *
+ * @return Status
+ */
+
+int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tP2pPsConfig NoA;
+ char *param;
+ int legacy_ps, opp_ps, ctwindow;
+
+ param = strchr(command, ' ');
+ if (param == NULL)
+ return -1;
+ param++;
+ sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
+ VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d \n",
+ __func__, legacy_ps, opp_ps, ctwindow);
+
+ /* PS Selection
+ * Opportunistic Power Save (1)
+ */
+
+ /* From wpa_cli user need to use separate command to set ctWindow and Opps
+ * When user want to set ctWindow during that time other parameters
+ * values are coming from wpa_supplicant as -1.
+ * Example : User want to set ctWindow with 30 then wpa_cli command :
+ * P2P_SET ctwindow 30
+ * Command Received at hdd_hostapd_ioctl is as below:
+ * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
+ */
+ if (ctwindow != -1)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Opportunistic Power Save is %s \n",
+ (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
+
+ if (ctwindow != pAdapter->ctw)
+ {
+ pAdapter->ctw = ctwindow;
+
+ if(pAdapter->ops)
+ {
+ NoA.opp_ps = pAdapter->ops;
+ NoA.ctWindow = pAdapter->ctw;
+ NoA.duration = 0;
+ NoA.single_noa_duration = 0;
+ NoA.interval = 0;
+ NoA.count = 0;
+ NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
+ NoA.sessionid = pAdapter->sessionId;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
+ "interval %d count %d single noa duration %d "
+ "PsSelection %x \n", __func__, NoA.opp_ps,
+ NoA.ctWindow, NoA.duration, NoA.interval,
+ NoA.count, NoA.single_noa_duration,
+ NoA.psSelection);
+
+ sme_p2pSetPs(hHal, &NoA);
+ }
+ return 0;
+ }
+ }
+
+ if (opp_ps != -1)
+ {
+ pAdapter->ops = opp_ps;
+
+ if ((opp_ps != -1) && (pAdapter->ctw))
+ {
+ NoA.opp_ps = opp_ps;
+ NoA.ctWindow = pAdapter->ctw;
+ NoA.duration = 0;
+ NoA.single_noa_duration = 0;
+ NoA.interval = 0;
+ NoA.count = 0;
+ NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
+ NoA.sessionid = pAdapter->sessionId;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
+ "interval %d count %d single noa duration %d "
+ "PsSelection %x \n", __func__, NoA.opp_ps,
+ NoA.ctWindow, NoA.duration, NoA.interval,
+ NoA.count, NoA.single_noa_duration,
+ NoA.psSelection);
+
+ sme_p2pSetPs(hHal, &NoA);
+ }
+ }
+ return status;
+}
+
+int hdd_setP2pPs( struct net_device *dev, void *msgData )
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tP2pPsConfig NoA;
+ p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
+
+ NoA.opp_ps = pappNoA->opp_ps;
+ NoA.ctWindow = pappNoA->ctWindow;
+ NoA.duration = pappNoA->duration;
+ NoA.interval = pappNoA->interval;
+ NoA.count = pappNoA->count;
+ NoA.single_noa_duration = pappNoA->single_noa_duration;
+ NoA.psSelection = pappNoA->psSelection;
+ NoA.sessionid = pAdapter->sessionId;
+
+ sme_p2pSetPs(hHal, &NoA);
+ return status;
+}
+#endif
+
+static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
+{
+ tANI_U8 sessionType;
+
+ switch( type )
+ {
+ case NL80211_IFTYPE_AP:
+ sessionType = WLAN_HDD_SOFTAP;
+ break;
+ case NL80211_IFTYPE_P2P_GO:
+ sessionType = WLAN_HDD_P2P_GO;
+ break;
+ case NL80211_IFTYPE_P2P_CLIENT:
+ sessionType = WLAN_HDD_P2P_CLIENT;
+ break;
+ case NL80211_IFTYPE_STATION:
+ sessionType = WLAN_HDD_INFRA_STATION;
+ break;
+ case NL80211_IFTYPE_MONITOR:
+ sessionType = WLAN_HDD_MONITOR;
+ break;
+ default:
+ sessionType = WLAN_HDD_INFRA_STATION;
+ break;
+ }
+
+ return sessionType;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+struct net_device* wlan_hdd_add_virtual_intf(
+ struct wiphy *wiphy, char *name, enum nl80211_iftype type,
+ u32 *flags, struct vif_params *params )
+#else
+int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
+ enum nl80211_iftype type,
+ u32 *flags, struct vif_params *params )
+#endif
+{
+ hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
+ hdd_adapter_t* pAdapter = NULL;
+
+ ENTER();
+
+ if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
+ {
+ if( (NL80211_IFTYPE_P2P_GO == type) ||
+ (NL80211_IFTYPE_P2P_CLIENT == type) )
+ {
+ /* Generate the P2P Interface Address. this address must be
+ * different from the P2P Device Address.
+ */
+ v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
+ p2pDeviceAddress.bytes[4] ^= 0x80;
+ pAdapter = hdd_open_adapter( pHddCtx,
+ wlan_hdd_get_session_type(type),
+ name, p2pDeviceAddress.bytes,
+ VOS_TRUE );
+ }
+ }
+ else
+ {
+ pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
+ name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
+ }
+
+ if( NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ return NULL;
+#else
+ return -EINVAL;
+#endif
+ }
+ EXIT();
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ return pAdapter->dev;
+#else
+ return 0;
+#endif
+}
+
+int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
+{
+ hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
+ hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ ENTER();
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
+ __func__,pVirtAdapter->device_mode);
+
+ wlan_hdd_release_intf_addr( pHddCtx,
+ pVirtAdapter->macAddressCurrent.bytes );
+
+ hdd_stop_adapter( pHddCtx, pVirtAdapter );
+ hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
+ EXIT();
+ return 0;
+}
+
+void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
+ tANI_U32 nFrameLength, tANI_U8* pbFrames,
+ tANI_U8 frameType )
+{
+ //Indicate a Frame over Monitor Intf.
+ int rxstat;
+ struct sk_buff *skb = NULL;
+ int needed_headroom = 0;
+ int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
+ HDD_RX_FLAG_MMIC_STRIPPED;
+
+ hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
+
+ VOS_ASSERT( (pbFrames != NULL) );
+
+ /* room for the radiotap header based on driver features
+ * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
+ * RX flags.
+ * */
+ needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
+
+ //alloc skb here
+ skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
+ if (unlikely(NULL == skb))
+ {
+ hddLog( LOGW, FL("Unable to allocate skb"));
+ return;
+ }
+ skb_reserve(skb, VPKT_SIZE_BUFFER);
+ if (unlikely(skb_headroom(skb) < nFrameLength))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "HDD [%d]: Insufficient headroom, "
+ "head[%p], data[%p], req[%d]",
+ __LINE__, skb->head, skb->data, nFrameLength);
+ kfree_skb(skb);
+ return ;
+ }
+ // actually push the data
+ memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
+ /* prepend radiotap information */
+ if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
+ {
+ hddLog( LOGE, FL("Not Able Add Radio Tap"));
+ //free skb
+ kfree_skb(skb);
+ return ;
+ }
+
+ skb_reset_mac_header( skb );
+ skb->dev = pMonAdapter->dev;
+ skb->protocol = eth_type_trans( skb, skb->dev );
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ rxstat = netif_rx_ni(skb);
+ if( NET_RX_SUCCESS == rxstat )
+ {
+ hddLog( LOG1, FL("Success"));
+ }
+ else
+ hddLog( LOGE, FL("Failed %d"), rxstat);
+
+ return ;
+}
+
+void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
+ tANI_U32 nFrameLength,
+ tANI_U8* pbFrames,
+ tANI_U8 frameType,
+ tANI_U32 rxChan )
+{
+ tANI_U16 freq;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d\n",
+ __func__, frameType, nFrameLength);
+
+ if (NULL == pAdapter)
+ {
+ hddLog( LOGE, FL("pAdapter is NULL"));
+ return;
+ }
+
+ if (NULL == pAdapter->dev)
+ {
+ hddLog( LOGE, FL("pAdapter->dev is NULL"));
+ return;
+ }
+
+ if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
+ {
+ hddLog( LOGE, FL("pAdapter has invalid magic"));
+ return;
+ }
+
+ if( !nFrameLength )
+ {
+ hddLog( LOGE, FL("Frame Length is Invalid ZERO"));
+ return;
+ }
+
+ if( ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
+ || ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
+ )
+ {
+ hdd_adapter_t *pMonAdapter =
+ hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
+
+ if( NULL != pMonAdapter )
+ {
+ hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
+ hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
+ pbFrames, frameType);
+ return;
+ }
+ }
+
+ //Channel indicated may be wrong. TODO
+ //Indicate an action frame.
+ if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
+ {
+ freq = ieee80211_channel_to_frequency( rxChan,
+ IEEE80211_BAND_2GHZ);
+ }
+ else
+ {
+ freq = ieee80211_channel_to_frequency( rxChan,
+ IEEE80211_BAND_5GHZ);
+ }
+
+ //Indicate Frame Over Normal Interface
+ hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
+ cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
+ pbFrames, nFrameLength,
+ GFP_ATOMIC );
+#else
+ cfg80211_rx_mgmt( pAdapter->dev, freq,
+ pbFrames, nFrameLength,
+ GFP_ATOMIC );
+#endif //LINUX_VERSION_CODE
+}
+
+/*
+ * ieee80211_add_rx_radiotap_header - add radiotap header
+ */
+static int hdd_wlan_add_rx_radiotap_hdr (
+ struct sk_buff *skb, int rtap_len, int flag )
+{
+ u8 rtap_temp[20] = {0};
+ struct ieee80211_radiotap_header *rthdr;
+ unsigned char *pos;
+ u16 rx_flags = 0;
+
+ rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
+
+ /* radiotap header, set always present flags */
+ rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
+ (1 << IEEE80211_RADIOTAP_RX_FLAGS));
+ rthdr->it_len = cpu_to_le16(rtap_len);
+
+ pos = (unsigned char *) (rthdr + 1);
+
+ /* the order of the following fields is important */
+
+ /* IEEE80211_RADIOTAP_FLAGS */
+ *pos = 0;
+ pos++;
+
+ /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
+ /* ensure 2 byte alignment for the 2 byte field as required */
+ if ((pos - (u8 *)rthdr) & 1)
+ pos++;
+ put_unaligned_le16(rx_flags, pos);
+ pos += 2;
+
+ // actually push the data
+ memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
+
+ return 0;
+}
+
+static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
+ hdd_cfg80211_state_t* cfgState,
+ tANI_BOOLEAN actionSendSuccess )
+{
+ struct ieee80211_radiotap_header *rthdr;
+ unsigned char *pos;
+ struct sk_buff *skb = cfgState->skb;
+
+ /* 2 Byte for TX flags and 1 Byte for Retry count */
+ u32 rtHdrLen = sizeof(*rthdr) + 3;
+
+ u8 *data;
+
+ /* We have to return skb with Data starting with MAC header. We have
+ * copied SKB data starting with MAC header to cfgState->buf. We will pull
+ * entire skb->len from skb and then we will push cfgState->buf to skb
+ * */
+ if( NULL == skb_pull(skb, skb->len) )
+ {
+ hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
+ kfree_skb(cfgState->skb);
+ return;
+ }
+
+ data = skb_push( skb, cfgState->len );
+
+ if (data == NULL)
+ {
+ hddLog( LOGE, FL("Not Able to Push %d byte to skb"), cfgState->len);
+ kfree_skb( cfgState->skb );
+ return;
+ }
+
+ memcpy( data, cfgState->buf, cfgState->len );
+
+ /* send frame to monitor interfaces now */
+ if( skb_headroom(skb) < rtHdrLen )
+ {
+ hddLog( LOGE, FL("No headroom for rtap header"));
+ kfree_skb(cfgState->skb);
+ return;
+ }
+
+ rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
+
+ memset( rthdr, 0, rtHdrLen );
+ rthdr->it_len = cpu_to_le16( rtHdrLen );
+ rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
+ (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
+ );
+
+ pos = (unsigned char *)( rthdr+1 );
+
+ // Fill TX flags
+ *pos = actionSendSuccess;
+ pos += 2;
+
+ // Fill retry count
+ *pos = 0;
+ pos++;
+
+ skb_set_mac_header( skb, 0 );
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = htons(ETH_P_802_2);
+ memset( skb->cb, 0, sizeof( skb->cb ) );
+ if (in_interrupt())
+ netif_rx( skb );
+ else
+ netif_rx_ni( skb );
+
+ /* Enable Queues which we have disabled earlier */
+ netif_tx_start_all_queues( pAdapter->dev );
+
+}
+#endif // CONFIG_CFG80211
diff --git a/CORE/HDD/src/wlan_hdd_scan.c b/CORE/HDD/src/wlan_hdd_scan.c
new file mode 100644
index 0000000..ed13968
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_scan.c
@@ -0,0 +1,1154 @@
+/*
+ * 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 wlan_hdd_scan.c
+
+ \brief WLAN Host Device Driver implementation
+
+ 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.
+
+
+ $Header:$ $DateTime: $ $Author: $
+
+
+ when who what, where, why
+ -------- --- --------------------------------------------------------
+ 04/5/09 Shailender Created module.
+
+ ==========================================================================*/
+ /* To extract the Scan results */
+
+/* Add a stream event */
+
+#include <wlan_qct_driver.h>
+#include <wlan_hdd_includes.h>
+#include <vos_api.h>
+#include <palTypes.h>
+#include <aniGlobal.h>
+#include <dot11f.h>
+#ifdef WLAN_BTAMP_FEATURE
+#include "bap_hdd_misc.h"
+#endif
+
+#ifdef CONFIG_CFG80211
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+#endif
+
+#define GET_IE_LEN_IN_BSS(lenInBss) ( lenInBss + sizeof(lenInBss) - \
+ ((int) OFFSET_OF( tSirBssDescription, ieFields)))
+
+#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
+#define WEXT_CSCAN_HEADER_SIZE 12
+#define WEXT_CSCAN_SSID_SECTION 'S'
+#define WEXT_CSCAN_CHANNEL_SECTION 'C'
+#define WEXT_CSCAN_NPROBE_SECTION 'N'
+#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
+#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
+#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
+#define WEXT_CSCAN_TYPE_SECTION 'T'
+#define WEXT_CSCAN_PENDING_SECTION 'O'
+#define WEXT_CSCAN_TYPE_DEFAULT 0
+#define WEXT_CSCAN_TYPE_PASSIVE 1
+#define WEXT_CSCAN_PASV_DWELL_TIME 130
+#define WEXT_CSCAN_PASV_DWELL_TIME_DEF 250
+#define WEXT_CSCAN_PASV_DWELL_TIME_MAX 3000
+#define WEXT_CSCAN_HOME_DWELL_TIME 130
+#define MAX_RATES 12
+
+#define WEXT_CSCAN_SCAN_DONE_WAIT_TIME 2000
+
+typedef struct hdd_scan_info{
+ struct net_device *dev;
+ struct iw_request_info *info;
+ char *start;
+ char *end;
+} hdd_scan_info_t, *hdd_scan_info_tp;
+
+static v_S31_t hdd_TranslateABGRateToMbpsRate(v_U8_t *pFcRate)
+{
+
+ /** Slightly more sophisticated processing has to take place here.
+ Basic rates are rounded DOWN. HT rates are rounded UP.*/
+ return ( (( ((v_S31_t) *pFcRate) & 0x007f) * 1000000) / 2);
+}
+
+
+static eHalStatus hdd_AddIwStreamEvent(int cmd, int length, char* data, hdd_scan_info_t *pscanInfo, char **last_event, char **current_event )
+{
+ struct iw_event event;
+
+ *last_event = *current_event;
+ vos_mem_zero(&event, sizeof (struct iw_event));
+ event.cmd = cmd;
+ event.u.data.flags = 1;
+ event.u.data.length = length;
+ *current_event = iwe_stream_add_point (pscanInfo->info,*current_event, pscanInfo->end, &event, data);
+
+ if(*last_event == *current_event)
+ {
+ /* no space to add event */
+ return -E2BIG; /* Error code, may be E2BIG */
+ }
+
+ return 0;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_GetWPARSNIEs() -
+
+ This function extract the WPA/RSN IE from the Bss descriptor IEs fields
+
+ \param - ieFields - Pointer to the Bss Descriptor IEs.
+ - ie_length - IE Length.
+ - last_event -Points to the last event.
+ - current_event - Points to the
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+
+/* Extract the WPA and/or RSN IEs */
+static eHalStatus hdd_GetWPARSNIEs( v_U8_t *ieFields, v_U16_t ie_length, char **last_event, char **current_event, hdd_scan_info_t *pscanInfo )
+{
+ v_U8_t eid, elen, *element;
+ v_U16_t tie_length=0;
+
+ ENTER();
+
+ element = ieFields;
+ tie_length = ie_length;
+
+ while( tie_length > 2 && element != NULL )
+ {
+ eid = element[0];
+ elen = element[1];
+
+ /*If element length is greater than total remaining ie length,
+ *break the loop*/
+ if ((elen+2) > tie_length)
+ break;
+
+ switch(eid)
+ {
+ case DOT11F_EID_WPA:
+ case DOT11F_EID_RSN:
+#ifdef FEATURE_WLAN_WAPI
+ case DOT11F_EID_WAPI:
+#endif
+ if(hdd_AddIwStreamEvent( IWEVGENIE, elen+2, (char*)element, pscanInfo, last_event, current_event ) < 0 )
+ return -E2BIG;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Next element */
+ tie_length -= (2 + elen);
+ element += 2 + elen;
+ }
+
+ return 0;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_IndicateScanResult() -
+
+ This function returns the scan results to the wpa_supplicant
+
+ \param - scanInfo - Pointer to the scan info structure.
+ - descriptor - Pointer to the Bss Descriptor.
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+#define MAX_CUSTOM_LEN 64
+static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResultInfo *scan_result)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(scanInfo->dev) ;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ tSirBssDescription *descriptor = &scan_result->BssDescriptor;
+ struct iw_event event;
+ char *current_event = scanInfo->start;
+ char *end = scanInfo->end;
+ char *last_event;
+ char *current_pad;
+ v_U16_t ie_length = 0;
+ v_U16_t capabilityInfo;
+ char *modestr;
+ int error;
+ char custom[MAX_CUSTOM_LEN];
+ char *p;
+
+ hddLog( LOG1, "hdd_IndicateScanResult %02x:%02x:%02x:%02x:%02x:%02x",
+ descriptor->bssId[0],
+ descriptor->bssId[1],
+ descriptor->bssId[2],
+ descriptor->bssId[3],
+ descriptor->bssId[4],
+ descriptor->bssId[5]);
+
+ error = 0;
+ last_event = current_event;
+ vos_mem_zero(&event, sizeof (event));
+
+ /* BSSID */
+ event.cmd = SIOCGIWAP;
+ event.u.ap_addr.sa_family = ARPHRD_ETHER;
+ vos_mem_copy (event.u.ap_addr.sa_data, descriptor->bssId,
+ sizeof (descriptor->bssId));
+ current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
+ &event, IW_EV_ADDR_LEN);
+
+ if (last_event == current_event)
+ {
+ /* no space to add event */
+ /* Error code may be E2BIG */
+ hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWAP ");
+ return -E2BIG;
+ }
+
+ last_event = current_event;
+ vos_mem_zero(&event, sizeof (struct iw_event));
+
+ /* Protocol Name */
+ event.cmd = SIOCGIWNAME;
+
+ switch (descriptor->nwType)
+ {
+ case eSIR_11A_NW_TYPE:
+ modestr = "a";
+ break;
+ case eSIR_11B_NW_TYPE:
+ modestr = "b";
+ break;
+ case eSIR_11G_NW_TYPE:
+ modestr = "g";
+ break;
+ case eSIR_11N_NW_TYPE:
+ modestr = "n";
+ break;
+ default:
+ hddLog( LOGW, "%s: Unknown network type [%d]",
+ __FUNCTION__, descriptor->nwType);
+ modestr = "?";
+ break;
+ }
+ snprintf(event.u.name, IFNAMSIZ, "IEEE 802.11%s", modestr);
+ current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
+ &event, IW_EV_CHAR_LEN);
+
+ if (last_event == current_event)
+ { /* no space to add event */
+ hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWNAME");
+ /* Error code, may be E2BIG */
+ return -E2BIG;
+ }
+
+ last_event = current_event;
+ vos_mem_zero( &event, sizeof (struct iw_event));
+
+ /*Freq*/
+ event.cmd = SIOCGIWFREQ;
+
+ event.u.freq.m = descriptor->channelId;
+ event.u.freq.e = 0;
+ event.u.freq.i = 0;
+ current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
+ &event, IW_EV_FREQ_LEN);
+
+ if (last_event == current_event)
+ { /* no space to add event */
+ return -E2BIG;
+ }
+
+ last_event = current_event;
+ vos_mem_zero( &event, sizeof (struct iw_event));
+
+ /* BSS Mode */
+ event.cmd = SIOCGIWMODE;
+
+ capabilityInfo = descriptor->capabilityInfo;
+
+ if (SIR_MAC_GET_ESS(capabilityInfo))
+ {
+ event.u.mode = IW_MODE_INFRA;
+ }
+ else if (SIR_MAC_GET_IBSS(capabilityInfo))
+ {
+ event.u.mode = IW_MODE_ADHOC;
+ }
+ else
+ {
+ /* neither ESS or IBSS */
+ event.u.mode = IW_MODE_AUTO;
+ }
+
+ current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
+ &event, IW_EV_UINT_LEN);
+
+ if (last_event == current_event)
+ { /* no space to add event */
+ hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWMODE");
+ return -E2BIG;
+ }
+ /* To extract SSID */
+ ie_length = GET_IE_LEN_IN_BSS( descriptor->length );
+
+ if (ie_length > 0)
+ {
+ tDot11fBeaconIEs dot11BeaconIEs;
+ tDot11fIESSID *pDot11SSID;
+ tDot11fIESuppRates *pDot11SuppRates;
+ tDot11fIEExtSuppRates *pDot11ExtSuppRates;
+ tDot11fIEHTCaps *pDot11IEHTCaps;
+ int numBasicRates = 0;
+ int maxNumRates = 0;
+
+ pDot11IEHTCaps = NULL;
+
+ dot11fUnpackBeaconIEs ((tpAniSirGlobal)
+ hHal, (tANI_U8 *) descriptor->ieFields, ie_length, &dot11BeaconIEs);
+
+ pDot11SSID = &dot11BeaconIEs.SSID;
+
+
+ if (pDot11SSID->present ) {
+ last_event = current_event;
+ vos_mem_zero (&event, sizeof (struct iw_event));
+
+ event.cmd = SIOCGIWESSID;
+ event.u.data.flags = 1;
+ event.u.data.length = scan_result->ssId.length;
+ current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
+ &event, (char *)scan_result->ssId.ssId);
+
+ if(last_event == current_event)
+ { /* no space to add event */
+ hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
+ return -E2BIG;
+ }
+ }
+
+ if( hdd_GetWPARSNIEs( ( tANI_U8 *) descriptor->ieFields, ie_length, &last_event, ¤t_event, scanInfo ) < 0 )
+ {
+ hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
+ return -E2BIG;
+ }
+
+ last_event = current_event;
+ current_pad = current_event + IW_EV_LCP_LEN;
+ vos_mem_zero( &event, sizeof (struct iw_event));
+
+ /*Rates*/
+ event.cmd = SIOCGIWRATE;
+
+
+ pDot11SuppRates = &dot11BeaconIEs.SuppRates;
+
+ if (pDot11SuppRates->present )
+ {
+ int i;
+
+ numBasicRates = pDot11SuppRates->num_rates;;
+ for (i=0; i<pDot11SuppRates->num_rates; i++)
+ {
+ if (0 != (pDot11SuppRates->rates[i] & 0x7F))
+ {
+ event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
+ &pDot11SuppRates->rates[i]);
+
+ current_pad = iwe_stream_add_value (scanInfo->info,current_event,
+ current_pad, end, &event, IW_EV_PARAM_LEN);
+ }
+ }
+
+ }
+
+ pDot11ExtSuppRates = &dot11BeaconIEs.ExtSuppRates;
+
+ if (pDot11ExtSuppRates->present )
+ {
+ int i,no_of_rates;
+ maxNumRates = numBasicRates + pDot11ExtSuppRates->num_rates;
+
+ /* Check to make sure the total number of rates
+ doesn't exceed IW_MAX_BITRATES */
+
+ maxNumRates = VOS_MIN(maxNumRates , IW_MAX_BITRATES);
+
+ if((maxNumRates - numBasicRates) > MAX_RATES)
+ {
+ no_of_rates = MAX_RATES;
+ hddLog( LOGW, "Accessing array out of bound that array is pDot11ExtSuppRates->rates ");
+ }
+ else
+ {
+ no_of_rates = maxNumRates - numBasicRates;
+ }
+ for ( i=0; i< no_of_rates ; i++ )
+ {
+ if (0 != (pDot11ExtSuppRates->rates[i] & 0x7F))
+ {
+ event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
+ &pDot11ExtSuppRates->rates[i]);
+
+ current_pad = iwe_stream_add_value (scanInfo->info,current_event,
+ current_pad, end, &event, IW_EV_PARAM_LEN);
+ }
+ }
+ }
+
+
+ if ((current_pad - current_event) >= IW_EV_LCP_LEN)
+ {
+ current_event = current_pad;
+ }
+ else
+ {
+ if (last_event == current_event)
+ { /* no space to add event */
+ hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWRATE");
+ return -E2BIG;
+ }
+ }
+
+ last_event = current_event;
+ vos_mem_zero (&event, sizeof (struct iw_event));
+
+
+ event.cmd = SIOCGIWENCODE;
+
+ if (SIR_MAC_GET_PRIVACY(capabilityInfo))
+ {
+ event.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ }
+ else
+ {
+ event.u.data.flags = IW_ENCODE_DISABLED;
+ }
+ event.u.data.length = 0;
+
+ current_event = iwe_stream_add_point(scanInfo->info,current_event, end, &event, (char *)pDot11SSID->ssid);
+
+
+ if(last_event == current_event)
+ { /* no space to add event
+ Error code, may be E2BIG */
+ return -E2BIG;
+ }
+ }
+
+ last_event = current_event;
+ vos_mem_zero( &event, sizeof (struct iw_event));
+
+ /*RSSI*/
+ event.cmd = IWEVQUAL;
+ event.u.qual.qual = descriptor->rssi;
+ event.u.qual.noise = descriptor->sinr;
+
+ /*To keep the rssi icon of the connected AP in the scan window
+ *and the rssi icon of the wireless networks in sync */
+ if (( eConnectionState_Associated ==
+ pAdapter->sessionCtx.station.conn_info.connState ) &&
+ ( VOS_TRUE == vos_mem_compare(descriptor->bssId,
+ pAdapter->sessionCtx.station.conn_info.bssId,
+ WNI_CFG_BSSID_LEN)))
+ {
+ event.u.qual.level = pAdapter->rssi;
+ }
+ else
+ {
+ event.u.qual.level = VOS_MIN ((descriptor->rssi + descriptor->sinr), 0);
+ }
+
+ event.u.qual.updated = IW_QUAL_ALL_UPDATED;
+
+ current_event = iwe_stream_add_event(scanInfo->info,current_event,
+ end, &event, IW_EV_QUAL_LEN);
+
+ if(last_event == current_event)
+ { /* no space to add event */
+ hddLog( LOGW, "hdd_IndicateScanResult: no space for IWEVQUAL");
+ return -E2BIG;
+ }
+
+
+ /* AGE */
+ event.cmd = IWEVCUSTOM;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN, " Age: %lu",
+ vos_timer_get_system_ticks() - descriptor->nReceivedTime);
+ event.u.data.length = p - custom;
+ current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
+ &event, custom);
+ if(last_event == current_event)
+ { /* no space to add event */
+ hddLog( LOGW, "hdd_IndicateScanResult: no space for IWEVCUSTOM (age)");
+ return -E2BIG;
+ }
+
+ scanInfo->start = current_event;
+
+ return 0;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief hdd_ScanRequestCallback() -
+
+ The sme module calls this callback function once it finish the scan request
+ and this function notifies the scan complete event to the wpa_supplicant.
+
+ \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 hdd_ScanRequestCallback(tHalHandle halHandle, void *pContext,
+ tANI_U32 scanId, eCsrScanStatus status)
+{
+ struct net_device *dev = (struct net_device *) pContext;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
+ union iwreq_data wrqu;
+ int we_event;
+ char *msg;
+
+ ENTER();
+
+ hddLog(LOGW,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
+ " returned status = %d", __FUNCTION__, halHandle, pContext,
+ (int) scanId, (int) status);
+
+ /* if there is a scan request pending when the wlan driver is unloaded
+ we may be invoked as SME flushes its pending queue. If that is the
+ case, the underlying net_device may have already been destroyed, so
+ do some quick sanity before proceeding */
+ if (pAdapter->dev != dev)
+ {
+ hddLog(LOGW, "%s: device mismatch %p vs %p",
+ __FUNCTION__, pAdapter->dev, dev);
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ /* Check the scanId */
+ if (pAdapter->scan_info.scanId != scanId)
+ {
+ hddLog(LOGW, "%s called with mismatched scanId pAdapter->scan_info.scanId = %d "
+ "scanId = %d ", __FUNCTION__, (int) pAdapter->scan_info.scanId,
+ (int) scanId);
+ }
+
+ /* Scan is no longer pending */
+ pAdapter->scan_info.mScanPending = VOS_FALSE;
+
+ // notify any applications that may be interested
+ memset(&wrqu, '\0', sizeof(wrqu));
+ we_event = SIOCGIWSCAN;
+ msg = NULL;
+ wireless_send_event(dev, we_event, &wrqu, msg);
+
+ EXIT();
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
+
+ return eHAL_STATUS_SUCCESS;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief iw_set_scan() -
+
+ This function process the scan request from the wpa_supplicant
+ and set the scan request to the SME
+
+ \param - dev - Pointer to the net device.
+ - info - Pointer to the iw_request_info.
+ - wrqu - Pointer to the iwreq_data.
+ - extra - Pointer to the data.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+
+int iw_set_scan(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
+ hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrScanRequest scanRequest;
+ v_U32_t scanId = 0;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ struct iw_scan_req *scanReq = (struct iw_scan_req *)extra;
+
+ ENTER();
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);
+
+#ifdef WLAN_BTAMP_FEATURE
+ //Scan not supported when AMP traffic is on.
+ if( VOS_TRUE == WLANBAP_AmpSessionOn() )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
+ return eHAL_STATUS_SUCCESS;
+ }
+#endif
+ if(pAdapter->scan_info.mScanPending == TRUE)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return eHAL_STATUS_SUCCESS;
+ }
+ vos_mem_zero( &scanRequest, sizeof(scanRequest));
+
+ if (NULL != wrqu->data.pointer)
+ {
+ /* set scanType, active or passive */
+ if ((IW_SCAN_TYPE_ACTIVE == scanReq->scan_type) || (eSIR_ACTIVE_SCAN == pAdapter->scan_info.scan_mode))
+ {
+ scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ }
+ else
+ {
+ scanRequest.scanType = eSIR_PASSIVE_SCAN;
+ }
+
+ /* set bssid using sockaddr from iw_scan_req */
+ vos_mem_copy(scanRequest.bssid,
+ &scanReq->bssid.sa_data, sizeof(scanRequest.bssid) );
+
+ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+
+ if(scanReq->essid_len) {
+ scanRequest.SSIDs.numOfSSIDs = 1;
+ scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
+ if(scanRequest.SSIDs.SSIDList) {
+ scanRequest.SSIDs.SSIDList->SSID.length = scanReq->essid_len;
+ vos_mem_copy(scanRequest.SSIDs.SSIDList-> SSID.ssId,scanReq->essid,scanReq->essid_len);
+ }
+ else
+ {
+ scanRequest.SSIDs.numOfSSIDs = 0;
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Unable to allocate memory",__FUNCTION__);
+ VOS_ASSERT(0);
+ }
+ }
+ }
+
+ /* set min and max channel time */
+ scanRequest.minChnTime = scanReq->min_channel_time;
+ scanRequest.maxChnTime = scanReq->max_channel_time;
+
+ }
+ else
+ {
+ if(pAdapter->scan_info.scan_mode == eSIR_ACTIVE_SCAN) {
+ /* set the scan type to active */
+ scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ } else {
+ scanRequest.scanType = eSIR_PASSIVE_SCAN;
+ }
+
+ vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
+
+ /* set min and max channel time to zero */
+ scanRequest.minChnTime = 0;
+ scanRequest.maxChnTime = 0;
+ }
+
+ /* set BSSType to default type */
+ scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
+
+ /*Scan all the channels */
+ scanRequest.ChannelInfo.numOfChannels = 0;
+
+ scanRequest.ChannelInfo.ChannelList = NULL;
+
+ /* set requestType to full scan */
+ scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
+
+ /* if previous genIE is not NULL, update ScanIE */
+ if (0 != pwextBuf->genIE.length)
+ {
+ memset( &pAdapter->scan_info.scanAddIE, 0, sizeof(pAdapter->scan_info.scanAddIE) );
+ memcpy( pAdapter->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata,
+ pwextBuf->genIE.length );
+ pAdapter->scan_info.scanAddIE.length = pwextBuf->genIE.length;
+
+ pwextBuf->roamProfile.pAddIEScan = pAdapter->scan_info.scanAddIE.addIEdata;
+ pwextBuf->roamProfile.nAddIEScanLength = pAdapter->scan_info.scanAddIE.length;
+
+ /* clear previous genIE after use it */
+ memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
+ }
+
+ /* push addIEScan in scanRequset if exist */
+ if (pAdapter->scan_info.scanAddIE.addIEdata &&
+ pAdapter->scan_info.scanAddIE.length)
+ {
+ scanRequest.uIEFieldLen = pAdapter->scan_info.scanAddIE.length;
+ scanRequest.pIEField = pAdapter->scan_info.scanAddIE.addIEdata;
+ }
+
+ status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal, pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev );
+ if (!HAL_STATUS_SUCCESS(status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:sme_ScanRequest fail %d!!!",__func__, status);
+ goto error;
+ }
+
+ pAdapter->scan_info.mScanPending = TRUE;
+
+ pAdapter->scan_info.scanId = scanId;
+
+error:
+ if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len))
+ vos_mem_free(scanRequest.SSIDs.SSIDList);
+
+ EXIT();
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
+ return status;
+}
+
+/**---------------------------------------------------------------------------
+
+ \brief iw_get_scan() -
+
+ This function returns the scan results to the wpa_supplicant
+
+ \param - dev - Pointer to the net device.
+ - info - Pointer to the iw_request_info.
+ - wrqu - Pointer to the iwreq_data.
+ - extra - Pointer to the data.
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+
+
+int iw_get_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ tCsrScanResultInfo *pScanResult;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ hdd_scan_info_t scanInfo;
+ tScanResultHandle pResult;
+ int i = 0;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter buffer length %d!!!",
+ __func__, (wrqu->data.length)?wrqu->data.length:IW_SCAN_MAX_DATA);
+ ENTER();
+
+ if (TRUE == pAdapter->scan_info.mScanPending)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
+ return -EAGAIN;
+ }
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return -EAGAIN;
+ }
+
+ scanInfo.dev = dev;
+ scanInfo.start = extra;
+ scanInfo.info = info;
+
+ if (0 == wrqu->data.length)
+ {
+ scanInfo.end = extra + IW_SCAN_MAX_DATA;
+ }
+ else
+ {
+ scanInfo.end = extra + wrqu->data.length;
+ }
+
+ status = sme_ScanGetResult(hHal,pAdapter->sessionId,NULL,&pResult);
+
+ if (NULL == pResult)
+ {
+ // no scan results
+ hddLog(LOG1,"iw_get_scan: NULL Scan Result ");
+ return 0;
+ }
+
+ pScanResult = sme_ScanResultGetFirst(hHal, pResult);
+
+ while (pScanResult)
+ {
+ status = hdd_IndicateScanResult(&scanInfo, pScanResult);
+ if (0 != status)
+ {
+ break;
+ }
+ i++;
+ pScanResult = sme_ScanResultGetNext(hHal, pResult);
+ }
+
+ sme_ScanResultPurge(hHal, pResult);
+
+ EXIT();
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit total %d BSS reported !!!",__func__, i);
+ return status;
+}
+
+#if 0
+static eHalStatus hdd_CscanRequestCallback(tHalHandle halHandle, void *pContext,
+ tANI_U32 scanId, eCsrScanStatus status)
+{
+ struct net_device *dev = (struct net_device *) pContext;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
+ hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ union iwreq_data wrqu;
+ int we_event;
+ char *msg;
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ ENTER();
+
+ hddLog(LOG1,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
+ " returned status = %d", __FUNCTION__, halHandle, pContext,
+ (int) scanId, (int) status);
+
+ /* Check the scanId */
+ if (pwextBuf->scanId != scanId)
+ {
+ hddLog(LOGW, "%s called with mismatched scanId pWextState->scanId = %d "
+ "scanId = %d ", __FUNCTION__, (int) pwextBuf->scanId,
+ (int) scanId);
+ }
+
+ /* Scan is no longer pending */
+ pwextBuf->mScanPending = VOS_FALSE;
+
+ // notify any applications that may be interested
+ memset(&wrqu, '\0', sizeof(wrqu));
+ we_event = SIOCGIWSCAN;
+ msg = NULL;
+ wireless_send_event(dev, we_event, &wrqu, msg);
+
+ vos_status = vos_event_set(&pwextBuf->vosevent);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos_event_set failed!!"));
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ EXIT();
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
+
+ return eHAL_STATUS_SUCCESS;
+}
+#endif
+
+int iw_set_cscan(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
+ hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrScanRequest scanRequest;
+ v_U32_t scanId = 0;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ v_U8_t channelIdx;
+
+ ENTER();
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);
+
+#ifdef WLAN_BTAMP_FEATURE
+ //Scan not supported when AMP traffic is on.
+ if( VOS_TRUE == WLANBAP_AmpSessionOn() )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
+ return eHAL_STATUS_SUCCESS;
+ }
+#endif
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return eHAL_STATUS_SUCCESS;
+ }
+
+ vos_mem_zero( &scanRequest, sizeof(scanRequest));
+ if (NULL != wrqu->data.pointer)
+ {
+ char *str_ptr = NULL;
+ tCsrSSIDInfo *SsidInfo = NULL;
+ int num_ssid = 0;
+ int i, j, ssid_start;
+ hdd_scan_pending_option_e scanPendingOption = WEXT_SCAN_PENDING_GIVEUP;
+
+ /* save the original buffer */
+ str_ptr = wrqu->data.pointer;
+
+ i = WEXT_CSCAN_HEADER_SIZE;
+
+ if( WEXT_CSCAN_PENDING_SECTION == str_ptr[i] )
+ {
+ scanPendingOption = (hdd_scan_pending_option_e)str_ptr[++i];
+ ++i;
+ }
+ pAdapter->scan_info.scan_pending_option = scanPendingOption;
+
+ if(pAdapter->scan_info.mScanPending == TRUE)
+ {
+ hddLog(LOG1,"%s: mScanPending is TRUE",__func__);
+ /* If any scan is pending, just giveup this scan request */
+ if(WEXT_SCAN_PENDING_GIVEUP == scanPendingOption)
+ {
+ pAdapter->scan_info.waitScanResult = FALSE;
+ return eHAL_STATUS_SUCCESS;
+ }
+ /* If any scan pending, wait till finish current scan,
+ and try this scan request when previous scan finish */
+ else if(WEXT_SCAN_PENDING_DELAY == scanPendingOption)
+ {
+ pAdapter->scan_info.waitScanResult = TRUE;
+ vos_event_reset(&pAdapter->scan_info.scan_finished_event);
+ if(vos_wait_single_event(&pAdapter->scan_info.scan_finished_event,
+ WEXT_CSCAN_SCAN_DONE_WAIT_TIME))
+ {
+ hddLog(LOG1,"%s: Previous SCAN does not finished on time",__func__);
+ return eHAL_STATUS_SUCCESS;
+ }
+ }
+ /* Piggyback previous scan result */
+ else if(WEXT_SCAN_PENDING_PIGGYBACK == scanPendingOption)
+ {
+ pAdapter->scan_info.waitScanResult = TRUE;
+ return eHAL_STATUS_SUCCESS;
+ }
+ }
+ pAdapter->scan_info.waitScanResult = FALSE;
+
+ /* Check for scan IE */
+ while( WEXT_CSCAN_SSID_SECTION == str_ptr[i] )
+ {
+ /* ssid_len */
+ if(str_ptr[++i] != WEXT_CSCAN_CHANNEL_SECTION)
+ {
+ /* total number of ssid's */
+ num_ssid++;
+ /* increment length filed */
+ i += str_ptr[i] + 1;
+ }
+ /* i should be saved and it will be pointing to 'C' */
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: numSsid %d !!!",__func__, num_ssid);
+ if( num_ssid )
+ {
+ /* To be fixed in SME and PE: override the number of ssid with 1,
+ * as SME and PE does not handle multiple SSID in scan request
+ * */
+ scanRequest.SSIDs.numOfSSIDs = num_ssid;
+ /* Allocate num_ssid tCsrSSIDInfo structure */
+ SsidInfo = scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(num_ssid*sizeof(tCsrSSIDInfo));
+ if(NULL == scanRequest.SSIDs.SSIDList) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "memory alloc failed SSIDInfo buffer");
+ return -ENOMEM;
+ }
+
+ /* copy all the ssid's and their length */
+ ssid_start = WEXT_CSCAN_HEADER_SIZE + 1;/* skipping 'S' */
+ for(j = 0; j < num_ssid; j++) {
+ if( SIR_MAC_MAX_SSID_LENGTH < str_ptr[ssid_start]){
+ scanRequest.SSIDs.numOfSSIDs -= 1;
+ } else{
+ /* get the ssid length */
+ SsidInfo->SSID.length = str_ptr[ssid_start++];
+ vos_mem_copy(SsidInfo->SSID.ssId, &str_ptr[ssid_start], SsidInfo->SSID.length);
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s\n", j, SsidInfo->SSID.ssId);
+ }
+ /* skipping length */
+ ssid_start += str_ptr[ssid_start - 1] + 1;
+ /* Store next ssid info */
+ SsidInfo++;
+ }
+ }
+
+ /* Check for Channel IE */
+ if ( WEXT_CSCAN_CHANNEL_SECTION == str_ptr[i])
+ {
+ if( str_ptr[++i] == 0 )
+ {
+ scanRequest.ChannelInfo.numOfChannels = 0;
+ scanRequest.ChannelInfo.ChannelList = NULL;
+ i++;
+ }
+ else {
+
+ /* increment the counter */
+ scanRequest.ChannelInfo.numOfChannels = str_ptr[i++];
+ /* store temp channel list */
+ /* SME expects 1 byte channel content */
+ scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(scanRequest.ChannelInfo.numOfChannels * sizeof(v_U8_t));
+ if(NULL == scanRequest.ChannelInfo.ChannelList)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "memory alloc failed for channel list creation");
+ status = -ENOMEM;
+ goto exit_point;
+ }
+
+ for(channelIdx = 0; channelIdx < scanRequest.ChannelInfo.numOfChannels; channelIdx++)
+ {
+ /* SCAN request from upper layer has 2 bytes channel */
+ scanRequest.ChannelInfo.ChannelList[channelIdx] = (v_U8_t)str_ptr[i];
+ i += sizeof(v_U16_t);
+ }
+ }
+ }
+
+ /* Set default */
+ scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ scanRequest.minChnTime = 0;
+ scanRequest.maxChnTime = 0;
+
+ /* Now i is pointing to passive dwell dwell time */
+ /* 'P',min dwell time, max dwell time */
+ /* next two offsets contain min and max channel time */
+ if( WEXT_CSCAN_PASV_DWELL_SECTION == (str_ptr[i]) )
+ {
+ /* No SSID specified, num_ssid == 0, then start paasive scan */
+ if (!num_ssid || (eSIR_PASSIVE_SCAN == pAdapter->scan_info.scan_mode))
+ {
+ scanRequest.scanType = eSIR_PASSIVE_SCAN;
+ scanRequest.minChnTime = (v_U8_t)str_ptr[++i];//scanReq->min_channel_time;
+ scanRequest.maxChnTime = (v_U8_t)str_ptr[++i];//scanReq->max_channel_time;
+ i++;
+ }
+ else
+ {
+ i += 3;
+ }
+ }
+
+ /* H indicates active channel time */
+ if( WEXT_CSCAN_HOME_DWELL_SECTION == (str_ptr[i]) )
+ {
+ if (num_ssid || (eSIR_ACTIVE_SCAN == pAdapter->scan_info.scan_mode))
+ {
+ scanRequest.scanType = eSIR_ACTIVE_SCAN;
+ scanRequest.minChnTime = str_ptr[++i];//scanReq->min_channel_time;
+ scanRequest.maxChnTime = str_ptr[++i];//scanReq->max_channel_time;
+ i++;
+ }
+ else
+ {
+ i +=3;
+ }
+ }
+ scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
+ /* set requestType to full scan */
+ scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
+ pAdapter->scan_info.mScanPending = TRUE;
+
+ /* if previous genIE is not NULL, update ScanIE */
+ if(0 != pwextBuf->genIE.length)
+ {
+ memset( &pAdapter->scan_info.scanAddIE, 0, sizeof(pAdapter->scan_info.scanAddIE) );
+ memcpy( pAdapter->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata,
+ pwextBuf->genIE.length );
+ pAdapter->scan_info.scanAddIE.length = pwextBuf->genIE.length;
+
+ pwextBuf->roamProfile.pAddIEScan = pAdapter->scan_info.scanAddIE.addIEdata;
+ pwextBuf->roamProfile.nAddIEScanLength = pAdapter->scan_info.scanAddIE.length;
+
+ /* clear previous genIE after use it */
+ memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
+ }
+
+ /* push addIEScan in scanRequset if exist */
+ if (pAdapter->scan_info.scanAddIE.addIEdata &&
+ pAdapter->scan_info.scanAddIE.length)
+ {
+ scanRequest.uIEFieldLen = pAdapter->scan_info.scanAddIE.length;
+ scanRequest.pIEField = pAdapter->scan_info.scanAddIE.addIEdata;
+ }
+
+ status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal,
+ pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev );
+ if( !HAL_STATUS_SUCCESS(status) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: SME scan fail status %d !!!",__func__, status);
+ pAdapter->scan_info.mScanPending = FALSE;
+ status = -EINVAL;
+ goto exit_point;
+ }
+
+ pAdapter->scan_info.scanId = scanId;
+
+ } //end of data->pointer
+ else {
+ status = -1;
+ }
+
+exit_point:
+
+ /* free ssidlist */
+ if (scanRequest.SSIDs.SSIDList)
+ {
+ vos_mem_free(scanRequest.SSIDs.SSIDList);
+ }
+ /* free the channel list */
+ if(scanRequest.ChannelInfo.ChannelList)
+ {
+ vos_mem_free((void*)scanRequest.ChannelInfo.ChannelList);
+ }
+
+ EXIT();
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
+ return status;
+}
+
+/* Abort any MAC scan if in progress */
+void hdd_abort_mac_scan(hdd_context_t* pHddCtx)
+{
+ sme_AbortMacScan(pHddCtx->hHal);
+}
+
diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
new file mode 100644
index 0000000..a4a5509
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
@@ -0,0 +1,1597 @@
+/*
+ * 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 wlan_hdd_softap_tx_rx.c
+
+ \brief Linux HDD Tx/RX APIs
+ Copyright 2008 (c) Qualcomm, Incorporated.
+ All Rights Reserved.
+ Qualcomm Confidential and Proprietary.
+
+ ==========================================================================*/
+#ifdef WLAN_SOFTAP_FEATURE
+
+/*---------------------------------------------------------------------------
+ Include files
+ -------------------------------------------------------------------------*/
+#include <linux/semaphore.h>
+#include <wlan_hdd_tx_rx.h>
+#include <wlan_hdd_softap_tx_rx.h>
+#include <wlan_hdd_dp_utils.h>
+#include <wlan_qct_tl.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+//#include <vos_list.h>
+#include <vos_types.h>
+#include <aniGlobal.h>
+#include <halTypes.h>
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+#include <halHddApis.h>
+#endif
+#include <net/ieee80211_radiotap.h>
+
+
+/*---------------------------------------------------------------------------
+ Preprocessor definitions and constants
+ -------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+ Type declarations
+ -------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+ Function definitions and documenation
+ -------------------------------------------------------------------------*/
+#if 0
+static void hdd_softap_dump_sk_buff(struct sk_buff * skb)
+{
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: head = %p ", __FUNCTION__, skb->head);
+ //VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: data = %p ", __FUNCTION__, skb->data);
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p ", __FUNCTION__, skb->tail);
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: end = %p ", __FUNCTION__, skb->end);
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: len = %d ", __FUNCTION__, skb->len);
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d ", __FUNCTION__, skb->data_len);
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d\n", __FUNCTION__, skb->mac_len);
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ",
+ skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
+ skb->data[5], skb->data[6], skb->data[7]);
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n",
+ skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
+ skb->data[13], skb->data[14], skb->data[15]);
+}
+#endif
+/**============================================================================
+ @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+static VOS_STATUS hdd_softap_flush_tx_queues( hdd_adapter_t *pAdapter )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ v_SINT_t i = -1;
+ v_U8_t STAId = 0;
+ hdd_list_node_t *anchor = NULL;
+ skb_list_node_t *pktNode = NULL;
+ struct sk_buff *skb = NULL;
+
+ spin_lock_bh( &pAdapter->staInfo_lock );
+ for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
+ {
+ if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
+ {
+ continue;
+ }
+
+ for (i = 0; i < NUM_TX_QUEUES; i ++)
+ {
+ spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
+ while (true)
+ {
+ status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
+
+ if (VOS_STATUS_E_EMPTY != status)
+ {
+ //If success then we got a valid packet from some AC
+ pktNode = list_entry(anchor, skb_list_node_t, anchor);
+ skb = pktNode->skb;
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
+ kfree_skb(skb);
+ continue;
+ }
+
+ //current list is empty
+ break;
+ }
+ pAdapter->aStaInfo[STAId].txSuspended[i] = VOS_FALSE;
+ spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
+ }
+ }
+
+ spin_unlock_bh( &pAdapter->staInfo_lock );
+
+ return status;
+}
+
+/**============================================================================
+ @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for
+ transmitting packets. There are 2 versions of this function. One that uses
+ locked queue and other that uses lockless queues. Both have been retained to
+ do some performance testing
+
+ @param skb : [in] pointer to OS packet (sk_buff)
+ @param dev : [in] pointer to Libra network device
+
+ @return : NET_XMIT_DROP if packets are dropped
+ : NET_XMIT_SUCCESS if packet is enqueued succesfully
+ ===========================================================================*/
+int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ VOS_STATUS status;
+ WLANTL_ACEnumType ac = WLANTL_AC_BE;
+ sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
+ skb_list_node_t *pktNode = NULL;
+ v_SIZE_t pktListSize = 0;
+ v_BOOL_t txSuspended = VOS_FALSE;
+ hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
+ hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
+ vos_list_node_t *anchor = NULL;
+ v_U8_t STAId = WLAN_MAX_STA_COUNT;
+ //Extract the destination address from ethernet frame
+ v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
+ int os_status = NETDEV_TX_OK;
+
+ pDestMacAddress = (v_MACADDR_t*)skb->data;
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: enter", __FUNCTION__);
+
+ spin_lock_bh( &pAdapter->staInfo_lock );
+ if (vos_is_macaddr_broadcast( pDestMacAddress ) || vos_is_macaddr_group(pDestMacAddress))
+ {
+ //The BC/MC station ID is assigned during BSS starting phase. SAP will return the station
+ //ID used for BC/MC traffic. The station id is registered to TL as well.
+ STAId = pHddApCtx->uBCStaId;
+
+ /* Setting priority for broadcast packets which doesn't go to select_queue function */
+ skb->priority = SME_QOS_WMM_UP_BE;
+ skb->queue_mapping = HDD_LINUX_AC_BE;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
+ "%s: BC/MC packet\n", __FUNCTION__);
+ }
+ else
+ {
+ STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
+ if (STAId == HDD_WLAN_INVALID_STA_ID)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to find right station", __FUNCTION__);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ kfree_skb(skb);
+ goto xmit_done;
+ }
+ else if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: STA is unregistered", __FUNCTION__, STAId);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ kfree_skb(skb);
+ goto xmit_done;
+ }
+
+ if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) &&
+ (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Station not connected yet", __FUNCTION__);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ kfree_skb(skb);
+ goto xmit_done;
+ }
+ else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState)
+ {
+ if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: NON-EAPOL packet in non-Authenticated state", __FUNCTION__);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ kfree_skb(skb);
+ goto xmit_done;
+ }
+ }
+ }
+
+ //Get TL AC corresponding to Qdisc queue index/AC.
+ ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
+ //user priority from IP header, which is already extracted and set from
+ //select_queue call back function
+ up = skb->priority;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: Classified as ac %d up %d", __FUNCTION__, ac, up);
+
+ // If the memory differentiation mode is enabled, the memory limit of each queue will be
+ // checked. Over-limit packets will be dropped.
+ spin_lock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
+ if(pktListSize >= pAdapter->aTxQueueLimit[ac])
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: station %d ac %d queue over limit %d \n", __FUNCTION__, STAId, ac, pktListSize);
+ pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
+ netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
+ txSuspended = VOS_TRUE;
+ }
+ spin_unlock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+
+ if (VOS_TRUE == txSuspended)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "%s: TX queue full for AC=%d Disable OS TX queue",
+ __FUNCTION__, ac );
+ os_status = NETDEV_TX_BUSY;
+ goto xmit_done;
+ }
+
+ //Use the skb->cb field to hold the list node information
+ pktNode = (skb_list_node_t *)&skb->cb;
+
+ //Stick the OS packet inside this node.
+ pktNode->skb = skb;
+
+ //Stick the User Priority inside this node
+ pktNode->userPriority = up;
+
+ INIT_LIST_HEAD(&pktNode->anchor);
+
+ spin_lock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
+ spin_unlock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s:Insert Tx queue failed. Pkt dropped", __FUNCTION__);
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+ ++pAdapter->stats.tx_dropped;
+ kfree_skb(skb);
+ goto xmit_done;
+ }
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
+
+ if (1 == pktListSize)
+ {
+ //Let TL know we have a packet to send for this AC
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, "%s: Failed to signal TL for AC=%d STAId =%d",
+ __FUNCTION__, ac, STAId );
+
+ //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
+ //as we are in a soft irq context. Also it must be the same packet that we just allocated.
+ spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
+ spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+ kfree_skb(skb);
+ goto xmit_done;
+ }
+ }
+ dev->trans_start = jiffies;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit \n", __FUNCTION__);
+
+xmit_done:
+ spin_unlock_bh( &pAdapter->staInfo_lock );
+ return os_status;
+}
+
+/**============================================================================
+ @brief hdd_softap_sta_2_sta_xmit This function for Transmitting the frames when the traffic is between two stations.
+
+ @param skb : [in] pointer to packet (sk_buff)
+ @param dev : [in] pointer to Libra network device
+ @param STAId : [in] Station Id of Destination Station
+ @param up : [in] User Priority
+
+ @return : NET_XMIT_DROP if packets are dropped
+ : NET_XMIT_SUCCESS if packet is enqueued succesfully
+ ===========================================================================*/
+VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb,
+ struct net_device *dev,
+ v_U8_t STAId,
+ v_U8_t up)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ skb_list_node_t *pktNode = NULL;
+ v_SIZE_t pktListSize = 0;
+ hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
+ v_U8_t ac;
+ vos_list_node_t *anchor = NULL;
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: enter", __FUNCTION__);
+
+ spin_lock_bh( &pAdapter->staInfo_lock );
+ if ( FALSE == pAdapter->aStaInfo[STAId].isUsed )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: STA is unregistered", __FUNCTION__, STAId );
+ kfree_skb(skb);
+ status = VOS_STATUS_E_FAILURE;
+ goto xmit_end;
+ }
+
+ /* If the QoS is not enabled on the receiving station, then send it with BE priority */
+ if ( !pAdapter->aStaInfo[STAId].isQosEnabled )
+ up = SME_QOS_WMM_UP_BE;
+
+ ac = hddWmmUpToAcMap[up];
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: Classified as ac %d up %d", __FUNCTION__, ac, up);
+
+ skb->queue_mapping = hddLinuxUpToAcMap[up];
+
+ //Use the skb->cb field to hold the list node information
+ pktNode = (skb_list_node_t *)&skb->cb;
+
+ //Stick the OS packet inside this node.
+ pktNode->skb = skb;
+
+ //Stick the User Priority inside this node
+ pktNode->userPriority = up;
+
+ INIT_LIST_HEAD(&pktNode->anchor);
+
+ spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
+ if(pAdapter->aStaInfo[STAId].txSuspended[ac] ||
+ pktListSize >= pAdapter->aTxQueueLimit[ac])
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: station %d ac %d queue over limit %d \n", __FUNCTION__, STAId, ac, pktListSize);
+ /* TODO:Rx Flowchart should be trigerred here to SUPEND SSC on RX side.
+ * SUSPEND should be done based on Threshold. RESUME would be
+ * triggered in fetch cbk after recovery.
+ */
+ kfree_skb(skb);
+ spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ status = VOS_STATUS_E_FAILURE;
+ goto xmit_end;
+ }
+ status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
+ spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s:Insert Tx queue failed. Pkt dropped", __FUNCTION__);
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+ ++pAdapter->stats.tx_dropped;
+ kfree_skb(skb);
+ status = VOS_STATUS_E_FAILURE;
+ goto xmit_end;
+ }
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
+
+ if (1 == pktListSize)
+ {
+ //Let TL know we have a packet to send for this AC
+ //VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __FUNCTION__);
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, "%s: Failed to signal TL for AC=%d STAId =%d",
+ __FUNCTION__, ac, STAId );
+
+ //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
+ //as we are in a soft irq context. Also it must be the same packet that we just allocated.
+ spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
+ spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+ kfree_skb(skb);
+ status = VOS_STATUS_E_FAILURE;
+ goto xmit_end;
+ }
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit \n", __FUNCTION__);
+
+xmit_end:
+ spin_unlock_bh( &pAdapter->staInfo_lock );
+ return status;
+}
+
+/**============================================================================
+ @brief hdd_softap_tx_timeout() - Function called by OS if there is any
+ timeout during transmission. Since HDD simply enqueues packet
+ and returns control to OS right away, this would never be invoked
+
+ @param dev : [in] pointer to Libra network device
+ @return : None
+ ===========================================================================*/
+void hdd_softap_tx_timeout(struct net_device *dev)
+{
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Transmission timeout occurred", __FUNCTION__);
+ //Getting here implies we disabled the TX queues for too long. Queues are
+ //disabled either because of disassociation or low resource scenarios. In
+ //case of disassociation it is ok to ignore this. But if associated, we have
+ //do possible recovery here
+}
+
+
+/**============================================================================
+ @brief hdd_softap_stats() - Function registered with the Linux OS for
+ device TX/RX statistic
+
+ @param dev : [in] pointer to Libra network device
+
+ @return : pointer to net_device_stats structure
+ ===========================================================================*/
+struct net_device_stats* hdd_softap_stats(struct net_device *dev)
+{
+ hdd_adapter_t* priv = netdev_priv(dev);
+ return &priv->stats;
+}
+
+
+/**============================================================================
+ @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ v_SINT_t i = -1;
+ v_SIZE_t size = 0;
+
+ v_U8_t STAId = 0;
+
+ v_U8_t pACWeights[] = {
+ HDD_SOFTAP_BK_WEIGHT_DEFAULT,
+ HDD_SOFTAP_BE_WEIGHT_DEFAULT,
+ HDD_SOFTAP_VI_WEIGHT_DEFAULT,
+ HDD_SOFTAP_VO_WEIGHT_DEFAULT
+ };
+ pAdapter->isVosOutOfResource = VOS_FALSE;
+
+ vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
+
+ while (++i != NUM_TX_QUEUES)
+ hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
+
+ /* Initial HDD buffer control / flow control fields*/
+ vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size);
+
+ pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
+ pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
+ pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
+ pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
+
+ spin_lock_init( &pAdapter->staInfo_lock );
+
+ for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
+ {
+ vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
+ for (i = 0; i < NUM_TX_QUEUES; i ++)
+ {
+ hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
+ }
+ }
+
+ /* Update the AC weights suitable for SoftAP mode of operation */
+ WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
+
+ return status;
+}
+
+/**============================================================================
+ @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+
+ status = hdd_softap_flush_tx_queues(pAdapter);
+
+ return status;
+}
+
+/**============================================================================
+ @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station
+
+ @param pAdapter : [in] pointer to adapter context
+ @param STAId : [in] Station ID to deinit
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ v_U8_t i = -1;
+
+ hdd_list_node_t *anchor = NULL;
+
+ skb_list_node_t *pktNode = NULL;
+ struct sk_buff *skb = NULL;
+
+ if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
+ {
+ return status;
+ }
+
+ for (i = 0; i < NUM_TX_QUEUES; i ++)
+ {
+ spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
+ while (true)
+ {
+ status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
+ if (VOS_STATUS_E_EMPTY != status)
+ {
+ //If success then we got a valid packet from some AC
+ pktNode = list_entry(anchor, skb_list_node_t, anchor);
+ skb = pktNode->skb;
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
+ kfree_skb(skb);
+ continue;
+ }
+
+ //current list is empty
+ break;
+ }
+ spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
+ }
+
+ return status;
+}
+
+/**============================================================================
+ @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @param STAId : [in] Station ID to deinit
+ @param pmacAddrSTA : [in] pointer to the MAC address of the station
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
+{
+ v_U8_t i = 0;
+ spin_lock_bh( &pAdapter->staInfo_lock );
+ if (pAdapter->aStaInfo[STAId].isUsed)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, "%s: Reinit station %d", __FUNCTION__, STAId );
+ spin_unlock_bh( &pAdapter->staInfo_lock );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
+ for (i = 0; i < NUM_TX_QUEUES; i ++)
+ {
+ hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
+ }
+
+ pAdapter->aStaInfo[STAId].isUsed = TRUE;
+ vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
+
+ spin_unlock_bh( &pAdapter->staInfo_lock );
+ return VOS_STATUS_SUCCESS;
+}
+
+/**============================================================================
+ @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a statioin in Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @param STAId : [in] Station ID to deinit
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ v_U8_t ac;
+ /**Track whether OS TX queue has been disabled.*/
+ v_BOOL_t txSuspended[NUM_TX_QUEUES];
+ v_U8_t tlAC;
+ hdd_hostapd_state_t *pHostapdState;
+
+ pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
+
+ spin_lock_bh( &pAdapter->staInfo_lock );
+ if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Deinit station not inited %d", __FUNCTION__, STAId );
+ spin_unlock_bh( &pAdapter->staInfo_lock );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ status = hdd_softap_flush_tx_queues_sta(pAdapter, STAId);
+
+ pAdapter->aStaInfo[STAId].isUsed = FALSE;
+
+ /* if this STA had any of its WMM TX queues suspended, then the
+ associated queue on the network interface was disabled. check
+ to see if that is the case, in which case we need to re-enable
+ the interface queue. but we only do this if the BSS is running
+ since, if the BSS is stopped, all of the interfaces have been
+ stopped and should not be re-enabled */
+
+ if (BSS_START == pHostapdState->bssState)
+ {
+ for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
+ {
+ tlAC = hdd_QdiscAcToTlAC[ac];
+ txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC];
+ }
+ }
+ vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
+
+ if (BSS_START == pHostapdState->bssState)
+ {
+ for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
+ {
+ if (txSuspended[ac])
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: TX queue re-enabled", __FUNCTION__);
+ netif_wake_subqueue(pAdapter->dev, ac);
+ }
+ }
+ }
+
+ spin_unlock_bh( &pAdapter->staInfo_lock );
+ return status;
+}
+
+/**============================================================================
+ @brief hdd_softap_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_softap_disconnect_tx_rx( hdd_adapter_t *pAdapter )
+{
+ return hdd_softap_flush_tx_queues(pAdapter);
+}
+
+/**============================================================================
+ @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL
+ to indicate that a packet has been transmitted across the bus
+ succesfully. OS packet resources can be released after this cbk.
+
+ @param vosContext : [in] pointer to VOS context
+ @param pVosPacket : [in] pointer to VOS packet (containing skb)
+ @param vosStatusIn : [in] status of the transmission
+
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext,
+ vos_pkt_t *pVosPacket,
+ VOS_STATUS vosStatusIn )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ hdd_adapter_t *pAdapter = NULL;
+ void* pOsPkt = NULL;
+
+ if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Return the skb to the OS
+ status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
+ if(!VOS_IS_STATUS_SUCCESS( status ))
+ {
+ //This is bad but still try to free the VOSS resources if we can
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __FUNCTION__);
+ vos_pkt_return_packet( pVosPacket );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Get the Adapter context.
+ pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev);
+ if(pAdapter == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ }
+ else
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
+ }
+
+ kfree_skb((struct sk_buff *)pOsPkt);
+
+ //Return the VOS packet resources.
+ status = vos_pkt_return_packet( pVosPacket );
+ if(!VOS_IS_STATUS_SUCCESS( status ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Could not return VOS packet to the pool", __FUNCTION__);
+ }
+
+ return status;
+}
+
+
+/**============================================================================
+ @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to
+ fetch a packet for transmission.
+
+ @param vosContext : [in] pointer to VOS context
+ @param staId : [in] Station for which TL is requesting a pkt
+ @param ac : [in] access category requested by TL
+ @param pVosPacket : [out] pointer to VOS packet packet pointer
+ @param pPktMetaInfo : [out] pointer to meta info for the pkt
+
+ @return : VOS_STATUS_E_EMPTY if no packets to transmit
+ : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext,
+ v_U8_t *pStaId,
+ WLANTL_ACEnumType ac,
+ vos_pkt_t **ppVosPacket,
+ WLANTL_MetaInfoType *pPktMetaInfo )
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ hdd_adapter_t *pAdapter = NULL;
+ hdd_list_node_t *anchor = NULL;
+ skb_list_node_t *pktNode = NULL;
+ struct sk_buff *skb = NULL;
+ vos_pkt_t *pVosPacket = NULL;
+ v_MACADDR_t* pDestMacAddress = NULL;
+ v_TIME_t timestamp;
+ v_SIZE_t size = 0;
+ v_U8_t STAId = WLAN_MAX_STA_COUNT;
+ hdd_context_t *pHddCtx = NULL;
+
+ //Sanity check on inputs
+ if ( ( NULL == vosContext ) ||
+ ( NULL == pStaId ) ||
+ ( NULL == ppVosPacket ) ||
+ ( NULL == pPktMetaInfo ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null Params being passed", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Get the HDD context.
+ pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
+ if ( NULL == pHddCtx )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pAdapter = pHddCtx->sta_to_adapter[*pStaId];
+ if( NULL == pAdapter )
+ {
+ VOS_ASSERT(0);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
+
+ STAId = *pStaId;
+ if (STAId >= WLAN_MAX_STA_COUNT)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid STAId %d passed by TL", __FUNCTION__, STAId);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Unregistered STAId %d passed by TL", __FUNCTION__, STAId);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ *ppVosPacket = NULL;
+
+ //Make sure the AC being asked for is sane
+ if( ac > WLANTL_MAX_AC || ac < 0)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid AC %d passed by TL", __FUNCTION__, ac);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: AC %d passed by TL", __FUNCTION__, ac);
+
+ //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
+ //This simplifies the locking and unlocking of Tx queue
+ status = vos_pkt_wrap_data_packet( &pVosPacket,
+ VOS_PKT_TYPE_TX_802_3_DATA,
+ NULL, //OS Pkt is not being passed
+ hdd_softap_tx_low_resource_cbk,
+ pAdapter );
+
+ if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
+ {
+ //Remember VOS is in a low resource situation
+ pAdapter->isVosOutOfResource = VOS_TRUE;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: VOSS in Low Resource scenario", __FUNCTION__);
+ //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC
+ as the other branch does.
+ */
+ spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size);
+
+ if (0 == size)
+ {
+ spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+ vos_pkt_return_packet(pVosPacket);
+ return VOS_STATUS_E_EMPTY;
+ }
+
+ status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor );
+ spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: AC %d has packets pending", __FUNCTION__, ac);
+
+ if(VOS_STATUS_SUCCESS == status)
+ {
+ //If success then we got a valid packet from some AC
+ pktNode = list_entry(anchor, skb_list_node_t, anchor);
+ skb = pktNode->skb;
+ }
+ else
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Error in de-queuing skb from Tx queue status = %d",
+ __FUNCTION__, status );
+ vos_pkt_return_packet(pVosPacket);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Attach skb to VOS packet.
+ status = vos_pkt_set_os_packet( pVosPacket, skb );
+ if (status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Error attaching skb", __FUNCTION__);
+ vos_pkt_return_packet(pVosPacket);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
+ kfree_skb(skb);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Just being paranoid. To be removed later
+ if(pVosPacket == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: VOS packet returned by VOSS is NULL", __FUNCTION__);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
+ kfree_skb(skb);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Return VOS packet to TL;
+ *ppVosPacket = pVosPacket;
+
+ //Fill out the meta information needed by TL
+ //FIXME This timestamp is really the time stamp of wrap_data_packet
+ vos_pkt_get_timestamp( pVosPacket, ×tamp );
+ pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
+ if ( 1 < size )
+ {
+ pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
+ }
+ else
+ {
+ pPktMetaInfo->bMorePackets = 0;
+ }
+
+ pPktMetaInfo->ucIsEapol = 0;
+
+ if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED)
+ {
+ if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: VOS packet is EAPOL packet", __FUNCTION__);
+ pPktMetaInfo->ucIsEapol = 1;
+ }
+ }
+
+//xg: @@@@: temporarily disble these. will revisit later
+#ifndef WLAN_SOFTAP_FEATURE
+ if(pAdapter->conn_info.uIsAuthenticated == VOS_TRUE)
+ pPktMetaInfo->ucIsEapol = 0;
+ else
+ pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
+
+ if ((HDD_WMM_USER_MODE_NO_QOS == pAdapter->cfg_ini->WmmMode) ||
+ (!pAdapter->hddWmmStatus.wmmQap))
+ {
+ // either we don't want QoS or the AP doesn't support QoS
+ pPktMetaInfo->ucUP = 0;
+ pPktMetaInfo->ucTID = 0;
+ }
+ else
+#endif
+ {
+ pPktMetaInfo->ucUP = pktNode->userPriority;
+ pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
+ }
+
+ pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
+ //Extract the destination address from ethernet frame
+ pDestMacAddress = (v_MACADDR_t*)skb->data;
+
+ // we need 802.3 to 802.11 frame translation
+ // (note that Bcast/Mcast will be translated in SW, unicast in HW)
+ pPktMetaInfo->ucDisableFrmXtl = 0;
+ pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
+ pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
+
+ if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) &&
+ (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: TX queue re-enabled", __FUNCTION__);
+ pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
+ netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
+ }
+
+ // We're giving the packet to TL so consider it transmitted from
+ // a statistics perspective. We account for it here instead of
+ // when the packet is returned for two reasons. First, TL will
+ // manipulate the skb to the point where the len field is not
+ // accurate, leading to inaccurate byte counts if we account for
+ // it later. Second, TL does not provide any feedback as to
+ // whether or not the packet was successfully sent over the air,
+ // so the packet counts will be the same regardless of where we
+ // account for them
+ pAdapter->stats.tx_bytes += skb->len;
+ ++pAdapter->stats.tx_packets;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: Valid VOS PKT returned to TL", __FUNCTION__);
+
+ return status;
+}
+
+
+/**============================================================================
+ @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the
+ case where VOS packets are not available at the time of the call to get
+ packets. This callback function is invoked by VOS when packets are
+ available.
+
+ @param pVosPacket : [in] pointer to VOS packet
+ @param userData : [in] opaque user data that was passed initially
+
+ @return : VOS_STATUS_E_FAILURE if any errors encountered,
+ : VOS_STATUS_SUCCESS otherwise
+ =============================================================================*/
+VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
+ v_VOID_t *userData )
+{
+ VOS_STATUS status;
+ v_SINT_t i = 0;
+ v_SIZE_t size = 0;
+ hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
+ v_U8_t STAId = WLAN_MAX_STA_COUNT;
+
+ if(pAdapter == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Return the packet to VOS. We just needed to know that VOS is out of low resource
+ //situation. Here we will only signal TL that there is a pending data for a STA.
+ //VOS packet will be requested (if needed) when TL comes back to fetch data.
+ vos_pkt_return_packet( pVosPacket );
+
+ pAdapter->isVosOutOfResource = VOS_FALSE;
+
+ // Indicate to TL that there is pending data if a queue is non empty.
+ // This Code wasnt included in earlier version which resulted in
+ // Traffic stalling
+ for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
+ {
+ if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) ||
+ (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED))
+ {
+ for( i=NUM_TX_QUEUES-1; i>=0; --i )
+ {
+ size = 0;
+ hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size);
+ if ( size > 0 )
+ {
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ STAId,
+ (WLANTL_ACEnumType)i );
+ if( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure in indicating pkt to TL for ac=%d", __FUNCTION__,i);
+ }
+ }
+ }
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+
+/**============================================================================
+ @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL.
+ TL will call this to notify the HDD when one or more packets were
+ received for a registered STA.
+
+ @param vosContext : [in] pointer to VOS context
+ @param pVosPacketChain : [in] pointer to VOS packet chain
+ @param staId : [in] Station Id (Adress 1 Index)
+ @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s).
+
+ @return : VOS_STATUS_E_FAILURE if any errors encountered,
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext,
+ vos_pkt_t *pVosPacketChain,
+ v_U8_t staId,
+ WLANTL_RxMetaInfoType* pRxMetaInfo )
+{
+ hdd_adapter_t *pAdapter = NULL;
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ int rxstat;
+ struct sk_buff *skb = NULL;
+ vos_pkt_t* pVosPacket;
+ vos_pkt_t* pNextVosPacket;
+ hdd_context_t *pHddCtx = NULL;
+
+ //Sanity check on inputs
+ if ( ( NULL == vosContext ) ||
+ ( NULL == pVosPacketChain ) ||
+ ( NULL == pRxMetaInfo ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
+ if ( NULL == pHddCtx )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pAdapter = pHddCtx->sta_to_adapter[staId];
+ if( NULL == pAdapter )
+ {
+ VOS_ASSERT(0);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
+
+ // walk the chain until all are processed
+ pVosPacket = pVosPacketChain;
+ do
+ {
+ // get the pointer to the next packet in the chain
+ // (but don't unlink the packet since we free the entire chain later)
+ status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
+
+ // both "success" and "empty" are acceptable results
+ if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure walking packet chain", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ // Extract the OS packet (skb).
+ // Tell VOS to detach the OS packet from the VOS packet
+ status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
+ if(!VOS_IS_STATUS_SUCCESS( status ))
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //hdd_softap_dump_sk_buff(skb);
+
+ skb->dev = pAdapter->dev;
+
+ if(skb->dev == NULL) {
+
+ hddLog(VOS_TRACE_LEVEL_FATAL, "ERROR!!Invalid netdevice\n");
+ return VOS_STATUS_E_FAILURE;
+ }
+ ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
+ ++pAdapter->stats.rx_packets;
+ pAdapter->stats.rx_bytes += skb->len;
+
+ if (WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId)
+ {
+ //MC/BC packets. Duplicate a copy of packet
+ struct sk_buff *pSkbCopy;
+ hdd_ap_ctx_t *pHddApCtx;
+
+ pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
+ if (!(pHddApCtx->apDisableIntraBssFwd))
+ {
+ pSkbCopy = skb_copy(skb, GFP_ATOMIC);
+ if (pSkbCopy)
+ {
+ hdd_softap_sta_2_sta_xmit(pSkbCopy, pSkbCopy->dev,
+ pHddApCtx->uBCStaId, (pRxMetaInfo->ucUP));
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: skb allocation fails", __FUNCTION__);
+ }
+
+
+ } //(WLAN_RX_BCMC_STA_ID == staId)
+
+ if ((WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId) ||
+ (WLAN_RX_SAP_SELF_STA_ID == pRxMetaInfo->ucDesSTAId))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
+ "%s: send one packet to kernel \n", __FUNCTION__);
+
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ rxstat = netif_rx_ni(skb);
+ if (NET_RX_SUCCESS == rxstat)
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
+ }
+ else
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
+ }
+ }
+ else if ((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->apDisableIntraBssFwd)
+ {
+ kfree_skb(skb);
+ }
+ else
+ {
+ //loopback traffic
+ status = hdd_softap_sta_2_sta_xmit(skb, skb->dev,
+ pRxMetaInfo->ucDesSTAId, (pRxMetaInfo->ucUP));
+ }
+
+ // now process the next packet in the chain
+ pVosPacket = pNextVosPacket;
+
+ } while (pVosPacket);
+
+ //Return the entire VOS packet chain to the resource pool
+ status = vos_pkt_return_packet( pVosPacketChain );
+ if(!VOS_IS_STATUS_SUCCESS( status ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __FUNCTION__);
+ }
+
+ pAdapter->dev->last_rx = jiffies;
+
+ return status;
+}
+
+VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
+{
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ hdd_context_t *pHddCtx = pAdapter->pHddCtx;
+
+ //Clear station in TL and then update HDD data structures. This helps
+ //to block RX frames from other station to this station.
+ vosStatus = WLANTL_ClearSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staId );
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "WLANTL_ClearSTAClient() failed to for staID %d. "
+ "Status= %d [0x%08lX]",
+ staId, vosStatus, vosStatus );
+ }
+
+ vosStatus = hdd_softap_deinit_tx_rx_sta ( pAdapter, staId );
+ if( VOS_STATUS_E_FAILURE == vosStatus )
+ {
+ VOS_TRACE ( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "hdd_softap_deinit_tx_rx_sta() failed for staID %d. "
+ "Status = %d [0x%08lX]",
+ staId, vosStatus, vosStatus );
+ return( vosStatus );
+ }
+
+ pHddCtx->sta_to_adapter[staId] = NULL;
+
+ return( vosStatus );
+}
+
+VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter,
+ v_BOOL_t fAuthRequired,
+ v_BOOL_t fPrivacyBit,
+ v_U8_t staId,
+ v_U8_t ucastSig,
+ v_U8_t bcastSig,
+ v_MACADDR_t *pPeerMacAddress,
+ v_BOOL_t fWmmEnabled )
+{
+ VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
+ WLAN_STADescType staDesc;
+ hdd_context_t *pHddCtx = pAdapter->pHddCtx;
+ hdd_adapter_t *pmonAdapter = NULL;
+
+ //eCsrEncryptionType connectedCipherAlgo;
+ //v_BOOL_t fConnected;
+
+ /*
+ * Clean up old entry if it is not cleaned up properly
+ */
+ if ( pAdapter->aStaInfo[staId].isUsed )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "clean up old entry for STA %d", staId);
+ hdd_softap_DeregisterSTA( pAdapter, staId );
+ }
+
+ // Get the Station ID from the one saved during the assocation.
+
+ staDesc.ucSTAId = staId;
+
+
+ /*Save the pAdapter Pointer for this staId*/
+ pHddCtx->sta_to_adapter[staId] = pAdapter;
+
+ staDesc.wSTAType = WLAN_STA_SOFTAP;
+
+ vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
+ vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 );
+ vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "register station \n");
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "station mac %02x:%02x:%02x:%02x:%02x:%02x",
+ staDesc.vSTAMACAddress.bytes[0],
+ staDesc.vSTAMACAddress.bytes[1],
+ staDesc.vSTAMACAddress.bytes[2],
+ staDesc.vSTAMACAddress.bytes[3],
+ staDesc.vSTAMACAddress.bytes[4],
+ staDesc.vSTAMACAddress.bytes[5]);
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "BSSIDforIBSS %02x:%02x:%02x:%02x:%02x:%02x",
+ staDesc.vBSSIDforIBSS.bytes[0],
+ staDesc.vBSSIDforIBSS.bytes[1],
+ staDesc.vBSSIDforIBSS.bytes[2],
+ staDesc.vBSSIDforIBSS.bytes[3],
+ staDesc.vBSSIDforIBSS.bytes[4],
+ staDesc.vBSSIDforIBSS.bytes[5]);
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "SOFTAP SELFMAC %02x:%02x:%02x:%02x:%02x:%02x",
+ staDesc.vSelfMACAddress.bytes[0],
+ staDesc.vSelfMACAddress.bytes[1],
+ staDesc.vSelfMACAddress.bytes[2],
+ staDesc.vSelfMACAddress.bytes[3],
+ staDesc.vSelfMACAddress.bytes[4],
+ staDesc.vSelfMACAddress.bytes[5]);
+
+ vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress);
+
+#ifdef WLAN_SOFTAP_FEATURE
+ staDesc.ucQosEnabled = fWmmEnabled;
+#else
+ // set the QoS field appropriately
+ if (hdd_wmm_is_active(pAdapter))
+ {
+ staDesc.ucQosEnabled = 1;
+ }
+ else
+ {
+ staDesc.ucQosEnabled = 0;
+ }
+#endif
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "HDD SOFTAP register TL QoS_enabled=%d",
+ staDesc.ucQosEnabled );
+
+ staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ;
+
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ /* Enable UMA for TX translation only when there is no concurrent session active */
+ if (vos_concurrent_sessions_running())
+ {
+ staDesc.ucSwFrameTXXlation = 1;
+ }
+ else
+ {
+ staDesc.ucSwFrameTXXlation = 0;
+ }
+
+ // Enable frame translation in software for AMSDU
+ // reception ONLY. The remaining rx is still
+ // translated in HW.
+ staDesc.ucSwFrameRXXlation = 1;
+#else
+ // For PRIMA UMA frame translation is not enable yet.
+ staDesc.ucSwFrameTXXlation = 1;
+ staDesc.ucSwFrameRXXlation = 1;
+#endif
+ staDesc.ucAddRmvLLC = 1;
+
+ // Initialize signatures and state
+ staDesc.ucUcastSig = ucastSig;
+ staDesc.ucBcastSig = bcastSig;
+ staDesc.ucInitState = fAuthRequired ?
+ WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
+
+ // Register the Station with TL...
+ vosStatus = WLANTL_RegisterSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ hdd_softap_rx_packet_cbk,
+ hdd_softap_tx_complete_cbk,
+ hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 );
+
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08lX]",
+ vosStatus, vosStatus );
+ return vosStatus;
+ }
+
+ // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
+ // then go to 'authenticated'. For all other authentication types (those that do
+ // not require upper layer authentication) we can put TL directly into 'authenticated'
+ // state.
+
+ //VOS_ASSERT( fConnected );
+ pAdapter->aStaInfo[staId].ucSTAId = staId;
+ pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
+
+ if ( !fAuthRequired )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
+
+ // Connections that do not need Upper layer auth, transition TL directly
+ // to 'Authenticated' state.
+ vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
+ WLANTL_STA_AUTHENTICATED );
+
+ pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED;
+ pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE;
+ }
+ else
+ {
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
+
+ vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
+ WLANTL_STA_CONNECTED );
+ pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED;
+
+ pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE;
+
+ }
+ pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx);
+ if(pmonAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Turn on Monitor the carrier\n");
+ netif_carrier_on(pmonAdapter->dev);
+ //Enable Tx queue
+ netif_tx_start_all_queues(pmonAdapter->dev);
+ }
+ netif_carrier_on(pAdapter->dev);
+ //Enable Tx queue
+ netif_tx_start_all_queues(pAdapter->dev);
+
+ return( vosStatus );
+}
+
+VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit)
+{
+ VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
+
+
+ pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
+ pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
+ vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0);
+
+ return vosStatus;
+}
+
+VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter)
+{
+ return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
+}
+
+VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter)
+{
+ VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
+ v_U8_t staId = 0;
+
+ vosStatus = hdd_softap_Deregister_BC_STA( pAdapter);
+
+ if (!HAL_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to deregister BC sta Id %d", __FUNCTION__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
+ }
+
+ for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
+ {
+ if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered
+ vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId);
+
+ if (!HAL_STATUS_SUCCESS(vosStatus))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to deregister sta Id %d", __FUNCTION__, staId);
+ }
+ }
+
+ return vosStatus;
+}
+
+VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state)
+{
+ v_U8_t ucSTAId = WLAN_MAX_STA_COUNT;
+ VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ tHalHandle hHalHandle = (tHalHandle ) vos_get_context(VOS_MODULE_ID_HAL, pVosContext);
+#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
+
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: enter", __FUNCTION__);
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ if(!hHalHandle )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_FATAL,
+ "%s: The hHalHandle is NULL ptr value");
+ VOS_ASSERT( 0 );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if (eHAL_STATUS_SUCCESS != halTable_FindStaidByAddr(hHalHandle, (tANI_U8 *)pDestMacAddress, &ucSTAId))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to find right station", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+#else
+ if (eHAL_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to find right station", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
+
+ if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Station MAC address does not matching", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state );
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s: change station to state %d succeed", __FUNCTION__, state);
+
+ if (eHAL_STATUS_SUCCESS == vosStatus)
+ {
+ pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+ "%s exit\n",__FUNCTION__);
+
+ return vosStatus;
+}
+
+
+VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId)
+{
+ v_U8_t i;
+
+ for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
+ {
+ if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) &&
+ pAdapter->aStaInfo[i].isUsed)
+ {
+ *staId = i;
+ return VOS_STATUS_SUCCESS;
+ }
+ }
+
+ return VOS_STATUS_E_FAILURE;
+}
+
+#endif //WLAN_SOFTAP_FEATURE
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
new file mode 100644
index 0000000..d48df9d
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -0,0 +1,1351 @@
+/*
+ * 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 wlan_hdd_tx_rx.c
+
+ \brief Linux HDD Tx/RX APIs
+ Copyright 2008 (c) Qualcomm, Incorporated.
+ All Rights Reserved.
+ Qualcomm Confidential and Proprietary.
+
+ ==========================================================================*/
+
+/*---------------------------------------------------------------------------
+ Include files
+ -------------------------------------------------------------------------*/
+#include <wlan_hdd_tx_rx.h>
+#include <wlan_hdd_softap_tx_rx.h>
+#include <wlan_hdd_dp_utils.h>
+#include <wlan_qct_tl.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+
+#ifdef CONFIG_CFG80211
+#include <wlan_hdd_p2p.h>
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+#include <net/ieee80211_radiotap.h>
+#include "sapApi.h"
+#endif
+
+/*---------------------------------------------------------------------------
+ Preprocessor definitions and constants
+ -------------------------------------------------------------------------*/
+
+const v_U8_t hddWmmAcToHighestUp[] = {
+ SME_QOS_WMM_UP_RESV,
+ SME_QOS_WMM_UP_EE,
+ SME_QOS_WMM_UP_VI,
+ SME_QOS_WMM_UP_NC
+};
+
+//Mapping Linux AC interpretation to TL AC.
+const v_U8_t hdd_QdiscAcToTlAC[] = {
+ WLANTL_AC_VO,
+ WLANTL_AC_VI,
+ WLANTL_AC_BE,
+ WLANTL_AC_BK,
+};
+
+#ifdef CONFIG_CFG80211
+static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
+#endif
+
+/*---------------------------------------------------------------------------
+ Type declarations
+ -------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+ Function definitions and documenation
+ -------------------------------------------------------------------------*/
+
+#ifdef DATA_PATH_UNIT_TEST
+//Utility function to dump an sk_buff
+static void dump_sk_buff(struct sk_buff * skb)
+{
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: head = %p ", __FUNCTION__, skb->head);
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: data = %p ", __FUNCTION__, skb->data);
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p ", __FUNCTION__, skb->tail);
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: end = %p ", __FUNCTION__, skb->end);
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: len = %d ", __FUNCTION__, skb->len);
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d ", __FUNCTION__, skb->data_len);
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d\n", __FUNCTION__, skb->mac_len);
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ",
+ skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
+ skb->data[5], skb->data[6], skb->data[7]);
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n",
+ skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
+ skb->data[13], skb->data[14], skb->data[15]);
+}
+
+//Function for Unit Test only
+static void transport_thread(hdd_adapter_t *pAdapter)
+{
+ v_U8_t staId;
+ WLANTL_ACEnumType ac = WLANTL_AC_BE;
+ vos_pkt_t *pVosPacket = NULL ;
+ vos_pkt_t dummyPacket;
+ WLANTL_MetaInfoType pktMetaInfo;
+ WLANTL_RxMetaInfoType pktRxMetaInfo;
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+
+ status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
+ &staId,
+ &ac,
+ &pVosPacket,
+ &pktMetaInfo );
+ if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test FAIL hdd_tx_fetch_packet_cbk", __FUNCTION__);
+ else
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test PASS hdd_tx_fetch_packet_cbk", __FUNCTION__);
+
+ status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);;
+ if (status != VOS_STATUS_SUCCESS)
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test FAIL hdd_tx_complete_cbk", __FUNCTION__);
+ else
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test PASS hdd_tx_complete_cbk", __FUNCTION__);
+
+ status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
+ if (status != VOS_STATUS_SUCCESS)
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test FAIL hdd_tx_low_resource_cbk", __FUNCTION__);
+ else
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test PASS hdd_tx_low_resource_cbk", __FUNCTION__);
+
+ status = hdd_rx_packet_cbk( pAdapter->pvosContext,
+ &dummyPacket,
+ staId,
+ &pktRxMetaInfo);
+ if (status != VOS_STATUS_SUCCESS)
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test FAIL hdd_rx_packet_cbk", __FUNCTION__);
+ else
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test PASS hdd_rx_packet_cbk", __FUNCTION__);
+
+}
+#endif
+
+
+/**============================================================================
+ @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ v_SINT_t i = -1;
+ hdd_list_node_t *anchor = NULL;
+ skb_list_node_t *pktNode = NULL;
+ struct sk_buff *skb = NULL;
+
+ while (++i != NUM_TX_QUEUES)
+ {
+ //Free up any packets in the Tx queue
+ spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
+ while (true)
+ {
+ status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
+ if(VOS_STATUS_E_EMPTY != status)
+ {
+ pktNode = list_entry(anchor, skb_list_node_t, anchor);
+ skb = pktNode->skb;
+ //TODO
+ //++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
+ kfree_skb(skb);
+ continue;
+ }
+ break;
+ }
+ spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
+ // backpressure is no longer in effect
+ pAdapter->isTxSuspended[i] = VOS_FALSE;
+ }
+
+ return status;
+}
+
+#ifdef CONFIG_CFG80211
+static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
+{
+ skb_list_node_t *pktNode = NULL;
+ struct sk_buff *skb = NULL;
+ v_SIZE_t size = 0;
+ WLANTL_ACEnumType ac = 0;
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ hdd_list_node_t *anchor = NULL;
+
+ if( NULL == pAdapter )
+ {
+ VOS_ASSERT(0);
+ return NULL;
+ }
+
+ // do we have any packets pending in this AC?
+ hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
+ if( size == 0 )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: NO Packet Pending", __FUNCTION__);
+ return NULL;
+ }
+
+ //Remove the packet from the queue
+ spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
+ status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
+ spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
+
+ if(VOS_STATUS_SUCCESS == status)
+ {
+ //If success then we got a valid packet from some AC
+ pktNode = list_entry(anchor, skb_list_node_t, anchor);
+ skb = pktNode->skb;
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Not able to remove Packet from the list",
+ __FUNCTION__);
+
+ return NULL;
+ }
+
+ // if we are in a backpressure situation see if we can turn the hose back on
+ if ( (pAdapter->isTxSuspended[ac]) &&
+ (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "%s: TX queue[%d] re-enabled", __FUNCTION__, ac);
+ pAdapter->isTxSuspended[ac] = VOS_FALSE;
+ /* Enable Queues which we have disabled earlier */
+ netif_tx_start_all_queues( pAdapter->dev );
+ }
+
+ return skb;
+}
+
+void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
+{
+ hdd_cfg80211_state_t *cfgState;
+ struct sk_buff* skb;
+ hdd_adapter_t* pMonAdapter = NULL;
+ struct ieee80211_hdr *hdr;
+
+ if (pAdapter == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: pAdapter is NULL", __func__);
+ return;
+ }
+
+ pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
+
+ cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+
+ if( NULL != cfgState->buf )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Already one MGMT packet Tx going on", __func__);
+ return;
+ }
+
+ skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
+
+ if (NULL == skb)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: No Packet Pending", __func__);
+ return;
+ }
+
+ cfgState->buf = vos_mem_malloc( skb->len ); //buf;
+ if( cfgState->buf == NULL )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to Allocate memory", __func__);
+ goto fail;
+ }
+
+ cfgState->len = skb->len;
+
+ vos_mem_copy( cfgState->buf, skb->data, skb->len);
+
+ cfgState->skb = skb; //buf;
+ cfgState->action_cookie = (tANI_U32)cfgState->buf;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
+ == HDD_FRAME_TYPE_MGMT )
+ {
+ if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
+ == HDD_FRAME_SUBTYPE_DEAUTH )
+ {
+ hdd_softap_sta_deauth( pAdapter, hdr->addr1 );
+ goto mgmt_handled;
+ }
+ else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
+ == HDD_FRAME_SUBTYPE_DISASSOC )
+ {
+ hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
+ goto mgmt_handled;
+ }
+ }
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
+
+ if (eHAL_STATUS_SUCCESS !=
+ WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ skb->data, skb->len) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: WLANSAP_SendAction returned fail", __func__);
+ hdd_sendActionCnf( pAdapter, FALSE );
+ }
+ return;
+
+mgmt_handled:
+ hdd_sendActionCnf( pAdapter, TRUE );
+ return;
+fail:
+ kfree_skb(pAdapter->skb_to_tx);
+ pAdapter->skb_to_tx = NULL;
+ return;
+}
+
+void hdd_mon_tx_work_queue(struct work_struct *work)
+{
+ hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
+ hdd_mon_tx_mgmt_pkt(pAdapter);
+}
+
+int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ v_U16_t rt_hdr_len;
+ struct ieee80211_hdr *hdr;
+ hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ struct ieee80211_radiotap_header *rtap_hdr =
+ (struct ieee80211_radiotap_header *)skb->data;
+
+ /*Supplicant sends the EAPOL packet on monitor interface*/
+ pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
+ if(pPgBkAdapter == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
+ __func__);
+ goto fail; /* too short to be possibly valid */
+ }
+
+ /* check if toal skb length is greater then radio tab header length of not */
+ if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
+ goto fail; /* too short to be possibly valid */
+
+ /* check if radio tap header version is correct or not */
+ if (unlikely(rtap_hdr->it_version))
+ goto fail; /* only version 0 is supported */
+
+ /*Strip off the radio tap header*/
+ rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
+
+ /* check if skb length if greator then total radio tap header length ot not*/
+ if (unlikely(skb->len < rt_hdr_len))
+ goto fail;
+
+ /* Update the trans_start for this netdev */
+ dev->trans_start = jiffies;
+ /*
+ * fix up the pointers accounting for the radiotap
+ * header still being in there.
+ */
+ skb_set_mac_header(skb, rt_hdr_len);
+ skb_set_network_header(skb, rt_hdr_len);
+ skb_set_transport_header(skb, rt_hdr_len);
+
+ /* Pull rtap header out of the skb */
+ skb_pull(skb, rt_hdr_len);
+
+ /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
+ * radio tap header and 802.11 header starts
+ */
+ hdr = (struct ieee80211_hdr *)skb->data;
+
+ /* Send data frames through the normal Data path. In this path we will
+ * conver rcvd 802.11 packet to 802.3 packet */
+ if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
+ {
+ v_U8_t da[6];
+ v_U8_t sa[6];
+
+ memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
+ memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
+
+ /* Pull 802.11 MAC header */
+ skb_pull(skb, HDD_80211_HEADER_LEN);
+
+ if ( HDD_FRAME_SUBTYPE_QOSDATA ==
+ (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
+ {
+ skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
+ }
+
+ /* Pull LLC header */
+ skb_pull(skb, HDD_LLC_HDR_LEN);
+
+ /* Create space for Ethernet header */
+ skb_push(skb, HDD_MAC_HDR_SIZE*2);
+ memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
+ memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
+
+ /* Only EAPOL Data packets are allowed through monitor interface */
+ if (vos_be16_to_cpu(
+ (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
+ != HDD_ETHERTYPE_802_1_X)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Not a Eapol packet. Drop this frame", __func__);
+ //If not EAPOL frames, drop them.
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
+
+ hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
+ return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
+ }
+ else
+ {
+ VOS_STATUS status;
+ WLANTL_ACEnumType ac = 0;
+ skb_list_node_t *pktNode = NULL;
+ v_SIZE_t pktListSize = 0;
+
+ spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
+ //If we have already reached the max queue size, disable the TX queue
+ if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
+ {
+ /* We want to process one packet at a time, so lets disable all TX queues
+ * and re-enable the queues once we get TX feedback for this packet */
+ netif_tx_stop_all_queues(pAdapter->dev);
+ pAdapter->isTxSuspended[ac] = VOS_TRUE;
+ spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+ return NETDEV_TX_BUSY;
+ }
+ spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+
+ //Use the skb->cb field to hold the list node information
+ pktNode = (skb_list_node_t *)&skb->cb;
+
+ //Stick the OS packet inside this node.
+ pktNode->skb = skb;
+
+ INIT_LIST_HEAD(&pktNode->anchor);
+
+ //Insert the OS packet into the appropriate AC queue
+ spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
+ status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
+ &pktNode->anchor, &pktListSize );
+ spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s:Insert Tx queue failed. Pkt dropped", __FUNCTION__);
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if ( pktListSize == 1 )
+ {
+ /* In this context we cannot acquire any mutex etc. And to transmit
+ * this packet we need to call SME API. So to take care of this we will
+ * schedule a workqueue
+ */
+ schedule_work(&pPgBkAdapter->monTxWorkQueue);
+ }
+ return NETDEV_TX_OK;
+ }
+
+fail:
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "%s: Packet Rcvd at Monitor interface is not proper,"
+ " Dropping the packet",
+ __func__);
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+#endif
+/**============================================================================
+ @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
+ transmitting packets. There are 2 versions of this function. One that uses
+ locked queue and other that uses lockless queues. Both have been retained to
+ do some performance testing
+
+ @param skb : [in] pointer to OS packet (sk_buff)
+ @param dev : [in] pointer to Libra network device
+
+ @return : NET_XMIT_DROP if packets are dropped
+ : NET_XMIT_SUCCESS if packet is enqueued succesfully
+ ===========================================================================*/
+int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ VOS_STATUS status;
+ WLANTL_ACEnumType ac;
+ sme_QosWmmUpType up;
+ skb_list_node_t *pktNode = NULL;
+ hdd_list_node_t *anchor = NULL;
+ v_SIZE_t pktListSize = 0;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ v_BOOL_t granted;
+
+ hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
+
+ v_BOOL_t txSuspended = VOS_FALSE;
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
+
+ //Get TL AC corresponding to Qdisc queue index/AC.
+ ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
+
+ //user priority from IP header, which is already extracted and set from
+ //select_queue call back function
+ up = skb->priority;
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
+
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: Classified as ac %d up %d", __FUNCTION__, ac, up);
+#endif // HDD_WMM_DEBUG
+
+ spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
+
+ //If we have already reached the max queue size, disable the TX queue
+ if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
+
+ netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
+ pAdapter->isTxSuspended[ac] = VOS_TRUE;
+ txSuspended = VOS_TRUE;
+ }
+
+ spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+ if (VOS_TRUE == txSuspended)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "%s: TX queue full for AC=%d Disable OS TX queue",
+ __FUNCTION__, ac );
+ return NETDEV_TX_BUSY;
+ }
+
+ //Use the skb->cb field to hold the list node information
+ pktNode = (skb_list_node_t *)&skb->cb;
+
+ //Stick the OS packet inside this node.
+ pktNode->skb = skb;
+
+ //Stick the User Priority inside this node
+ pktNode->userPriority = up;
+
+
+ INIT_LIST_HEAD(&pktNode->anchor);
+
+ //Insert the OS packet into the appropriate AC queue
+ spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
+ status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
+ spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s:Insert Tx queue failed. Pkt dropped", __FUNCTION__);
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+ ++pAdapter->stats.tx_dropped;
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
+
+ //Make sure we have access to this access category
+ if (likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) ||
+ ( pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
+ {
+ granted = VOS_TRUE;
+ }
+ else
+ {
+ status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
+ }
+
+ if ( granted && ( pktListSize == 1 ))
+ {
+ //Let TL know we have a packet to send for this AC
+ //VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __FUNCTION__);
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pHddStaCtx->conn_info.staId[0], ac );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Failed to signal TL for AC=%d", __FUNCTION__, ac );
+
+ //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
+ //as we are in a soft irq context. Also it must be the same packet that we just allocated.
+ spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
+ status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
+ spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+ }
+
+ dev->trans_start = jiffies;
+
+ return NETDEV_TX_OK;
+}
+
+/**============================================================================
+ @brief hdd_tx_timeout() - Function called by OS if there is any
+ timeout during transmission. Since HDD simply enqueues packet
+ and returns control to OS right away, this would never be invoked
+
+ @param dev : [in] pointer to Libra network device
+ @return : None
+ ===========================================================================*/
+void hdd_tx_timeout(struct net_device *dev)
+{
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Transmission timeout occurred", __FUNCTION__);
+ //Getting here implies we disabled the TX queues for too long. Queues are
+ //disabled either because of disassociation or low resource scenarios. In
+ //case of disassociation it is ok to ignore this. But if associated, we have
+ //do possible recovery here
+}
+
+
+/**============================================================================
+ @brief hdd_stats() - Function registered with the Linux OS for
+ device TX/RX statistic
+
+ @param dev : [in] pointer to Libra network device
+
+ @return : pointer to net_device_stats structure
+ ===========================================================================*/
+struct net_device_stats* hdd_stats(struct net_device *dev)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ return &pAdapter->stats;
+}
+
+
+/**============================================================================
+ @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ v_SINT_t i = -1;
+
+ pAdapter->isVosOutOfResource = VOS_FALSE;
+
+ //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
+ //Will be zeroed out during alloc
+
+ while (++i != NUM_TX_QUEUES)
+ {
+ pAdapter->isTxSuspended[i] = VOS_FALSE;
+ hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
+ }
+
+ return status;
+}
+
+
+/**============================================================================
+ @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ v_SINT_t i = -1;
+
+ status = hdd_flush_tx_queues(pAdapter);
+ while (++i != NUM_TX_QUEUES)
+ {
+ //Free up actual list elements in the Tx queue
+ hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
+ }
+
+ return status;
+}
+
+
+/**============================================================================
+ @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
+ modules in HDD
+
+ @param pAdapter : [in] pointer to adapter context
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
+{
+ return hdd_flush_tx_queues(pAdapter);
+}
+
+
+/**============================================================================
+ @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
+
+ @param pVosPacket : [in] pointer to vos packet
+ @return : VOS_TRUE if the packet is EAPOL
+ : VOS_FALSE otherwise
+ ===========================================================================*/
+
+v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
+{
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ v_BOOL_t fEAPOL = VOS_FALSE;
+ void *pBuffer = NULL;
+
+
+ vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
+ &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
+ if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ if ( vos_be16_to_cpu( *(unsigned short*)pBuffer ) == HDD_ETHERTYPE_802_1_X )
+ {
+ fEAPOL = VOS_TRUE;
+ }
+ }
+
+ return fEAPOL;
+}
+
+
+#ifdef FEATURE_WLAN_WAPI // Need to update this function
+/**============================================================================
+ @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
+
+ @param pVosPacket : [in] pointer to vos packet
+ @return : VOS_TRUE if the packet is WAI
+ : VOS_FALSE otherwise
+ ===========================================================================*/
+
+v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
+{
+ VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
+ v_BOOL_t fIsWAI = VOS_FALSE;
+ void *pBuffer = NULL;
+
+ // Need to update this function
+ vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
+ &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
+
+ if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ if ( vos_be16_to_cpu( *(unsigned short*)pBuffer ) == HDD_ETHERTYPE_WAI)
+ {
+ fIsWAI = VOS_TRUE;
+ }
+ }
+
+ return fIsWAI;
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+/**============================================================================
+ @brief hdd_tx_complete_cbk() - Callback function invoked by TL
+ to indicate that a packet has been transmitted across the SDIO bus
+ succesfully. OS packet resources can be released after this cbk.
+
+ @param vosContext : [in] pointer to VOS context
+ @param pVosPacket : [in] pointer to VOS packet (containing skb)
+ @param vosStatusIn : [in] status of the transmission
+
+ @return : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
+ vos_pkt_t *pVosPacket,
+ VOS_STATUS vosStatusIn )
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ hdd_adapter_t *pAdapter = NULL;
+ hdd_context_t *pHddCtx = NULL;
+ void* pOsPkt = NULL;
+
+ if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Return the skb to the OS
+ status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
+ if(!VOS_IS_STATUS_SUCCESS( status ))
+ {
+ //This is bad but still try to free the VOSS resources if we can
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __FUNCTION__);
+ vos_pkt_return_packet( pVosPacket );
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Get the HDD context.
+ pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
+ //Get the Adapter context.
+ pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
+ if(pAdapter == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ }
+ else
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
+ }
+
+ kfree_skb((struct sk_buff *)pOsPkt);
+
+ //Return the VOS packet resources.
+ status = vos_pkt_return_packet( pVosPacket );
+ if(!VOS_IS_STATUS_SUCCESS( status ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Could not return VOS packet to the pool", __FUNCTION__);
+ }
+
+ return status;
+}
+
+
+/**============================================================================
+ @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
+ fetch a packet for transmission.
+
+ @param vosContext : [in] pointer to VOS context
+ @param staId : [in] Station for which TL is requesting a pkt
+ @param ac : [in] access category requested by TL
+ @param pVosPacket : [out] pointer to VOS packet packet pointer
+ @param pPktMetaInfo : [out] pointer to meta info for the pkt
+
+ @return : VOS_STATUS_E_EMPTY if no packets to transmit
+ : VOS_STATUS_E_FAILURE if any errors encountered
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
+ v_U8_t *pStaId,
+ WLANTL_ACEnumType ac,
+ vos_pkt_t **ppVosPacket,
+ WLANTL_MetaInfoType *pPktMetaInfo )
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ hdd_adapter_t *pAdapter = NULL;
+ hdd_context_t *pHddCtx = NULL;
+ hdd_list_node_t *anchor = NULL;
+ skb_list_node_t *pktNode = NULL;
+ struct sk_buff *skb = NULL;
+ vos_pkt_t *pVosPacket = NULL;
+ v_MACADDR_t* pDestMacAddress = NULL;
+ v_TIME_t timestamp;
+ WLANTL_ACEnumType newAc;
+ v_SIZE_t size = 0;
+ tANI_U8 acAdmitted, i;
+
+ //Sanity check on inputs
+ if ( ( NULL == vosContext ) ||
+ ( NULL == pStaId ) ||
+ ( NULL == ppVosPacket ) ||
+ ( NULL == pPktMetaInfo ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null Params being passed", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Get the HDD context.
+ pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
+ if(pHddCtx == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pAdapter = pHddCtx->sta_to_adapter[*pStaId];
+ if( NULL == pAdapter )
+ {
+ VOS_ASSERT(0);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
+
+ *ppVosPacket = NULL;
+
+ //Make sure the AC being asked for is sane
+ if( ac >= WLANTL_MAX_AC || ac < 0)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Invalid AC %d passed by TL", __FUNCTION__, ac);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
+
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,"%s: AC %d passed by TL", __FUNCTION__, ac);
+#endif // HDD_WMM_DEBUG
+
+ // We find an AC with packets
+ // or we determine we have no more packets to send
+ // HDD is not allowed to change AC.
+
+ // has this AC been admitted? or
+ // To allow EAPOL packets when not authenticated
+ if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: no packets pending", __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ // do we have any packets pending in this AC?
+ hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
+ if( size > 0 )
+ {
+ // yes, so process it
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: AC %d has packets pending", __FUNCTION__, ac);
+#endif // HDD_WMM_DEBUG
+ }
+ else
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: no packets pending", __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
+ //This simplifies the locking and unlocking of Tx queue
+ status = vos_pkt_wrap_data_packet( &pVosPacket,
+ VOS_PKT_TYPE_TX_802_3_DATA,
+ NULL, //OS Pkt is not being passed
+ hdd_tx_low_resource_cbk,
+ pAdapter );
+
+ if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
+ {
+ //Remember VOS is in a low resource situation
+ pAdapter->isVosOutOfResource = VOS_TRUE;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: VOSS in Low Resource scenario", __FUNCTION__);
+ //TL will now think we have no more packets in this AC
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Remove the packet from the queue
+ spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
+ status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
+ spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
+
+ if(VOS_STATUS_SUCCESS == status)
+ {
+ //If success then we got a valid packet from some AC
+ pktNode = list_entry(anchor, skb_list_node_t, anchor);
+ skb = pktNode->skb;
+ }
+ else
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Error in de-queuing "
+ "skb from Tx queue status = %d", __FUNCTION__, status );
+ vos_pkt_return_packet(pVosPacket);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Attach skb to VOS packet.
+ status = vos_pkt_set_os_packet( pVosPacket, skb );
+ if (status != VOS_STATUS_SUCCESS)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Error attaching skb", __FUNCTION__);
+ vos_pkt_return_packet(pVosPacket);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
+ kfree_skb(skb);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Just being paranoid. To be removed later
+ if(pVosPacket == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: VOS packet returned by VOSS is NULL", __FUNCTION__);
+ ++pAdapter->stats.tx_dropped;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
+ kfree_skb(skb);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Return VOS packet to TL;
+ *ppVosPacket = pVosPacket;
+
+ //Fill out the meta information needed by TL
+ //FIXME This timestamp is really the time stamp of wrap_data_packet
+ vos_pkt_get_timestamp( pVosPacket, ×tamp );
+ pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
+
+ if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
+ pPktMetaInfo->ucIsEapol = 0;
+ else
+ pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
+
+#ifdef FEATURE_WLAN_WAPI
+ // Override usIsEapol value when its zero for WAPI case
+ pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
+#endif /* FEATURE_WLAN_WAPI */
+
+ if ((HDD_WMM_USER_MODE_NO_QOS == pHddCtx->cfg_ini->WmmMode) ||
+ (!pAdapter->hddWmmStatus.wmmQap))
+ {
+ // either we don't want QoS or the AP doesn't support QoS
+ pPktMetaInfo->ucUP = 0;
+ pPktMetaInfo->ucTID = 0;
+ }
+ else
+ {
+ /* 1. Check if ACM is set for this AC
+ * 2. If set, check if this AC had already admitted
+ * 3. If not already admitted, downgrade the UP to next best UP */
+ if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
+ pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid)
+ {
+ pPktMetaInfo->ucUP = pktNode->userPriority;
+ pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
+ }
+ else
+ {
+ //Downgrade the UP
+ acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
+ newAc = WLANTL_AC_BK;
+ for (i=ac-1; i>0; i--)
+ {
+ if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
+ {
+ newAc = i;
+ break;
+ }
+ }
+ pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
+ pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,"Downgrading UP %d to UP %d ", pktNode->userPriority, pPktMetaInfo->ucUP);
+ }
+ }
+
+ pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
+ pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
+ if ( 1 < size )
+ {
+ pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
+ }
+ else
+ {
+ pPktMetaInfo->bMorePackets = 0;
+ }
+
+ //Extract the destination address from ethernet frame
+ pDestMacAddress = (v_MACADDR_t*)skb->data;
+ pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
+ pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
+
+
+
+ // if we are in a backpressure situation see if we can turn the hose back on
+ if ( (pAdapter->isTxSuspended[ac]) &&
+ (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "%s: TX queue[%d] re-enabled", __FUNCTION__, ac);
+ pAdapter->isTxSuspended[ac] = VOS_FALSE;
+ netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
+ skb_get_queue_mapping(skb) ));
+ }
+
+
+ // We're giving the packet to TL so consider it transmitted from
+ // a statistics perspective. We account for it here instead of
+ // when the packet is returned for two reasons. First, TL will
+ // manipulate the skb to the point where the len field is not
+ // accurate, leading to inaccurate byte counts if we account for
+ // it later. Second, TL does not provide any feedback as to
+ // whether or not the packet was successfully sent over the air,
+ // so the packet counts will be the same regardless of where we
+ // account for them
+ pAdapter->stats.tx_bytes += skb->len;
+ ++pAdapter->stats.tx_packets;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
+ ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
+
+ if(pHddCtx->cfg_ini->thermalMitigationEnable)
+ {
+ if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Tm Lock fail", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
+ {
+ if(0 == pHddCtx->tmInfo.txFrameCount)
+ {
+ /* Just recovered from sleep timeout */
+ pHddCtx->tmInfo.lastOpenTs = timestamp;
+ }
+
+ if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
+ (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
+ {
+ spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
+ /* During TX open duration, TX frame count is larger than threshold
+ * Block TX during Sleep time */
+ netif_tx_stop_all_queues(pAdapter->dev);
+ spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+ pHddCtx->tmInfo.lastblockTs = timestamp;
+ if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
+ {
+ vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
+ }
+ }
+ else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
+ (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
+ {
+ /* During TX open duration, TX frame count is less than threshold
+ * Reset count and timestamp to prepare next cycle */
+ pHddCtx->tmInfo.lastOpenTs = timestamp;
+ pHddCtx->tmInfo.txFrameCount = 0;
+ }
+ else
+ {
+ /* Do Nothing */
+ }
+ pHddCtx->tmInfo.txFrameCount++;
+ }
+ mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
+ }
+
+
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,"%s: Valid VOS PKT returned to TL", __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+
+ return status;
+}
+
+
+/**============================================================================
+ @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
+ case where VOS packets are not available at the time of the call to get
+ packets. This callback function is invoked by VOS when packets are
+ available.
+
+ @param pVosPacket : [in] pointer to VOS packet
+ @param userData : [in] opaque user data that was passed initially
+
+ @return : VOS_STATUS_E_FAILURE if any errors encountered,
+ : VOS_STATUS_SUCCESS otherwise
+ =============================================================================*/
+VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
+ v_VOID_t *userData )
+{
+ VOS_STATUS status;
+ v_SINT_t i = 0;
+ v_SIZE_t size = 0;
+ hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
+
+ if(pAdapter == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ //Return the packet to VOS. We just needed to know that VOS is out of low resource
+ //situation. Here we will only signal TL that there is a pending data for a STA.
+ //VOS packet will be requested (if needed) when TL comes back to fetch data.
+ vos_pkt_return_packet( pVosPacket );
+
+ pAdapter->isVosOutOfResource = VOS_FALSE;
+
+ //Indicate to TL that there is pending data if a queue is non empty
+ for( i=NUM_TX_QUEUES-1; i>=0; --i )
+ {
+ size = 0;
+ hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
+ if ( size > 0 )
+ {
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
+ (WLANTL_ACEnumType)i );
+ if( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure in indicating pkt to TL for ac=%d", __FUNCTION__,i);
+ }
+ }
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+
+/**============================================================================
+ @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
+ TL will call this to notify the HDD when one or more packets were
+ received for a registered STA.
+
+ @param vosContext : [in] pointer to VOS context
+ @param pVosPacketChain : [in] pointer to VOS packet chain
+ @param staId : [in] Station Id
+ @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
+
+ @return : VOS_STATUS_E_FAILURE if any errors encountered,
+ : VOS_STATUS_SUCCESS otherwise
+ ===========================================================================*/
+VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
+ vos_pkt_t *pVosPacketChain,
+ v_U8_t staId,
+ WLANTL_RxMetaInfoType* pRxMetaInfo )
+{
+ hdd_adapter_t *pAdapter = NULL;
+ hdd_context_t *pHddCtx = NULL;
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ int rxstat;
+ struct sk_buff *skb = NULL;
+ vos_pkt_t* pVosPacket;
+ vos_pkt_t* pNextVosPacket;
+
+ //Sanity check on inputs
+ if ( ( NULL == vosContext ) ||
+ ( NULL == pVosPacketChain ) ||
+ ( NULL == pRxMetaInfo ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
+ if ( NULL == pHddCtx )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pAdapter = pHddCtx->sta_to_adapter[staId];
+ if( NULL == pAdapter )
+ {
+ VOS_ASSERT(0);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
+
+ // walk the chain until all are processed
+ pVosPacket = pVosPacketChain;
+ do
+ {
+ // get the pointer to the next packet in the chain
+ // (but don't unlink the packet since we free the entire chain later)
+ status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
+
+ // both "success" and "empty" are acceptable results
+ if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure walking packet chain", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ // Extract the OS packet (skb).
+ // Tell VOS to detach the OS packet from the VOS packet
+ status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
+ if(!VOS_IS_STATUS_SUCCESS( status ))
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ skb->dev = pAdapter->dev;
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
+ ++pAdapter->stats.rx_packets;
+ pAdapter->stats.rx_bytes += skb->len;
+ rxstat = netif_rx_ni(skb);
+ if (NET_RX_SUCCESS == rxstat)
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
+ }
+ else
+ {
+ ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
+ }
+ // now process the next packet in the chain
+ pVosPacket = pNextVosPacket;
+
+ } while (pVosPacket);
+
+ //Return the entire VOS packet chain to the resource pool
+ status = vos_pkt_return_packet( pVosPacketChain );
+ if(!VOS_IS_STATUS_SUCCESS( status ))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __FUNCTION__);
+ }
+
+ pAdapter->dev->last_rx = jiffies;
+
+ return status;
+}
+
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
new file mode 100644
index 0000000..4dc3cc7
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -0,0 +1,6054 @@
+/*
+ * 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 wlan_hdd_wext.c
+
+ \brief Airgo Linux Wireless Extensions Common Control Plane Types and
+ interfaces.
+
+ $Id: wlan_hdd_wext.c,v 1.34 2007/04/14 01:49:23 jimz Exp jimz $
+
+ Copyright (C) 2007 Airgo Networks, Incorporated
+
+ This file defines all of the types that are utilized by the CCP module
+ of the "Portable" HDD. This file also includes the underlying Linux
+ Wireless Extensions Data types referred to by CCP.
+
+ ======================================================================== */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/wireless.h>
+#include <wlan_hdd_includes.h>
+#include <wlan_btc_svc.h>
+#include <wlan_nlink_common.h>
+#ifdef WLAN_BTAMP_FEATURE
+#include <bap_hdd_main.h>
+#endif
+#include <vos_api.h>
+#include <net/arp.h>
+#include "ccmApi.h"
+#include "sirParams.h"
+#include "csrApi.h"
+#include "csrInsideApi.h"
+#if defined WLAN_FEATURE_VOWIFI
+#include "smeRrmInternal.h"
+#endif
+#include <aniGlobal.h>
+#include "dot11f.h"
+#include <wlan_hdd_wowl.h>
+#include <wlan_hdd_cfg.h>
+#include <wlan_hdd_wmm.h>
+#include "utilsApi.h"
+#ifdef WLAN_FEATURE_P2P
+#include "wlan_hdd_p2p.h"
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include "wlan_hdd_power.h"
+#include "qwlan_version.h"
+#include <vos_power.h>
+#include "wlan_hdd_host_offload.h"
+#include "wlan_hdd_keep_alive.h"
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+#include "wlan_hdd_packet_filtering.h"
+#endif
+
+#ifdef CONFIG_CFG80211
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+#endif
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include "wlan_qct_pal_trace.h"
+#endif // FEATURE_WLAN_INTEGRATED_SOC
+
+#include "wlan_hdd_misc.h"
+#include "bap_hdd_misc.h"
+
+#include "wlan_hdd_dev_pwr.h"
+#include "qc_sap_ioctl.h"
+#define WE_MAX_STR_LEN 1024
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+extern void hdd_suspend_wlan(struct early_suspend *wlan_suspend);
+extern void hdd_resume_wlan(struct early_suspend *wlan_suspend);
+#endif
+
+
+#define HDD_FINISH_ULA_TIME_OUT 800
+
+extern int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand);
+int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
+
+static int ioctl_debug = 0;
+module_param(ioctl_debug, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+struct statsContext
+{
+ struct completion completion;
+ hdd_adapter_t *pAdapter;
+ unsigned int magic;
+};
+
+#define STATS_CONTEXT_MAGIC 0x53544154 //STAT
+#define RSSI_CONTEXT_MAGIC 0x52535349 //RSSI
+#define POWER_CONTEXT_MAGIC 0x504F5752 // POWR
+
+/* To Validate Channel against the Frequency and Vice-Versa */
+static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2},
+ {2422, 3}, {2427, 4}, {2432, 5}, {2437, 6}, {2442, 7}, {2447, 8},
+ {2452, 9}, {2457, 10}, {2462, 11}, {2467 ,12}, {2472, 13},
+ {2484, 14}, {4920, 240}, {4940, 244}, {4960, 248}, {4980, 252},
+ {5040, 208}, {5060, 212}, {5080, 216}, {5180, 36}, {5200, 40}, {5220, 44},
+ {5240, 48}, {5260, 52}, {5280, 56}, {5300, 60}, {5320, 64}, {5500, 100},
+ {5520, 104}, {5540, 108}, {5560, 112}, {5580, 116}, {5600, 120},
+ {5620, 124}, {5640, 128}, {5660, 132}, {5680, 136}, {5700, 140},
+ {5745, 149}, {5765, 153}, {5785, 157}, {5805, 161}, {5825, 165} };
+
+#define FREQ_CHAN_MAP_TABLE_SIZE sizeof(freq_chan_map)/sizeof(freq_chan_map[0])
+
+/* Private ioctls and their sub-ioctls */
+#define WLAN_PRIV_SET_INT_GET_NONE (SIOCIWFIRSTPRIV + 0)
+#define WE_SET_11D_STATE 1
+#define WE_WOWL 2
+#define WE_SET_POWER 3
+#define WE_SET_MAX_ASSOC 4
+#define WE_SET_SAP_AUTO_CHANNEL_SELECTION 5
+#define WE_SET_DATA_INACTIVITY_TO 6
+#define WE_SET_MAX_TX_POWER 7
+#define WE_SET_HIGHER_DTIM_TRANSITION 8
+#define WE_SET_TM_LEVEL 9
+
+/* Private ioctls and their sub-ioctls */
+#define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1)
+#define WE_GET_11D_STATE 1
+#define WE_IBSS_STATUS 2
+#define WE_PMC_STATE 3
+#define WE_GET_WLAN_DBG 4
+#define WE_MODULE_DOWN_IND 5
+#define WE_GET_MAX_ASSOC 6
+#define WE_GET_WDI_DBG 7
+#define WE_GET_SAP_AUTO_CHANNEL_SELECTION 8
+#define WE_GET_CONCURRENCY_MODE 9
+/* Private ioctls and their sub-ioctls */
+#define WLAN_PRIV_SET_INT_GET_INT (SIOCIWFIRSTPRIV + 2)
+
+/* Private ioctls and their sub-ioctls */
+#define WLAN_PRIV_SET_CHAR_GET_NONE (SIOCIWFIRSTPRIV + 3)
+#define WE_WOWL_ADD_PTRN 1
+#define WE_WOWL_DEL_PTRN 2
+#if defined WLAN_FEATURE_VOWIFI
+#define WE_NEIGHBOR_REPORT_REQUEST 3
+#endif
+#define WE_SET_AP_WPS_IE 4 //This is called in station mode to set probe rsp ie.
+#define WE_SET_CONFIG 5
+
+/* Private ioctls and their sub-ioctls */
+#define WLAN_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV + 4)
+#define WE_SET_WLAN_DBG 1
+#define WE_SET_WDI_DBG 2
+#define WE_SET_SAP_CHANNELS 3
+
+/* Private ioctls and their sub-ioctls */
+#define WLAN_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 5)
+#define WE_WLAN_VERSION 1
+#define WE_GET_STATS 2
+#define WE_GET_CFG 3
+#define WE_GET_WMM_STATUS 4
+#define WE_GET_CHANNEL_LIST 5
+
+/* Private ioctls and their sub-ioctls */
+#define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6)
+#define WE_CLEAR_STATS 1
+#define WE_INIT_AP 2
+#define WE_STOP_AP 3
+#define WE_ENABLE_AMP 4
+#define WE_DISABLE_AMP 5
+
+/* Private ioctls and their sub-ioctls */
+#define WLAN_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV + 7)
+#define WE_LOG_DUMP_CMD 1
+
+#ifdef WLAN_FEATURE_P2P
+#define WE_P2P_NOA_CMD 2
+#endif
+
+#define MAX_VAR_ARGS 7
+
+/* Private ioctls (with no sub-ioctls) */
+/* note that they must be odd so that they have "get" semantics */
+#define WLAN_PRIV_ADD_TSPEC (SIOCIWFIRSTPRIV + 9)
+#define WLAN_PRIV_DEL_TSPEC (SIOCIWFIRSTPRIV + 11)
+#define WLAN_PRIV_GET_TSPEC (SIOCIWFIRSTPRIV + 13)
+
+#ifdef FEATURE_WLAN_WAPI
+/* Private ioctls EVEN NO: SET, ODD NO:GET */
+#define WLAN_PRIV_SET_WAPI_MODE (SIOCIWFIRSTPRIV + 8)
+#define WLAN_PRIV_GET_WAPI_MODE (SIOCIWFIRSTPRIV + 16)
+#define WLAN_PRIV_SET_WAPI_ASSOC_INFO (SIOCIWFIRSTPRIV + 10)
+#define WLAN_PRIV_SET_WAPI_KEY (SIOCIWFIRSTPRIV + 12)
+#define WLAN_PRIV_SET_WAPI_BKID (SIOCIWFIRSTPRIV + 14)
+#define WLAN_PRIV_GET_WAPI_BKID (SIOCIWFIRSTPRIV + 15)
+#define WAPI_PSK_AKM_SUITE 0x02721400
+#define WAPI_CERT_AKM_SUITE 0x01721400
+#endif
+
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#define WLAN_PRIV_SET_FTIES (SIOCIWFIRSTPRIV + 20)
+#endif
+
+/* Private ioctl for setting the host offload feature */
+#define WLAN_PRIV_SET_HOST_OFFLOAD (SIOCIWFIRSTPRIV + 18)
+
+/* Private ioctl to get the statistics */
+#define WLAN_GET_WLAN_STATISTICS (SIOCIWFIRSTPRIV + 21)
+
+/* Private ioctl to set the Keep Alive Params */
+#define WLAN_SET_KEEPALIVE_PARAMS (SIOCIWFIRSTPRIV + 22)
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+/* Private ioctl to set the Packet Filtering Params */
+#define WLAN_SET_PACKET_FILTER_PARAMS (SIOCIWFIRSTPRIV + 23)
+#endif
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+/* Private ioctl to get the statistics */
+#define WLAN_SET_PNO (SIOCIWFIRSTPRIV + 24)
+#endif
+
+#define WLAN_SET_BAND_CONFIG (SIOCIWFIRSTPRIV + 25) /*Don't change this number*/
+
+#define WLAN_PRIV_SET_MCBC_FILTER (SIOCIWFIRSTPRIV + 26)
+#define WLAN_PRIV_CLEAR_MCBC_FILTER (SIOCIWFIRSTPRIV + 27)
+#define WLAN_SET_POWER_PARAMS (SIOCIWFIRSTPRIV + 29)
+#define WLAN_GET_LINK_SPEED (SIOCIWFIRSTPRIV + 31)
+
+#define WLAN_STATS_INVALID 0
+#define WLAN_STATS_RETRY_CNT 1
+#define WLAN_STATS_MUL_RETRY_CNT 2
+#define WLAN_STATS_TX_FRM_CNT 3
+#define WLAN_STATS_RX_FRM_CNT 4
+#define WLAN_STATS_FRM_DUP_CNT 5
+#define WLAN_STATS_FAIL_CNT 6
+#define WLAN_STATS_RTS_FAIL_CNT 7
+#define WLAN_STATS_ACK_FAIL_CNT 8
+#define WLAN_STATS_RTS_SUC_CNT 9
+#define WLAN_STATS_RX_DISCARD_CNT 10
+#define WLAN_STATS_RX_ERROR_CNT 11
+#define WLAN_STATS_TX_BYTE_CNT 12
+
+#define WLAN_STATS_RX_BYTE_CNT 13
+#define WLAN_STATS_RX_RATE 14
+#define WLAN_STATS_TX_RATE 15
+
+#define FILL_TLV(__p, __type, __size, __val, __tlen) \
+{\
+ if ((__tlen + __size + 2) < WE_MAX_STR_LEN) \
+ {\
+ *__p++ = __type;\
+ *__p++ = __size;\
+ memcpy(__p, __val, __size);\
+ __p += __size;\
+ __tlen += __size + 2;\
+ }\
+ else \
+ { \
+ hddLog(VOS_TRACE_LEVEL_ERROR, "FILL_TLV Failed!!!\n");\
+ } \
+}while(0);
+
+#define VERSION_VALUE_MAX_LEN 32
+
+#define TX_PER_TRACKING_DEFAULT_RATIO 5
+#define TX_PER_TRACKING_MAX_RATIO 10
+#define TX_PER_TRACKING_DEFAULT_WATERMARK 5
+
+#define WLAN_HDD_UI_BAND_AUTO 0
+#define WLAN_HDD_UI_BAND_5_GHZ 1
+#define WLAN_HDD_UI_BAND_2_4_GHZ 2
+#define WLAN_HDD_UI_SET_BAND_VALUE_OFFSET 8
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest);
+void wlan_hdd_set_mc_addr_list(hdd_context_t *pHddCtx, v_U8_t set);
+#endif
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+/**---------------------------------------------------------------------------
+
+ \brief hdd_wlan_get_version() -
+
+ This function use to get Wlan Driver And Firmware Version.
+
+ \param - pAdapter Pointer to the adapter.
+ wrqu - Pointer to IOCTL REQUEST Data.
+ extra - Pointer to char
+
+ \return - 0 for success, non zero for failure
+
+ --------------------------------------------------------------------------*/
+int hdd_wlan_get_version(hdd_adapter_t *pAdapter, union iwreq_data *wrqu,
+ char *extra)
+{
+ VOS_STATUS status;
+ FwVersionInfo fwversion;
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ v_U32_t reg_val;
+ char *buf = extra;
+
+ buf += snprintf(buf, VERSION_VALUE_MAX_LEN, "%s_", WLAN_CHIP_VERSION);
+ /*Read the RevID*/
+ status = sme_DbgReadRegister(hHal, QWLAN_RFAPB_REV_ID_REG, ®_val);
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) ) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s Failed!!!\n", __func__);
+ return -EINVAL;
+ }
+
+ buf += snprintf(buf, VERSION_VALUE_MAX_LEN, "%x.%x-", (v_U8_t)(reg_val >> 8),
+ (v_U8_t)(reg_val & 0x000000FF));
+
+ status = sme_GetFwVersion(hHal, &fwversion);
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) ) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s Failed!!!\n", __func__);
+ return -EINVAL;
+ }
+ buf += snprintf(buf, VERSION_VALUE_MAX_LEN, "%s-", QWLAN_VERSIONSTR);
+ buf += snprintf(buf, VERSION_VALUE_MAX_LEN, "%ld.%ld.%ld.%ld",
+ fwversion.uMj, fwversion.uMn,
+ fwversion.uPatch, fwversion.uBuild);
+ wrqu->data.length = strlen(extra);
+
+ return 0;
+}
+
+#endif
+int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu)
+{
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ v_U32_t threshold = 0,status = 0;
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return status;
+ }
+
+ if ( eHAL_STATUS_SUCCESS !=
+ ccmCfgGetInt(hHal, WNI_CFG_RTS_THRESHOLD, &threshold) )
+ {
+ return -EIO;
+ }
+ wrqu->rts.value = threshold;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ ("Rts-Threshold=%ld!!\n"), wrqu->rts.value);
+
+ EXIT();
+
+ return 0;
+}
+
+int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu)
+{
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ v_U32_t threshold = 0,status = 0;
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return status;
+ }
+
+ if ( ccmCfgGetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, &threshold)
+ != eHAL_STATUS_SUCCESS )
+ {
+ return -EIO;
+ }
+ wrqu->frag.value = threshold;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ ("Frag-Threshold=%ld!!\n"), wrqu->frag.value);
+
+ EXIT();
+
+ return 0;
+}
+
+int hdd_wlan_get_freq(v_U32_t channel, v_U32_t *pfreq)
+{
+ if((channel > 0) && (channel <= (FREQ_CHAN_MAP_TABLE_SIZE - 1)))
+ {
+ *pfreq = freq_chan_map[channel - 1].freq * 100000;
+ return 0;
+ }
+ else
+ return -EINVAL;
+}
+
+static v_BOOL_t
+hdd_IsAuthTypeRSN( tHalHandle halHandle, eCsrAuthType authType)
+{
+ v_BOOL_t rsnType = VOS_FALSE;
+ // is the authType supported?
+ switch (authType)
+ {
+ case eCSR_AUTH_TYPE_NONE: //never used
+ rsnType = eANI_BOOLEAN_FALSE;
+ break;
+ // MAC layer authentication types
+ case eCSR_AUTH_TYPE_OPEN_SYSTEM:
+ rsnType = eANI_BOOLEAN_FALSE;
+ break;
+ case eCSR_AUTH_TYPE_SHARED_KEY:
+ rsnType = eANI_BOOLEAN_FALSE;
+ break;
+ case eCSR_AUTH_TYPE_AUTOSWITCH:
+ rsnType = eANI_BOOLEAN_FALSE;
+ break;
+
+ // Upper layer authentication types
+ case eCSR_AUTH_TYPE_WPA:
+ rsnType = eANI_BOOLEAN_TRUE;
+ break;
+ case eCSR_AUTH_TYPE_WPA_PSK:
+ rsnType = eANI_BOOLEAN_TRUE;
+ break;
+ case eCSR_AUTH_TYPE_WPA_NONE:
+ rsnType = eANI_BOOLEAN_TRUE;
+ break;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eCSR_AUTH_TYPE_FT_RSN:
+#endif
+ case eCSR_AUTH_TYPE_RSN:
+ rsnType = eANI_BOOLEAN_TRUE;
+ break;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eCSR_AUTH_TYPE_FT_RSN_PSK:
+#endif
+ case eCSR_AUTH_TYPE_RSN_PSK:
+ rsnType = eANI_BOOLEAN_TRUE;
+ break;
+ //case eCSR_AUTH_TYPE_FAILED:
+ case eCSR_AUTH_TYPE_UNKNOWN:
+ rsnType = eANI_BOOLEAN_FALSE;
+ break;
+ default:
+ hddLog(LOGE, FL("%s called with unknown authType - default to Open, None\n"),
+ __FUNCTION__);
+ rsnType = eANI_BOOLEAN_FALSE;
+ break;
+ }
+ hddLog(LOGE, FL("%s called with authType: %d, returned: %d\n"),
+ __FUNCTION__, authType, rsnType);
+ return rsnType;
+}
+
+static void hdd_GetRssiCB( v_S7_t rssi, tANI_U32 staId, void *pContext )
+{
+ struct statsContext *pStatsContext;
+ hdd_adapter_t *pAdapter;
+
+ if (ioctl_debug)
+ {
+ pr_info("%s: rssi [%d] STA [%d] pContext [%p]\n",
+ __FUNCTION__, (int)rssi, (int)staId, pContext);
+ }
+
+ if (NULL == pContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Bad param, pContext [%p]",
+ __FUNCTION__, pContext);
+ return;
+ }
+
+ /* there is a race condition that exists between this callback function
+ and the caller since the caller could time out either before or
+ while this code is executing. we'll assume the timeout hasn't
+ occurred, but we'll verify that right before we save our work */
+
+ pStatsContext = pContext;
+ pAdapter = pStatsContext->pAdapter;
+ if ((NULL == pAdapter) || (RSSI_CONTEXT_MAGIC != pStatsContext->magic))
+ {
+ /* the caller presumably timed out so there is nothing we can do */
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ "%s: Invalid context, pAdapter [%p] magic [%08x]",
+ __FUNCTION__, pAdapter, pStatsContext->magic);
+ if (ioctl_debug)
+ {
+ pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n",
+ __FUNCTION__, pAdapter, pStatsContext->magic);
+ }
+ return;
+ }
+
+ /* the race is on. caller could have timed out immediately after
+ we verified the magic, but if so, caller will wait a short time
+ for us to copy over the rssi */
+ pAdapter->rssi = rssi;
+
+ /* and notify the caller */
+ complete(&pStatsContext->completion);
+}
+
+VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value)
+{
+ struct statsContext context;
+ hdd_context_t *pHddCtx;
+ hdd_station_ctx_t *pHddStaCtx;
+ eHalStatus hstatus;
+ long lrc;
+
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ "%s: Invalid context, pAdapter", __func__);
+ return VOS_STATUS_E_FAULT;
+ }
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!",__func__);
+ /* return a cached value */
+ *rssi_value = pAdapter->rssi;
+ return VOS_STATUS_SUCCESS;
+ }
+
+ pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ init_completion(&context.completion);
+ context.pAdapter = pAdapter;
+ context.magic = RSSI_CONTEXT_MAGIC;
+
+ hstatus = sme_GetRssi(pHddCtx->hHal, hdd_GetRssiCB,
+ pHddStaCtx->conn_info.staId[ 0 ],
+ pHddStaCtx->conn_info.bssId,
+ &context, pHddCtx->pvosContext);
+ if (eHAL_STATUS_SUCCESS != hstatus)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI",
+ __FUNCTION__);
+ /* we'll returned a cached value below */
+ }
+ else
+ {
+ /* request was sent -- wait for the response */
+ lrc = wait_for_completion_interruptible_timeout(&context.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
+ /* either we have a response or we timed out
+ either way, first invalidate our magic */
+ context.magic = 0;
+ if (lrc <= 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while retrieving RSSI ",
+ __FUNCTION__, (0 == lrc) ? "timeout" : "interrupt");
+ /* there is a race condition such that the callback
+ function could be executing at the same time we are. of
+ primary concern is if the callback function had already
+ verified the "magic" but hasn't yet set the completion
+ variable. Since the completion variable is on our
+ stack, we'll delay just a bit to make sure the data is
+ still valid if that is the case */
+ msleep(50);
+ /* we'll now returned a cached value below */
+ }
+ }
+ *rssi_value = pAdapter->rssi;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+void hdd_StatisticsCB( void *pStats, void *pContext )
+{
+ hdd_adapter_t *pAdapter = (hdd_adapter_t *)pContext;
+ hdd_stats_t *pStatsCache = NULL;
+ hdd_wext_state_t *pWextState;
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+
+ tCsrSummaryStatsInfo *pSummaryStats = NULL;
+ tCsrGlobalClassAStatsInfo *pClassAStats = NULL;
+ tCsrGlobalClassBStatsInfo *pClassBStats = NULL;
+ tCsrGlobalClassCStatsInfo *pClassCStats = NULL;
+ tCsrGlobalClassDStatsInfo *pClassDStats = NULL;
+ tCsrPerStaStatsInfo *pPerStaStats = NULL;
+
+ if (pAdapter!= NULL)
+ pStatsCache = &pAdapter->hdd_stats;
+
+
+ pSummaryStats = (tCsrSummaryStatsInfo *)pStats;
+ pClassAStats = (tCsrGlobalClassAStatsInfo *)( pSummaryStats + 1 );
+ pClassBStats = (tCsrGlobalClassBStatsInfo *)( pClassAStats + 1 );
+ pClassCStats = (tCsrGlobalClassCStatsInfo *)( pClassBStats + 1 );
+ pClassDStats = (tCsrGlobalClassDStatsInfo *)( pClassCStats + 1 );
+ pPerStaStats = (tCsrPerStaStatsInfo *)( pClassDStats + 1 );
+
+ if (pStatsCache!=NULL)
+ {
+ // and copy the stats into the cache we keep in the adapter instance structure
+ vos_mem_copy( &pStatsCache->summary_stat, pSummaryStats, sizeof( pStatsCache->summary_stat ) );
+ vos_mem_copy( &pStatsCache->ClassA_stat, pClassAStats, sizeof( pStatsCache->ClassA_stat ) );
+ vos_mem_copy( &pStatsCache->ClassB_stat, pClassBStats, sizeof( pStatsCache->ClassB_stat ) );
+ vos_mem_copy( &pStatsCache->ClassC_stat, pClassCStats, sizeof( pStatsCache->ClassC_stat ) );
+ vos_mem_copy( &pStatsCache->ClassD_stat, pClassDStats, sizeof( pStatsCache->ClassD_stat ) );
+ vos_mem_copy( &pStatsCache->perStaStats, pPerStaStats, sizeof( pStatsCache->perStaStats ) );
+ }
+
+ if(pAdapter)
+ {
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ if(pWextState)
+ {
+ vos_status = vos_event_set(&pWextState->vosevent);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: vos_event_set failed", __FUNCTION__);
+ return;
+ }
+ }
+ }
+}
+
+void ccmCfgSetCallback(tHalHandle halHandle, tANI_S32 result)
+{
+ v_CONTEXT_t pVosContext;
+ hdd_context_t *pHddCtx;
+ VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx );
+#if 0
+ hdd_wext_state_t *pWextState;
+ v_U32_t roamId;
+#endif
+
+ ENTER();
+
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS,NULL);
+
+ pHddCtx = (hdd_context_t*) vos_get_context(VOS_MODULE_ID_HDD,pVosContext);
+ if (NULL == pHddCtx)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid pHddCtx", __FUNCTION__);
+ return;
+ }
+#if 0
+ pWextState = pAdapter->pWextState;
+#endif
+
+ if (WNI_CFG_NEED_RESTART == result || WNI_CFG_NEED_RELOAD == result)
+ {
+ //TODO Verify is this is really used. If yes need to fix it.
+ hdd_reconnect_all_adapters( pHddCtx );
+#if 0
+ pAdapter->conn_info.connState = eConnectionState_NotConnected;
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+ vosStatus = sme_RoamDisconnect(halHandle, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
+
+ if(VOS_STATUS_SUCCESS == vosStatus)
+ wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+
+ sme_RoamConnect(halHandle,
+ pAdapter->sessionId, &(pWextState->roamProfile),
+ &roamId);
+#endif
+ }
+
+ EXIT();
+
+}
+
+void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter)
+{
+ int i = 0;
+ hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ /* clear WPA/RSN/WSC IE information in the profile */
+ pWextState->roamProfile.nWPAReqIELength = 0;
+ pWextState->roamProfile.pWPAReqIE = (tANI_U8 *)NULL;
+ pWextState->roamProfile.nRSNReqIELength = 0;
+ pWextState->roamProfile.pRSNReqIE = (tANI_U8 *)NULL;
+
+ pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
+ pWextState->roamProfile.pAddIEScan = (tANI_U8 *)NULL;
+ pWextState->roamProfile.nAddIEScanLength = 0;
+ pWextState->roamProfile.pAddIEAssoc = (tANI_U8 *)NULL;
+ pWextState->roamProfile.nAddIEAssocLength = 0;
+
+ pWextState->roamProfile.EncryptionType.numEntries = 1;
+ pWextState->roamProfile.EncryptionType.encryptionType[0]
+ = eCSR_ENCRYPT_TYPE_NONE;
+
+ pWextState->roamProfile.mcEncryptionType.numEntries = 1;
+ pWextState->roamProfile.mcEncryptionType.encryptionType[0]
+ = eCSR_ENCRYPT_TYPE_NONE;
+
+ pWextState->roamProfile.AuthType.numEntries = 1;
+ pWextState->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+
+ pWextState->authKeyMgmt = 0;
+
+ for (i=0; i < CSR_MAX_NUM_KEY; i++)
+ {
+ if (pWextState->roamProfile.Keys.KeyMaterial[i])
+ {
+ pWextState->roamProfile.Keys.KeyLength[i] = 0;
+ }
+ }
+#ifdef FEATURE_WLAN_WAPI
+ pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_OPEN;
+ pAdapter->wapi_info.nWapiMode = 0;
+#endif
+
+ vos_mem_zero((void *)(pWextState->req_bssId), WNI_CFG_BSSID_LEN);
+
+}
+
+void wlan_hdd_ula_done_cb(v_VOID_t *callbackContext)
+{
+ hdd_adapter_t *pAdapter = (hdd_adapter_t*)callbackContext;
+ hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ complete(&pWextState->completion_var);
+}
+
+VOS_STATUS wlan_hdd_check_ula_done(hdd_adapter_t *pAdapter)
+{
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ VOS_STATUS vos_status;
+
+ if (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated)
+ {
+ INIT_COMPLETION(pWextState->completion_var);
+
+ /*To avoid race condition between the set key and the last EAPOL
+ packet, notify TL to finish upper layer authentication incase if the
+ last EAPOL packet pending in the TL queue.*/
+ vos_status = WLANTL_Finish_ULA(wlan_hdd_ula_done_cb,pAdapter);
+
+ if ( vos_status != VOS_STATUS_SUCCESS )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] WLANTL_Finish_ULA returned ERROR status= %d",
+ __LINE__, vos_status );
+ return vos_status;
+
+ }
+
+ wait_for_completion_timeout(&pWextState->completion_var,
+ msecs_to_jiffies(HDD_FINISH_ULA_TIME_OUT));
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+v_U8_t* wlan_hdd_get_vendor_oui_ie_ptr(v_U8_t *oui, v_U8_t oui_size, v_U8_t *ie, int ie_len)
+{
+
+ int left = ie_len;
+ v_U8_t *ptr = ie;
+ v_U8_t elem_id,elem_len;
+ v_U8_t eid = 0xDD;
+
+ if ( NULL == ie || 0 == ie_len )
+ return NULL;
+
+ while(left >= 2)
+ {
+ elem_id = ptr[0];
+ elem_len = ptr[1];
+ left -= 2;
+ if(elem_len > left)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "****Invalid IEs eid = %d elem_len=%d left=%d*****\n",
+ eid,elem_len,left);
+ return NULL;
+ }
+ if (elem_id == eid)
+ {
+ if(memcmp( &ptr[2], oui, oui_size)==0)
+ return ptr;
+ }
+
+ left -= elem_len;
+ ptr += (elem_len + 2);
+ }
+ return NULL;
+}
+
+static int iw_set_commit(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hddLog( LOG1, "In %s\n", __FUNCTION__);
+ /* Do nothing for now */
+ return 0;
+}
+
+static int iw_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ char *wrqu, char *extra)
+{
+
+ ENTER();
+ strlcpy(wrqu, "Qcom:802.11n", IFNAMSIZ);
+ EXIT();
+ return 0;
+}
+
+static int iw_set_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_wext_state_t *pWextState;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tCsrRoamProfile *pRoamProfile;
+ eCsrRoamBssType LastBSSType;
+ eMib_dot11DesiredBssType connectedBssType;
+ hdd_config_t *pConfig;
+#ifdef CONFIG_CFG80211
+ struct wireless_dev *wdev;
+#endif
+
+ ENTER();
+
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ "%s: Invalid context, pAdapter", __func__);
+ return 0;
+ }
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ if (pWextState == NULL)
+ {
+ hddLog (LOGE, "%s ERROR: Data Storage Corruption", __FUNCTION__);
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_CFG80211
+ wdev = dev->ieee80211_ptr;
+#endif
+ pRoamProfile = &pWextState->roamProfile;
+ LastBSSType = pRoamProfile->BSSType;
+
+ hddLog( LOG1,"%s Old Bss type = %d", __FUNCTION__, LastBSSType);
+
+ switch (wrqu->mode)
+ {
+ case IW_MODE_ADHOC:
+ hddLog( LOG1,"%s Setting AP Mode as IW_MODE_ADHOC", __FUNCTION__);
+ pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
+ // Set the phymode correctly for IBSS.
+ pConfig = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
+ pWextState->roamProfile.phyMode = hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
+#ifdef CONFIG_CFG80211
+ wdev->iftype = NL80211_IFTYPE_ADHOC;
+#endif
+ break;
+ case IW_MODE_INFRA:
+ hddLog( LOG1, "%s Setting AP Mode as IW_MODE_INFRA", __FUNCTION__);
+ pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
+#ifdef CONFIG_CFG80211
+ wdev->iftype = NL80211_IFTYPE_STATION;
+#endif
+ break;
+ case IW_MODE_AUTO:
+ hddLog(LOG1,"%s Setting AP Mode as IW_MODE_AUTO", __FUNCTION__);
+ pRoamProfile->BSSType = eCSR_BSS_TYPE_ANY;
+ break;
+ default:
+ hddLog(LOG1,"%s Unknown AP Mode value", __FUNCTION__);
+ return -EOPNOTSUPP;
+ }
+
+ if ( LastBSSType != pRoamProfile->BSSType )
+ {
+ //the BSS mode changed
+ // We need to issue disconnect if connected or in IBSS disconnect state
+ if ( hdd_connGetConnectedBssType( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
+ ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
+ {
+ VOS_STATUS vosStatus;
+ // need to issue a disconnect to CSR.
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+ vosStatus = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ eCSR_DISCONNECT_REASON_IBSS_LEAVE );
+ if(VOS_STATUS_SUCCESS == vosStatus)
+ wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+ }
+ }
+
+
+
+ EXIT();
+ return 0;
+}
+
+
+static int iw_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ v_U32_t *uwrq, char *extra)
+{
+
+ hdd_wext_state_t *pWextState;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ hddLog (LOG1, "In %s",__FUNCTION__);
+
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ "%s: Invalid context, pAdapter", __func__);
+ return 0;
+ }
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ if (pWextState == NULL)
+ {
+ hddLog (LOGE, "%s ERROR: Data Storage Corruption", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ switch (pWextState->roamProfile.BSSType)
+ {
+ case eCSR_BSS_TYPE_INFRASTRUCTURE:
+ hddLog(LOG1, "%s returns IW_MODE_INFRA\n", __FUNCTION__);
+ *uwrq = IW_MODE_INFRA ;
+ break;
+ case eCSR_BSS_TYPE_IBSS:
+ case eCSR_BSS_TYPE_START_IBSS:
+ hddLog( LOG1,"%s returns IW_MODE_ADHOC\n", __FUNCTION__);
+ *uwrq= IW_MODE_ADHOC;
+ break;
+ case eCSR_BSS_TYPE_ANY:
+ hddLog( LOG1,"%s returns IW_MODE_AUTO\n", __FUNCTION__);
+ *uwrq= IW_MODE_AUTO;
+ break;
+ default:
+ hddLog( LOG1,"%s returns APMODE_UNKNOWN\n", __FUNCTION__);
+ break;
+ }
+ return 0;
+}
+
+static int iw_set_freq(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ v_U32_t numChans = 0;
+ v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ v_U32_t indx = 0;
+ v_U32_t status = 0;
+
+ hdd_wext_state_t *pWextState;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ tCsrRoamProfile * pRoamProfile;
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return status;
+ }
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ pRoamProfile = &pWextState->roamProfile;
+
+ hddLog(LOG1,"setCHANNEL ioctl\n");
+
+ /* Link is up then return cant set channel*/
+ if(eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState ||
+ eConnectionState_Associated == pHddStaCtx->conn_info.connState)
+ {
+ hddLog( LOGE, "IBSS Associated\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* Settings by Frequency as input */
+ if((wrqu->freq.e == 1) && (wrqu->freq.m >= (tANI_U32)2.412e8) &&
+ (wrqu->freq.m <= (tANI_U32)5.825e8))
+ {
+ tANI_U32 freq = wrqu->freq.m / 100000;
+
+ while ((indx < FREQ_CHAN_MAP_TABLE_SIZE) && (freq != freq_chan_map[indx].freq))
+ indx++;
+ if (indx >= FREQ_CHAN_MAP_TABLE_SIZE)
+ {
+ return -EINVAL;
+ }
+ wrqu->freq.e = 0;
+ wrqu->freq.m = freq_chan_map[indx].chan;
+
+ }
+
+ if (wrqu->freq.e == 0)
+ {
+ if((wrqu->freq.m < WNI_CFG_CURRENT_CHANNEL_STAMIN) ||
+ (wrqu->freq.m > WNI_CFG_CURRENT_CHANNEL_STAMAX))
+ {
+ hddLog(LOG1,"%s: Channel [%d] is outside valid range from %d to %d\n",
+ __FUNCTION__, wrqu->freq.m, WNI_CFG_CURRENT_CHANNEL_STAMIN,
+ WNI_CFG_CURRENT_CHANNEL_STAMAX);
+ return -EINVAL;
+ }
+
+ numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+
+ if (ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
+ validChan, &numChans) != eHAL_STATUS_SUCCESS){
+ return -EIO;
+ }
+
+ for (indx = 0; indx < numChans; indx++) {
+ if (wrqu->freq.m == validChan[indx]){
+ break;
+ }
+ }
+ }
+ else{
+
+ return -EINVAL;
+ }
+
+ if(indx >= numChans)
+ {
+ return -EINVAL;
+ }
+
+ /* Set the Operational Channel */
+ numChans = pRoamProfile->ChannelInfo.numOfChannels = 1;
+ pHddStaCtx->conn_info.operationChannel = wrqu->freq.m;
+ pRoamProfile->ChannelInfo.ChannelList = &pHddStaCtx->conn_info.operationChannel;
+
+ hddLog(LOG1,"pRoamProfile->operationChannel = %d\n", wrqu->freq.m);
+
+ EXIT();
+
+ return status;
+}
+
+static int iw_get_freq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *fwrq, char *extra)
+{
+ v_U32_t status = 0,channel,freq = 0;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal;
+ hdd_wext_state_t *pWextState;
+ tCsrRoamProfile * pRoamProfile;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return status;
+ }
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+
+ pRoamProfile = &pWextState->roamProfile;
+
+ if( pHddStaCtx->conn_info.connState== eConnectionState_Associated )
+ {
+ if (sme_GetOperationChannel(hHal, &channel) != eHAL_STATUS_SUCCESS)
+ {
+ return -EIO;
+ }
+ else
+ {
+ fwrq->m = channel;
+ fwrq->e = 0;
+ }
+ }
+ else
+ {
+ channel = pHddStaCtx->conn_info.operationChannel;
+ status = hdd_wlan_get_freq(channel,&freq);
+ fwrq->m = freq;
+ fwrq->e = 0;
+ }
+ return status;
+}
+
+static int iw_get_tx_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ if (pHddCtx->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return -EBUSY;
+ }
+
+ if(eConnectionState_Associated != pHddStaCtx->conn_info.connState)
+ {
+ wrqu->txpower.value = 0;
+ return 0;
+ }
+ wlan_hdd_get_classAstats(pAdapter);
+ wrqu->txpower.value = pAdapter->hdd_stats.ClassA_stat.max_pwr;
+
+ return 0;
+}
+
+static int iw_set_tx_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ ENTER();
+
+ if ( ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, wrqu->txpower.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS )
+ {
+ return -EIO;
+ }
+
+ EXIT();
+
+ return 0;
+}
+
+static int iw_get_bitrate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ hdd_wext_state_t *pWextState;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return status;
+ }
+
+ if(eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
+ wrqu->bitrate.value = 0;
+ }
+ else {
+ status = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_HDD,
+ SME_SUMMARY_STATS |
+ SME_GLOBAL_CLASSA_STATS |
+ SME_GLOBAL_CLASSB_STATS |
+ SME_GLOBAL_CLASSC_STATS |
+ SME_GLOBAL_CLASSD_STATS |
+ SME_PER_STA_STATS,
+ hdd_StatisticsCB, 0, FALSE,
+ pHddStaCtx->conn_info.staId[0], pAdapter );
+
+ if(eHAL_STATUS_SUCCESS != status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to retrieve statistics",
+ __FUNCTION__);
+ return status;
+ }
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ vos_status = vos_wait_single_event(&pWextState->vosevent, WLAN_WAIT_TIME_STATS);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: SME timeout while retrieving statistics",
+ __FUNCTION__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ wrqu->bitrate.value = pAdapter->hdd_stats.ClassA_stat.tx_rate*500*1000;
+ }
+
+ EXIT();
+
+ return vos_status;
+}
+/* ccm call back function */
+
+static int iw_set_bitrate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *pWextState;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ v_U8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN];
+ v_U32_t a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN;
+ v_U32_t b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN;
+ v_U32_t i, rate;
+ v_U32_t valid_rate = FALSE, active_phy_mode = 0;
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
+ {
+ return -ENXIO ;
+ }
+
+ rate = wrqu->bitrate.value;
+
+ if (rate == -1)
+ {
+ rate = WNI_CFG_FIXED_RATE_AUTO;
+ valid_rate = TRUE;
+ }
+ else if (ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ WNI_CFG_DOT11_MODE, &active_phy_mode) == eHAL_STATUS_SUCCESS)
+ {
+ if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G
+ || active_phy_mode == WNI_CFG_DOT11_MODE_11B)
+ {
+ if ((ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ WNI_CFG_SUPPORTED_RATES_11A,
+ supp_rates, &a_len) == eHAL_STATUS_SUCCESS) &&
+ (ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ WNI_CFG_SUPPORTED_RATES_11B,
+ supp_rates, &b_len) == eHAL_STATUS_SUCCESS))
+ {
+ for (i = 0; i < (b_len + a_len); ++i)
+ {
+ /* supported rates returned is double the actual rate so we divide it by 2 */
+ if ((supp_rates[i]&0x7F)/2 == rate)
+ {
+ valid_rate = TRUE;
+ rate = i + WNI_CFG_FIXED_RATE_1MBPS;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (valid_rate != TRUE)
+ {
+ return -EINVAL;
+ }
+ if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ WNI_CFG_FIXED_RATE, rate,
+ ccmCfgSetCallback,eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
+ {
+ return -EIO;
+ }
+ return 0;
+}
+
+
+static int iw_set_genie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ u_int8_t *genie;
+ v_U16_t remLen;
+
+ ENTER();
+ if(!wrqu->data.length) {
+ hdd_clearRoamProfileIe(pAdapter);
+ EXIT();
+ return 0;
+ }
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ genie = wrqu->data.pointer;
+ remLen = wrqu->data.length;
+
+ hddLog(LOG1,"iw_set_genie ioctl IE[0x%X], LEN[%d]\n", genie[0], genie[1]);
+
+ /* clear any previous genIE before this call */
+ memset( &pWextState->genIE, 0, sizeof(pWextState->genIE) );
+
+ while (remLen >= 2)
+ {
+ v_U16_t eLen = 0;
+ v_U8_t elementId;
+ elementId = *genie++;
+ eLen = *genie++;
+ remLen -= 2;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
+ __func__, elementId, eLen);
+
+ switch ( elementId )
+ {
+ case IE_EID_VENDOR:
+ if ((IE_LEN_SIZE+IE_EID_SIZE+IE_VENDOR_OUI_SIZE) > eLen) /* should have at least OUI */
+ return -EINVAL;
+
+ if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
+ {
+ v_U16_t curGenIELen = pWextState->genIE.length;
+ hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS OUI(%02x %02x %02x %02x) IE(len %d)",
+ __func__, genie[0], genie[1], genie[2], genie[3], eLen + 2);
+
+ if( SIR_MAC_MAX_IE_LENGTH < (pWextState->genIE.length + eLen) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. "
+ "Need bigger buffer space\n");
+ VOS_ASSERT(0);
+ return -ENOMEM;
+ }
+ // save to Additional IE ; it should be accumulated to handle WPS IE + other IE
+ memcpy( pWextState->genIE.addIEdata + curGenIELen, genie - 2, eLen + 2);
+ pWextState->genIE.length += eLen + 2;
+ }
+ else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
+ {
+ hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
+ memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
+ memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2));
+ pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
+ pWextState->roamProfile.nWPAReqIELength = eLen + 2;
+ }
+ else /* any vendorId except WPA IE should be accumulated to genIE */
+ {
+ v_U16_t curGenIELen = pWextState->genIE.length;
+ hddLog (VOS_TRACE_LEVEL_INFO, "%s Set OUI(%02x %02x %02x %02x) IE(len %d)",
+ __func__, genie[0], genie[1], genie[2], genie[3], eLen + 2);
+
+ if( SIR_MAC_MAX_IE_LENGTH < (pWextState->genIE.length + eLen) )
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. "
+ "Need bigger buffer space\n");
+ VOS_ASSERT(0);
+ return -ENOMEM;
+ }
+ // save to Additional IE ; it should be accumulated to handle WPS IE + other IE
+ memcpy( pWextState->genIE.addIEdata + curGenIELen, genie - 2, eLen + 2);
+ pWextState->genIE.length += eLen + 2;
+ }
+ break;
+ case DOT11F_EID_RSN:
+ hddLog (LOG1, "%s Set RSN IE (len %d)",__FUNCTION__, eLen+2);
+ memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
+ memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2));
+ pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
+ pWextState->roamProfile.nRSNReqIELength = eLen + 2;
+ break;
+
+ default:
+ hddLog (LOGE, "%s Set UNKNOWN IE %X",__FUNCTION__, elementId);
+ return 0;
+ }
+ genie += eLen;
+ remLen -= eLen;
+ }
+ EXIT();
+ return 0;
+}
+
+static int iw_get_genie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ hdd_wext_state_t *pWextState;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ eHalStatus status;
+ v_U32_t length = DOT11F_IE_RSN_MAX_LEN;
+ v_U8_t genIeBytes[DOT11F_IE_RSN_MAX_LEN];
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+
+ hddLog(LOG1,"getGEN_IE ioctl\n");
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ if( pHddStaCtx->conn_info.connState == eConnectionState_NotConnected)
+ {
+ return -ENXIO;
+ }
+
+ // Return something ONLY if we are associated with an RSN or WPA network
+ if ( VOS_TRUE != hdd_IsAuthTypeRSN(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pWextState->roamProfile.negotiatedAuthType))
+ {
+ return -ENXIO;
+ }
+
+ // Actually retrieve the RSN IE from CSR. (We previously sent it down in the CSR Roam Profile.)
+ status = csrRoamGetWpaRsnReqIE(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ &length,
+ genIeBytes);
+ wrqu->data.length = VOS_MIN((u_int16_t) length, DOT11F_IE_RSN_MAX_LEN);
+
+ vos_mem_copy( wrqu->data.pointer, (v_VOID_t*)genIeBytes, wrqu->data.length);
+
+ hddLog(LOG1,"%s: RSN IE of %d bytes returned\n", __FUNCTION__, wrqu->data.length );
+
+ EXIT();
+
+ return 0;
+}
+
+static int iw_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
+ int keyId;
+ eCsrAuthType authType = eCSR_AUTH_TYPE_NONE;
+ int i;
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ keyId = pRoamProfile->Keys.defaultIndex;
+
+ if(keyId < 0 || keyId >= MAX_WEP_KEYS)
+ {
+ hddLog(LOG1,"%s: Invalid keyId : %d\n",__FUNCTION__,keyId);
+ return -EINVAL;
+ }
+
+ if(pRoamProfile->Keys.KeyLength[keyId] > 0)
+ {
+ dwrq->flags |= IW_ENCODE_ENABLED;
+ dwrq->length = pRoamProfile->Keys.KeyLength[keyId];
+ vos_mem_copy(extra,&(pRoamProfile->Keys.KeyMaterial[keyId][0]),pRoamProfile->Keys.KeyLength[keyId]);
+
+ dwrq->flags |= (keyId + 1);
+
+ }
+ else
+ {
+ dwrq->flags |= IW_ENCODE_DISABLED;
+ }
+
+ for(i=0; i < MAX_WEP_KEYS; i++)
+ {
+ if(pRoamProfile->Keys.KeyMaterial[i] == NULL)
+ {
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if(MAX_WEP_KEYS == i)
+ {
+ dwrq->flags |= IW_ENCODE_NOKEY;
+ }
+
+ authType = ((hdd_station_ctx_t*)WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
+
+ if(eCSR_AUTH_TYPE_OPEN_SYSTEM == authType)
+ {
+ dwrq->flags |= IW_ENCODE_OPEN;
+ }
+ else
+ {
+ dwrq->flags |= IW_ENCODE_RESTRICTED;
+ }
+ EXIT();
+ return 0;
+}
+
+#define PAE_ROLE_AUTHENTICATOR 1 // =1 for authenticator,
+#define PAE_ROLE_SUPPLICANT 0 // =0 for supplicant
+
+
+/*
+ * This function sends a single 'key' to LIM at all time.
+ */
+
+static int iw_get_rts_threshold(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ v_U32_t status = 0;
+
+ status = hdd_wlan_get_rts_threshold(pAdapter,wrqu);
+
+ return status;
+}
+
+static int iw_set_rts_threshold(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+
+ ENTER();
+
+ if ( wrqu->rts.value < WNI_CFG_RTS_THRESHOLD_STAMIN || wrqu->rts.value > WNI_CFG_RTS_THRESHOLD_STAMAX )
+ {
+ return -EINVAL;
+ }
+
+ if ( ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, wrqu->rts.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS )
+ {
+ return -EIO;
+ }
+
+ EXIT();
+
+ return 0;
+}
+
+static int iw_get_frag_threshold(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ v_U32_t status = 0;
+
+ status = hdd_wlan_get_frag_threshold(pAdapter,wrqu);
+
+ return status;
+}
+
+static int iw_set_frag_threshold(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+
+ ENTER();
+
+ if ( wrqu->frag.value < WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN || wrqu->frag.value > WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX )
+ {
+ return -EINVAL;
+ }
+
+ if ( ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, wrqu->frag.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS )
+ {
+ return -EIO;
+ }
+
+ EXIT();
+
+ return 0;
+}
+
+static int iw_get_power_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ ENTER();
+ return -EOPNOTSUPP;
+}
+
+static int iw_set_power_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ ENTER();
+ return -EOPNOTSUPP;
+}
+
+static int iw_get_range(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ struct iw_range *range = (struct iw_range *) extra;
+
+ v_U8_t channels[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+
+ v_U32_t num_channels = sizeof(channels);
+ v_U8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN];
+ v_U32_t a_len;
+ v_U32_t b_len;
+ v_U32_t active_phy_mode = 0;
+ v_U8_t index = 0, i;
+
+ ENTER();
+
+ wrqu->data.length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(struct iw_range));
+
+
+ /*Get the phy mode*/
+ if (ccmCfgGetInt(hHal,
+ WNI_CFG_DOT11_MODE, &active_phy_mode) == eHAL_STATUS_SUCCESS)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "active_phy_mode = %ld", active_phy_mode);
+
+ if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G)
+ {
+ /*Get the supported rates for 11G band*/
+ if (ccmCfgGetStr(hHal,
+ WNI_CFG_SUPPORTED_RATES_11A,
+ supp_rates, &a_len) == eHAL_STATUS_SUCCESS)
+ {
+ if (a_len > WNI_CFG_SUPPORTED_RATES_11A_LEN)
+ {
+ a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN;
+ }
+ for (i = 0; i < a_len; i++)
+ {
+ range->bitrate[i] = ((supp_rates[i] & 0x7F) / 2) * 1000000;
+ }
+ range->num_bitrates = a_len;
+ }
+ else
+ {
+ return -EIO;
+ }
+ }
+ else if (active_phy_mode == WNI_CFG_DOT11_MODE_11B)
+ {
+ /*Get the supported rates for 11B band*/
+ if (ccmCfgGetStr(hHal,
+ WNI_CFG_SUPPORTED_RATES_11B,
+ supp_rates, &b_len) == eHAL_STATUS_SUCCESS)
+ {
+ if (b_len > WNI_CFG_SUPPORTED_RATES_11B_LEN)
+ {
+ b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN;
+ }
+ for (i = 0; i < b_len; i++)
+ {
+ range->bitrate[i] = ((supp_rates[i] & 0x7F) / 2) * 1000000;
+ }
+ range->num_bitrates = b_len;
+ }
+ else
+ {
+ return -EIO;
+ }
+ }
+ }
+
+ range->max_rts = WNI_CFG_RTS_THRESHOLD_STAMAX;
+ range->min_frag = WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN;
+ range->max_frag = WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX;
+
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13;
+ range->num_encoding_sizes = 2;
+ range->max_encoding_tokens = MAX_WEP_KEYS;
+
+ // we support through Wireless Extensions 22
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 22;
+
+ /*Supported Channels and Frequencies*/
+ if (ccmCfgGetStr((hHal), WNI_CFG_VALID_CHANNEL_LIST, channels, &num_channels) != eHAL_STATUS_SUCCESS)
+ {
+ return -EIO;
+ }
+ if (num_channels > IW_MAX_FREQUENCIES)
+ {
+ num_channels = IW_MAX_FREQUENCIES;
+ }
+
+ range->num_channels = num_channels;
+ range->num_frequency = num_channels;
+
+ for (index=0; index < num_channels; index++)
+ {
+ v_U32_t frq_indx = 0;
+
+ range->freq[index].i = channels[index];
+ while (frq_indx < FREQ_CHAN_MAP_TABLE_SIZE)
+ {
+ if(channels[index] == freq_chan_map[frq_indx].chan)
+ {
+ range->freq[index].m = freq_chan_map[frq_indx].freq * 100000;
+ range->freq[index].e = 1;
+ break;
+ }
+ frq_indx++;
+ }
+ }
+
+ /* Event capability (kernel + driver) */
+ range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+ IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+ IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
+ range->event_capa[1] = IW_EVENT_CAPA_K_1;
+
+ /*Encryption capability*/
+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
+ /* Txpower capability */
+ range->txpower_capa = IW_TXPOW_MWATT;
+
+ /*Scanning capability*/
+ #if WIRELESS_EXT >= 22
+ range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_CHANNEL;
+ #endif
+
+ EXIT();
+ return 0;
+}
+
+/* Callback function registered with PMC to know status of PMC request */
+static void iw_power_callback_fn (void *pContext, eHalStatus status)
+{
+ struct statsContext *pStatsContext;
+ hdd_adapter_t *pAdapter;
+
+ if (NULL == pContext)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Bad param, pContext [%p]",
+ __FUNCTION__, pContext);
+ return;
+ }
+
+ /* there is a race condition that exists between this callback function
+ and the caller since the caller could time out either before or
+ while this code is executing. we'll assume the timeout hasn't
+ occurred, but we'll verify that right before we save our work */
+
+ pStatsContext = (struct statsContext *)pContext;
+ pAdapter = pStatsContext->pAdapter;
+
+ if ((NULL == pAdapter) || (POWER_CONTEXT_MAGIC != pStatsContext->magic))
+ {
+ /* the caller presumably timed out so there is nothing we can do */
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ "%s: Invalid context, pAdapter [%p] magic [%08x]",
+ __FUNCTION__, pAdapter, pStatsContext->magic);
+
+ if (ioctl_debug)
+ {
+ pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n",
+ __FUNCTION__, pAdapter, pStatsContext->magic);
+ }
+ return;
+ }
+
+ /* and notify the caller */
+ complete(&pStatsContext->completion);
+}
+
+/* Callback function for tx per hit */
+void hdd_tx_per_hit_cb (void *pCallbackContext)
+{
+ hdd_adapter_t *pAdapter = (hdd_adapter_t *)pCallbackContext;
+ unsigned char tx_fail[16];
+ union iwreq_data wrqu;
+
+ if (NULL == pAdapter)
+ {
+ hddLog(LOGE, "hdd_tx_per_hit_cb: pAdapter is NULL\n");
+ return;
+ }
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlcpy(tx_fail, "TX_FAIL", sizeof(tx_fail));
+ wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, tx_fail);
+}
+
+void hdd_GetClassA_statisticsCB(void *pStats, void *pContext)
+{
+ struct statsContext *pStatsContext;
+ tCsrGlobalClassAStatsInfo *pClassAStats;
+ hdd_adapter_t *pAdapter;
+
+ if (ioctl_debug)
+ {
+ pr_info("%s: pStats [%p] pContext [%p]\n",
+ __FUNCTION__, pStats, pContext);
+ }
+
+ if ((NULL == pStats) || (NULL == pContext))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Bad param, pStats [%p] pContext [%p]",
+ __FUNCTION__, pStats, pContext);
+ return;
+ }
+
+ /* there is a race condition that exists between this callback function
+ and the caller since the caller could time out either before or
+ while this code is executing. we'll assume the timeout hasn't
+ occurred, but we'll verify that right before we save our work */
+
+ pClassAStats = pStats;
+ pStatsContext = pContext;
+ pAdapter = pStatsContext->pAdapter;
+ if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
+ {
+ /* the caller presumably timed out so there is nothing we can do */
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ "%s: Invalid context, pAdapter [%p] magic [%08x]",
+ __FUNCTION__, pAdapter, pStatsContext->magic);
+ if (ioctl_debug)
+ {
+ pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n",
+ __FUNCTION__, pAdapter, pStatsContext->magic);
+ }
+ return;
+ }
+
+ /* the race is on. caller could have timed out immediately after
+ we verified the magic, but if so, caller will wait a short time
+ for us to copy over the stats. do so as a struct copy */
+ pAdapter->hdd_stats.ClassA_stat = *pClassAStats;
+
+ /* and notify the caller */
+ complete(&pStatsContext->completion);
+}
+
+VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter)
+{
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ eHalStatus hstatus;
+ long lrc;
+ struct statsContext context;
+
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Padapter is NULL", __func__);
+ return VOS_STATUS_E_FAULT;
+ }
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return VOS_STATUS_SUCCESS;
+ }
+
+ /* we are connected
+ prepare our callback context */
+ init_completion(&context.completion);
+ context.pAdapter = pAdapter;
+ context.magic = STATS_CONTEXT_MAGIC;
+ /* query only for Class A statistics (which include link speed) */
+ hstatus = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ eCSR_HDD,
+ SME_GLOBAL_CLASSA_STATS,
+ hdd_GetClassA_statisticsCB,
+ 0, // not periodic
+ FALSE, //non-cached results
+ pHddStaCtx->conn_info.staId[0],
+ &context);
+ if (eHAL_STATUS_SUCCESS != hstatus)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to retrieve Class A statistics ",
+ __FUNCTION__);
+ /* we'll returned a cached value below */
+ }
+ else
+ {
+ /* request was sent -- wait for the response */
+ lrc = wait_for_completion_interruptible_timeout(&context.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
+ /* either we have a response or we timed out
+ either way, first invalidate our magic */
+ context.magic = 0;
+ if (lrc <= 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: SME %s while retrieving Class A statistics",
+ __FUNCTION__, (0 == lrc) ? "timeout" : "interrupt");
+ /* there is a race condition such that the callback
+ function could be executing at the same time we are. of
+ primary concern is if the callback function had already
+ verified the "magic" but hasn't yet set the completion
+ variable. Since the completion variable is on our
+ stack, we'll delay just a bit to make sure the data is
+ still valid if that is the case */
+ msleep(50);
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+/*
+ * Support for the LINKSPEED private command
+ * Per the WiFi framework the response must be of the form
+ * "LinkSpeed xx"
+ */
+static int iw_get_linkspeed(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ char *pLinkSpeed = (char*)extra;
+ int len = sizeof(v_U16_t) + 1;
+ v_U16_t link_speed;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ int rc;
+
+ if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
+ {
+ /* we are not connected so we don't have a classAstats */
+ link_speed = 0;
+ }
+ else
+ {
+ wlan_hdd_get_classAstats(pAdapter);
+ //The linkspeed returned by HAL is in units of 500kbps.
+ //converting it to mbps
+ link_speed = pAdapter->hdd_stats.ClassA_stat.tx_rate/2;
+ }
+
+ wrqu->data.length = len;
+ // return the linkspeed in the format required by the WiFi Framework
+ rc = snprintf(pLinkSpeed, len, "%u", link_speed);
+ if ((rc < 0) || (rc >= len))
+ {
+ // encoding or length error?
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to encode link speed, got [%s]",
+ __FUNCTION__,pLinkSpeed);
+ return -EIO;
+ }
+
+ /* a value is being successfully returned */
+ return 0;
+}
+
+
+/*
+ * Support for the RSSI & RSSI-APPROX private commands
+ * Per the WiFi framework the response must be of the form
+ * "<ssid> rssi <xx>"
+ * unless we are not associated, in which case the response is
+ * "OK"
+ */
+static int iw_get_rssi(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ char *cmd = (char*)wrqu->data.pointer;
+ int len = wrqu->data.length;
+ v_S7_t s7Rssi = 0;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
+ VOS_STATUS vosStatus;
+ int rc;
+
+ if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
+ (0 == ssidlen) || (ssidlen >= len))
+ {
+ /* we are not connected or our SSID is too long
+ so we cannot report an rssi */
+ rc = snprintf(cmd, len, "OK");
+ }
+ else
+ {
+ /* we are connected with a valid SSID
+ so we can write the SSID into the return buffer
+ (note that it is not NUL-terminated) */
+ memcpy(cmd, pHddStaCtx->conn_info.SSID.SSID.ssId, ssidlen );
+
+ vosStatus = wlan_hdd_get_rssi(pAdapter, &s7Rssi);
+
+ if (VOS_STATUS_SUCCESS == vosStatus)
+ {
+ /* append the rssi to the ssid in the format required by
+ the WiFI Framework */
+ rc = snprintf(&cmd[ssidlen], len - ssidlen, " rssi %d", s7Rssi);
+ }
+ else
+ {
+ rc = -1;
+ }
+ }
+
+ /* verify that we wrote a valid response */
+ if ((rc < 0) || (rc >= len))
+ {
+ // encoding or length error?
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to encode RSSI, got [%s]",
+ __FUNCTION__, cmd);
+ return -EIO;
+ }
+
+ /* a value is being successfully returned */
+ return 0;
+}
+
+/*
+ * Support for SoftAP channel range private command
+ */
+static int iw_softap_set_channel_range( struct net_device *dev,
+ int startChannel,
+ int endChannel,
+ int band)
+{
+ eHalStatus status;
+ int ret = 0;
+ hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
+
+ status = WLANSAP_SetChannelRange(hHal, startChannel, endChannel, band);
+ if (VOS_STATUS_SUCCESS != status)
+ {
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode)
+{
+ struct statsContext context;
+ eHalStatus status;
+ hdd_context_t *pHddCtx;
+
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "Adapter NULL");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "power mode=%d", mode);
+ pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ init_completion(&context.completion);
+
+ context.pAdapter = pAdapter;
+ context.magic = POWER_CONTEXT_MAGIC;
+
+ if (DRIVER_POWER_MODE_ACTIVE == mode)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering "
+ "Full Power", __func__);
+ status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ iw_power_callback_fn, &context,
+ eSME_FULL_PWR_NEEDED_BY_HDD);
+ // Enter Full power command received from GUI this means we are disconnected
+ // Set PMC remainInPowerActiveTillDHCP flag to disable auto BMPS entry by PMC
+ sme_SetDHCPTillPowerActiveFlag(pHddCtx->hHal, TRUE);
+ if (eHAL_STATUS_PMC_PENDING == status)
+ {
+ int lrc = wait_for_completion_interruptible_timeout(
+ &context.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
+ context.magic = 0;
+ if (lrc <= 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while requesting fullpower ",
+ __FUNCTION__, (0 == lrc) ? "timeout" : "interrupt");
+ /* there is a race condition such that the callback
+ function could be executing at the same time we are. of
+ primary concern is if the callback function had already
+ verified the "magic" but hasn't yet set the completion
+ variable. Since the completion variable is on our
+ stack, we'll delay just a bit to make sure the data is
+ still valid if that is the case */
+ msleep(50);
+ /* we'll now returned a cached value below */
+ }
+ }
+ }
+ else if (DRIVER_POWER_MODE_AUTO == mode)
+ {
+ if (pHddCtx->cfg_ini->fIsBmpsEnabled)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering Bmps ",
+ __func__);
+ // Enter BMPS command received from GUI this means DHCP is completed
+ // Clear PMC remainInPowerActiveTillDHCP flag to enable auto BMPS entry
+ sme_SetDHCPTillPowerActiveFlag(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ FALSE);
+ status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ iw_power_callback_fn, &context);
+ if (eHAL_STATUS_PMC_PENDING == status)
+ {
+ int lrc = wait_for_completion_interruptible_timeout(
+ &context.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
+ context.magic = 0;
+ if (lrc <= 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while requesting BMPS ",
+ __FUNCTION__, (0 == lrc) ? "timeout" : "interrupt");
+ /* there is a race condition such that the callback
+ function could be executing at the same time we are. of
+ primary concern is if the callback function had already
+ verified the "magic" but hasn't yet set the completion
+ variable. Since the completion variable is on our
+ stack, we'll delay just a bit to make sure the data is
+ still valid if that is the case */
+ msleep(50);
+ /* we'll now returned a cached value below */
+ }
+ }
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "BMPS is not "
+ "enabled in the cfg");
+ }
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+VOS_STATUS wlan_hdd_exit_lowpower(hdd_context_t *pHddCtx,
+ hdd_adapter_t *pAdapter)
+{
+ VOS_STATUS vos_Status;
+
+ if ((NULL == pAdapter) || (NULL == pHddCtx))
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid pointer");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ /**Exit from Deep sleep or standby if we get the driver
+ START cmd from android GUI
+ */
+ if (WLAN_MAP_DRIVER_STOP_TO_STANDBY == pHddCtx->cfg_ini->nEnableDriverStop)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: WLAN being exit "
+ "from Stand by",__func__);
+ vos_Status = hdd_exit_standby(pHddCtx);
+ }
+ else if (eHDD_SUSPEND_DEEP_SLEEP == pHddCtx->hdd_ps_state)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: WLAN being exit "
+ "from deep sleep",__func__);
+ vos_Status = hdd_exit_deep_sleep(pHddCtx, pAdapter);
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_WARN, "%s: Not in standby or deep sleep. "
+ "Ignore start cmd %d", __func__, pHddCtx->hdd_ps_state);
+ vos_Status = VOS_STATUS_SUCCESS;
+ }
+
+ return vos_Status;
+}
+
+VOS_STATUS wlan_hdd_enter_lowpower(hdd_context_t *pHddCtx)
+{
+ VOS_STATUS vos_Status = VOS_STATUS_E_FAILURE;
+
+ if (NULL == pHddCtx)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "HDD context NULL");
+ return VOS_STATUS_E_FAULT;
+ }
+
+ if (WLAN_MAP_DRIVER_STOP_TO_STANDBY == pHddCtx->cfg_ini->nEnableDriverStop)
+ {
+ //Execute standby procedure.
+ //Executing standby procedure will cause the STA to
+ //disassociate first and then the chip will be put into standby.
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Wlan driver entering Stand by mode");
+ vos_Status = hdd_enter_standby(pHddCtx);
+ }
+ else if (WLAN_MAP_DRIVER_STOP_TO_DEEP_SLEEP ==
+ pHddCtx->cfg_ini->nEnableDriverStop)
+ {
+ //Execute deep sleep procedure
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Wlan driver entering "
+ "deep sleep mode\n");
+ //Deep sleep not supported
+ vos_Status = hdd_enter_standby(pHddCtx);
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO_LOW, "%s: Driver stop is not enabled %d",
+ __func__, pHddCtx->cfg_ini->nEnableDriverStop);
+ vos_Status = VOS_STATUS_SUCCESS;
+ }
+
+ return vos_Status;
+}
+
+static int iw_set_priv(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ char *cmd = (char*)wrqu->data.pointer;
+ int cmd_len = wrqu->data.length;
+ int ret = 0;
+ int status = 0;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ ENTER();
+
+ if (ioctl_debug)
+ {
+ pr_info("%s: req [%s] len [%d]\n", __FUNCTION__, cmd, cmd_len);
+ }
+
+ hddLog(VOS_TRACE_LEVEL_INFO_MED, "***Received %s cmd from Wi-Fi GUI***", cmd);
+
+ if (pHddCtx->isLogpInProgress) {
+ if (ioctl_debug)
+ {
+ pr_info("%s: RESTART in progress\n", __FUNCTION__);
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return status;
+ }
+
+ if(strncmp(cmd, "CSCAN",5) == 0 )
+ {
+ status = iw_set_cscan(dev, info, wrqu, extra);
+ }
+ else if( strcasecmp(cmd, "start") == 0 ) {
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Start command\n");
+ /*Exit from Deep sleep or standby if we get the driver START cmd from android GUI*/
+ status = wlan_hdd_exit_lowpower(pHddCtx, pAdapter);
+
+ if(status == VOS_STATUS_SUCCESS)
+ {
+ union iwreq_data wrqu;
+ char buf[10];
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlcpy(buf, "START", sizeof(buf));
+ wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf);
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: START CMD Status %d", __func__, status);
+ }
+ goto done;
+ }
+ else if( strcasecmp(cmd, "stop") == 0 )
+ {
+ union iwreq_data wrqu;
+ char buf[10];
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Stop command\n");
+
+ wlan_hdd_enter_lowpower(pHddCtx);
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlcpy(buf, "STOP", sizeof(buf));
+ wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf);
+ status = VOS_STATUS_SUCCESS;
+ goto done;
+ }
+ else if (strcasecmp(cmd, "macaddr") == 0)
+ {
+ ret = snprintf(cmd, cmd_len, "Macaddr = " MAC_ADDRESS_STR,
+ MAC_ADDR_ARRAY(pAdapter->macAddressCurrent.bytes));
+ }
+ else if (strcasecmp(cmd, "scan-active") == 0)
+ {
+ pAdapter->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
+ ret = snprintf(cmd, cmd_len, "OK");
+ }
+ else if (strcasecmp(cmd, "scan-passive") == 0)
+ {
+ pAdapter->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
+ ret = snprintf(cmd, cmd_len, "OK");
+ }
+ else if( strcasecmp(cmd, "scan-mode") == 0 )
+ {
+ ret = snprintf(cmd, cmd_len, "ScanMode = %u", pAdapter->scan_info.scan_mode);
+ }
+ else if( strcasecmp(cmd, "linkspeed") == 0 )
+ {
+ status = iw_get_linkspeed(dev, info, wrqu, extra);
+ }
+ else if( strncasecmp(cmd, "COUNTRY", 7) == 0 ) {
+ char *country_code;
+
+ country_code = cmd + 8;
+
+ status = (int)sme_ChangeCountryCode(pHddCtx->hHal,
+ NULL,
+ country_code,
+ pAdapter,
+ pHddCtx->pvosContext);
+ if( 0 != status )
+ {
+ VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+ "%s: SME Change Country code fail \n",__func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ }
+ else if( strncasecmp(cmd, "rssi", 4) == 0 )
+ {
+ status = iw_get_rssi(dev, info, wrqu, extra);
+ }
+ else if( strncasecmp(cmd, "powermode", 9) == 0 ) {
+ int mode;
+ char *ptr = (char*)(cmd + 9);
+
+ sscanf(ptr,"%d",&mode);
+ wlan_hdd_enter_bmps(pAdapter, mode);
+ /*TODO:Set the power mode*/
+ }
+ else if (strncasecmp(cmd, "getpower", 8) == 0 ) {
+ v_U32_t pmc_state;
+ v_U16_t value;
+
+ pmc_state = pmcGetPmcState(WLAN_HDD_GET_HAL_CTX(pAdapter));
+ if(pmc_state == BMPS) {
+ value = DRIVER_POWER_MODE_AUTO;
+ }
+ else {
+ value = DRIVER_POWER_MODE_ACTIVE;
+ }
+ ret = snprintf(cmd, cmd_len, "powermode = %u", value);
+ }
+ else if( strncasecmp(cmd, "btcoexmode", 10) == 0 ) {
+ hddLog( VOS_TRACE_LEVEL_INFO, "btcoexmode\n");
+ /*TODO: set the btcoexmode*/
+ }
+ else if( strcasecmp(cmd, "btcoexstat") == 0 ) {
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "BtCoex Status\n");
+ /*TODO: Return the btcoex status*/
+ }
+ else if( strcasecmp(cmd, "rxfilter-start") == 0 ) {
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Start command\n");
+
+ /*TODO: Enable Rx data Filter*/
+ }
+ else if( strcasecmp(cmd, "rxfilter-stop") == 0 ) {
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Stop command\n");
+
+ /*TODO: Disable Rx data Filter*/
+ }
+ else if( strcasecmp(cmd, "rxfilter-statistics") == 0 ) {
+
+ hddLog( VOS_TRACE_LEVEL_INFO, "Rx Data Filter Statistics command\n");
+ /*TODO: rxfilter-statistics*/
+ }
+ else if( strncasecmp(cmd, "rxfilter-add", 12) == 0 ) {
+
+ hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-add\n");
+ /*TODO: rxfilter-add*/
+ }
+ else if( strncasecmp(cmd, "rxfilter-remove",15) == 0 ) {
+
+ hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-remove\n");
+ /*TODO: rxfilter-remove*/
+ }
+#ifdef FEATURE_WLAN_SCAN_PNO
+ else if( strncasecmp(cmd, "pno",3) == 0 ) {
+
+ hddLog( VOS_TRACE_LEVEL_INFO, "pno\n");
+ status = iw_set_pno(dev, info, wrqu, extra, 3);
+ return status;
+ }
+ else if( strncasecmp(cmd, "rssifilter",10) == 0 ) {
+
+ hddLog( VOS_TRACE_LEVEL_INFO, "rssifilter\n");
+ status = iw_set_rssi_filter(dev, info, wrqu, extra, 10);
+ return status;
+ }
+#endif /*FEATURE_WLAN_SCAN_PNO*/
+ else if( strncasecmp(cmd, "powerparams",11) == 0 ) {
+ hddLog( VOS_TRACE_LEVEL_INFO, "powerparams\n");
+ status = iw_set_power_params(dev, info, wrqu, extra, 11);
+ return status;
+ }
+ else if( 0 == strncasecmp(cmd, "CONFIG-TX-TRACKING", 18) ) {
+ tSirTxPerTrackingParam tTxPerTrackingParam;
+ char *ptr = (char*)(cmd + 18);
+ sscanf(ptr,"%hhu %hhu %hhu %lu",&(tTxPerTrackingParam.ucTxPerTrackingEnable), &(tTxPerTrackingParam.ucTxPerTrackingPeriod),
+ &(tTxPerTrackingParam.ucTxPerTrackingRatio), &(tTxPerTrackingParam.uTxPerTrackingWatermark));
+
+ // parameters checking
+ // period has to be larger than 0
+ if (0 == tTxPerTrackingParam.ucTxPerTrackingPeriod)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Period input is not correct");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ // use default value 5 is the input is not reasonable. in unit of 10%
+ if ((tTxPerTrackingParam.ucTxPerTrackingRatio > TX_PER_TRACKING_MAX_RATIO) || (0 == tTxPerTrackingParam.ucTxPerTrackingRatio))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Ratio input is not good. use default 5");
+ tTxPerTrackingParam.ucTxPerTrackingRatio = TX_PER_TRACKING_DEFAULT_RATIO;
+ }
+
+ // default is 5
+ if (0 == tTxPerTrackingParam.uTxPerTrackingWatermark)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Tx Packet number input is not good. use default 5");
+ tTxPerTrackingParam.uTxPerTrackingWatermark = TX_PER_TRACKING_DEFAULT_WATERMARK;
+ }
+
+ status = sme_SetTxPerTracking(pHddCtx->hHal, hdd_tx_per_hit_cb, (void*)pAdapter, &tTxPerTrackingParam);
+ if(status != eHAL_STATUS_SUCCESS){
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Set Tx PER Tracking Failed!");
+ }
+ }
+ else {
+ hddLog( VOS_TRACE_LEVEL_WARN, "Unsupported GUI command %s", cmd);
+ }
+done:
+ /* many of the commands write information back into the command
+ string using snprintf(). check the return value here in one
+ place */
+ if ((ret < 0) || (ret >= cmd_len))
+ {
+ /* there was an encoding error or overflow */
+ status = -EIO;
+ }
+
+ if (ioctl_debug)
+ {
+ pr_info("%s: rsp [%s] len [%d] status %d\n",
+ __FUNCTION__, cmd, wrqu->data.length, status);
+ }
+ return status;
+
+}
+
+static int iw_set_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ ENTER();
+ return 0;
+}
+
+static int iw_get_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ ENTER();
+ return 0;
+}
+
+static struct iw_statistics *get_wireless_stats(struct net_device *dev)
+{
+ ENTER();
+ return NULL;
+}
+
+static int iw_set_encode(struct net_device *dev,struct iw_request_info *info,
+ union iwreq_data *wrqu,char *extra)
+
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ struct iw_point *encoderq = &(wrqu->encoding);
+ v_U32_t keyId;
+ v_U8_t key_length;
+ eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ v_BOOL_t fKeyPresent = 0;
+ int i;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+
+ keyId = encoderq->flags & IW_ENCODE_INDEX;
+
+ if(keyId)
+ {
+ if(keyId > MAX_WEP_KEYS)
+ {
+ return -EINVAL;
+ }
+
+ fKeyPresent = 1;
+ keyId--;
+ }
+ else
+ {
+ fKeyPresent = 0;
+ }
+
+
+ if(wrqu->data.flags & IW_ENCODE_DISABLED)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****iwconfig wlan0 key off*****\n");
+ if(!fKeyPresent) {
+
+ for(i=0;i < CSR_MAX_NUM_KEY; i++) {
+
+ if(pWextState->roamProfile.Keys.KeyMaterial[i])
+ pWextState->roamProfile.Keys.KeyLength[i] = 0;
+ }
+ }
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+ pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
+ pWextState->roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+ pWextState->roamProfile.mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+
+ pHddStaCtx->conn_info.ucEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ pHddStaCtx->conn_info.mcEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
+
+ if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
+ {
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+ status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED );
+ if(VOS_STATUS_SUCCESS == status)
+ wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+ }
+
+ return status;
+
+ }
+
+ if (wrqu->data.flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED))
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "iwconfig wlan0 key on");
+
+ pHddStaCtx->conn_info.authType = (encoderq->flags & IW_ENCODE_RESTRICTED) ? eCSR_AUTH_TYPE_SHARED_KEY : eCSR_AUTH_TYPE_OPEN_SYSTEM;
+
+ }
+
+
+ if(wrqu->data.length > 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s : wrqu->data.length : %d",__FUNCTION__,wrqu->data.length);
+
+ key_length = wrqu->data.length;
+
+ /* IW_ENCODING_TOKEN_MAX is the value that is set for wrqu->data.length by iwconfig.c when 'iwconfig wlan0 key on' is issued.*/
+
+ if(5 == key_length)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Call with WEP40,key_len=%d",__FUNCTION__,key_length);
+
+ if((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
+ {
+ encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
+ }
+ else
+ {
+ encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
+ }
+ }
+ else if(13 == key_length)
+ {
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s:Call with WEP104,key_len:%d",__FUNCTION__,key_length);
+
+ if((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
+ {
+ encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
+ }
+ else
+ {
+ encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
+ }
+ }
+ else
+ {
+ hddLog(VOS_TRACE_LEVEL_WARN, "%s: Invalid WEP key length :%d",
+ __FUNCTION__, key_length);
+ return -EINVAL;
+ }
+
+ pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
+ pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
+ pWextState->roamProfile.EncryptionType.numEntries = 1;
+ pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
+ pWextState->roamProfile.mcEncryptionType.numEntries = 1;
+ pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
+
+ if((eConnectionState_NotConnected == pHddStaCtx->conn_info.connState) &&
+ ((eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) ||
+ (eCSR_AUTH_TYPE_SHARED_KEY == pHddStaCtx->conn_info.authType)))
+ {
+
+ vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[keyId][0],extra,key_length);
+
+ pWextState->roamProfile.Keys.KeyLength[keyId] = (v_U8_t)key_length;
+ pWextState->roamProfile.Keys.defaultIndex = (v_U8_t)keyId;
+
+ return status;
+ }
+ }
+
+ return 0;
+}
+
+static int iw_get_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
+ int keyId;
+ eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
+ eCsrAuthType authType = eCSR_AUTH_TYPE_NONE;
+ int i;
+
+ ENTER();
+
+ keyId = pRoamProfile->Keys.defaultIndex;
+
+ if(keyId < 0 || keyId >= MAX_WEP_KEYS)
+ {
+ hddLog(LOG1,"%s: Invalid keyId : %d\n",__FUNCTION__,keyId);
+ return -EINVAL;
+ }
+
+ if(pRoamProfile->Keys.KeyLength[keyId] > 0)
+ {
+ dwrq->flags |= IW_ENCODE_ENABLED;
+ dwrq->length = pRoamProfile->Keys.KeyLength[keyId];
+ palCopyMemory(dev,extra,&(pRoamProfile->Keys.KeyMaterial[keyId][0]),pRoamProfile->Keys.KeyLength[keyId]);
+ }
+ else
+ {
+ dwrq->flags |= IW_ENCODE_DISABLED;
+ }
+
+ for(i=0; i < MAX_WEP_KEYS; i++)
+ {
+ if(pRoamProfile->Keys.KeyMaterial[i] == NULL)
+ {
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if(MAX_WEP_KEYS == i)
+ {
+ dwrq->flags |= IW_ENCODE_NOKEY;
+ }
+ else
+ {
+ dwrq->flags |= IW_ENCODE_ENABLED;
+ }
+
+ encryptionType = pRoamProfile->EncryptionType.encryptionType[0];
+
+ if(eCSR_ENCRYPT_TYPE_NONE == encryptionType)
+ {
+ dwrq->flags |= IW_ENCODE_DISABLED;
+ }
+
+ authType = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
+
+ if(IW_AUTH_ALG_OPEN_SYSTEM == authType)
+ {
+ dwrq->flags |= IW_ENCODE_OPEN;
+ }
+ else
+ {
+ dwrq->flags |= IW_ENCODE_RESTRICTED;
+ }
+ EXIT();
+ return 0;
+
+}
+
+static int iw_set_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ eHalStatus halStatus= eHAL_STATUS_SUCCESS;
+
+ tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
+ v_U32_t status = 0;
+
+ struct iw_encode_ext *ext = (struct iw_encode_ext*)extra;
+
+ v_U8_t groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+
+ int key_index;
+ struct iw_point *encoding = &wrqu->encoding;
+ tCsrRoamSetKey setKey;
+ v_U32_t roamId= 0xFF;
+ VOS_STATUS vos_status;
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ key_index = encoding->flags & IW_ENCODE_INDEX;
+
+ if(key_index > 0) {
+
+ /*Convert from 1-based to 0-based keying*/
+ key_index--;
+ }
+ if(!ext->key_len) {
+
+ /*Set the encrytion type to NONE*/
+ pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+ return status;
+ }
+
+ if(eConnectionState_NotConnected == pHddStaCtx->conn_info.connState &&
+ (IW_ENCODE_ALG_WEP == ext->alg))
+ {
+ if(IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) {
+
+ VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,("Invalid Configuration:%s \n"),__FUNCTION__);
+ return -EINVAL;
+ }
+ else {
+ /*Static wep, update the roam profile with the keys */
+ if(ext->key && (ext->key_len <= eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES) &&
+ key_index < CSR_MAX_NUM_KEY) {
+ vos_mem_copy(&pRoamProfile->Keys.KeyMaterial[key_index][0],ext->key,ext->key_len);
+ pRoamProfile->Keys.KeyLength[key_index] = (v_U8_t)ext->key_len;
+
+ if(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ pRoamProfile->Keys.defaultIndex = (v_U8_t)key_index;
+
+ }
+ }
+ return status;
+ }
+
+ vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
+
+ setKey.keyId = key_index;
+ setKey.keyLength = ext->key_len;
+
+ if(ext->key_len <= CSR_MAX_KEY_LEN) {
+ vos_mem_copy(&setKey.Key[0],ext->key,ext->key_len);
+ }
+
+ if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ /*Key direction for group is RX only*/
+ setKey.keyDirection = eSIR_RX_ONLY;
+ vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
+ }
+ else {
+
+ setKey.keyDirection = eSIR_TX_RX;
+ vos_mem_copy(setKey.peerMac,ext->addr.sa_data,WNI_CFG_BSSID_LEN);
+ }
+
+ /*For supplicant pae role is zero*/
+ setKey.paeRole = 0;
+
+ switch(ext->alg)
+ {
+ case IW_ENCODE_ALG_NONE:
+ setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
+ break;
+
+ case IW_ENCODE_ALG_WEP:
+ setKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104;
+ break;
+
+ case IW_ENCODE_ALG_TKIP:
+ {
+ v_U8_t *pKey = &setKey.Key[0];
+
+ setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
+
+ vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
+
+ /*Supplicant sends the 32bytes key in this order
+
+ |--------------|----------|----------|
+ | Tk1 |TX-MIC | RX Mic |
+ |--------------|----------|----------|
+ <---16bytes---><--8bytes--><--8bytes-->
+
+ */
+ /*Sme expects the 32 bytes key to be in the below order
+
+ |--------------|----------|----------|
+ | Tk1 |RX-MIC | TX Mic |
+ |--------------|----------|----------|
+ <---16bytes---><--8bytes--><--8bytes-->
+ */
+ /* Copy the Temporal Key 1 (TK1) */
+ vos_mem_copy(pKey,ext->key,16);
+
+ /*Copy the rx mic first*/
+ vos_mem_copy(&pKey[16],&ext->key[24],8);
+
+ /*Copy the tx mic */
+ vos_mem_copy(&pKey[24],&ext->key[16],8);
+
+ }
+ break;
+
+ case IW_ENCODE_ALG_CCMP:
+ setKey.encType = eCSR_ENCRYPT_TYPE_AES;
+ break;
+
+#ifdef FEATURE_WLAN_CCX
+#define IW_ENCODE_ALG_KRK 6
+ case IW_ENCODE_ALG_KRK:
+ setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
+ break;
+#endif /* FEATURE_WLAN_CCX */
+
+ default:
+ setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
+ break;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ ("%s:cipher_alg:%d key_len[%d] *pEncryptionType :%d \n"),__FUNCTION__,(int)ext->alg,(int)ext->key_len,setKey.encType);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/* The supplicant may attempt to set the PTK once pre-authentication is done.
+ Save the key in the UMAC and include it in the ADD BSS request */
+ halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
+ if( halStatus == eHAL_STATUS_SUCCESS )
+ {
+ return halStatus;
+ }
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
+
+ vos_status = wlan_hdd_check_ula_done(pAdapter);
+ if ( vos_status != VOS_STATUS_SUCCESS )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
+ __LINE__, vos_status );
+
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+ }
+
+ halStatus = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),pAdapter->sessionId, &setKey, &roamId );
+
+ if ( halStatus != eHAL_STATUS_SUCCESS )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] sme_RoamSetKey returned ERROR status= %d",
+ __LINE__, halStatus );
+
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+ }
+
+ return halStatus;
+}
+
+static int iw_set_retry(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+
+ ENTER();
+
+ if(wrqu->retry.value < WNI_CFG_LONG_RETRY_LIMIT_STAMIN ||
+ wrqu->retry.value > WNI_CFG_LONG_RETRY_LIMIT_STAMAX) {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("Invalid Retry-Limit=%ld!!\n"),wrqu->retry.value);
+
+ return -EINVAL;
+ }
+
+ if(wrqu->retry.flags & IW_RETRY_LIMIT) {
+
+ if((wrqu->retry.flags & IW_RETRY_LONG))
+ {
+ if ( ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, wrqu->retry.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS )
+ {
+ return -EIO;
+ }
+ }
+ else if((wrqu->retry.flags & IW_RETRY_SHORT))
+ {
+ if ( ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, wrqu->retry.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS )
+ {
+ return -EIO;
+ }
+ }
+ }
+ else
+ {
+ return -EOPNOTSUPP;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("Set Retry-Limit=%ld!!\n"),wrqu->retry.value);
+
+ EXIT();
+
+ return 0;
+
+}
+
+static int iw_get_retry(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ v_U32_t retry = 0;
+
+ ENTER();
+
+ if((wrqu->retry.flags & IW_RETRY_LONG))
+ {
+ wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
+
+ if ( ccmCfgGetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, &retry) != eHAL_STATUS_SUCCESS )
+ {
+ return -EIO;
+ }
+
+ wrqu->retry.value = retry;
+ }
+ else if ((wrqu->retry.flags & IW_RETRY_SHORT))
+ {
+ wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
+
+ if ( ccmCfgGetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, &retry) != eHAL_STATUS_SUCCESS )
+ {
+ return -EIO;
+ }
+
+ wrqu->retry.value = retry;
+ }
+ else {
+ return -EOPNOTSUPP;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("Retry-Limit=%ld!!\n"),retry);
+
+ EXIT();
+
+ return 0;
+}
+
+static int iw_set_mlme(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+
+ ENTER();
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ //reason_code is unused. By default it is set to eCSR_DISCONNECT_REASON_UNSPECIFIED
+ switch (mlme->cmd) {
+ case IW_MLME_DISASSOC:
+ case IW_MLME_DEAUTH:
+
+ if( pHddStaCtx->conn_info.connState == eConnectionState_Associated )
+ {
+ eCsrRoamDisconnectReason reason = eCSR_DISCONNECT_REASON_UNSPECIFIED;
+
+ if( mlme->reason_code == HDD_REASON_MICHAEL_MIC_FAILURE )
+ reason = eCSR_DISCONNECT_REASON_MIC_ERROR;
+
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+ status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,reason);
+
+ if(VOS_STATUS_SUCCESS == status)
+ wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+ else
+ hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate : csrRoamDisconnect failure returned %d \n",
+ __FUNCTION__, (int)mlme->cmd, (int)status );
+
+ /* Resetting authKeyMgmt */
+ (WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->authKeyMgmt = 0;
+
+ netif_tx_disable(dev);
+ netif_carrier_off(dev);
+
+ }
+ else
+ {
+ hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate called but station is not in associated state \n", __FUNCTION__, (int)mlme->cmd );
+ }
+ break;
+ default:
+ hddLog(LOGE,"%s %d Command should be Disassociate/Deauthenticate \n", __FUNCTION__, (int)mlme->cmd );
+ return -EINVAL;
+ }//end of switch
+
+ EXIT();
+
+ return status;
+
+}
+
+/* set param sub-ioctls */
+static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ int *value = (int *)extra;
+ int sub_cmd = value[0];
+ int set_value = value[1];
+ int ret = 0; /* success */
+ int enable_pbm, enable_mp;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ v_U8_t nEnableSuspendOld;
+#endif
+ INIT_COMPLETION(pWextState->completion_var);
+
+ switch(sub_cmd)
+ {
+ case WE_SET_11D_STATE:
+ {
+ tSmeConfigParams smeConfig;;
+ if((ENABLE_11D == set_value) || (DISABLE_11D == set_value)) {
+
+ sme_GetConfigParam(hHal,&smeConfig);
+ smeConfig.csrConfig.Is11dSupportEnabled = (v_BOOL_t)set_value;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("11D state=%ld!!\n"),smeConfig.csrConfig.Is11dSupportEnabled);
+
+ sme_UpdateConfig(hHal,&smeConfig);
+ }
+ else {
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case WE_WOWL:
+ {
+ switch (set_value)
+ {
+ case 0x00:
+ hdd_exit_wowl();
+ break;
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ enable_mp = (set_value & 0x01) ? 1 : 0;
+ enable_pbm = (set_value & 0x02) ? 1 : 0;
+ hddLog(LOGE, "magic packet ? = %s pattern byte matching ? = %s\n",
+ (enable_mp ? "YES":"NO"), (enable_pbm ? "YES":"NO"));
+ hdd_enter_wowl(pAdapter, enable_mp, enable_pbm);
+ break;
+ default:
+ hddLog(LOGE, "Invalid arg %d in WE_WOWL IOCTL\n", set_value);
+ ret = -EINVAL;
+ break;
+ }
+
+ break;
+ }
+ case WE_SET_POWER:
+ {
+ switch (set_value)
+ {
+ case 0: //Full Power
+ {
+ struct statsContext context;
+ eHalStatus status;
+
+ init_completion(&context.completion);
+
+ context.pAdapter = pAdapter;
+ context.magic = POWER_CONTEXT_MAGIC;
+
+ status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ iw_power_callback_fn, &context,
+ eSME_FULL_PWR_NEEDED_BY_HDD);
+ if(eHAL_STATUS_PMC_PENDING == status)
+ {
+ int lrc = wait_for_completion_interruptible_timeout(
+ &context.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
+ context.magic = 0;
+ if (lrc <= 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while "
+ "requesting fullpower ",
+ __FUNCTION__, (0 == lrc) ?
+ "timeout" : "interrupt");
+ /* there is a race condition such that the callback
+ function could be executing at the same time we are. of
+ primary concern is if the callback function had already
+ verified the "magic" but hasn't yet set the completion
+ variable. Since the completion variable is on our
+ stack, we'll delay just a bit to make sure the data is
+ still valid if that is the case */
+ msleep(50);
+ /* we'll now returned a cached value below */
+ }
+ }
+ hddLog(LOGE, "iwpriv Full Power completed\n");
+ break;
+ }
+ case 1: //Enable BMPS
+ sme_EnablePowerSave(hHal, ePMC_BEACON_MODE_POWER_SAVE);
+ break;
+ case 2: //Disable BMPS
+ sme_DisablePowerSave(hHal, ePMC_BEACON_MODE_POWER_SAVE);
+ break;
+ case 3: //Request Bmps
+ {
+ struct statsContext context;
+ eHalStatus status;
+
+ init_completion(&context.completion);
+
+ context.pAdapter = pAdapter;
+ context.magic = POWER_CONTEXT_MAGIC;
+
+ status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ iw_power_callback_fn, &context);
+ if(eHAL_STATUS_PMC_PENDING == status)
+ {
+ int lrc = wait_for_completion_interruptible_timeout(
+ &context.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
+ context.magic = 0;
+ if (lrc <= 0)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while "
+ "requesting BMPS",
+ __FUNCTION__, (0 == lrc) ? "timeout" :
+ "interrupt");
+ /* there is a race condition such that the callback
+ function could be executing at the same time we are. of
+ primary concern is if the callback function had already
+ verified the "magic" but hasn't yet set the completion
+ variable. Since the completion variable is on our
+ stack, we'll delay just a bit to make sure the data is
+ still valid if that is the case */
+ msleep(50);
+ /* we'll now returned a cached value below */
+ }
+ }
+ hddLog(LOGE, "iwpriv Request BMPS completed\n");
+ break;
+ }
+ case 4: //Enable IMPS
+ sme_EnablePowerSave(hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ break;
+ case 5: //Disable IMPS
+ sme_DisablePowerSave(hHal, ePMC_IDLE_MODE_POWER_SAVE);
+ break;
+ case 6: //Enable Standby
+ sme_EnablePowerSave(hHal, ePMC_STANDBY_MODE_POWER_SAVE);
+ break;
+ case 7: //Disable Standby
+ sme_DisablePowerSave(hHal, ePMC_STANDBY_MODE_POWER_SAVE);
+ break;
+ case 8: //Request Standby
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ (void)hdd_enter_standby(pAdapter->pHddCtx);
+#endif
+#endif
+ break;
+ case 9: //Start Auto Bmps Timer
+ sme_StartAutoBmpsTimer(hHal);
+ break;
+ case 10://Stop Auto BMPS Timer
+ sme_StopAutoBmpsTimer(hHal);
+ break;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ case 11://suspend to standby
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ nEnableSuspendOld = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend;
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = 1;
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ hdd_suspend_wlan(NULL);
+#endif
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = nEnableSuspendOld;
+#endif
+ break;
+ case 12://suspend to deep sleep
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ nEnableSuspendOld = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend;
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = 2;
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ hdd_suspend_wlan(NULL);
+#endif
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = nEnableSuspendOld;
+#endif
+ break;
+ case 13://resume from suspend
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ hdd_resume_wlan(NULL);
+#endif
+#endif
+ break;
+#endif
+ case 14://reset wlan (power down/power up)
+ vos_chipReset(NULL, VOS_FALSE, NULL, NULL, VOS_CHIP_RESET_UNKNOWN_EXCEPTION);
+ break;
+ default:
+ hddLog(LOGE, "Invalid arg %d in WE_SET_POWER IOCTL\n", set_value);
+ ret = -EINVAL;
+ break;
+ }
+ break;
+ }
+
+ case WE_SET_MAX_ASSOC:
+ {
+ if ((WNI_CFG_ASSOC_STA_LIMIT_STAMIN > set_value) ||
+ (WNI_CFG_ASSOC_STA_LIMIT_STAMAX < set_value))
+ {
+ ret = -EINVAL;
+ }
+ else if ( ccmCfgSetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT,
+ set_value, NULL, eANI_BOOLEAN_FALSE)
+ != eHAL_STATUS_SUCCESS )
+ {
+ ret = -EIO;
+ }
+ break;
+ }
+
+ case WE_SET_SAP_AUTO_CHANNEL_SELECTION:
+ {
+ if( 0 == set_value )
+ {
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->apAutoChannelSelection = 0;
+ }
+ else if ( 1 == set_value )
+ {
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->apAutoChannelSelection = 1;
+ }
+ else
+ {
+ hddLog(LOGE, "Invalid arg %d in WE_SET_SAP_AUTO_CHANNEL_SELECTION IOCTL\n", set_value);
+ ret = -EINVAL;
+ }
+ break;
+ }
+
+ case WE_SET_DATA_INACTIVITY_TO:
+ {
+ if ((set_value < CFG_DATA_INACTIVITY_TIMEOUT_MIN) ||
+ (set_value > CFG_DATA_INACTIVITY_TIMEOUT_MAX) ||
+ (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
+ WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT,
+ set_value,
+ NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE))
+ {
+ hddLog(LOGE,"Failure: Could not pass on "
+ "WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT configuration info "
+ "to CCM\n");
+ ret = -EINVAL;
+ }
+ break;
+ }
+ case WE_SET_MAX_TX_POWER:
+ {
+ tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+ tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Setting maximum tx power %d dBm",
+ __func__, set_value);
+ if( sme_SetMaxTxPower(hHal, bssid, selfMac, set_value) !=
+ eHAL_STATUS_SUCCESS )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
+ __func__);
+ return -EIO;
+ }
+
+ break;
+ }
+ case WE_SET_HIGHER_DTIM_TRANSITION:
+ {
+ if(!((set_value == eANI_BOOLEAN_FALSE) ||
+ (set_value == eANI_BOOLEAN_TRUE)))
+ {
+ hddLog(LOGE, "Dynamic DTIM Incorrect data:%d", set_value);
+ ret = -EINVAL;
+ }
+ else
+ {
+ if(pAdapter->higherDtimTransition != set_value)
+ {
+ pAdapter->higherDtimTransition = set_value;
+ hddLog(LOG1, "%s: higherDtimTransition set to :%d", __FUNCTION__, pAdapter->higherDtimTransition);
+ }
+ }
+
+ break;
+ }
+
+ case WE_SET_TM_LEVEL:
+ {
+ hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter);
+ hddLog(VOS_TRACE_LEVEL_INFO, "Set Thermal Mitigation Level %d", (int)set_value);
+ hddDevTmLevelChangedHandler(hddCtxt->parent_dev, set_value);
+
+ break;
+ }
+
+ default:
+ {
+ hddLog(LOGE, "Invalid IOCTL setvalue command %d value %d \n",
+ sub_cmd, set_value);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/* set param sub-ioctls */
+static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ VOS_STATUS vstatus;
+ int sub_cmd = wrqu->data.flags;
+ int ret = 0; /* success */
+ hdd_adapter_t *pAdapter = (netdev_priv(dev));
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+#ifdef WLAN_FEATURE_VOWIFI
+ hdd_config_t *pConfig = pHddCtx->cfg_ini;
+#endif /* WLAN_FEATURE_VOWIFI */
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received length %d", __FUNCTION__, wrqu->data.length);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received data %s", __FUNCTION__, (char*)wrqu->data.pointer);
+
+ switch(sub_cmd)
+ {
+ case WE_WOWL_ADD_PTRN:
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "ADD_PTRN\n");
+ hdd_add_wowl_ptrn((char*)wrqu->data.pointer);
+ break;
+ case WE_WOWL_DEL_PTRN:
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "DEL_PTRN\n");
+ hdd_del_wowl_ptrn((char*)wrqu->data.pointer);
+ break;
+#if defined WLAN_FEATURE_VOWIFI
+ case WE_NEIGHBOR_REPORT_REQUEST:
+ {
+ tRrmNeighborReq neighborReq;
+ tRrmNeighborRspCallbackInfo callbackInfo;
+
+ if (pConfig->fRrmEnable)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Neighbor Request\n");
+ neighborReq.no_ssid = (wrqu->data.length - 1) ? false : true ;
+ if( !neighborReq.no_ssid )
+ {
+ neighborReq.ssid.length = (wrqu->data.length - 1) > 32 ? 32 : (wrqu->data.length - 1) ;
+ vos_mem_copy( neighborReq.ssid.ssId, wrqu->data.pointer, neighborReq.ssid.length );
+ }
+
+ callbackInfo.neighborRspCallback = NULL;
+ callbackInfo.neighborRspCallbackContext = NULL;
+ callbackInfo.timeout = 5000; //5 seconds
+ sme_NeighborReportRequest( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &neighborReq, &callbackInfo );
+ }
+ else
+ {
+ hddLog(LOGE, "%s: Ignoring neighbor request as RRM is not enabled\n", __func__);
+ ret = -EINVAL;
+ }
+ }
+ break;
+#endif
+#ifdef WLAN_FEATURE_P2P
+ case WE_SET_AP_WPS_IE:
+ hddLog( LOGE, "Received WE_SET_AP_WPS_IE" );
+#ifdef WLAN_FEATURE_P2P
+ sme_updateP2pIe( WLAN_HDD_GET_HAL_CTX(pAdapter), wrqu->data.pointer, wrqu->data.length );
+#endif // WLAN_FEATURE_P2P
+ break;
+#endif
+ case WE_SET_CONFIG:
+ vstatus = hdd_execute_config_command(pHddCtx, wrqu->data.pointer);
+ if (VOS_STATUS_SUCCESS != vstatus)
+ {
+ ret = -EINVAL;
+ }
+ break;
+ default:
+ {
+ hddLog(LOGE, "%s: Invalid sub command %d\n",__FUNCTION__, sub_cmd);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ return ret;
+}
+
+/* get param sub-ioctls */
+static int iw_setnone_getint(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ int *value = (int *)extra;
+ int ret = 0; /* success */
+
+
+ switch (value[0])
+ {
+ case WE_GET_11D_STATE:
+ {
+ tSmeConfigParams smeConfig;;
+
+ sme_GetConfigParam(hHal,&smeConfig);
+
+ *value = smeConfig.csrConfig.Is11dSupportEnabled;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("11D state=%ld!!\n"),*value);
+
+ break;
+ }
+
+ case WE_IBSS_STATUS:
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****Return IBSS Status*****\n");
+ break;
+
+ case WE_PMC_STATE:
+ {
+ *value = pmcGetPmcState(hHal);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("PMC state=%ld!!\n"),*value);
+ break;
+ }
+ case WE_GET_WLAN_DBG:
+ {
+ vos_trace_display();
+ *value = 0;
+ break;
+ }
+ case WE_MODULE_DOWN_IND:
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: sending WLAN_MODULE_DOWN_IND", __FUNCTION__);
+ send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
+#ifdef WLAN_BTAMP_FEATURE
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: Take down AMP PAL", __FUNCTION__);
+ BSL_Deinit(vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
+#endif
+ //WLANBAP_Close(vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
+
+ *value = 0;
+ break;
+ }
+ case WE_GET_MAX_ASSOC:
+ {
+ if (ccmCfgGetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, (tANI_U32 *)value) != eHAL_STATUS_SUCCESS)
+ {
+ ret = -EIO;
+ }
+ break;
+ }
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ case WE_GET_WDI_DBG:
+ {
+ wpalTraceDisplay();
+ *value = 0;
+ break;
+ }
+#endif // FEATURE_WLAN_INTEGRATED_SOC
+
+ case WE_GET_SAP_AUTO_CHANNEL_SELECTION:
+ {
+ *value = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->apAutoChannelSelection;
+ break;
+ }
+ case WE_GET_CONCURRENCY_MODE:
+ {
+ *value = hdd_get_concurrency_mode ( );
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("concurrency mode=%d \n"),*value);
+ break;
+ }
+
+ default:
+ {
+ hddLog(LOGE, "Invalid IOCTL get_value command %d ",value[0]);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/* set param sub-ioctls */
+int iw_set_three_ints_getnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int *value = (int *)extra;
+ int sub_cmd = value[0];
+ int ret = 0;
+
+ switch(sub_cmd)
+ {
+ case WE_SET_WLAN_DBG:
+ {
+ vos_trace_setValue( value[1], value[2], value[3]);
+ break;
+ }
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ case WE_SET_WDI_DBG:
+ {
+ wpalTraceSetLevel( value[1], value[2], value[3]);
+ break;
+ }
+#endif // FEATURE_WLAN_INTEGRATED_SOC
+ case WE_SET_SAP_CHANNELS:
+ {
+ ret = iw_softap_set_channel_range( dev, value[1], value[2], value[3]);
+ break;
+ }
+
+ default:
+ {
+ hddLog(LOGE, "Invalid IOCTL command %d \n", sub_cmd );
+ break;
+ }
+ }
+ return ret;
+}
+
+static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ int sub_cmd = wrqu->data.flags;
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ VOS_STATUS status;
+#endif // FEATURE_WLAN_NON_INTEGRATED_SOC
+ switch(sub_cmd)
+ {
+ case WE_WLAN_VERSION:
+ {
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ status = hdd_wlan_get_version(pAdapter, wrqu, extra);
+#else // FEATURE_WLAN_NON_INTEGRATED_SOC
+ char *buf = extra;
+ wrqu->data.length = snprintf(buf, WE_MAX_STR_LEN, "%s_",
+ WLAN_CHIP_VERSION);
+#endif
+ break;
+ }
+
+ case WE_GET_STATS:
+ {
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ hdd_tx_rx_stats_t *pStats = &pAdapter->hdd_stats.hddTxRxStats;
+ hdd_chip_reset_stats_t *pResetStats = &pHddCtx->hddChipResetStats;
+
+ snprintf(extra, WE_MAX_STR_LEN,
+ "\nTransmit"
+ "\ncalled %u, dropped %u, backpressured %u, queued %u"
+ "\n dropped BK %u, BE %u, VI %u, VO %u"
+ "\n classified BK %u, BE %u, VI %u, VO %u"
+ "\nbackpressured BK %u, BE %u, VI %u, VO %u"
+ "\n queued BK %u, BE %u, VI %u, VO %u"
+ "\nfetched %u, empty %u, lowres %u, deqerr %u"
+ "\ndequeued %u, depressured %u, completed %u, flushed %u"
+ "\n fetched BK %u, BE %u, VI %u, VO %u"
+ "\n dequeued BK %u, BE %u, VI %u, VO %u"
+ "\n depressured BK %u, BE %u, VI %u, VO %u"
+ "\n flushed BK %u, BE %u, VI %u, VO %u"
+ "\n\nReceive"
+ "\nchains %u, packets %u, dropped %u, delivered %u, refused %u"
+ "\n\nResetsStats"
+ "\n TotalLogp %u Cmd53 %u MutexRead %u MIF-Error %u FW-Heartbeat %u Others %u"
+ "\n",
+ pStats->txXmitCalled,
+ pStats->txXmitDropped,
+ pStats->txXmitBackPressured,
+ pStats->txXmitQueued,
+
+ pStats->txXmitDroppedAC[WLANTL_AC_BK],
+ pStats->txXmitDroppedAC[WLANTL_AC_BE],
+ pStats->txXmitDroppedAC[WLANTL_AC_VI],
+ pStats->txXmitDroppedAC[WLANTL_AC_VO],
+
+ pStats->txXmitClassifiedAC[WLANTL_AC_BK],
+ pStats->txXmitClassifiedAC[WLANTL_AC_BE],
+ pStats->txXmitClassifiedAC[WLANTL_AC_VI],
+ pStats->txXmitClassifiedAC[WLANTL_AC_VO],
+
+ pStats->txXmitBackPressuredAC[WLANTL_AC_BK],
+ pStats->txXmitBackPressuredAC[WLANTL_AC_BE],
+ pStats->txXmitBackPressuredAC[WLANTL_AC_VI],
+ pStats->txXmitBackPressuredAC[WLANTL_AC_VO],
+
+ pStats->txXmitQueuedAC[WLANTL_AC_BK],
+ pStats->txXmitQueuedAC[WLANTL_AC_BE],
+ pStats->txXmitQueuedAC[WLANTL_AC_VI],
+ pStats->txXmitQueuedAC[WLANTL_AC_VO],
+
+ pStats->txFetched,
+ pStats->txFetchEmpty,
+ pStats->txFetchLowResources,
+ pStats->txFetchDequeueError,
+
+ pStats->txFetchDequeued,
+ pStats->txFetchDePressured,
+ pStats->txCompleted,
+ pStats->txFlushed,
+
+ pStats->txFetchedAC[WLANTL_AC_BK],
+ pStats->txFetchedAC[WLANTL_AC_BE],
+ pStats->txFetchedAC[WLANTL_AC_VI],
+ pStats->txFetchedAC[WLANTL_AC_VO],
+
+ pStats->txFetchDequeuedAC[WLANTL_AC_BK],
+ pStats->txFetchDequeuedAC[WLANTL_AC_BE],
+ pStats->txFetchDequeuedAC[WLANTL_AC_VI],
+ pStats->txFetchDequeuedAC[WLANTL_AC_VO],
+
+ pStats->txFetchDePressuredAC[WLANTL_AC_BK],
+ pStats->txFetchDePressuredAC[WLANTL_AC_BE],
+ pStats->txFetchDePressuredAC[WLANTL_AC_VI],
+ pStats->txFetchDePressuredAC[WLANTL_AC_VO],
+
+ pStats->txFlushedAC[WLANTL_AC_BK],
+ pStats->txFlushedAC[WLANTL_AC_BE],
+ pStats->txFlushedAC[WLANTL_AC_VI],
+ pStats->txFlushedAC[WLANTL_AC_VO],
+
+ pStats->rxChains,
+ pStats->rxPackets,
+ pStats->rxDropped,
+ pStats->rxDelivered,
+ pStats->rxRefused,
+
+ pResetStats->totalLogpResets,
+ pResetStats->totalCMD53Failures,
+ pResetStats->totalMutexReadFailures,
+ pResetStats->totalMIFErrorFailures,
+ pResetStats->totalFWHearbeatFailures,
+ pResetStats->totalUnknownExceptions
+ );
+ wrqu->data.length = strlen(extra)+1;
+ break;
+ }
+
+ case WE_GET_CFG:
+ {
+ hdd_cfg_get_config(WLAN_HDD_GET_CTX(pAdapter), extra, WE_MAX_STR_LEN);
+ wrqu->data.length = strlen(extra)+1;
+ break;
+ }
+
+ case WE_GET_WMM_STATUS:
+ {
+ snprintf(extra, WE_MAX_STR_LEN,
+ "\nDir: 0=up, 1=down, 3=both\n"
+ "|------------------------|\n"
+ "|AC | ACM |Admitted| Dir |\n"
+ "|------------------------|\n"
+ "|VO | %d | %3s | %d |\n"
+ "|VI | %d | %3s | %d |\n"
+ "|BE | %d | %3s | %d |\n"
+ "|BK | %d | %3s | %d |\n"
+ "|------------------------|\n",
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcAccessRequired,
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcAccessAllowed?"YES":"NO",
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcTspecInfo.ts_info.direction,
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcAccessRequired,
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcAccessAllowed?"YES":"NO",
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcTspecInfo.ts_info.direction,
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcAccessRequired,
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcAccessAllowed?"YES":"NO",
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcTspecInfo.ts_info.direction,
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcAccessRequired,
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcAccessAllowed?"YES":"NO",
+ pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcTspecInfo.ts_info.direction);
+
+ wrqu->data.length = strlen(extra)+1;
+ break;
+ }
+ case WE_GET_CHANNEL_LIST:
+ {
+ VOS_STATUS status;
+ v_U8_t i, len;
+ char* buf ;
+ tChannelListInfo channel_list;
+
+ status = iw_softap_get_channel_list(dev, info, wrqu, (char *)&channel_list);
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s GetChannelList Failed!!!\n",__func__);
+ return -EINVAL;
+ }
+ buf = extra;
+
+ /**
+ * Maximum channels = WNI_CFG_VALID_CHANNEL_LIST_LEN. Maximum buffer
+ * needed = 5 * number of channels. Check if sufficient buffer is available and
+ * then proceed to fill the buffer.
+ */
+ if(WE_MAX_STR_LEN < (5 * WNI_CFG_VALID_CHANNEL_LIST_LEN))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s Insufficient Buffer to populate channel list\n",__func__);
+ return -EINVAL;
+ }
+ len = snprintf(buf, 5, "%u ", channel_list.num_channels);
+ buf += len;
+ for(i = 0 ; i < channel_list.num_channels; i++)
+ {
+ len = snprintf(buf, 5,
+ "%u ", channel_list.channels[i]);
+ buf += len;
+ }
+ wrqu->data.length = strlen(extra)+1;
+
+ break;
+ }
+ default:
+ {
+ hddLog(LOGE, "Invalid IOCTL command %d \n", sub_cmd );
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* action sub-ioctls */
+static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ int sub_cmd = wrqu->data.flags;
+ int ret = 0; /* sucess */
+
+ switch (sub_cmd)
+ {
+ case WE_CLEAR_STATS:
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: clearing", __FUNCTION__);
+ memset(&pAdapter->stats, 0, sizeof(pAdapter->stats));
+ memset(&pAdapter->hdd_stats, 0, sizeof(pAdapter->hdd_stats));
+ break;
+ }
+#ifdef WLAN_SOFTAP_FEATURE
+ case WE_INIT_AP:
+ {
+ pr_info("Init AP trigger\n");
+ hdd_open_adapter( WLAN_HDD_GET_CTX(pAdapter), WLAN_HDD_SOFTAP, "softap.%d",
+ wlan_hdd_get_intf_addr( WLAN_HDD_GET_CTX(pAdapter) ),TRUE);
+ break;
+ }
+ case WE_STOP_AP:
+ {
+ /*FIX ME: Need to be revisited if multiple SAPs to be supported */
+ /* As Soft AP mode has been changed to STA already with killing of Hostapd,
+ * this is a dead code and need to find the adpater by name rather than mode */
+ hdd_adapter_t* pAdapter_to_stop =
+ hdd_get_adapter_by_name(WLAN_HDD_GET_CTX(pAdapter), "softap.0");
+ if( pAdapter_to_stop )
+ {
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ pr_info("Stopping AP mode\n");
+
+ /*Make sure that pAdapter cleaned properly*/
+ hdd_stop_adapter( pHddCtx, pAdapter_to_stop );
+ hdd_deinit_adapter( pHddCtx, pAdapter_to_stop );
+ memset(&pAdapter_to_stop->sessionCtx, 0, sizeof(pAdapter_to_stop->sessionCtx));
+
+ wlan_hdd_release_intf_addr(WLAN_HDD_GET_CTX(pAdapter),
+ pAdapter_to_stop->macAddressCurrent.bytes);
+ hdd_close_adapter(WLAN_HDD_GET_CTX(pAdapter), pAdapter_to_stop,
+ TRUE);
+ }
+ else
+ {
+ printk(KERN_ERR"SAP adaptor not found to stop it!\n");
+ }
+
+ break;
+ }
+#endif
+#ifdef WLAN_BTAMP_FEATURE
+ case WE_ENABLE_AMP:
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: enabling AMP", __FUNCTION__);
+ WLANBAP_RegisterWithHCI(pAdapter);
+ break;
+ }
+ case WE_DISABLE_AMP:
+ {
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ VOS_STATUS status;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __FUNCTION__);
+
+ pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+ status = WLANBAP_StopAmp();
+ if(VOS_STATUS_SUCCESS != status )
+ {
+ pHddCtx->isAmpAllowed = VOS_TRUE;
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ "%s: Failed to stop AMP", __func__);
+ }
+ else
+ {
+ //a state m/c implementation in PAL is TBD to avoid this delay
+ msleep(500);
+ pHddCtx->isAmpAllowed = VOS_FALSE;
+ WLANBAP_DeregisterFromHCI();
+ }
+
+ break;
+ }
+#endif
+
+ default:
+ {
+ hddLog(LOGE, "%s: unknown ioctl %d", __FUNCTION__, sub_cmd);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int iw_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ int sub_cmd = wrqu->data.flags;
+ int *value = (int*)wrqu->data.pointer;
+ int apps_args[MAX_VAR_ARGS] = {0};
+ int num_args = wrqu->data.length;
+
+ hddLog(LOG1, "%s: Received length %d", __FUNCTION__, wrqu->data.length);
+ if (num_args > MAX_VAR_ARGS)
+ {
+ num_args = MAX_VAR_ARGS;
+ }
+ vos_mem_copy(apps_args, value, (sizeof(int)) * num_args);
+
+ switch (sub_cmd)
+ {
+ case WE_LOG_DUMP_CMD:
+ {
+ hddLog(LOG1, "%s: LOG_DUMP %d arg1 %d arg2 %d arg3 %d arg4 %d",
+ __FUNCTION__, apps_args[0], apps_args[1], apps_args[2],
+ apps_args[3], apps_args[4]);
+
+ logPrintf(hHal, apps_args[0], apps_args[1], apps_args[2],
+ apps_args[3], apps_args[4]);
+
+ }
+ break;
+
+#ifdef WLAN_FEATURE_P2P
+ case WE_P2P_NOA_CMD:
+ {
+ p2p_app_setP2pPs_t p2pNoA;
+
+ p2pNoA.opp_ps = apps_args[0];
+ p2pNoA.ctWindow = apps_args[1];
+ p2pNoA.duration = apps_args[2];
+ p2pNoA.interval = apps_args[3];
+ p2pNoA.count = apps_args[4];
+ p2pNoA.single_noa_duration = apps_args[5];
+ p2pNoA.psSelection = apps_args[6];
+
+ hddLog(LOG1, "%s: P2P_NOA_ATTR:oppPS %d ctWindow %d duration %d "
+ "interval %d count %d single noa duration %d PsSelection %x",
+ __FUNCTION__, apps_args[0], apps_args[1], apps_args[2],
+ apps_args[3], apps_args[4], apps_args[5], apps_args[6]);
+
+ hdd_setP2pPs(dev, &p2pNoA);
+
+ }
+ break;
+#endif
+
+ default:
+ {
+ hddLog(LOGE, "Invalid IOCTL command %d", sub_cmd );
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+static int iw_add_tspec(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra;
+ int params[HDD_WLAN_WMM_PARAM_COUNT];
+ sme_QosWmmTspecInfo tSpec;
+ v_U32_t handle;
+
+ // make sure the application is sufficiently priviledged
+ // note that the kernel will do this for "set" ioctls, but since
+ // this ioctl wants to return status to user space it must be
+ // defined as a "get" ioctl
+ if (!capable(CAP_NET_ADMIN))
+ {
+ return -EPERM;
+ }
+
+ // we must be associated in order to add a tspec
+ if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
+ {
+ *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ return 0;
+ }
+
+ // since we are defined to be a "get" ioctl, and since the number
+ // of params exceeds the number of params that wireless extensions
+ // will pass down in the iwreq_data, we must copy the "set" params
+ // from user space ourselves
+ if (copy_from_user(¶ms, wrqu->data.pointer, sizeof(params)))
+ {
+ // hmmm, can't get them
+ return -EIO;
+ }
+
+ // clear the tspec
+ memset(&tSpec, 0, sizeof(tSpec));
+
+ // validate the handle
+ handle = params[HDD_WLAN_WMM_PARAM_HANDLE];
+ if (HDD_WMM_HANDLE_IMPLICIT == handle)
+ {
+ // that one is reserved
+ *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ return 0;
+ }
+
+ // validate the TID
+ if (params[HDD_WLAN_WMM_PARAM_TID] > 7)
+ {
+ // out of range
+ *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ return 0;
+ }
+ tSpec.ts_info.tid = params[HDD_WLAN_WMM_PARAM_TID];
+
+ // validate the direction
+ switch (params[HDD_WLAN_WMM_PARAM_DIRECTION])
+ {
+ case HDD_WLAN_WMM_DIRECTION_UPSTREAM:
+ tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_UPLINK;
+ break;
+
+ case HDD_WLAN_WMM_DIRECTION_DOWNSTREAM:
+ tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_DOWNLINK;
+ break;
+
+ case HDD_WLAN_WMM_DIRECTION_BIDIRECTIONAL:
+ tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_BOTH;
+ break;
+
+ default:
+ // unknown
+ *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ return 0;
+ }
+
+ // validate the user priority
+ if (params[HDD_WLAN_WMM_PARAM_USER_PRIORITY] >= SME_QOS_WMM_UP_MAX)
+ {
+ // out of range
+ *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ return 0;
+ }
+ tSpec.ts_info.up = params[HDD_WLAN_WMM_PARAM_USER_PRIORITY];
+
+ tSpec.nominal_msdu_size = params[HDD_WLAN_WMM_PARAM_NOMINAL_MSDU_SIZE];
+ tSpec.maximum_msdu_size = params[HDD_WLAN_WMM_PARAM_MAXIMUM_MSDU_SIZE];
+ tSpec.min_data_rate = params[HDD_WLAN_WMM_PARAM_MINIMUM_DATA_RATE];
+ tSpec.mean_data_rate = params[HDD_WLAN_WMM_PARAM_MEAN_DATA_RATE];
+ tSpec.peak_data_rate = params[HDD_WLAN_WMM_PARAM_PEAK_DATA_RATE];
+ tSpec.max_burst_size = params[HDD_WLAN_WMM_PARAM_MAX_BURST_SIZE];
+ tSpec.min_phy_rate = params[HDD_WLAN_WMM_PARAM_MINIMUM_PHY_RATE];
+ tSpec.surplus_bw_allowance = params[HDD_WLAN_WMM_PARAM_SURPLUS_BANDWIDTH_ALLOWANCE];
+ tSpec.min_service_interval = params[HDD_WLAN_WMM_PARAM_SERVICE_INTERVAL];
+ tSpec.max_service_interval = params[HDD_WLAN_WMM_PARAM_MAX_SERVICE_INTERVAL];
+ tSpec.suspension_interval = params[HDD_WLAN_WMM_PARAM_SUSPENSION_INTERVAL];
+ tSpec.inactivity_interval = params[HDD_WLAN_WMM_PARAM_INACTIVITY_INTERVAL];
+
+ tSpec.ts_info.burst_size_defn = params[HDD_WLAN_WMM_PARAM_BURST_SIZE_DEFN];
+
+ // validate the ts info ack policy
+ switch (params[HDD_WLAN_WMM_PARAM_ACK_POLICY])
+ {
+ case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK:
+ tSpec.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
+ break;
+
+ case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK:
+ tSpec.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK;
+ break;
+
+ default:
+ // unknown
+ *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ return 0;
+ }
+
+ *pStatus = hdd_wmm_addts(pAdapter, handle, &tSpec);
+ return 0;
+}
+
+
+static int iw_del_tspec(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ int *params = (int *)extra;
+ hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra;
+ v_U32_t handle;
+
+ // make sure the application is sufficiently priviledged
+ // note that the kernel will do this for "set" ioctls, but since
+ // this ioctl wants to return status to user space it must be
+ // defined as a "get" ioctl
+ if (!capable(CAP_NET_ADMIN))
+ {
+ return -EPERM;
+ }
+
+ // although we are defined to be a "get" ioctl, the params we require
+ // will fit in the iwreq_data, therefore unlike iw_add_tspec() there
+ // is no need to copy the params from user space
+
+ // validate the handle
+ handle = params[HDD_WLAN_WMM_PARAM_HANDLE];
+ if (HDD_WMM_HANDLE_IMPLICIT == handle)
+ {
+ // that one is reserved
+ *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ return 0;
+ }
+
+ *pStatus = hdd_wmm_delts(pAdapter, handle);
+ return 0;
+}
+
+
+static int iw_get_tspec(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ int *params = (int *)extra;
+ hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra;
+ v_U32_t handle;
+
+ // although we are defined to be a "get" ioctl, the params we require
+ // will fit in the iwreq_data, therefore unlike iw_add_tspec() there
+ // is no need to copy the params from user space
+
+ // validate the handle
+ handle = params[HDD_WLAN_WMM_PARAM_HANDLE];
+ if (HDD_WMM_HANDLE_IMPLICIT == handle)
+ {
+ // that one is reserved
+ *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ return 0;
+ }
+
+ *pStatus = hdd_wmm_checkts(pAdapter, handle);
+ return 0;
+}
+
+
+#ifdef FEATURE_WLAN_WAPI
+static int iw_qcom_set_wapi_mode(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
+
+ WAPI_FUNCTION_MODE *pWapiMode = (WAPI_FUNCTION_MODE *)wrqu->data.pointer;
+
+ hddLog(LOG1, "The function iw_qcom_set_wapi_mode called");
+ hddLog(LOG1, "%s: Received data %s", __FUNCTION__, (char*)wrqu->data.pointer);
+ hddLog(LOG1, "%s: Received length %d", __FUNCTION__, wrqu->data.length);
+ hddLog(LOG1, "%s: Input Data (wreq) WAPI Mode:%02d", __FUNCTION__, pWapiMode->wapiMode);
+
+
+ if(WZC_ORIGINAL == pWapiMode->wapiMode) {
+ hddLog(LOG1, "%s: WAPI Mode Set to OFF", __FUNCTION__);
+ /* Set Encryption mode to defualt , this allows next successfull non-WAPI Association */
+ pRoamProfile->EncryptionType.numEntries = 1;
+ pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+ pRoamProfile->mcEncryptionType.numEntries = 1;
+ pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+
+ pRoamProfile->AuthType.numEntries = 1;
+ pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+ pRoamProfile->AuthType.authType[0] = pHddStaCtx->conn_info.authType;
+ }
+ else if(WAPI_EXTENTION == pWapiMode->wapiMode) {
+ hddLog(LOG1, "%s: WAPI Mode Set to ON", __FUNCTION__);
+ }
+ else
+ return -EINVAL;
+
+ pAdapter->wapi_info.nWapiMode = pWapiMode->wapiMode;
+
+ return 0;
+}
+
+static int iw_qcom_get_wapi_mode(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ WAPI_FUNCTION_MODE *pWapiMode = (WAPI_FUNCTION_MODE *)(extra);
+
+ hddLog(LOG1, "The function iw_qcom_get_wapi_mode called");
+
+ pWapiMode->wapiMode = pAdapter->wapi_info.nWapiMode;
+ hddLog(LOG1, "%s: GET WAPI Mode Value:%02d", __FUNCTION__, pWapiMode->wapiMode);
+ printk("\nGET WAPI MODE:%d",pWapiMode->wapiMode);
+ return 0;
+}
+
+static int iw_qcom_set_wapi_assoc_info(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+// WAPI_AssocInfo *pWapiAssocInfo = (WAPI_AssocInfo *)(wrqu->data.pointer);
+ WAPI_AssocInfo *pWapiAssocInfo = (WAPI_AssocInfo *)(extra);
+ int i = 0, j = 0;
+ hddLog(LOG1, "The function iw_qcom_set_wapi_assoc_info called");
+ hddLog(LOG1, "%s: Received length %d", __FUNCTION__, wrqu->data.length);
+ hddLog(LOG1, "%s: Received data %s", __FUNCTION__, (char*)wrqu->data.pointer);
+ hddLog(LOG1, "%s: Received data %s", __FUNCTION__, (char*)extra);
+
+ VOS_ASSERT(pWapiAssocInfo);
+
+ hddLog(LOG1, "%s: INPUT DATA:\nElement ID:0x%02x Length:0x%02x Version:0x%04x\n",__FUNCTION__,pWapiAssocInfo->elementID,pWapiAssocInfo->length,pWapiAssocInfo->version);
+ hddLog(LOG1,"%s: akm Suite Cnt:0x%04x",__FUNCTION__,pWapiAssocInfo->akmSuiteCount);
+ for(i =0 ; i < 16 ; i++)
+ hddLog(LOG1,"akm suite[%02d]:0x%08lx",i,pWapiAssocInfo->akmSuite[i]);
+
+ hddLog(LOG1,"%s: Unicast Suite Cnt:0x%04x",__FUNCTION__,pWapiAssocInfo->unicastSuiteCount);
+ for(i =0 ; i < 16 ; i++)
+ hddLog(LOG1, "Unicast suite[%02d]:0x%08lx",i,pWapiAssocInfo->unicastSuite[i]);
+
+ hddLog(LOG1,"%s: Multicast suite:0x%08lx Wapi capa:0x%04x",__FUNCTION__,pWapiAssocInfo->multicastSuite,pWapiAssocInfo->wapiCability);
+ hddLog(LOG1, "%s: BKID Cnt:0x%04x\n",__FUNCTION__,pWapiAssocInfo->bkidCount);
+ for(i = 0 ; i < 16 ; i++) {
+ hddLog(LOG1, "BKID List[%02d].bkid:0x",i);
+ for(j = 0 ; j < 16 ; j++)
+ hddLog(LOG1,"%02x",pWapiAssocInfo->bkidList[i].bkid[j]);
+ }
+
+ /* We are not using the entire IE as provided by the supplicant.
+ * This is being calculated by SME. This is the same as in the
+ * case of WPA. Only the auth mode information needs to be
+ * extracted here*/
+ if ( pWapiAssocInfo->akmSuite[0] == WAPI_PSK_AKM_SUITE ) {
+ hddLog(LOG1, "%s: WAPI AUTH MODE SET TO PSK",__FUNCTION__);
+ pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
+ }
+
+ if ( pWapiAssocInfo->akmSuite[0] == WAPI_CERT_AKM_SUITE) {
+ hddLog(LOG1, "%s: WAPI AUTH MODE SET TO CERTIFICATE",__FUNCTION__);
+ pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
+ }
+ return 0;
+}
+
+static int iw_qcom_set_wapi_key(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+ tANI_U32 roamId = 0xFF;
+ tANI_U8 *pKeyPtr = NULL;
+ v_BOOL_t isConnected = TRUE;
+ tCsrRoamSetKey setKey;
+ int i = 0;
+
+// WLAN_WAPI_KEY *pWapiKey = (WLAN_WAPI_KEY *)(wrqu->data.pointer);
+ WLAN_WAPI_KEY *pWapiKey = (WLAN_WAPI_KEY *)(extra);
+
+ hddLog(LOG1, "The function iw_qcom_set_wapi_key called ");
+ hddLog(LOG1, "%s: Received length %d", __FUNCTION__, wrqu->data.length);
+ hddLog(LOG1, "%s: Received data %s", __FUNCTION__, (char*)wrqu->data.pointer);
+ hddLog(LOG1, "%s: Received data %s", __FUNCTION__, (char*)extra);
+
+ hddLog(LOG1,":s: INPUT DATA:\nKey Type:0x%02x Key Direction:0x%02x KEY ID:0x%02x\n", __FUNCTION__,pWapiKey->keyType,pWapiKey->keyDirection,pWapiKey->keyId);
+ hddLog(LOG1,"Add Index:0x");
+ for(i =0 ; i < 12 ; i++)
+ hddLog(LOG1,"%02x",pWapiKey->addrIndex[i]);
+
+ hddLog(LOG1,"\n%s: WAPI ENCRYPTION KEY LENGTH:0x%04x", __FUNCTION__,pWapiKey->wpiekLen);
+ hddLog(LOG1, "WAPI ENCRYPTION KEY:0x");
+ for(i =0 ; i < 16 ; i++)
+ hddLog(LOG1,"%02x",pWapiKey->wpiek[i]);
+
+ hddLog(LOG1,"\n%s: WAPI INTEGRITY CHECK KEY LENGTH:0x%04x", __FUNCTION__,pWapiKey->wpickLen);
+ hddLog(LOG1,"WAPI INTEGRITY CHECK KEY:0x");
+ for(i =0 ; i < 16 ; i++)
+ hddLog(LOG1,"%02x",pWapiKey->wpick[i]);
+
+ hddLog(LOG1,"\nWAPI PN NUMBER:0x");
+ for(i = 0 ; i < 16 ; i++)
+ hddLog(LOG1,"%02x",pWapiKey->pn[i]);
+
+ // Clear the setkey memory
+ vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
+ // Store Key ID
+ setKey.keyId = (unsigned char)( pWapiKey->keyId );
+ // SET WAPI Encryption
+ setKey.encType = eCSR_ENCRYPT_TYPE_WPI;
+ // Key Directionn both TX and RX
+ setKey.keyDirection = eSIR_TX_RX; // Do WE NEED to update this based on Key Type as GRP/UNICAST??
+ // the PAE role
+ setKey.paeRole = 0 ;
+
+ switch ( pWapiKey->keyType )
+ {
+ case HDD_PAIRWISE_WAPI_KEY:
+ {
+ isConnected = hdd_connIsConnected(pHddStaCtx);
+ vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
+ break;
+ }
+ case HDD_GROUP_WAPI_KEY:
+ {
+ vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
+ break;
+ }
+ default:
+ {
+ //Any other option is invalid.
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] %s() failed to Set Key. Invalid key type %d", __LINE__,__FUNCTION__ , -1 );
+
+ hddLog(LOGE," %s: Error WAPI Key Add Type",__FUNCTION__);
+ halStatus = !eHAL_STATUS_SUCCESS; // NEED TO UPDATE THIS WITH CORRECT VALUE
+ break; // NEED RETURN FROM HERE ????
+ }
+ }
+
+ // Concatenating the Encryption Key (EK) and the MIC key (CK): EK followed by CK
+ setKey.keyLength = (v_U16_t)((pWapiKey->wpiekLen)+(pWapiKey->wpickLen));
+ pKeyPtr = setKey.Key;
+ memcpy( pKeyPtr, pWapiKey->wpiek, pWapiKey->wpiekLen );
+ pKeyPtr += pWapiKey->wpiekLen;
+ memcpy( pKeyPtr, pWapiKey->wpick, pWapiKey->wpickLen );
+
+ // Set the new key with SME.
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
+
+ if ( isConnected ) {
+ halStatus = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &setKey, &roamId );
+ if ( halStatus != eHAL_STATUS_SUCCESS )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "[%4d] sme_RoamSetKey returned ERROR status= %d", __LINE__, halStatus );
+
+ pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
+ }
+ }
+#if 0 /// NEED TO CHECK ON THIS
+ else
+ {
+ // Store the keys in the adapter to be moved to the profile & passed to
+ // SME in the ConnectRequest if we are not yet in connected state.
+ memcpy( &pAdapter->setKey[ setKey.keyId ], &setKey, sizeof( setKey ) );
+ pAdapter->fKeySet[ setKey.keyId ] = TRUE;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ " Saving key [idx= %d] to apply when moving to connected state ",
+ setKey.keyId );
+
+ }
+#endif
+ return halStatus;
+}
+
+static int iw_qcom_set_wapi_bkid(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+#ifdef WLAN_DEBUG
+ int i = 0;
+ WLAN_BKID_LIST *pBkid = ( WLAN_BKID_LIST *) (wrqu->data.pointer);
+#endif
+
+ hddLog(LOG1, "The function iw_qcom_set_wapi_bkid called");
+ hddLog(LOG1, "%s: Received length %d", __FUNCTION__, wrqu->data.length);
+ hddLog(LOG1, "%s: Received data %s", __FUNCTION__, (char*)wrqu->data.pointer);
+ hddLog(LOG1, "%s: Received data %s", __FUNCTION__, (char*)extra);
+
+ hddLog(LOG1,"%s: INPUT DATA:\n BKID Length:0x%08lx\n", __FUNCTION__,pBkid->length);
+ hddLog(LOG1,"%s: BKID Cnt:0x%04lx",pBkid->BKIDCount);
+
+ hddLog(LOG1,"BKID KEY LIST[0]:0x");
+#ifdef WLAN_DEBUG
+ for(i =0 ; i < 16 ; i++)
+ hddLog(LOG1,"%02x",pBkid->BKID[0].bkid[i]);
+#endif
+
+ return 0;
+}
+
+static int iw_qcom_get_wapi_bkid(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /* Yet to implement this function, 19th April 2010 */
+ hddLog(LOG1, "The function iw_qcom_get_wapi_bkid called ");
+
+ return 0;
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+//
+//
+// Each time the supplicant has the auth_request or reassoc request
+// IEs ready. This is pushed to the driver. The driver will inturn use
+// it to send out the auth req and reassoc req for 11r FT Assoc.
+//
+static int iw_set_fties(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ //v_CONTEXT_t pVosContext;
+
+ if (!wrqu->data.length)
+ {
+ hddLog(LOGE, FL("%s called with 0 length IEs\n"));
+ return -EINVAL;
+ }
+ if (wrqu->data.pointer == NULL)
+ {
+ hddLog(LOGE, FL("%s called with NULL IE\n"));
+ return -EINVAL;
+ }
+
+ // Added for debug on reception of Re-assoc Req.
+ if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
+ {
+ hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
+ wrqu->data.length);
+ hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
+ }
+
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__, wrqu->data.length);
+#endif
+
+ // Pass the received FT IEs to SME
+ sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, wrqu->data.pointer,
+ wrqu->data.length);
+
+ return 0;
+}
+#endif
+
+static int iw_set_dynamic_mcbc_filter(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tpMcBcFilterCfg pRequest = (tpMcBcFilterCfg)wrqu->data.pointer;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: Set MC BC Filter Config request: %d",
+ __FUNCTION__, pRequest->mcastBcastFilterSetting);
+
+ pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting =
+ pRequest->mcastBcastFilterSetting;
+ pHddCtx->dynamic_mcbc_filter.enableCfg = TRUE;
+
+ return 0;
+}
+
+static int iw_clear_dynamic_mcbc_filter(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: ", __FUNCTION__);
+
+ pHddCtx->dynamic_mcbc_filter.enableCfg = FALSE;
+
+ return 0;
+}
+
+static int iw_set_host_offload(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tpHostOffloadRequest pRequest = (tpHostOffloadRequest)wrqu->data.pointer;
+ tSirHostOffloadReq offloadRequest;
+
+ /* Debug display of request components. */
+ switch (pRequest->offloadType)
+ {
+ case WLAN_IPV4_ARP_REPLY_OFFLOAD:
+ hddLog(VOS_TRACE_LEVEL_WARN, "%s: Host offload request: ARP reply", __FUNCTION__);
+ switch (pRequest->enableOrDisable)
+ {
+ case WLAN_OFFLOAD_DISABLE:
+ hddLog(VOS_TRACE_LEVEL_WARN, " disable");
+ break;
+ case WLAN_OFFLOAD_ARP_AND_BC_FILTER_ENABLE:
+ hddLog(VOS_TRACE_LEVEL_WARN, " BC Filtering enable");
+ case WLAN_OFFLOAD_ENABLE:
+ hddLog(VOS_TRACE_LEVEL_WARN, " ARP offload enable");
+ hddLog(VOS_TRACE_LEVEL_WARN, " IP address: %d.%d.%d.%d",
+ pRequest->params.hostIpv4Addr[0], pRequest->params.hostIpv4Addr[1],
+ pRequest->params.hostIpv4Addr[2], pRequest->params.hostIpv4Addr[3]);
+ }
+ break;
+
+ case WLAN_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD:
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Host offload request: neighbor discovery\n",
+ __FUNCTION__);
+ switch (pRequest->enableOrDisable)
+ {
+ case WLAN_OFFLOAD_DISABLE:
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " disable");
+ break;
+ case WLAN_OFFLOAD_ENABLE:
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " enable");
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " IP address: %x:%x:%x:%x:%x:%x:%x:%x",
+ *(v_U16_t *)(pRequest->params.hostIpv6Addr),
+ *(v_U16_t *)(pRequest->params.hostIpv6Addr + 2),
+ *(v_U16_t *)(pRequest->params.hostIpv6Addr + 4),
+ *(v_U16_t *)(pRequest->params.hostIpv6Addr + 6),
+ *(v_U16_t *)(pRequest->params.hostIpv6Addr + 8),
+ *(v_U16_t *)(pRequest->params.hostIpv6Addr + 10),
+ *(v_U16_t *)(pRequest->params.hostIpv6Addr + 12),
+ *(v_U16_t *)(pRequest->params.hostIpv6Addr + 14));
+ }
+ }
+
+ /* Execute offload request. The reason that we can copy the request information
+ from the ioctl structure to the SME structure is that they are laid out
+ exactly the same. Otherwise, each piece of information would have to be
+ copied individually. */
+ memcpy(&offloadRequest, pRequest, wrqu->data.length);
+ if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), &offloadRequest))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute host offload request\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int iw_set_keepalive_params(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tpKeepAliveRequest pRequest = (tpKeepAliveRequest)wrqu->data.pointer;
+ tSirKeepAliveReq keepaliveRequest;
+
+ if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s:LOGP in Progress. Ignore!!!",__func__);
+ return 0;
+ }
+
+ /* Debug display of request components. */
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set Keep Alive Request : TimePeriod %d size %d",
+ __FUNCTION__,pRequest->timePeriod, sizeof(tKeepAliveRequest));
+
+ switch (pRequest->packetType)
+ {
+ case WLAN_KEEP_ALIVE_NULL_PKT:
+ hddLog(VOS_TRACE_LEVEL_WARN, "%s: Keep Alive Request: Tx NULL", __FUNCTION__);
+ break;
+
+ case WLAN_KEEP_ALIVE_UNSOLICIT_ARP_RSP:
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Keep Alive Request: Tx UnSolicited ARP RSP\n",
+ __FUNCTION__);
+
+ hddLog(VOS_TRACE_LEVEL_WARN, " Host IP address: %d.%d.%d.%d",
+ pRequest->hostIpv4Addr[0], pRequest->hostIpv4Addr[1],
+ pRequest->hostIpv4Addr[2], pRequest->hostIpv4Addr[3]);
+
+ hddLog(VOS_TRACE_LEVEL_WARN, " Dest IP address: %d.%d.%d.%d",
+ pRequest->destIpv4Addr[0], pRequest->destIpv4Addr[1],
+ pRequest->destIpv4Addr[2], pRequest->destIpv4Addr[3]);
+
+ hddLog(VOS_TRACE_LEVEL_WARN, " Dest MAC address: %d:%d:%d:%d:%d:%d",
+ pRequest->destMacAddr[0], pRequest->destMacAddr[1],
+ pRequest->destMacAddr[2], pRequest->destMacAddr[3],
+ pRequest->destMacAddr[4], pRequest->destMacAddr[5]);
+ break;
+
+ }
+
+ /* Execute keep alive request. The reason that we can copy the request information
+ from the ioctl structure to the SME structure is that they are laid out
+ exactly the same. Otherwise, each piece of information would have to be
+ copied individually. */
+ memcpy(&keepaliveRequest, pRequest, wrqu->data.length);
+
+ hddLog(VOS_TRACE_LEVEL_ERROR, "set Keep: TP before SME %d\n", keepaliveRequest.timePeriod);
+
+ if (eHAL_STATUS_SUCCESS != sme_SetKeepAlive(WLAN_HDD_GET_HAL_CTX(pAdapter), &keepaliveRequest))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Keep Alive\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest)
+{
+ tSirRcvPktFilterCfgType packetFilterSetReq;
+ tSirRcvFltPktClearParam packetFilterClrReq;
+ int i=0;
+
+ if (pHddCtx->cfg_ini->disablePacketFilter)
+ {
+ hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Packet Filtering Disabled. Returning ",
+ __FUNCTION__ );
+ return 0;
+ }
+
+ /* Debug display of request components. */
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Packet Filter Request : FA %d params %d",
+ __FUNCTION__, pRequest->filterAction, pRequest->numParams);
+
+ switch (pRequest->filterAction)
+ {
+ case HDD_RCV_FILTER_SET:
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set Packet Filter Request for Id: %d",
+ __FUNCTION__, pRequest->filterId);
+
+ packetFilterSetReq.filterId = pRequest->filterId;
+ if ( pRequest->numParams >= HDD_MAX_CMP_PER_PACKET_FILTER)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Number of Params exceed Max limit %d\n",
+ __func__, pRequest->numParams);
+ return -EINVAL;
+ }
+ packetFilterSetReq.numFieldParams = pRequest->numParams;
+ packetFilterSetReq.coalesceTime = 0;
+ packetFilterSetReq.filterType = 1;
+ for (i=0; i < pRequest->numParams; i++)
+ {
+ packetFilterSetReq.paramsData[i].protocolLayer = pRequest->paramsData[i].protocolLayer;
+ packetFilterSetReq.paramsData[i].cmpFlag = pRequest->paramsData[i].cmpFlag;
+ packetFilterSetReq.paramsData[i].dataOffset = pRequest->paramsData[i].dataOffset;
+ packetFilterSetReq.paramsData[i].dataLength = pRequest->paramsData[i].dataLength;
+ packetFilterSetReq.paramsData[i].reserved = 0;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "Proto %d Comp Flag %d Filter Type\n",
+ pRequest->paramsData[i].protocolLayer, pRequest->paramsData[i].cmpFlag,
+ packetFilterSetReq.filterType);
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "Data Offset %d Data Len %d\n",
+ pRequest->paramsData[i].dataOffset, pRequest->paramsData[i].dataLength);
+
+ memcpy(&packetFilterSetReq.paramsData[i].compareData,
+ pRequest->paramsData[i].compareData, pRequest->paramsData[i].dataLength);
+ memcpy(&packetFilterSetReq.paramsData[i].dataMask,
+ pRequest->paramsData[i].dataMask, pRequest->paramsData[i].dataLength);
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "CData %d CData %d CData %d CData %d CData %d CData %d\n",
+ pRequest->paramsData[i].compareData[0], pRequest->paramsData[i].compareData[1],
+ pRequest->paramsData[i].compareData[2], pRequest->paramsData[i].compareData[3],
+ pRequest->paramsData[i].compareData[4], pRequest->paramsData[i].compareData[5]);
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "MData %d MData %d MData %d MData %d MData %d MData %d\n",
+ pRequest->paramsData[i].dataMask[0], pRequest->paramsData[i].dataMask[1],
+ pRequest->paramsData[i].dataMask[2], pRequest->paramsData[i].dataMask[3],
+ pRequest->paramsData[i].dataMask[4], pRequest->paramsData[i].dataMask[5]);
+ }
+
+ if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx, &packetFilterSetReq))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Set Filter\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ break;
+
+ case HDD_RCV_FILTER_CLEAR:
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Clear Packet Filter Request for Id: %d\n",
+ __FUNCTION__, pRequest->filterId);
+ packetFilterClrReq.filterId = pRequest->filterId;
+ if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx, &packetFilterClrReq))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Clear Filter\n",
+ __func__);
+ return -EINVAL;
+ }
+ break;
+
+ default :
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Packet Filter Request: Invalid %d\n",
+ __FUNCTION__, pRequest->filterAction);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void wlan_hdd_set_mc_addr_list(hdd_context_t *pHddCtx, v_U8_t set)
+{
+ v_U8_t filterAction = 0;
+ tPacketFilterCfg request = {0};
+ v_U8_t i = 0;
+
+ filterAction = set ? HDD_RCV_FILTER_SET : HDD_RCV_FILTER_CLEAR;
+
+ /*set mulitcast addr list*/
+ for (i = 0; i < pHddCtx->mc_addr_list.mc_cnt; i++)
+ {
+ memset(&request, 0, sizeof (tPacketFilterCfg));
+ request.filterAction = filterAction;
+ request.filterId = i;
+ if (set)
+ {
+ request.numParams = 1;
+ request.paramsData[0].protocolLayer = HDD_FILTER_PROTO_TYPE_MAC;
+ request.paramsData[0].cmpFlag = HDD_FILTER_CMP_TYPE_EQUAL;
+ request.paramsData[0].dataOffset = WLAN_HDD_80211_FRM_DA_OFFSET;
+ request.paramsData[0].dataLength = ETH_ALEN;
+ memcpy(&(request.paramsData[0].compareData[0]),
+ &(pHddCtx->mc_addr_list.addr[i][0]), ETH_ALEN);
+ /*set mulitcast filters*/
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s: %s multicast filter: addr ="
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ __func__, set ? "setting" : "clearing",
+ request.paramsData[0].compareData[0],
+ request.paramsData[0].compareData[1],
+ request.paramsData[0].compareData[2],
+ request.paramsData[0].compareData[3],
+ request.paramsData[0].compareData[4],
+ request.paramsData[0].compareData[5]);
+ }
+ wlan_hdd_set_filter(pHddCtx, &request);
+ }
+ pHddCtx->mc_addr_list.isFilterApplied = set ? TRUE : FALSE;
+}
+
+static int iw_set_packet_filter_params(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tpPacketFilterCfg pRequest = (tpPacketFilterCfg)wrqu->data.pointer;
+ return wlan_hdd_set_filter(WLAN_HDD_GET_CTX(pAdapter), pRequest);
+}
+#endif
+static int iw_get_statistics(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ hdd_wext_state_t *pWextState;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ char *p = extra;
+ int tlen = 0;
+ tCsrSummaryStatsInfo *pStats = &(pAdapter->hdd_stats.summary_stat);
+
+ tCsrGlobalClassAStatsInfo *aStats = &(pAdapter->hdd_stats.ClassA_stat);
+ tCsrGlobalClassDStatsInfo *dStats = &(pAdapter->hdd_stats.ClassD_stat);
+
+ ENTER();
+
+ if (pHddCtx->isLogpInProgress) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
+ return -EINVAL;
+ }
+
+ if (eConnectionState_Associated != (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) {
+
+ wrqu->txpower.value = 0;
+ }
+ else {
+ status = sme_GetStatistics( pHddCtx->hHal, eCSR_HDD,
+ SME_SUMMARY_STATS |
+ SME_GLOBAL_CLASSA_STATS |
+ SME_GLOBAL_CLASSB_STATS |
+ SME_GLOBAL_CLASSC_STATS |
+ SME_GLOBAL_CLASSD_STATS |
+ SME_PER_STA_STATS,
+ hdd_StatisticsCB, 0, FALSE,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], pAdapter );
+
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: Unable to retrieve SME statistics",
+ __FUNCTION__);
+ return -EINVAL;
+ }
+
+ pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ vos_status = vos_wait_single_event(&pWextState->vosevent, WLAN_WAIT_TIME_STATS);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: SME timeout while retrieving statistics",
+ __FUNCTION__);
+ /*Remove the SME statistics list by passing NULL in callback argument*/
+ status = sme_GetStatistics( pHddCtx->hHal, eCSR_HDD,
+ SME_SUMMARY_STATS |
+ SME_GLOBAL_CLASSA_STATS |
+ SME_GLOBAL_CLASSB_STATS |
+ SME_GLOBAL_CLASSC_STATS |
+ SME_GLOBAL_CLASSD_STATS |
+ SME_PER_STA_STATS,
+ NULL, 0, FALSE,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], pAdapter );
+
+ return -EINVAL;
+ }
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_RETRY_CNT,
+ (tANI_U8) sizeof (pStats->retry_cnt),
+ (char*) &(pStats->retry_cnt[0]),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_MUL_RETRY_CNT,
+ (tANI_U8) sizeof (pStats->multiple_retry_cnt),
+ (char*) &(pStats->multiple_retry_cnt[0]),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_FRM_CNT,
+ (tANI_U8) sizeof (pStats->tx_frm_cnt),
+ (char*) &(pStats->tx_frm_cnt[0]),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_FRM_CNT,
+ (tANI_U8) sizeof (pStats->rx_frm_cnt),
+ (char*) &(pStats->rx_frm_cnt),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_FRM_DUP_CNT,
+ (tANI_U8) sizeof (pStats->frm_dup_cnt),
+ (char*) &(pStats->frm_dup_cnt),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_FAIL_CNT,
+ (tANI_U8) sizeof (pStats->fail_cnt),
+ (char*) &(pStats->fail_cnt[0]),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_RTS_FAIL_CNT,
+ (tANI_U8) sizeof (pStats->rts_fail_cnt),
+ (char*) &(pStats->rts_fail_cnt),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_ACK_FAIL_CNT,
+ (tANI_U8) sizeof (pStats->ack_fail_cnt),
+ (char*) &(pStats->ack_fail_cnt),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_RTS_SUC_CNT,
+ (tANI_U8) sizeof (pStats->rts_succ_cnt),
+ (char*) &(pStats->rts_succ_cnt),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_DISCARD_CNT,
+ (tANI_U8) sizeof (pStats->rx_discard_cnt),
+ (char*) &(pStats->rx_discard_cnt),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_ERROR_CNT,
+ (tANI_U8) sizeof (pStats->rx_error_cnt),
+ (char*) &(pStats->rx_error_cnt),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_BYTE_CNT,
+ (tANI_U8) sizeof (pStats->tx_byte_cnt),
+ (char*) &(pStats->tx_byte_cnt),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_BYTE_CNT,
+ (tANI_U8) sizeof (dStats->rx_byte_cnt),
+ (char*) &(dStats->rx_byte_cnt),
+ tlen);
+
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_RATE,
+ (tANI_U8) sizeof (dStats->rx_rate),
+ (char*) &(dStats->rx_rate),
+ tlen);
+
+ /* Transmit rate, in units of 500 kbit/sec */
+ FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_RATE,
+ (tANI_U8) sizeof (aStats->tx_rate),
+ (char*) &(aStats->tx_rate),
+ tlen);
+
+ wrqu->data.length = tlen;
+
+ }
+
+ EXIT();
+
+ return 0;
+}
+
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+
+/*Max Len for PNO notification*/
+#define MAX_PNO_NOTIFY_LEN 100
+void found_pref_network_cb (void *callbackContext,
+ tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
+{
+ hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
+ union iwreq_data wrqu;
+ char buf[MAX_PNO_NOTIFY_LEN+1];
+
+ hddLog(VOS_TRACE_LEVEL_WARN, "A preferred network was found: %s with rssi: -%d",
+ pPrefNetworkFoundInd->ssId.ssId, pPrefNetworkFoundInd->rssi);
+
+ // create the event
+ memset(&wrqu, 0, sizeof(wrqu));
+ memset(buf, 0, sizeof(buf));
+
+ snprintf(buf, MAX_PNO_NOTIFY_LEN, "QCOM: Found preferred network: %s with RSSI of -%u",
+ pPrefNetworkFoundInd->ssId.ssId,
+ (unsigned int)pPrefNetworkFoundInd->rssi);
+
+ wrqu.data.pointer = buf;
+ wrqu.data.length = strlen(buf);
+
+ // send the event
+
+ wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf);
+
+}
+
+
+/*string based input*/
+VOS_STATUS iw_set_pno(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra, int nOffset)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tSirPNOScanReq pnoRequest;
+ char *ptr;
+ v_U8_t i,j, ucParams, ucMode;
+ /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "PNO data len %d data %s",
+ wrqu->data.length,
+ wrqu->data.pointer);
+
+ if (wrqu->data.length <= nOffset )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "PNO input is not correct");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ pnoRequest.enable = 0;
+ pnoRequest.ucNetworksCount = 0;
+ /*-----------------------------------------------------------------------
+ Input is string based and expected to be like this:
+
+ <enabled> <netw_count>
+ for each network:
+ <ssid_len> <ssid> <authentication> <encryption>
+ <ch_num> <channel_list optional> <bcast_type> <rssi_threshold>
+ <scan_timers> <scan_time> <scan_repeat> <scan_time> <scan_repeat>
+
+ e.g:
+ 1 2 4 test 0 0 3 1 6 11 2 40 5 test2 4 4 6 1 2 3 4 5 6 1 0 2 5 2 300 0
+
+ this translates into:
+ -----------------------------
+ enable PNO
+ look for 2 networks:
+ test - with authentication type 0 and encryption type 0,
+ that can be found on 3 channels: 1 6 and 11 ,
+ SSID bcast type is unknown (directed probe will be sent if AP not found)
+ and must meet -40dBm RSSI
+
+ test2 - with auth and enrytption type 4/4
+ that can be found on 6 channels 1, 2, 3, 4, 5 and 6
+ bcast type is non-bcast (directed probe will be sent)
+ and must not meet any RSSI threshold
+
+ scan every 5 seconds 2 times, scan every 300 seconds until stopped
+ -----------------------------------------------------------------------*/
+ ptr = (char*)(wrqu->data.pointer + nOffset);
+
+ sscanf(ptr,"%hhu%n", &(pnoRequest.enable), &nOffset);
+
+ if ( 0 == pnoRequest.enable )
+ {
+ /*Disable PNO*/
+ memset(&pnoRequest, 0, sizeof(pnoRequest));
+ sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), &pnoRequest,
+ pAdapter->sessionId,
+ found_pref_network_cb, pAdapter);
+ return VOS_STATUS_SUCCESS;
+ }
+
+ ptr += nOffset;
+ sscanf(ptr,"%hhu %n", &(pnoRequest.ucNetworksCount), &nOffset);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "PNO enable %d networks count %d offset %d",
+ pnoRequest.enable,
+ pnoRequest.ucNetworksCount,
+ nOffset);
+
+ /* Parameters checking:
+ ucNetworksCount has to be larger than 0*/
+ if (( 0 == pnoRequest.ucNetworksCount ) ||
+ ( pnoRequest.ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Network input is not correct");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ptr += nOffset;
+
+ for ( i = 0; i < pnoRequest.ucNetworksCount; i++ )
+ {
+
+ pnoRequest.aNetworks[i].ssId.length = 0;
+
+ sscanf(ptr,"%hhu %n",
+ &(pnoRequest.aNetworks[i].ssId.length), &nOffset);
+
+ if (( 0 == pnoRequest.aNetworks[i].ssId.length ) ||
+ ( pnoRequest.aNetworks[i].ssId.length > 32 ) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "SSID Len %d is not correct for network %d",
+ pnoRequest.aNetworks[i].ssId.length, i);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /*Advance to SSID*/
+ ptr += nOffset;
+
+ ucParams = sscanf(ptr,"%32s %lu %lu %hhu %n",
+ pnoRequest.aNetworks[i].ssId.ssId,
+ &(pnoRequest.aNetworks[i].authentication),
+ &(pnoRequest.aNetworks[i].encryption),
+ &(pnoRequest.aNetworks[i].ucChannelCount),
+ &nOffset);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "PNO len %d ssid %s auth %d encry %d channel count %d offset %d",
+ pnoRequest.aNetworks[i].ssId.length,
+ pnoRequest.aNetworks[i].ssId.ssId,
+ pnoRequest.aNetworks[i].authentication,
+ pnoRequest.aNetworks[i].encryption,
+ pnoRequest.aNetworks[i].ucChannelCount,
+ nOffset );
+
+ if ( 4 != ucParams )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "Incorrect cmd");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /*Advance to channel list*/
+ ptr += nOffset;
+
+ if ( SIR_PNO_MAX_NETW_CHANNELS < pnoRequest.aNetworks[i].ucChannelCount )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "Incorrect number of channels");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if ( 0 != pnoRequest.aNetworks[i].ucChannelCount)
+ {
+ for ( j = 0; j < pnoRequest.aNetworks[i].ucChannelCount; j++)
+ {
+ sscanf(ptr,"%hhu %n",
+ &(pnoRequest.aNetworks[i].aChannels[j]), &nOffset);
+ /*Advance to next channel number*/
+ ptr += nOffset;
+ }
+ }
+
+ sscanf(ptr,"%lu %n",
+ &(pnoRequest.aNetworks[i].bcastNetwType), &nOffset);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "PNO bcastNetwType %d offset %d",
+ pnoRequest.aNetworks[i].bcastNetwType,
+ nOffset );
+
+ /*Advance to rssi Threshold*/
+ ptr += nOffset;
+
+ sscanf(ptr,"%hhu %n",
+ &(pnoRequest.aNetworks[i].rssiThreshold), &nOffset);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "PNO rssi %d offset %d",
+ pnoRequest.aNetworks[i].rssiThreshold,
+ nOffset );
+ /*Advance to next network*/
+ ptr += nOffset;
+ }/*For ucNetworkCount*/
+
+ ucParams = sscanf(ptr,"%hhu %n",
+ &(pnoRequest.scanTimers.ucScanTimersCount), &nOffset);
+
+ /*Read the scan timers*/
+ if (( 1 == ucParams )&&( pnoRequest.scanTimers.ucScanTimersCount >= 0 ))
+ {
+ ptr += nOffset;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Scan timer count %d offset %d",
+ pnoRequest.scanTimers.ucScanTimersCount,
+ nOffset );
+
+ if ( SIR_PNO_MAX_SCAN_TIMERS < pnoRequest.scanTimers.ucScanTimersCount )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Incorrect cmd - too many scan timers");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ for ( i = 0; i < pnoRequest.scanTimers.ucScanTimersCount; i++ )
+ {
+ ucParams = sscanf(ptr,"%lu %lu %n",
+ &(pnoRequest.scanTimers.aTimerValues[i].uTimerValue),
+ &( pnoRequest.scanTimers.aTimerValues[i].uTimerRepeat),
+ &nOffset);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "PNO Timer value %d Timer repeat %d offset %d",
+ pnoRequest.scanTimers.aTimerValues[i].uTimerValue,
+ pnoRequest.scanTimers.aTimerValues[i].uTimerRepeat,
+ nOffset );
+
+ if ( 2 != ucParams )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Incorrect cmd - diff params then expected %d", ucParams);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ptr += nOffset;
+ }
+
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "No scan timers provided param count %d scan timers %d",
+ ucParams, pnoRequest.scanTimers.ucScanTimersCount );
+
+ /*Scan timers defaults to 5 minutes*/
+ pnoRequest.scanTimers.ucScanTimersCount = 1;
+ pnoRequest.scanTimers.aTimerValues[0].uTimerValue = 60;
+ pnoRequest.scanTimers.aTimerValues[0].uTimerRepeat = 0;
+ }
+
+ ucParams = sscanf(ptr,"%hhu %n",
+ &(ucMode), &nOffset);
+
+ pnoRequest.modePNO = ucMode;
+ /*for LA we just expose suspend option*/
+ if (( 1 != ucParams )||( ucMode >= SIR_PNO_MODE_MAX ))
+ {
+ pnoRequest.modePNO = SIR_PNO_MODE_ON_SUSPEND;
+ }
+
+ sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), &pnoRequest,
+ pAdapter->sessionId,
+ found_pref_network_cb, pAdapter);
+
+ return VOS_STATUS_SUCCESS;
+}/*iw_set_pno*/
+
+VOS_STATUS iw_set_rssi_filter(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra, int nOffset)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ v_U8_t rssiThreshold = 0;
+ v_U8_t nRead;
+
+ nRead = sscanf(wrqu->data.pointer + nOffset,"%hhu",
+ &rssiThreshold);
+
+ if ( 1 != nRead )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ "Incorrect format");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ sme_SetRSSIFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), rssiThreshold);
+ return VOS_STATUS_SUCCESS;
+}
+
+
+static int iw_set_pno_priv(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Set PNO Private");
+ return iw_set_pno(dev,info,wrqu,extra,0);
+}
+#endif /*FEATURE_WLAN_SCAN_PNO*/
+
+//Common function to SetBand
+int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ tANI_U8 band = 0;
+ eCsrBand currBand = eCSR_BAND_MAX;
+
+ band = ptr[WLAN_HDD_UI_SET_BAND_VALUE_OFFSET] - '0'; /*convert the band value from ascii to integer*/
+
+ switch(band)
+ {
+ case WLAN_HDD_UI_BAND_AUTO:
+ band = eCSR_BAND_ALL;
+ break;
+ case WLAN_HDD_UI_BAND_5_GHZ:
+ band = eCSR_BAND_5G;
+ break;
+ case WLAN_HDD_UI_BAND_2_4_GHZ:
+ band = eCSR_BAND_24;
+ break;
+ default:
+ band = eCSR_BAND_MAX;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change band to %u",
+ __FUNCTION__, band);
+
+ if (band == eCSR_BAND_MAX)
+ {
+ /* Received change band request with invalid band value */
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid band value %u", __FUNCTION__, band);
+ return -EIO;
+ }
+
+ if (eHAL_STATUS_SUCCESS != sme_GetFreqBand(hHal, &currBand))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Failed to get current band config",
+ __FUNCTION__);
+ return -EIO;
+ }
+
+ if (currBand != band)
+ {
+ /* Change band request received.
+ * Abort pending scan requests, flush the existing scan results,
+ * and change the band capability
+ */
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Current band value = %u, new setting %u ",
+ __FUNCTION__, currBand, band);
+
+ if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
+ {
+ hdd_station_ctx_t *pHddStaCtx = &(pAdapter)->sessionCtx.station;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ long lrc;
+
+ /* STA already connected on current band, So issue disconnect first,
+ * then change the band*/
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "%s STA connected in band %u, Changing band to %u, Issuing Disconnect",
+ __func__, csrGetCurrentBand(hHal), band);
+
+ pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
+ INIT_COMPLETION(pAdapter->disconnect_comp_var);
+
+ status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
+
+ if ( VOS_STATUS_SUCCESS != status)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s csrRoamDisconnect failure, returned %d \n",
+ __func__, (int)status );
+ return -EINVAL;
+ }
+
+ lrc = wait_for_completion_interruptible_timeout(
+ &pAdapter->disconnect_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+
+ if(lrc <= 0) {
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,"%s: %s while while waiting for csrRoamDisconnect ",
+ __FUNCTION__, (0 == lrc) ? "Timeout" : "Interrupt");
+
+ return (0 == lrc) ? -ETIMEDOUT : -EINTR;
+ }
+ }
+
+ hdd_abort_mac_scan(pHddCtx);
+ sme_ScanFlushResult(hHal, pAdapter->sessionId);
+ if(eHAL_STATUS_SUCCESS != sme_SetFreqBand(hHal, (eCsrBand)band))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+ "%s: failed to set the band value to %u ",
+ __FUNCTION__, band);
+ return -EINVAL;
+ }
+#ifdef CONFIG_CFG80211
+ wlan_hdd_cfg80211_update_band(pHddCtx->wiphy, (eCsrBand)band);
+#endif
+ }
+ return 0;
+}
+
+static int iw_set_band_config(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ tANI_U8 *ptr = (tANI_U8*)wrqu->data.pointer;
+ int ret = 0;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: ", __FUNCTION__);
+
+ if (memcmp(ptr, "SETBAND ", 8) == 0)
+ {
+ /* Change band request received */
+ ret = hdd_setBand_helper(dev, ptr);
+ return ret;
+
+ }
+ return 0;
+}
+
+static int iw_set_power_params_priv(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Set power params Private");
+ return iw_set_power_params(dev,info,wrqu,extra,0);
+}
+
+
+
+/*string based input*/
+VOS_STATUS iw_set_power_params(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra, int nOffset)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tSirSetPowerParamsReq powerRequest;
+ char *ptr;
+ v_U8_t ucType;
+ v_U32_t uTotalSize, uValue;
+ /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Power Params data len %d data %s",
+ wrqu->data.length,
+ wrqu->data.pointer);
+
+ if (wrqu->data.length <= nOffset )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "set power param input is not correct");
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ uTotalSize = wrqu->data.length - nOffset;
+
+ /*-----------------------------------------------------------------------
+ Input is string based and expected to be like this:
+
+ <param_type> <param_value> <param_type> <param_value> ...
+
+ e.g:
+ 1 2 2 3 3 0 4 1 5 1
+
+ e.g. setting just a few:
+ 1 2 4 1
+
+ parameter types:
+ -----------------------------
+ 1 - Ignore DTIM
+ 2 - Listen Interval
+ 3 - Broadcast Multicas Filter
+ 4 - Beacon Early Termination
+ 5 - Beacon Early Termination Interval
+ -----------------------------------------------------------------------*/
+ powerRequest.uIgnoreDTIM = SIR_NOCHANGE_POWER_VALUE;
+ powerRequest.uListenInterval = SIR_NOCHANGE_POWER_VALUE;
+ powerRequest.uBcastMcastFilter = SIR_NOCHANGE_POWER_VALUE;
+ powerRequest.uEnableBET = SIR_NOCHANGE_POWER_VALUE;
+ powerRequest.uBETInterval = SIR_NOCHANGE_POWER_VALUE;
+
+ ptr = (char*)(wrqu->data.pointer + nOffset);
+
+ while ( uTotalSize )
+ {
+ sscanf(ptr,"%hhu %n", &(ucType), &nOffset);
+
+ uTotalSize -= nOffset;
+
+ if (!uTotalSize)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Invalid input parametery type : %d with no value at offset %d",
+ ucType, nOffset);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ ptr += nOffset;
+ sscanf(ptr,"%lu %n", &(uValue), &nOffset);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Power request parameter %d value %d offset %d",
+ ucType, uValue, nOffset);
+
+ switch (ucType)
+ {
+ case eSIR_IGNORE_DTIM:
+ powerRequest.uIgnoreDTIM = uValue;
+ break;
+ case eSIR_LISTEN_INTERVAL:
+ powerRequest.uListenInterval = uValue;
+ break;
+ case eSIR_MCAST_BCAST_FILTER:
+ powerRequest.uBcastMcastFilter = uValue;
+ break;
+ case eSIR_ENABLE_BET:
+ powerRequest.uEnableBET = uValue;
+ break;
+ case eSIR_BET_INTERVAL:
+ powerRequest.uBETInterval = uValue;
+ break;
+ default:
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Invalid input parametery type : %d with value: %d at offset %d",
+ ucType, uValue, nOffset);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ uTotalSize -= nOffset;
+ ptr += nOffset;
+
+ }/*Go for as long as we have a valid string*/
+
+ /* put the device into full power*/
+ wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
+
+ /* Apply the power save params*/
+ sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
+
+ /* put the device back to power save*/
+ wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
+
+ return VOS_STATUS_SUCCESS;
+}/*iw_set_power_params*/
+
+
+// Define the Wireless Extensions to the Linux Network Device structure
+// A number of these routines are NULL (meaning they are not implemented.)
+
+static const iw_handler we_handler[] =
+{
+ (iw_handler) iw_set_commit, /* SIOCSIWCOMMIT */
+ (iw_handler) iw_get_name, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) iw_set_freq, /* SIOCSIWFREQ */
+ (iw_handler) iw_get_freq, /* SIOCGIWFREQ */
+ (iw_handler) iw_set_mode, /* SIOCSIWMODE */
+ (iw_handler) iw_get_mode, /* SIOCGIWMODE */
+ (iw_handler) NULL, /* SIOCSIWSENS */
+ (iw_handler) NULL, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* SIOCSIWRANGE */
+ (iw_handler) iw_get_range, /* SIOCGIWRANGE */
+ (iw_handler) iw_set_priv, /* SIOCSIWPRIV */
+ (iw_handler) NULL, /* SIOCGIWPRIV */
+ (iw_handler) NULL, /* SIOCSIWSTATS */
+ (iw_handler) NULL, /* SIOCGIWSTATS */
+ iw_handler_set_spy, /* SIOCSIWSPY */
+ iw_handler_get_spy, /* SIOCGIWSPY */
+ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
+ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
+ (iw_handler) iw_set_ap_address, /* SIOCSIWAP */
+ (iw_handler) iw_get_ap_address, /* SIOCGIWAP */
+ (iw_handler) iw_set_mlme, /* SIOCSIWMLME */
+ (iw_handler) NULL, /* SIOCGIWAPLIST */
+ (iw_handler) iw_set_scan, /* SIOCSIWSCAN */
+ (iw_handler) iw_get_scan, /* SIOCGIWSCAN */
+ (iw_handler) iw_set_essid, /* SIOCSIWESSID */
+ (iw_handler) iw_get_essid, /* SIOCGIWESSID */
+ (iw_handler) iw_set_nick, /* SIOCSIWNICKN */
+ (iw_handler) iw_get_nick, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) iw_set_bitrate, /* SIOCSIWRATE */
+ (iw_handler) iw_get_bitrate, /* SIOCGIWRATE */
+ (iw_handler) iw_set_rts_threshold,/* SIOCSIWRTS */
+ (iw_handler) iw_get_rts_threshold,/* SIOCGIWRTS */
+ (iw_handler) iw_set_frag_threshold, /* SIOCSIWFRAG */
+ (iw_handler) iw_get_frag_threshold, /* SIOCGIWFRAG */
+ (iw_handler) iw_set_tx_power, /* SIOCSIWTXPOW */
+ (iw_handler) iw_get_tx_power, /* SIOCGIWTXPOW */
+ (iw_handler) iw_set_retry, /* SIOCSIWRETRY */
+ (iw_handler) iw_get_retry, /* SIOCGIWRETRY */
+ (iw_handler) iw_set_encode, /* SIOCSIWENCODE */
+ (iw_handler) iw_get_encode, /* SIOCGIWENCODE */
+ (iw_handler) iw_set_power_mode, /* SIOCSIWPOWER */
+ (iw_handler) iw_get_power_mode, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) iw_set_genie, /* SIOCSIWGENIE */
+ (iw_handler) iw_get_genie, /* SIOCGIWGENIE */
+ (iw_handler) iw_set_auth, /* SIOCSIWAUTH */
+ (iw_handler) iw_get_auth, /* SIOCGIWAUTH */
+ (iw_handler) iw_set_encodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) iw_get_encodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCSIWPMKSA */
+};
+
+static const iw_handler we_private[] = {
+
+ [WLAN_PRIV_SET_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_setint_getnone, //set priv ioctl
+ [WLAN_PRIV_SET_NONE_GET_INT - SIOCIWFIRSTPRIV] = iw_setnone_getint, //get priv ioctl
+ [WLAN_PRIV_SET_CHAR_GET_NONE - SIOCIWFIRSTPRIV] = iw_setchar_getnone, //get priv ioctl
+ [WLAN_PRIV_SET_THREE_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_three_ints_getnone,
+ [WLAN_PRIV_GET_CHAR_SET_NONE - SIOCIWFIRSTPRIV] = iw_get_char_setnone,
+ [WLAN_PRIV_SET_NONE_GET_NONE - SIOCIWFIRSTPRIV] = iw_setnone_getnone, //action priv ioctl
+ [WLAN_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_var_ints_getnone,
+ [WLAN_PRIV_ADD_TSPEC - SIOCIWFIRSTPRIV] = iw_add_tspec,
+ [WLAN_PRIV_DEL_TSPEC - SIOCIWFIRSTPRIV] = iw_del_tspec,
+ [WLAN_PRIV_GET_TSPEC - SIOCIWFIRSTPRIV] = iw_get_tspec,
+
+#ifdef FEATURE_WLAN_WAPI
+ [WLAN_PRIV_SET_WAPI_MODE - SIOCIWFIRSTPRIV] = iw_qcom_set_wapi_mode,
+ [WLAN_PRIV_GET_WAPI_MODE - SIOCIWFIRSTPRIV] = iw_qcom_get_wapi_mode,
+ [WLAN_PRIV_SET_WAPI_ASSOC_INFO - SIOCIWFIRSTPRIV] = iw_qcom_set_wapi_assoc_info,
+ [WLAN_PRIV_SET_WAPI_KEY - SIOCIWFIRSTPRIV] = iw_qcom_set_wapi_key,
+ [WLAN_PRIV_SET_WAPI_BKID - SIOCIWFIRSTPRIV] = iw_qcom_set_wapi_bkid,
+ [WLAN_PRIV_GET_WAPI_BKID - SIOCIWFIRSTPRIV] = iw_qcom_get_wapi_bkid,
+#endif /* FEATURE_WLAN_WAPI */
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ [WLAN_PRIV_SET_FTIES - SIOCIWFIRSTPRIV] = iw_set_fties,
+#endif
+ [WLAN_PRIV_SET_HOST_OFFLOAD - SIOCIWFIRSTPRIV] = iw_set_host_offload,
+ [WLAN_GET_WLAN_STATISTICS - SIOCIWFIRSTPRIV] = iw_get_statistics,
+ [WLAN_SET_KEEPALIVE_PARAMS - SIOCIWFIRSTPRIV] = iw_set_keepalive_params
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ ,
+ [WLAN_SET_PACKET_FILTER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_packet_filter_params
+#endif
+#ifdef FEATURE_WLAN_SCAN_PNO
+ ,
+ [WLAN_SET_PNO - SIOCIWFIRSTPRIV] = iw_set_pno_priv
+#endif
+ ,
+ [WLAN_SET_BAND_CONFIG - SIOCIWFIRSTPRIV] = iw_set_band_config,
+ [WLAN_PRIV_SET_MCBC_FILTER - SIOCIWFIRSTPRIV] = iw_set_dynamic_mcbc_filter,
+ [WLAN_PRIV_CLEAR_MCBC_FILTER - SIOCIWFIRSTPRIV] = iw_clear_dynamic_mcbc_filter,
+ [WLAN_SET_POWER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_power_params_priv,
+ [WLAN_GET_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_linkspeed
+};
+
+/*Maximum command length can be only 15 */
+static const struct iw_priv_args we_private_args[] = {
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_SET_INT_GET_NONE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "" },
+
+ /* handlers for sub-ioctl */
+ { WE_SET_11D_STATE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set11Dstate" },
+
+ { WE_WOWL,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "wowl" },
+
+ { WE_SET_POWER,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "setPower" },
+
+ { WE_SET_MAX_ASSOC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "setMaxAssoc" },
+
+ { WE_SET_SAP_AUTO_CHANNEL_SELECTION,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "setAutoChannel" },
+
+ { WE_SET_DATA_INACTIVITY_TO,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "inactivityTO" },
+
+ { WE_SET_MAX_TX_POWER,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "setMaxTxPower" },
+ /* set Higher DTIM Transition (DTIM1 to DTIM3)
+ * 1 = enable and 0 = disable */
+ {
+ WE_SET_HIGHER_DTIM_TRANSITION,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "setHDtimTransn" },
+
+ { WE_SET_TM_LEVEL,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "setTmLevel" },
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_SET_NONE_GET_INT,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "" },
+
+ /* handlers for sub-ioctl */
+ { WE_GET_11D_STATE,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get11Dstate" },
+
+ { WE_IBSS_STATUS,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "getAdhocStatus" },
+
+ { WE_PMC_STATE,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "pmcState" },
+
+ { WE_GET_WLAN_DBG,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "getwlandbg" },
+
+ { WE_MODULE_DOWN_IND,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "moduleDownInd" },
+
+ { WE_GET_MAX_ASSOC,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "getMaxAssoc" },
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ { WE_GET_WDI_DBG,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "getwdidbg" },
+#endif // FEATURE_WLAN_INTEGRATED_SOC
+
+ { WE_GET_SAP_AUTO_CHANNEL_SELECTION,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "getAutoChannel" },
+
+ { WE_GET_CONCURRENCY_MODE,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "getconcurrency" },
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_SET_CHAR_GET_NONE,
+ IW_PRIV_TYPE_CHAR| 512,
+ 0,
+ "" },
+
+ /* handlers for sub-ioctl */
+ { WE_WOWL_ADD_PTRN,
+ IW_PRIV_TYPE_CHAR| 512,
+ 0,
+ "wowlAddPtrn" },
+
+ { WE_WOWL_DEL_PTRN,
+ IW_PRIV_TYPE_CHAR| 512,
+ 0,
+ "wowlDelPtrn" },
+
+#if defined WLAN_FEATURE_VOWIFI
+ /* handlers for sub-ioctl */
+ { WE_NEIGHBOR_REPORT_REQUEST,
+ IW_PRIV_TYPE_CHAR | 512,
+ 0,
+ "neighbor" },
+#endif
+ { WE_SET_AP_WPS_IE,
+ IW_PRIV_TYPE_CHAR| 512,
+ 0,
+ "set_ap_wps_ie" },
+
+ { WE_SET_CONFIG,
+ IW_PRIV_TYPE_CHAR| 512,
+ 0,
+ "setConfig" },
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_SET_THREE_INT_GET_NONE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ 0,
+ "" },
+
+ /* handlers for sub-ioctl */
+ { WE_SET_WLAN_DBG,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ 0,
+ "setwlandbg" },
+
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+ { WE_SET_WDI_DBG,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ 0,
+ "setwdidbg" },
+#endif // FEATURE_WLAN_INTEGRATED_SOC
+
+ { WE_SET_SAP_CHANNELS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ 0,
+ "setsapchannels" },
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_GET_CHAR_SET_NONE,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ "" },
+
+ /* handlers for sub-ioctl */
+ { WE_WLAN_VERSION,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ "version" },
+ { WE_GET_STATS,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ "getStats" },
+ { WE_GET_CFG,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ "getConfig" },
+ { WE_GET_WMM_STATUS,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ "getWmmStatus" },
+ {
+ WE_GET_CHANNEL_LIST,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ "getChannelList" },
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_SET_NONE_GET_NONE,
+ 0,
+ 0,
+ "" },
+
+ /* handlers for sub-ioctl */
+ { WE_CLEAR_STATS,
+ 0,
+ 0,
+ "clearStats" },
+ { WE_INIT_AP,
+ 0,
+ 0,
+ "initAP" },
+ { WE_STOP_AP,
+ 0,
+ 0,
+ "exitAP" },
+ { WE_ENABLE_AMP,
+ 0,
+ 0,
+ "enableAMP" },
+ { WE_DISABLE_AMP,
+ 0,
+ 0,
+ "disableAMP" },
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_SET_VAR_INT_GET_NONE,
+ IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
+ 0,
+ "" },
+
+ /* handlers for sub-ioctl */
+ { WE_LOG_DUMP_CMD,
+ IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
+ 0,
+ "dump" },
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_ADD_TSPEC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | HDD_WLAN_WMM_PARAM_COUNT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "addTspec" },
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_DEL_TSPEC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "delTspec" },
+
+ /* handlers for main ioctl */
+ { WLAN_PRIV_GET_TSPEC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "getTspec" },
+
+
+#ifdef FEATURE_WLAN_WAPI
+ /* handlers for main ioctl SET_WAPI_MODE */
+ { WLAN_PRIV_SET_WAPI_MODE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "SET_WAPI_MODE" },
+
+ /* handlers for main ioctl GET_WAPI_MODE */
+ { WLAN_PRIV_GET_WAPI_MODE,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "GET_WAPI_MODE" },
+
+ /* handlers for main ioctl SET_ASSOC_INFO */
+ { WLAN_PRIV_SET_WAPI_ASSOC_INFO,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 400,
+ 0,
+ "SET_WAPI_ASSOC" },
+
+ /* handlers for main ioctl SET_WAPI_KEY */
+ { WLAN_PRIV_SET_WAPI_KEY,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 71,
+ 0,
+ "SET_WAPI_KEY" },
+
+ /* handlers for main ioctl SET_WAPI_BKID */
+ { WLAN_PRIV_SET_WAPI_BKID,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 24,
+ 0,
+ "SET_WAPI_BKID" },
+
+ /* handlers for main ioctl GET_WAPI_BKID */
+ { WLAN_PRIV_GET_WAPI_BKID,
+ 0,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 24,
+ "GET_WAPI_BKID" },
+#endif /* FEATURE_WLAN_WAPI */
+
+ /* handlers for main ioctl - host offload */
+ {
+ WLAN_PRIV_SET_HOST_OFFLOAD,
+ IW_PRIV_TYPE_BYTE | sizeof(tHostOffloadRequest),
+ 0,
+ "setHostOffload" },
+
+ {
+ WLAN_GET_WLAN_STATISTICS,
+ 0,
+ IW_PRIV_TYPE_BYTE | WE_MAX_STR_LEN,
+ "getWlanStats" },
+
+ {
+ WLAN_SET_KEEPALIVE_PARAMS,
+ IW_PRIV_TYPE_BYTE | sizeof(tKeepAliveRequest),
+ 0,
+ "setKeepAlive" },
+#ifdef WLAN_FEATURE_PACKET_FILTERING
+ {
+ WLAN_SET_PACKET_FILTER_PARAMS,
+ IW_PRIV_TYPE_BYTE | sizeof(tPacketFilterCfg),
+ 0,
+ "setPktFilter" },
+#endif
+#ifdef FEATURE_WLAN_SCAN_PNO
+ {
+ WLAN_SET_PNO,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ 0,
+ "setpno" },
+#endif
+ {
+ WLAN_SET_BAND_CONFIG,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ 0,
+ "SETBAND" },
+ /* handlers for dynamic MC BC ioctl */
+ {
+ WLAN_PRIV_SET_MCBC_FILTER,
+ IW_PRIV_TYPE_BYTE | sizeof(tMcBcFilterCfg),
+ 0,
+ "setMCBCFilter" },
+ {
+ WLAN_PRIV_CLEAR_MCBC_FILTER,
+ 0,
+ 0,
+ "clearMCBCFilter" },
+ {
+ WLAN_SET_POWER_PARAMS,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ 0,
+ "setpowerparams" },
+ {
+ WLAN_GET_LINK_SPEED,
+ IW_PRIV_TYPE_CHAR | 18,
+ IW_PRIV_TYPE_CHAR | 3, "getLinkSpeed" },
+};
+
+
+
+const struct iw_handler_def we_handler_def = {
+ .num_standard = sizeof(we_handler) / sizeof(we_handler[0]),
+ .num_private = sizeof(we_private) / sizeof(we_private[0]),
+ .num_private_args = sizeof(we_private_args) / sizeof(we_private_args[0]),
+
+ .standard = (iw_handler *)we_handler,
+ .private = (iw_handler *)we_private,
+ .private_args = we_private_args,
+ .get_wireless_stats = get_wireless_stats,
+};
+
+int hdd_set_wext(hdd_adapter_t *pAdapter)
+{
+ hdd_wext_state_t *pwextBuf;
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+
+ // Now configure the roaming profile links. To SSID and bssid.
+ pwextBuf->roamProfile.SSIDs.numOfSSIDs = 0;
+ pwextBuf->roamProfile.SSIDs.SSIDList = &pHddStaCtx->conn_info.SSID;
+
+ pwextBuf->roamProfile.BSSIDs.numOfBSSIDs = 0;
+ pwextBuf->roamProfile.BSSIDs.bssid = &pHddStaCtx->conn_info.bssId;
+
+ /*Set the numOfChannels to zero to scan all the channels*/
+ pwextBuf->roamProfile.ChannelInfo.numOfChannels = 0;
+ pwextBuf->roamProfile.ChannelInfo.ChannelList = NULL;
+
+ /* Default is no encryption */
+ pwextBuf->roamProfile.EncryptionType.numEntries = 1;
+ pwextBuf->roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+
+ pwextBuf->roamProfile.mcEncryptionType.numEntries = 1;
+ pwextBuf->roamProfile.mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
+
+ pwextBuf->roamProfile.BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
+
+ /* Default is no authentication */
+ pwextBuf->roamProfile.AuthType.numEntries = 1;
+ pwextBuf->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+
+ pwextBuf->roamProfile.phyMode = eCSR_DOT11_MODE_TAURUS;
+ pwextBuf->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
+
+ /*Set the default scan mode*/
+ pAdapter->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
+
+ hdd_clearRoamProfileIe(pAdapter);
+
+ return VOS_STATUS_SUCCESS;
+
+ }
+
+int hdd_register_wext(struct net_device *dev)
+ {
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+ VOS_STATUS status;
+
+ ENTER();
+
+ // Zero the memory. This zeros the profile structure.
+ memset(pwextBuf, 0,sizeof(hdd_wext_state_t));
+
+ init_completion(&(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->completion_var);
+
+
+ status = hdd_set_wext(pAdapter);
+
+ if(!VOS_IS_STATUS_SUCCESS(status)) {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: hdd_set_wext failed!!\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_event_init(&pwextBuf->vosevent)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos event init failed!!\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_event_init(&pwextBuf->scanevent)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD scan event init failed!!\n"));
+ return eHAL_STATUS_FAILURE;
+ }
+
+ // Register as a wireless device
+ dev->wireless_handlers = (struct iw_handler_def *)&we_handler_def;
+
+ EXIT();
+ return 0;
+}
+
+int hdd_UnregisterWext(struct net_device *dev)
+{
+#if 0
+ hdd_wext_state_t *wextBuf;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ ENTER();
+ // Set up the pointer to the Wireless Extensions state structure
+ wextBuf = pAdapter->pWextState;
+
+ // De-allocate the Wireless Extensions state structure
+ kfree(wextBuf);
+
+ // Clear out the pointer to the Wireless Extensions state structure
+ pAdapter->pWextState = NULL;
+
+ EXIT();
+#endif
+ dev->wireless_handlers = NULL;
+ return 0;
+}
+
+
diff --git a/CORE/HDD/src/wlan_hdd_wmm.c b/CORE/HDD/src/wlan_hdd_wmm.c
new file mode 100644
index 0000000..c8da218
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_wmm.c
@@ -0,0 +1,2501 @@
+/*
+ * 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 wlan_hdd_wmm.c
+
+ This module (wlan_hdd_wmm.h interface + wlan_hdd_wmm.c implementation)
+ houses all the logic for WMM in HDD.
+
+ On the control path, it has the logic to setup QoS, modify QoS and delete
+ QoS (QoS here refers to a TSPEC). The setup QoS comes in two flavors: an
+ explicit application invoked and an internal HDD invoked. The implicit QoS
+ is for applications that do NOT call the custom QCT WLAN OIDs for QoS but
+ which DO mark their traffic for priortization. It also has logic to start,
+ update and stop the U-APSD trigger frame generation. It also has logic to
+ read WMM related config parameters from the registry.
+
+ On the data path, it has the logic to figure out the WMM AC of an egress
+ packet and when to signal TL to serve a particular AC queue. It also has the
+ logic to retrieve a packet based on WMM priority in response to a fetch from
+ TL.
+
+ The remaining functions are utility functions for information hiding.
+
+
+ Copyright (c) 2008-9 QUALCOMM Incorporated.
+ All Rights Reserved.
+ Qualcomm Confidential and Proprietary
+============================================================================*/
+
+/*---------------------------------------------------------------------------
+ Include files
+ -------------------------------------------------------------------------*/
+#include <wlan_hdd_tx_rx.h>
+#include <wlan_hdd_dp_utils.h>
+#include <wlan_hdd_wmm.h>
+#include <wlan_hdd_ether.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/semaphore.h>
+#include <wlan_hdd_hostapd.h>
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include <wlan_hdd_softap_tx_rx.h>
+#endif
+
+// change logging behavior based upon debug flag
+#ifdef HDD_WMM_DEBUG
+#define WMM_TRACE_LEVEL_FATAL VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_ERROR VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_WARN VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_INFO VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_INFO_HIGH VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_INFO_LOW VOS_TRACE_LEVEL_FATAL
+#else
+#define WMM_TRACE_LEVEL_FATAL VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_ERROR VOS_TRACE_LEVEL_ERROR
+#define WMM_TRACE_LEVEL_WARN VOS_TRACE_LEVEL_WARN
+#define WMM_TRACE_LEVEL_INFO VOS_TRACE_LEVEL_INFO
+#define WMM_TRACE_LEVEL_INFO_HIGH VOS_TRACE_LEVEL_INFO_HIGH
+#define WMM_TRACE_LEVEL_INFO_LOW VOS_TRACE_LEVEL_INFO_LOW
+#endif
+
+
+// UAPSD Mask bits
+// (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored)
+#define HDD_AC_VO 0x1
+#define HDD_AC_VI 0x2
+#define HDD_AC_BK 0x4
+#define HDD_AC_BE 0x8
+
+#define WLAN_HDD_MAX_DSCP 0x3f
+
+static sme_QosWmmUpType hddWmmDscpToUpMap[WLAN_HDD_MAX_DSCP+1];
+
+const v_U8_t hddWmmUpToAcMap[] = {
+ WLANTL_AC_BE,
+ WLANTL_AC_BK,
+ WLANTL_AC_BK,
+ WLANTL_AC_BE,
+ WLANTL_AC_VI,
+ WLANTL_AC_VI,
+ WLANTL_AC_VO,
+ WLANTL_AC_VO
+};
+
+//Linux based UP -> AC Mapping
+const v_U8_t hddLinuxUpToAcMap[8] = {
+ HDD_LINUX_AC_BE,
+ HDD_LINUX_AC_BK,
+ HDD_LINUX_AC_BK,
+ HDD_LINUX_AC_BE,
+ HDD_LINUX_AC_VI,
+ HDD_LINUX_AC_VI,
+ HDD_LINUX_AC_VO,
+ HDD_LINUX_AC_VO
+};
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+/**
+ @brief hdd_wmm_enable_tl_uapsd() - function which decides whether and
+ how to update UAPSD parameters in TL
+
+ @param pQosContext : [in] the pointer the QoS instance control block
+
+ @return
+ None
+*/
+static void hdd_wmm_enable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext)
+{
+ hdd_adapter_t* pAdapter = pQosContext->pAdapter;
+ WLANTL_ACEnumType acType = pQosContext->acType;
+ hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+ VOS_STATUS status;
+ v_U32_t service_interval;
+ v_U32_t suspension_interval;
+ sme_QosWmmDirType direction;
+
+
+ // The TSPEC must be valid
+ if (pAc->wmmAcTspecValid == VOS_FALSE)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Invoked with invalid TSPEC",
+ __FUNCTION__);
+ return;
+ }
+
+ // determine the service interval
+ if (pAc->wmmAcTspecInfo.min_service_interval)
+ {
+ service_interval = pAc->wmmAcTspecInfo.min_service_interval;
+ }
+ else if (pAc->wmmAcTspecInfo.max_service_interval)
+ {
+ service_interval = pAc->wmmAcTspecInfo.max_service_interval;
+ }
+ else
+ {
+ // no service interval is present in the TSPEC
+ // this is OK, there just won't be U-APSD
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: No service interval supplied",
+ __FUNCTION__);
+ return;
+ }
+
+ // determine the suspension interval & direction
+ suspension_interval = pAc->wmmAcTspecInfo.suspension_interval;
+ direction = pAc->wmmAcTspecInfo.ts_info.direction;
+
+ // if we have previously enabled U-APSD, have any params changed?
+ if ((pAc->wmmAcUapsdInfoValid) &&
+ (pAc->wmmAcUapsdServiceInterval == service_interval) &&
+ (pAc->wmmAcUapsdSuspensionInterval == suspension_interval) &&
+ (pAc->wmmAcUapsdDirection == direction))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: No change in U-APSD parameters",
+ __FUNCTION__);
+ return;
+ }
+
+ // are we in the appropriate power save modes?
+ if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), ePMC_BEACON_MODE_POWER_SAVE))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: BMPS is not enabled",
+ __FUNCTION__);
+ return;
+ }
+
+ if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), ePMC_UAPSD_MODE_POWER_SAVE))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: U-APSD is not enabled",
+ __FUNCTION__);
+ return;
+ }
+
+ // everything is in place to notify TL
+ status = WLANTL_EnableUAPSDForAC((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ acType,
+ pAc->wmmAcTspecInfo.ts_info.tid,
+ pAc->wmmAcTspecInfo.ts_info.up,
+ service_interval,
+ suspension_interval,
+ direction);
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Failed to enable U-APSD for AC=%d",
+ __FUNCTION__, acType );
+ return;
+ }
+
+ // stash away the parameters that were used
+ pAc->wmmAcUapsdInfoValid = VOS_TRUE;
+ pAc->wmmAcUapsdServiceInterval = service_interval;
+ pAc->wmmAcUapsdSuspensionInterval = suspension_interval;
+ pAc->wmmAcUapsdDirection = direction;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Enabled UAPSD in TL srv_int=%ld "
+ "susp_int=%ld dir=%d AC=%d",
+ __FUNCTION__,
+ service_interval,
+ suspension_interval,
+ direction,
+ acType);
+
+}
+
+/**
+ @brief hdd_wmm_disable_tl_uapsd() - function which decides whether
+ to disable UAPSD parameters in TL
+
+ @param pQosContext : [in] the pointer the QoS instance control block
+
+ @return
+ None
+*/
+static void hdd_wmm_disable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext)
+{
+ hdd_adapter_t* pAdapter = pQosContext->pAdapter;
+ WLANTL_ACEnumType acType = pQosContext->acType;
+ hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+ VOS_STATUS status;
+
+
+ // have we previously enabled UAPSD?
+ if (pAc->wmmAcUapsdInfoValid == VOS_TRUE)
+ {
+ status = WLANTL_DisableUAPSDForAC((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ acType);
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Failed to disable U-APSD for AC=%d",
+ __FUNCTION__, acType );
+ }
+ else
+ {
+ // TL no longer has valid UAPSD info
+ pAc->wmmAcUapsdInfoValid = VOS_FALSE;
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Disabled UAPSD in TL for AC=%d",
+ __FUNCTION__,
+ acType);
+ }
+ }
+}
+
+#endif
+
+/**
+ @brief hdd_wmm_free_context() - function which frees a QoS context
+
+ @param pQosContext : [in] the pointer the QoS instance control block
+
+ @return
+ None
+*/
+static void hdd_wmm_free_context (hdd_wmm_qos_context_t* pQosContext)
+{
+ hdd_adapter_t* pAdapter;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered, context %p",
+ __FUNCTION__, pQosContext);
+
+ if (unlikely((NULL == pQosContext) ||
+ (HDD_WMM_CTX_MAGIC != pQosContext->magic)))
+ {
+ // must have been freed in another thread
+ return;
+ }
+
+ // get pointer to the adapter context
+ pAdapter = pQosContext->pAdapter;
+
+ // take the wmmLock since we're manipulating the context list
+ mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+
+ // make sure nobody thinks this is a valid context
+ pQosContext->magic = 0;
+
+ // unlink the context
+ list_del(&pQosContext->node);
+
+ // done manipulating the list
+ mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+
+ // reclaim memory
+ kfree(pQosContext);
+
+}
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+/**
+ @brief hdd_wmm_notify_app() - function which notifies an application
+ changes in state of it flow
+
+ @param pQosContext : [in] the pointer the QoS instance control block
+
+ @return
+ None
+*/
+#define MAX_NOTIFY_LEN 50
+static void hdd_wmm_notify_app (hdd_wmm_qos_context_t* pQosContext)
+{
+ hdd_adapter_t* pAdapter;
+ union iwreq_data wrqu;
+ char buf[MAX_NOTIFY_LEN+1];
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered, context %p",
+ __FUNCTION__, pQosContext);
+
+ if (unlikely((NULL == pQosContext) ||
+ (HDD_WMM_CTX_MAGIC != pQosContext->magic)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Invalid QoS Context",
+ __FUNCTION__);
+ return;
+ }
+
+
+ // create the event
+ memset(&wrqu, 0, sizeof(wrqu));
+ memset(buf, 0, sizeof(buf));
+
+ snprintf(buf, MAX_NOTIFY_LEN, "QCOM: TS change[%u: %u]",
+ (unsigned int)pQosContext->handle,
+ (unsigned int)pQosContext->lastStatus);
+
+ wrqu.data.pointer = buf;
+ wrqu.data.length = strlen(buf);
+
+ // get pointer to the adapter
+ pAdapter = pQosContext->pAdapter;
+
+ // send the event
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Sending [%s]", __FUNCTION__, buf);
+ wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf);
+}
+
+
+/**
+ @brief hdd_wmm_is_access_allowed() - function which determines if access
+ is allowed for the given AC. this is designed to be called during SME
+ callback processing since that is when access can be granted or removed
+
+ @param pAdapter : [in] pointer to adapter context
+ @param pAc : [in] pointer to the per-AC status
+
+ @return : VOS_TRUE - access is allowed
+ : VOS_FALSE - access is not allowed
+ None
+*/
+static v_BOOL_t hdd_wmm_is_access_allowed(hdd_adapter_t* pAdapter,
+ hdd_wmm_ac_status_t* pAc)
+{
+ // if we don't want QoS or the AP doesn't support QoS
+ // or we don't want to do implicit QoS
+ // or if AP doesn't require admission for this AC
+ // then we have access
+ if (!hdd_wmm_is_active(pAdapter) ||
+ !(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->bImplicitQosEnabled ||
+ !pAc->wmmAcAccessRequired)
+ {
+ return VOS_TRUE;
+ }
+
+ // if implicit QoS has already completed, successfully or not,
+ // then access is allowed
+ if (pAc->wmmAcAccessGranted || pAc->wmmAcAccessFailed)
+ {
+ return VOS_TRUE;
+ }
+
+ // admission is required and implicit QoS hasn't completed
+ // however explicit QoS may have completed and we'll have
+ // a Tspec
+ // if we don't have a Tspec then access is not allowed
+ if (!pAc->wmmAcTspecValid)
+ {
+ return VOS_FALSE;
+ }
+
+ // we have a Tspec -- does it allow upstream or bidirectional traffic?
+ // if it only allows downstream traffic then access is not allowed
+ if (pAc->wmmAcTspecInfo.ts_info.direction == SME_QOS_WMM_TS_DIR_DOWNLINK)
+ {
+ return VOS_FALSE;
+ }
+
+ // we meet all of the criteria for access
+ return VOS_TRUE;
+}
+
+#ifdef FEATURE_WLAN_CCX
+/**
+ @brief hdd_wmm_inactivity_timer_cb() - timer handler function which is
+ called for every inactivity interval per AC. This function gets the
+ current transmitted packets on the given AC, and checks if there where
+ any TX activity from the previous interval. If there was no traffic
+ then it would delete the TS that was negotiated on that AC.
+
+ @param pUserData : [in] pointer to pQosContext
+
+ @return : NONE
+*/
+void hdd_wmm_inactivity_timer_cb( v_PVOID_t pUserData )
+{
+ hdd_wmm_qos_context_t* pQosContext = (hdd_wmm_qos_context_t*)pUserData;
+ hdd_adapter_t* pAdapter;
+ hdd_wmm_ac_status_t *pAc;
+ hdd_wlan_wmm_status_e status;
+ VOS_STATUS vos_status;
+ v_U32_t currentTrafficCnt = 0;
+ WLANTL_ACEnumType acType = pQosContext->acType;
+
+ pAdapter = pQosContext->pAdapter;
+ pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+
+ // Get the Tx stats for this AC.
+ currentTrafficCnt = pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->acType];
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ FL("WMM inactivity Timer for AC=%d, currentCnt=%d, prevCnt=%d\n"),
+ acType, (int)currentTrafficCnt, (int)pAc->wmmPrevTrafficCnt);
+ if (pAc->wmmPrevTrafficCnt == currentTrafficCnt)
+ {
+ // If there is no traffic activity, delete the TSPEC for this AC
+ status = hdd_wmm_delts(pAdapter, pQosContext->handle);
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ FL("Deleted TS on AC %d, due to inactivity with status = %d!!!"),
+ acType, status);
+ }
+ else
+ {
+ pAc->wmmPrevTrafficCnt = currentTrafficCnt;
+ if (pAc->wmmInactivityTimer.state == VOS_TIMER_STATE_STOPPED)
+ {
+ // Restart the timer
+ vos_status = vos_timer_start(&pAc->wmmInactivityTimer, pAc->wmmInactivityTime);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ FL("Restarting inactivity timer failed on AC %d"), acType);
+ }
+ }
+ else
+ {
+ VOS_ASSERT(vos_timer_getCurrentState(
+ &pAc->wmmInactivityTimer) == VOS_TIMER_STATE_STOPPED);
+ }
+ }
+
+ return;
+}
+
+
+/**
+ @brief hdd_wmm_enable_inactivity_timer() - function to enable the
+ traffic inactivity timer for the given AC, if the inactivity_interval
+ specified in the ADDTS parameters is non-zero
+
+ @param pQosContext : [in] pointer to pQosContext
+ @param inactivityTime: [in] value of the inactivity interval in millisecs
+
+ @return : VOS_STATUS_E_FAILURE
+ VOS_STATUS_SUCCESS
+*/
+VOS_STATUS hdd_wmm_enable_inactivity_timer(hdd_wmm_qos_context_t* pQosContext, v_U32_t inactivityTime)
+{
+ VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
+ hdd_adapter_t* pAdapter = pQosContext->pAdapter;
+ WLANTL_ACEnumType acType = pQosContext->acType;
+ hdd_wmm_ac_status_t *pAc;
+
+ pAdapter = pQosContext->pAdapter;
+ pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+
+
+ // If QoS-Tspec is successfully setup and if the inactivity timer is non-zero,
+ // a traffic inactivity timer needs to be started for the given AC
+ vos_status = vos_timer_init(
+ &pAc->wmmInactivityTimer,
+ VOS_TIMER_TYPE_SW,
+ hdd_wmm_inactivity_timer_cb,
+ (v_PVOID_t)pQosContext );
+ if ( !VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ FL("Initializing inactivity timer failed on AC %d"), acType);
+ return vos_status;
+ }
+
+ // Start the inactivity timer
+ vos_status = vos_timer_start(
+ &pAc->wmmInactivityTimer,
+ inactivityTime);
+ if ( !VOS_IS_STATUS_SUCCESS(vos_status))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ FL("Starting inactivity timer failed on AC %d"), acType);
+ return vos_status;
+ }
+ pAc->wmmInactivityTime = inactivityTime;
+ // Initialize the current tx traffic count on this AC
+ pAc->wmmPrevTrafficCnt = pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->acType];
+
+ return vos_status;
+}
+
+/**
+ @brief hdd_wmm_enable_inactivity_timer() - function to disable the
+ traffic inactivity timer for the given AC. This would be called when
+ deleting the TS.
+
+ @param pQosContext : [in] pointer to pQosContext
+
+ @return : VOS_STATUS_E_FAILURE
+ VOS_STATUS_SUCCESS
+*/
+VOS_STATUS hdd_wmm_disable_inactivity_timer(hdd_wmm_qos_context_t* pQosContext)
+{
+ hdd_adapter_t* pAdapter = pQosContext->pAdapter;
+ WLANTL_ACEnumType acType = pQosContext->acType;
+ hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+ VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
+
+ // Clear the timer and the counter
+ pAc->wmmInactivityTime = 0;
+ pAc->wmmPrevTrafficCnt = 0;
+ vos_timer_stop(&pAc->wmmInactivityTimer);
+ vos_status = vos_timer_destroy(&pAc->wmmInactivityTimer);
+
+ return vos_status;
+}
+#endif // FEATURE_WLAN_CCX
+
+/**
+ @brief hdd_wmm_sme_callback() - callback registered by HDD with SME for receiving
+ QoS notifications. Even though this function has a static scope it gets called
+ externally through some function pointer magic (so there is a need for
+ rigorous parameter checking)
+
+ @param hHal : [in] the HAL handle
+ @param HddCtx : [in] the HDD specified handle
+ @param pCurrentQosInfo : [in] the TSPEC params
+ @param SmeStatus : [in] the QoS related SME status
+
+ @return
+ eHAL_STATUS_SUCCESS if all good, eHAL_STATUS_FAILURE otherwise
+*/
+static eHalStatus hdd_wmm_sme_callback (tHalHandle hHal,
+ void * hddCtx,
+ sme_QosWmmTspecInfo* pCurrentQosInfo,
+ sme_QosStatusType smeStatus,
+ v_U32_t qosFlowId)
+{
+ hdd_wmm_qos_context_t* pQosContext = hddCtx;
+ hdd_adapter_t* pAdapter;
+ WLANTL_ACEnumType acType;
+ hdd_wmm_ac_status_t *pAc;
+ VOS_STATUS status;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered, context %p",
+ __FUNCTION__, pQosContext);
+
+ if (unlikely((NULL == pQosContext) ||
+ (HDD_WMM_CTX_MAGIC != pQosContext->magic)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Invalid QoS Context",
+ __FUNCTION__);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ pAdapter = pQosContext->pAdapter;
+ acType = pQosContext->acType;
+ pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: status %d flowid %d info %p",
+ __FUNCTION__, smeStatus, qosFlowId, pCurrentQosInfo);
+
+ switch (smeStatus)
+ {
+
+ case SME_QOS_STATUS_SETUP_SUCCESS_IND:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Setup is complete",
+ __FUNCTION__);
+
+ // there will always be a TSPEC returned with this status, even if
+ // a TSPEC is not exchanged OTA
+ if (pCurrentQosInfo)
+ {
+ pAc->wmmAcTspecValid = VOS_TRUE;
+ memcpy(&pAc->wmmAcTspecInfo,
+ pCurrentQosInfo,
+ sizeof(pAc->wmmAcTspecInfo));
+ }
+
+ if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Implicit Qos, notifying TL for TL AC %d",
+ __FUNCTION__, acType);
+
+ // this was triggered by implicit QoS so we know packets are pending
+ // update state
+ pAc->wmmAcAccessAllowed = VOS_TRUE;
+ pAc->wmmAcAccessGranted = VOS_TRUE;
+ pAc->wmmAcAccessPending = VOS_FALSE;
+
+ // notify TL that packets are pending
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ acType );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Failed to signal TL for AC=%d",
+ __FUNCTION__, acType );
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+#ifdef FEATURE_WLAN_CCX
+ // Check if the inactivity interval is specified
+ if (pCurrentQosInfo->inactivity_interval) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Inactivity timer value = %d for AC=%d\n",
+ __FUNCTION__, pCurrentQosInfo->inactivity_interval, acType);
+ hdd_wmm_enable_inactivity_timer(pQosContext, pCurrentQosInfo->inactivity_interval);
+ }
+#endif // FEATURE_WLAN_CCX
+
+ // notify TL to enable trigger frames if necessary
+ hdd_wmm_enable_tl_uapsd(pQosContext);
+
+ break;
+
+ case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Setup is complete (U-APSD set previously)",
+ __FUNCTION__);
+
+ if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Implicit Qos, notifying TL",
+ __FUNCTION__);
+
+ // this was triggered by implicit QoS so we know packets are pending
+ // update state
+ pAc->wmmAcAccessAllowed = VOS_TRUE;
+ pAc->wmmAcAccessGranted = VOS_TRUE;
+ pAc->wmmAcAccessPending = VOS_FALSE;
+
+ // notify TL that packets are pending
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ acType );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Failed to signal TL for AC=%d",
+ __FUNCTION__, acType );
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+ break;
+
+ case SME_QOS_STATUS_SETUP_FAILURE_RSP:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Setup failed",
+ __FUNCTION__);
+ // QoS setup failed
+
+ if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Implicit Qos, notifying TL",
+ __FUNCTION__);
+
+ // we note the failure, but we also mark access as allowed so that
+ // the packets will flow. Note that the MAC will "do the right thing"
+ pAc->wmmAcAccessPending = VOS_FALSE;
+ pAc->wmmAcAccessFailed = VOS_TRUE;
+ pAc->wmmAcAccessAllowed = VOS_TRUE;
+
+ // this was triggered by implicit QoS so we know packets are pending
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ acType );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Failed to signal TL for AC=%d",
+ __FUNCTION__, acType );
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+ /* Setting up QoS Failed, QoS context can be released.
+ * SME is releasing this flow information and if HDD doen't release this context,
+ * next time if application uses the same handle to set-up QoS, HDD (as it has
+ * QoS context for this handle) will issue Modify QoS request to SME but SME will
+ * reject as no it has no information for this flow.
+ */
+ hdd_wmm_free_context(pQosContext);
+ break;
+
+ case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Setup Invalid Params, notify TL",
+ __FUNCTION__);
+ // QoS setup failed
+
+ if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Implicit Qos, notifying TL",
+ __FUNCTION__);
+
+ // we note the failure, but we also mark access as allowed so that
+ // the packets will flow. Note that the MAC will "do the right thing"
+ pAc->wmmAcAccessPending = VOS_FALSE;
+ pAc->wmmAcAccessFailed = VOS_TRUE;
+ pAc->wmmAcAccessAllowed = VOS_TRUE;
+
+ // this was triggered by implicit QoS so we know packets are pending
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ acType );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Failed to signal TL for AC=%d",
+ __FUNCTION__, acType );
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ hdd_wmm_notify_app(pQosContext);
+ }
+ break;
+
+ case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Setup failed, not a QoS AP\n",
+ __FUNCTION__);
+ if (!HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
+ hdd_wmm_notify_app(pQosContext);
+ }
+ break;
+
+ case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Setup pending",
+ __FUNCTION__);
+ // not a callback status -- ignore if we get it
+ break;
+
+ case SME_QOS_STATUS_SETUP_MODIFIED_IND:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Setup modified",
+ __FUNCTION__);
+ if (pCurrentQosInfo)
+ {
+ // update the TSPEC
+ pAc->wmmAcTspecValid = VOS_TRUE;
+ memcpy(&pAc->wmmAcTspecInfo,
+ pCurrentQosInfo,
+ sizeof(pAc->wmmAcTspecInfo));
+
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFIED;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+ // need to tell TL to update its UAPSD handling
+ hdd_wmm_enable_tl_uapsd(pQosContext);
+ }
+ break;
+
+ case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+ if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Implicit Qos, notifying TL",
+ __FUNCTION__);
+
+ // this was triggered by implicit QoS so we know packets are pending
+ pAc->wmmAcAccessPending = VOS_FALSE;
+ pAc->wmmAcAccessGranted = VOS_TRUE;
+ pAc->wmmAcAccessAllowed = VOS_TRUE;
+
+ // notify TL that packets are pending
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ acType );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Failed to signal TL for AC=%d",
+ __FUNCTION__, acType );
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD;
+ hdd_wmm_notify_app(pQosContext);
+ }
+ break;
+
+ case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
+ // nothing to do for now
+ break;
+
+ case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Setup successful but U-APSD failed",
+ __FUNCTION__);
+
+ if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Implicit Qos, notifying TL",
+ __FUNCTION__);
+
+ // QoS setup was successful but setting U=APSD failed
+ // Since the OTA part of the request was successful, we don't mark
+ // this as a failure.
+ // the packets will flow. Note that the MAC will "do the right thing"
+ pAc->wmmAcAccessGranted = VOS_TRUE;
+ pAc->wmmAcAccessAllowed = VOS_TRUE;
+ pAc->wmmAcAccessFailed = VOS_FALSE;
+ pAc->wmmAcAccessPending = VOS_FALSE;
+
+ // this was triggered by implicit QoS so we know packets are pending
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ acType );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Failed to signal TL for AC=%d",
+ __FUNCTION__, acType );
+ }
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_UAPSD_SET_FAILED;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+ // Since U-APSD portion failed disabled trigger frame generation
+ hdd_wmm_disable_tl_uapsd(pQosContext);
+
+ break;
+
+ case SME_QOS_STATUS_RELEASE_SUCCESS_RSP:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Release is complete",
+ __FUNCTION__);
+
+ if (pCurrentQosInfo)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: flows still active",
+ __FUNCTION__);
+
+ // there is still at least one flow active for this AC
+ // so update the AC state
+ memcpy(&pAc->wmmAcTspecInfo,
+ pCurrentQosInfo,
+ sizeof(pAc->wmmAcTspecInfo));
+
+ // need to tell TL to update its UAPSD handling
+ hdd_wmm_enable_tl_uapsd(pQosContext);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: last flow",
+ __FUNCTION__);
+
+ // this is the last flow active for this AC so update the AC state
+ pAc->wmmAcTspecValid = VOS_FALSE;
+
+ // need to tell TL to update its UAPSD handling
+ hdd_wmm_disable_tl_uapsd(pQosContext);
+ }
+
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+ // we are done with this flow
+ hdd_wmm_free_context(pQosContext);
+ break;
+
+ case SME_QOS_STATUS_RELEASE_FAILURE_RSP:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Release failure",
+ __FUNCTION__);
+
+ // we don't need to update our state or TL since nothing has changed
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+ break;
+
+ case SME_QOS_STATUS_RELEASE_QOS_LOST_IND:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: QOS Lost indication received",
+ __FUNCTION__);
+
+ // current TSPEC is no longer valid
+ pAc->wmmAcTspecValid = VOS_FALSE;
+
+ // need to tell TL to update its UAPSD handling
+ hdd_wmm_disable_tl_uapsd(pQosContext);
+
+ if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+ {
+ // we no longer have implicit access granted
+ pAc->wmmAcAccessGranted = VOS_FALSE;
+ pAc->wmmAcAccessFailed = VOS_FALSE;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Explicit Qos, notifying userspace",
+ __FUNCTION__);
+
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_LOST;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+ // we are done with this flow
+ hdd_wmm_free_context(pQosContext);
+ break;
+
+ case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Release pending",
+ __FUNCTION__);
+ // not a callback status -- ignore if we get it
+ break;
+
+ case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Release Invalid Params",
+ __FUNCTION__);
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
+ hdd_wmm_notify_app(pQosContext);
+ }
+ break;
+
+ case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Modification is complete, notify TL",
+ __FUNCTION__);
+
+ // there will always be a TSPEC returned with this status, even if
+ // a TSPEC is not exchanged OTA
+ if (pCurrentQosInfo)
+ {
+ pAc->wmmAcTspecValid = VOS_TRUE;
+ memcpy(&pAc->wmmAcTspecInfo,
+ pCurrentQosInfo,
+ sizeof(pAc->wmmAcTspecInfo));
+ }
+
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+ // notify TL to enable trigger frames if necessary
+ hdd_wmm_enable_tl_uapsd(pQosContext);
+
+ break;
+
+ case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY:
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING;
+ hdd_wmm_notify_app(pQosContext);
+ }
+ break;
+
+ case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP:
+ // the flow modification failed so we'll leave in place
+ // whatever existed beforehand
+
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
+ hdd_wmm_notify_app(pQosContext);
+ }
+ break;
+
+ case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: modification pending",
+ __FUNCTION__);
+ // not a callback status -- ignore if we get it
+ break;
+
+ case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+ // the flow modification was successful but no QoS changes required
+
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD;
+ hdd_wmm_notify_app(pQosContext);
+ }
+ break;
+
+ case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP:
+ // invalid params -- notify the application
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM;
+ hdd_wmm_notify_app(pQosContext);
+ }
+ break;
+
+ case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_PENDING:
+ // nothing to do for now. when APSD is established we'll have work to do
+ break;
+
+ case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED:
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Modify successful but U-APSD failed",
+ __FUNCTION__);
+
+ // QoS modification was successful but setting U=APSD failed.
+ // This will always be an explicit QoS instance, so all we can
+ // do is notify the application and let it clean up.
+ if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+ {
+ // this was triggered by an application
+ pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_UAPSD_SET_FAILED;
+ hdd_wmm_notify_app(pQosContext);
+ }
+
+ // Since U-APSD portion failed disabled trigger frame generation
+ hdd_wmm_disable_tl_uapsd(pQosContext);
+
+ break;
+
+ case SME_QOS_STATUS_HANDING_OFF:
+ // no roaming so we won't see this
+ break;
+
+ case SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND:
+ // need to tell TL to stop trigger frame generation
+ hdd_wmm_disable_tl_uapsd(pQosContext);
+ break;
+
+ case SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND:
+ // need to tell TL to start sending trigger frames again
+ hdd_wmm_enable_tl_uapsd(pQosContext);
+ break;
+
+ default:
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: unexpected SME Status=%d\n",
+ __FUNCTION__, smeStatus );
+ VOS_ASSERT(0);
+ }
+
+ // our access to the particular access category may have changed.
+ // some of the implicit QoS cases above may have already set this
+ // prior to invoking TL (so that we will properly service the
+ // Tx queues) but let's consistently handle all cases here
+ pAc->wmmAcAccessAllowed = hdd_wmm_is_access_allowed(pAdapter, pAc);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: complete, access for TL AC %d is%sallowed",
+ __FUNCTION__,
+ acType,
+ pAc->wmmAcAccessAllowed ? " " : " not ");
+
+ return eHAL_STATUS_SUCCESS;
+}
+#endif
+
+/**============================================================================
+ @brief hdd_wmm_do_implicit_qos() - Function which will attempt to setup
+ QoS for any AC requiring it
+
+ @param work : [in] pointer to work structure
+
+ @return : void
+ ===========================================================================*/
+static void hdd_wmm_do_implicit_qos(struct work_struct *work)
+{
+ hdd_wmm_qos_context_t* pQosContext =
+ container_of(work, hdd_wmm_qos_context_t, wmmAcSetupImplicitQos);
+ hdd_adapter_t* pAdapter;
+ WLANTL_ACEnumType acType;
+ hdd_wmm_ac_status_t *pAc;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ VOS_STATUS status;
+ sme_QosStatusType smeStatus;
+#endif
+ sme_QosWmmTspecInfo qosInfo;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered, context %p",
+ __FUNCTION__, pQosContext);
+
+ if (unlikely(HDD_WMM_CTX_MAGIC != pQosContext->magic))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Invalid QoS Context",
+ __FUNCTION__);
+ return;
+ }
+
+ pAdapter = pQosContext->pAdapter;
+ acType = pQosContext->acType;
+ pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: pAdapter %p acType %d",
+ __FUNCTION__, pAdapter, acType);
+
+ if (!pAc->wmmAcAccessNeeded)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: AC %d doesn't need service",
+ __FUNCTION__, acType);
+ pQosContext->magic = 0;
+ kfree(pQosContext);
+ return;
+ }
+
+ pAc->wmmAcAccessPending = VOS_TRUE;
+ pAc->wmmAcAccessNeeded = VOS_FALSE;
+
+ memset(&qosInfo, 0, sizeof(qosInfo));
+
+ switch (acType)
+ {
+ case WLANTL_AC_VO:
+ qosInfo.ts_info.up = SME_QOS_WMM_UP_VO;
+ qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x01;
+ qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcVo;
+ qosInfo.ts_info.tid = 255;
+ qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcVo;
+ qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcVo;
+ qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv;
+ qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcVo;
+ qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcVo;
+ qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSuspIntv;
+ break;
+ case WLANTL_AC_VI:
+ qosInfo.ts_info.up = SME_QOS_WMM_UP_VI;
+ qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x02;
+ qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcVi;
+ qosInfo.ts_info.tid = 255;
+ qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcVi;
+ qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcVi;
+ qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv;
+ qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcVi;
+ qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcVi;
+ qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSuspIntv;
+ break;
+ default:
+ case WLANTL_AC_BE:
+ qosInfo.ts_info.up = SME_QOS_WMM_UP_BE;
+ qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x08;
+ qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcBe;
+ qosInfo.ts_info.tid = 255;
+ qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcBe;
+ qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcBe;
+ qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv;
+ qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcBe;
+ qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcBe;
+ qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSuspIntv;
+ break;
+ case WLANTL_AC_BK:
+ qosInfo.ts_info.up = SME_QOS_WMM_UP_BK;
+ qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x04;
+ qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcBk;
+ qosInfo.ts_info.tid = 255;
+ qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcBk;
+ qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcBk;
+ qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv;
+ qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcBk;
+ qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcBk;
+ qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv;
+ break;
+ }
+#ifdef FEATURE_WLAN_CCX
+ qosInfo.inactivity_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraInactivityInterval;
+#endif
+ qosInfo.ts_info.burst_size_defn = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->burstSizeDefinition;
+
+ switch ((WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->tsInfoAckPolicy)
+ {
+ case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK:
+ qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
+ break;
+
+ case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK:
+ qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK;
+ break;
+
+ default:
+ // unknown
+ qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
+ }
+
+ if(qosInfo.ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK)
+ {
+ if(!sme_QosIsTSInfoAckPolicyValid((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter), &qosInfo, pAdapter->sessionId))
+ {
+ qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
+ }
+ }
+
+ mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+ list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList);
+ mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ smeStatus = sme_QosSetupReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ &qosInfo,
+ hdd_wmm_sme_callback,
+ pQosContext,
+ qosInfo.ts_info.up,
+ &pQosContext->qosFlowId);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: sme_QosSetupReq returned %d flowid %d",
+ __FUNCTION__, smeStatus, pQosContext->qosFlowId);
+
+ // need to check the return values and act appropriately
+ switch (smeStatus)
+ {
+ case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
+ case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
+ // setup is pending, so no more work to do now.
+ // all further work will be done in hdd_wmm_sme_callback()
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Setup is pending, no further work",
+ __FUNCTION__);
+
+ break;
+
+
+ case SME_QOS_STATUS_SETUP_FAILURE_RSP:
+ // we can't tell the difference between when a request fails because
+ // AP rejected it versus when SME encountered an internal error
+
+ // in either case SME won't ever reference this context so
+ // free the record
+ hdd_wmm_free_context(pQosContext);
+
+ // fall through and start packets flowing
+ case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+ // no ACM in effect, no need to setup U-APSD
+ case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
+ // no ACM in effect, U-APSD is desired but was already setup
+
+ // for these cases everything is already setup so we can
+ // signal TL that it has work to do
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Setup is complete, notify TL",
+ __FUNCTION__);
+
+ pAc->wmmAcAccessAllowed = VOS_TRUE;
+ pAc->wmmAcAccessGranted = VOS_TRUE;
+ pAc->wmmAcAccessPending = VOS_FALSE;
+
+ status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ acType );
+
+ if ( !VOS_IS_STATUS_SUCCESS( status ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Failed to signal TL for AC=%d",
+ __FUNCTION__, acType );
+ }
+
+ break;
+
+
+ default:
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: unexpected SME Status=%d\n",
+ __FUNCTION__, smeStatus );
+ VOS_ASSERT(0);
+ }
+#endif
+
+}
+
+/**============================================================================
+ @brief hdd_wmm_init() - Function which will initialize the WMM configuation
+ and status to an initial state. The configuration can later be overwritten
+ via application APIs
+
+ @param pHddCtx : [in] pointer to HDD context
+
+ @return : VOS_STATUS_SUCCESS if succssful
+ : other values if failure
+
+ ===========================================================================*/
+VOS_STATUS hdd_wmm_init ( hdd_context_t* pHddCtx )
+{
+ v_U8_t dscp;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered", __FUNCTION__);
+
+ // DSCP to User Priority Lookup Table
+ for (dscp = 0; dscp <= WLAN_HDD_MAX_DSCP; dscp++)
+ {
+ hddWmmDscpToUpMap[dscp] = SME_QOS_WMM_UP_BE;
+ }
+ hddWmmDscpToUpMap[8] = SME_QOS_WMM_UP_BK;
+ hddWmmDscpToUpMap[16] = SME_QOS_WMM_UP_RESV;
+ hddWmmDscpToUpMap[24] = SME_QOS_WMM_UP_EE;
+ hddWmmDscpToUpMap[32] = SME_QOS_WMM_UP_CL;
+ hddWmmDscpToUpMap[40] = SME_QOS_WMM_UP_VI;
+ hddWmmDscpToUpMap[48] = SME_QOS_WMM_UP_VO;
+ hddWmmDscpToUpMap[56] = SME_QOS_WMM_UP_NC;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**============================================================================
+ @brief hdd_wmm_adapter_init() - Function which will initialize the WMM configuation
+ and status to an initial state. The configuration can later be overwritten
+ via application APIs
+
+ @param pAdapter : [in] pointer to Adapter context
+
+ @return : VOS_STATUS_SUCCESS if succssful
+ : other values if failure
+
+ ===========================================================================*/
+VOS_STATUS hdd_wmm_adapter_init( hdd_adapter_t *pAdapter )
+{
+ hdd_wmm_ac_status_t *pAcStatus;
+ WLANTL_ACEnumType acType;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered", __FUNCTION__);
+
+ pAdapter->hddWmmStatus.wmmQap = VOS_FALSE;
+ INIT_LIST_HEAD(&pAdapter->hddWmmStatus.wmmContextList);
+ mutex_init(&pAdapter->hddWmmStatus.wmmLock);
+
+ for (acType = 0; acType < WLANTL_MAX_AC; acType++)
+ {
+ pAcStatus = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+ pAcStatus->wmmAcAccessRequired = VOS_FALSE;
+ pAcStatus->wmmAcAccessNeeded = VOS_FALSE;
+ pAcStatus->wmmAcAccessPending = VOS_FALSE;
+ pAcStatus->wmmAcAccessFailed = VOS_FALSE;
+ pAcStatus->wmmAcAccessGranted = VOS_FALSE;
+ pAcStatus->wmmAcAccessAllowed = VOS_FALSE;
+ pAcStatus->wmmAcTspecValid = VOS_FALSE;
+ pAcStatus->wmmAcUapsdInfoValid = VOS_FALSE;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+/**============================================================================
+ @brief hdd_wmm_close() - Function which will perform any necessary work to
+ to clean up the WMM functionality prior to the kernel module unload
+
+ @param pAdapter : [in] pointer to adapter context
+
+ @return : VOS_STATUS_SUCCESS if succssful
+ : other values if failure
+
+ ===========================================================================*/
+VOS_STATUS hdd_wmm_adapter_close ( hdd_adapter_t* pAdapter )
+{
+ hdd_wmm_qos_context_t* pQosContext;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered", __FUNCTION__);
+
+ // free any context records that we still have linked
+ while (!list_empty(&pAdapter->hddWmmStatus.wmmContextList))
+ {
+ pQosContext = list_first_entry(&pAdapter->hddWmmStatus.wmmContextList,
+ hdd_wmm_qos_context_t, node);
+#ifdef FEATURE_WLAN_CCX
+ hdd_wmm_disable_inactivity_timer(pQosContext);
+#endif
+ hdd_wmm_free_context(pQosContext);
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**============================================================================
+ @brief hdd_wmm_classify_pkt() - Function which will classify an OS packet
+ into a WMM AC based on either 802.1Q or DSCP
+
+ @param pAdapter : [in] pointer to adapter context
+ @param skb : [in] pointer to OS packet (sk_buff)
+ @param pAcType : [out] pointer to WMM AC type of OS packet
+
+ @return : None
+ ===========================================================================*/
+v_VOID_t hdd_wmm_classify_pkt ( hdd_adapter_t* pAdapter,
+ struct sk_buff *skb,
+ WLANTL_ACEnumType* pAcType,
+ sme_QosWmmUpType *pUserPri)
+{
+ unsigned char * pPkt;
+ union generic_ethhdr *pHdr;
+ struct iphdr *pIpHdr;
+ unsigned char tos;
+ unsigned char dscp;
+ sme_QosWmmUpType userPri;
+ WLANTL_ACEnumType acType;
+
+ // this code is executed for every packet therefore
+ // all debug code is kept conditional
+
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered", __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+
+ pPkt = skb->data;
+ pHdr = (union generic_ethhdr *)pPkt;
+
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: proto/length is 0x%04x",
+ __FUNCTION__, pHdr->eth_II.h_proto);
+#endif // HDD_WMM_DEBUG
+
+ if (HDD_WMM_CLASSIFICATION_DSCP == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->PktClassificationBasis)
+ {
+ if (pHdr->eth_II.h_proto == htons(ETH_P_IP))
+ {
+ // case 1: Ethernet II IP packet
+ pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_II)];
+ tos = pIpHdr->tos;
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Ethernet II IP Packet, tos is %d",
+ __FUNCTION__, tos);
+#endif // HDD_WMM_DEBUG
+
+ }
+ else if ((ntohs(pHdr->eth_II.h_proto) < WLAN_MIN_PROTO) &&
+ (pHdr->eth_8023.h_snap.dsap == WLAN_SNAP_DSAP) &&
+ (pHdr->eth_8023.h_snap.ssap == WLAN_SNAP_SSAP) &&
+ (pHdr->eth_8023.h_snap.ctrl == WLAN_SNAP_CTRL) &&
+ (pHdr->eth_8023.h_proto == htons(ETH_P_IP)))
+ {
+ // case 2: 802.3 LLC/SNAP IP packet
+ pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_8023)];
+ tos = pIpHdr->tos;
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: 802.3 LLC/SNAP IP Packet, tos is %d",
+ __FUNCTION__, tos);
+#endif // HDD_WMM_DEBUG
+ }
+ else if (pHdr->eth_II.h_proto == htons(ETH_P_8021Q))
+ {
+ // VLAN tagged
+
+ if (pHdr->eth_IIv.h_vlan_encapsulated_proto == htons(ETH_P_IP))
+ {
+ // case 3: Ethernet II vlan-tagged IP packet
+ pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_IIv)];
+ tos = pIpHdr->tos;
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Ethernet II VLAN tagged IP Packet, tos is %d",
+ __FUNCTION__, tos);
+#endif // HDD_WMM_DEBUG
+ }
+ else if ((ntohs(pHdr->eth_IIv.h_vlan_encapsulated_proto) < WLAN_MIN_PROTO) &&
+ (pHdr->eth_8023v.h_snap.dsap == WLAN_SNAP_DSAP) &&
+ (pHdr->eth_8023v.h_snap.ssap == WLAN_SNAP_SSAP) &&
+ (pHdr->eth_8023v.h_snap.ctrl == WLAN_SNAP_CTRL) &&
+ (pHdr->eth_8023v.h_proto == htons(ETH_P_IP)))
+ {
+ // case 4: 802.3 LLC/SNAP vlan-tagged IP packet
+ pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_8023v)];
+ tos = pIpHdr->tos;
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: 802.3 LLC/SNAP VLAN tagged IP Packet, tos is %d",
+ __FUNCTION__, tos);
+#endif // HDD_WMM_DEBUG
+ }
+ else
+ {
+ // default
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
+ "%s: VLAN tagged Unhandled Protocol, using default tos",
+ __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+ tos = 0;
+ }
+ }
+ else
+ {
+ // default
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
+ "%s: Unhandled Protocol, using default tos",
+ __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+ //Give the highest priority to 802.1x packet
+ if (pHdr->eth_II.h_proto == htons(HDD_ETHERTYPE_802_1_X))
+ tos = 0xC0;
+ else
+ tos = 0;
+ }
+
+ dscp = (tos>>2) & 0x3f;
+ userPri = hddWmmDscpToUpMap[dscp];
+
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: tos is %d, dscp is %d, up is %d",
+ __FUNCTION__, tos, dscp, userPri);
+#endif // HDD_WMM_DEBUG
+
+ }
+ else if (HDD_WMM_CLASSIFICATION_802_1Q == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->PktClassificationBasis)
+ {
+ if (pHdr->eth_IIv.h_vlan_proto == htons(ETH_P_8021Q))
+ {
+ // VLAN tagged
+ userPri = (ntohs(pHdr->eth_IIv.h_vlan_TCI)>>13) & 0x7;
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Tagged frame, UP is %d",
+ __FUNCTION__, userPri);
+#endif // HDD_WMM_DEBUG
+ }
+ else
+ {
+ // not VLAN tagged, use default
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
+ "%s: Untagged frame, using default UP",
+ __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+ //Give the highest priority to 802.1x packet
+ if (pHdr->eth_II.h_proto == htons(HDD_ETHERTYPE_802_1_X))
+ userPri = SME_QOS_WMM_UP_VO;
+ else
+ userPri = SME_QOS_WMM_UP_BE;
+ }
+ }
+ else
+ {
+ // default
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Unknown classification scheme, using default UP",
+ __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+ userPri = SME_QOS_WMM_UP_BE;
+ }
+
+ acType = hddWmmUpToAcMap[userPri];
+
+#ifdef HDD_WMM_DEBUG
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: UP is %d, AC is %d",
+ __FUNCTION__, userPri, acType);
+#endif // HDD_WMM_DEBUG
+
+ *pUserPri = userPri;
+ *pAcType = acType;
+
+ return;
+}
+
+/**============================================================================
+ @brief hdd_hostapd_select_quueue() - Function which will classify the packet
+ according to linux qdisc expectation.
+
+
+ @param dev : [in] pointer to net_device structure
+ @param skb : [in] pointer to os packet
+
+ @return : Qdisc queue index
+ ===========================================================================*/
+v_U16_t hdd_hostapd_select_queue(struct net_device * dev, struct sk_buff *skb)
+{
+ WLANTL_ACEnumType ac;
+ sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
+ v_USHORT_t queueIndex;
+ v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
+ hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ tpAniSirGlobal pMac = (tpAniSirGlobal) vos_get_context(VOS_MODULE_ID_HAL, pHddCtx->pvosContext);
+#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
+ v_U8_t STAId;
+ v_U8_t *pSTAId = (v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
+
+ /*Get the Station ID*/
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ if (eHAL_STATUS_SUCCESS != halTable_FindStaidByAddr(pMac, (tANI_U8 *)pDestMacAddress, &STAId))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to find right station", __FUNCTION__);
+ *pSTAId = HDD_WLAN_INVALID_STA_ID;
+ goto done;
+ }
+#else
+ if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &STAId))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to find right station", __FUNCTION__);
+ *pSTAId = HDD_WLAN_INVALID_STA_ID;
+ goto done;
+ }
+#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
+
+ spin_lock_bh( &pAdapter->staInfo_lock );
+ if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[STAId].macAddrSTA, pDestMacAddress))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Station MAC address does not matching", __FUNCTION__);
+
+ *pSTAId = HDD_WLAN_INVALID_STA_ID;
+ goto release_lock;
+ }
+ if (pAdapter->aStaInfo[STAId].isUsed && pAdapter->aStaInfo[STAId].isQosEnabled && (HDD_WMM_USER_MODE_NO_QOS != pHddCtx->cfg_ini->WmmMode))
+ {
+ /* Get the user priority from IP header & corresponding AC */
+ hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up);
+ }
+ *pSTAId = STAId;
+
+release_lock:
+ spin_unlock_bh( &pAdapter->staInfo_lock );
+done:
+ skb->priority = up;
+ queueIndex = hddLinuxUpToAcMap[skb->priority];
+
+ return queueIndex;
+}
+
+/**============================================================================
+ @brief hdd_wmm_select_quueue() - Function which will classify the packet
+ according to linux qdisc expectation.
+
+
+ @param dev : [in] pointer to net_device structure
+ @param skb : [in] pointer to os packet
+
+ @return : Qdisc queue index
+ ===========================================================================*/
+v_U16_t hdd_wmm_select_queue(struct net_device * dev, struct sk_buff *skb)
+{
+ WLANTL_ACEnumType ac;
+ sme_QosWmmUpType up = 0;
+ v_USHORT_t queueIndex;
+
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ // if we don't want QoS or the AP doesn't support Qos
+ // All traffic will get equal opportuniy to transmit data frames.
+ if( hdd_wmm_is_active(pAdapter) ) {
+ /* Get the user priority from IP header & corresponding AC */
+ hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up);
+ }
+
+ skb->priority = up;
+ queueIndex = hddLinuxUpToAcMap[skb->priority];
+
+ return queueIndex;
+}
+
+/**============================================================================
+ @brief hdd_wmm_acquire_access() - Function which will attempt to acquire
+ admittance for a WMM AC
+
+ @param pAdapter : [in] pointer to adapter context
+ @param acType : [in] WMM AC type of OS packet
+ @param pGranted : [out] pointer to boolean flag when indicates if access
+ has been granted or not
+
+ @return : VOS_STATUS_SUCCESS if succssful
+ : other values if failure
+ ===========================================================================*/
+VOS_STATUS hdd_wmm_acquire_access( hdd_adapter_t* pAdapter,
+ WLANTL_ACEnumType acType,
+ v_BOOL_t * pGranted )
+{
+ hdd_wmm_qos_context_t *pQosContext;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered for AC %d", __FUNCTION__, acType);
+
+ if (!hdd_wmm_is_active(pAdapter) || !(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->bImplicitQosEnabled)
+ {
+ // either we don't want QoS or the AP doesn't support QoS
+ // or we don't want to do implicit QoS
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: QoS not configured on both ends ", __FUNCTION__);
+
+ pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE;
+ *pGranted = VOS_TRUE;
+ return VOS_STATUS_SUCCESS;
+ }
+
+ // do we already have an implicit QoS request pending for this AC?
+ if ((pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded) ||
+ (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessPending))
+ {
+ // request already pending so we need to wait for that response
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Implicit QoS for TL AC %d already scheduled",
+ __FUNCTION__, acType);
+
+ *pGranted = VOS_FALSE;
+ return VOS_STATUS_SUCCESS;
+ }
+
+ // did we already fail to establish implicit QoS for this AC?
+ // (if so, access should have been granted when the failure was handled)
+ if (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessFailed)
+ {
+ // request previously failed
+ // allow access, but we'll be downgraded
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Implicit QoS for TL AC %d previously failed",
+ __FUNCTION__, acType);
+
+ pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE;
+ *pGranted = VOS_TRUE;
+ return VOS_STATUS_SUCCESS;
+ }
+
+ // we need to establish implicit QoS
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Need to schedule implicit QoS for TL AC %d, pAdapter is %p",
+ __FUNCTION__, acType, pAdapter);
+
+ pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded = VOS_TRUE;
+
+ pQosContext = kmalloc(sizeof(*pQosContext), GFP_KERNEL);
+ if (NULL == pQosContext)
+ {
+ // no memory for QoS context. Nothing we can do but let data flow
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Unable to allocate context", __FUNCTION__);
+ pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE;
+ *pGranted = VOS_TRUE;
+ return VOS_STATUS_SUCCESS;
+ }
+
+ pQosContext->acType = acType;
+ pQosContext->pAdapter = pAdapter;
+ pQosContext->qosFlowId = 0;
+ pQosContext->handle = HDD_WMM_HANDLE_IMPLICIT;
+ pQosContext->magic = HDD_WMM_CTX_MAGIC;
+ INIT_WORK(&pQosContext->wmmAcSetupImplicitQos,
+ hdd_wmm_do_implicit_qos);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Scheduling work for AC %d, context %p",
+ __FUNCTION__, acType, pQosContext);
+
+ schedule_work(&pQosContext->wmmAcSetupImplicitQos);
+
+ // caller will need to wait until the work takes place and
+ // TSPEC negotiation completes
+ *pGranted = VOS_FALSE;
+ return VOS_STATUS_SUCCESS;
+}
+
+/**============================================================================
+ @brief hdd_wmm_assoc() - Function which will handle the housekeeping
+ required by WMM when association takes place
+
+ @param pAdapter : [in] pointer to adapter context
+ @param pRoamInfo: [in] pointer to roam information
+ @param eBssType : [in] type of BSS
+
+ @return : VOS_STATUS_SUCCESS if succssful
+ : other values if failure
+ ===========================================================================*/
+VOS_STATUS hdd_wmm_assoc( hdd_adapter_t* pAdapter,
+ tCsrRoamInfo *pRoamInfo,
+ eCsrRoamBssType eBssType )
+{
+ tANI_U8 uapsdMask;
+ VOS_STATUS status;
+
+ // when we associate we need to notify TL if it needs to enable
+ // UAPSD for any access categories
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered", __FUNCTION__);
+
+ if (pRoamInfo->fReassocReq)
+ {
+ // when we reassociate we should continue to use whatever
+ // parameters were previously established. if we are
+ // reassociating due to a U-APSD change for a particular
+ // Access Category, then the change will be communicated
+ // to HDD via the QoS callback associated with the given
+ // flow, and U-APSD parameters will be updated there
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Reassoc so no work, Exiting", __FUNCTION__);
+
+ return VOS_STATUS_SUCCESS;
+ }
+
+ // get the negotiated UAPSD Mask
+ uapsdMask = pRoamInfo->u.pConnectedProfile->modifyProfileFields.uapsd_mask;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: U-APSD mask is 0x%02x", __FUNCTION__, (int) uapsdMask);
+
+ if (uapsdMask & HDD_AC_VO)
+ {
+ status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ WLANTL_AC_VO,
+ 7,
+ 7,
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv,
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSuspIntv,
+ WLANTL_BI_DIR );
+
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
+ }
+
+ if (uapsdMask & HDD_AC_VI)
+ {
+ status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ WLANTL_AC_VI,
+ 5,
+ 5,
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv,
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSuspIntv,
+ WLANTL_BI_DIR );
+
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
+ }
+
+ if (uapsdMask & HDD_AC_BK)
+ {
+ status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ WLANTL_AC_BK,
+ 2,
+ 2,
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv,
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv,
+ WLANTL_BI_DIR );
+
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
+ }
+
+ if (uapsdMask & HDD_AC_BE)
+ {
+ status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ WLANTL_AC_BE,
+ 3,
+ 3,
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv,
+ (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSuspIntv,
+ WLANTL_BI_DIR );
+
+ VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Exiting", __FUNCTION__);
+
+ return VOS_STATUS_SUCCESS;
+}
+
+
+
+static const v_U8_t acmMaskBit[WLANTL_MAX_AC] =
+ {
+ 0x4, /* WLANTL_AC_BK */
+ 0x8, /* WLANTL_AC_BE */
+ 0x2, /* WLANTL_AC_VI */
+ 0x1 /* WLANTL_AC_VO */
+ };
+
+/**============================================================================
+ @brief hdd_wmm_connect() - Function which will handle the housekeeping
+ required by WMM when a connection is established
+
+ @param pAdapter : [in] pointer to adapter context
+ @param pRoamInfo: [in] pointer to roam information
+ @param eBssType : [in] type of BSS
+
+ @return : VOS_STATUS_SUCCESS if succssful
+ : other values if failure
+ ===========================================================================*/
+VOS_STATUS hdd_wmm_connect( hdd_adapter_t* pAdapter,
+ tCsrRoamInfo *pRoamInfo,
+ eCsrRoamBssType eBssType )
+{
+ int ac;
+ v_BOOL_t qap;
+ v_BOOL_t qosConnection;
+ v_U8_t acmMask;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered", __FUNCTION__);
+
+ if ((eCSR_BSS_TYPE_INFRASTRUCTURE == eBssType) &&
+ pRoamInfo &&
+ pRoamInfo->u.pConnectedProfile)
+ {
+ qap = pRoamInfo->u.pConnectedProfile->qap;
+ qosConnection = pRoamInfo->u.pConnectedProfile->qosConnection;
+ acmMask = pRoamInfo->u.pConnectedProfile->acm_mask;
+ }
+ else
+ {
+ qap = VOS_TRUE;
+ qosConnection = VOS_TRUE;
+ acmMask = 0x0;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: qap is %d, qosConnection is %d, acmMask is 0x%x",
+ __FUNCTION__, qap, qosConnection, acmMask);
+
+ pAdapter->hddWmmStatus.wmmQap = qap;
+ pAdapter->hddWmmStatus.wmmQosConnection = qosConnection;
+
+ for (ac = 0; ac < WLANTL_MAX_AC; ac++)
+ {
+ if (qap &&
+ qosConnection &&
+ (acmMask & acmMaskBit[ac]))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: ac %d on",
+ __FUNCTION__, ac);
+
+ // admission is required
+ pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired = VOS_TRUE;
+ pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = VOS_FALSE;
+ pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessGranted = VOS_FALSE;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: ac %d off",
+ __FUNCTION__, ac);
+ // admission is not required so access is allowed
+ pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired = VOS_FALSE;
+ pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = VOS_TRUE;
+ }
+
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Exiting", __FUNCTION__);
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**============================================================================
+ @brief hdd_wmm_get_uapsd_mask() - Function which will calculate the
+ initial value of the UAPSD mask based upon the device configuration
+
+ @param pAdapter : [in] pointer to adapter context
+ @param pUapsdMask: [in] pointer to where the UAPSD Mask is to be stored
+
+ @return : VOS_STATUS_SUCCESS if succssful
+ : other values if failure
+ ===========================================================================*/
+VOS_STATUS hdd_wmm_get_uapsd_mask( hdd_adapter_t* pAdapter,
+ tANI_U8 *pUapsdMask )
+{
+ tANI_U8 uapsdMask;
+
+ if (HDD_WMM_USER_MODE_NO_QOS == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
+ {
+ // no QOS then no UAPSD
+ uapsdMask = 0;
+ }
+ else
+ {
+ // start with the default mask
+ uapsdMask = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
+
+ // disable UAPSD for any ACs with a 0 Service Interval
+ if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv == 0 )
+ {
+ uapsdMask &= ~HDD_AC_VO;
+ }
+
+ if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv == 0 )
+ {
+ uapsdMask &= ~HDD_AC_VI;
+ }
+
+ if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv == 0 )
+ {
+ uapsdMask &= ~HDD_AC_BK;
+ }
+
+ if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv == 0 )
+ {
+ uapsdMask &= ~HDD_AC_BE;
+ }
+ }
+
+ // return calculated mask
+ *pUapsdMask = uapsdMask;
+ return VOS_STATUS_SUCCESS;
+}
+
+
+/**============================================================================
+ @brief hdd_wmm_is_active() - Function which will determine if WMM is
+ active on the current connection
+
+ @param pAdapter : [in] pointer to adapter context
+
+ @return : VOS_TRUE if WMM is enabled
+ : VOS_FALSE if WMM is not enabled
+ ===========================================================================*/
+v_BOOL_t hdd_wmm_is_active( hdd_adapter_t* pAdapter )
+{
+ if ((!pAdapter->hddWmmStatus.wmmQosConnection) ||
+ (!pAdapter->hddWmmStatus.wmmQap))
+ {
+ return VOS_FALSE;
+ }
+ else
+ {
+ return VOS_TRUE;
+ }
+}
+
+/**============================================================================
+ @brief hdd_wmm_addts() - Function which will add a traffic spec at the
+ request of an application
+
+ @param pAdapter : [in] pointer to adapter context
+ @param handle : [in] handle to uniquely identify a TS
+ @param pTspec : [in] pointer to the traffic spec
+
+ @return : HDD_WLAN_WMM_STATUS_*
+ ===========================================================================*/
+hdd_wlan_wmm_status_e hdd_wmm_addts( hdd_adapter_t* pAdapter,
+ v_U32_t handle,
+ sme_QosWmmTspecInfo* pTspec )
+{
+ hdd_wmm_qos_context_t *pQosContext;
+ hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS ;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ sme_QosStatusType smeStatus;
+#endif
+ v_BOOL_t found = VOS_FALSE;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered with handle 0x%x", __FUNCTION__, handle);
+
+ // see if a context already exists with the given handle
+ mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+ list_for_each_entry(pQosContext,
+ &pAdapter->hddWmmStatus.wmmContextList,
+ node)
+ {
+ if (pQosContext->handle == handle)
+ {
+ found = VOS_TRUE;
+ break;
+ }
+ }
+ mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+ if (found)
+ {
+ // record with that handle already exists
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Record already exists with handle 0x%x",
+ __FUNCTION__, handle);
+
+ /* Application is trying to modify some of the Tspec params. Allow it */
+ smeStatus = sme_QosModifyReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pTspec,
+ pQosContext->qosFlowId);
+
+ // need to check the return value and act appropriately
+ switch (smeStatus)
+ {
+ case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP:
+ status = HDD_WLAN_WMM_STATUS_MODIFY_PENDING;
+ break;
+ case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+ status = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD;
+ break;
+ case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY:
+ status = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING;
+ break;
+ case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP:
+ status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM;
+ break;
+ case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP:
+ status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
+ break;
+ case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
+ status = HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
+ break;
+ default:
+ // we didn't get back one of the SME_QOS_STATUS_MODIFY_* status codes
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: unexpected SME Status=%d\n", smeStatus );
+ VOS_ASSERT(0);
+ return HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
+ }
+
+ // we were successful, save the status
+ pQosContext->lastStatus = status;
+ return status;
+ }
+
+ pQosContext = kmalloc(sizeof(*pQosContext), GFP_KERNEL);
+ if (NULL == pQosContext)
+ {
+ // no memory for QoS context. Nothing we can do
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: Unable to allocate QoS context", __FUNCTION__);
+ return HDD_WLAN_WMM_STATUS_INTERNAL_FAILURE;
+ }
+
+ // we assume the tspec has already been validated by the caller
+
+ pQosContext->handle = handle;
+ pQosContext->acType = hddWmmUpToAcMap[pTspec->ts_info.up];
+ pQosContext->pAdapter = pAdapter;
+ pQosContext->qosFlowId = 0;
+ pQosContext->magic = HDD_WMM_CTX_MAGIC;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: Setting up QoS, context %p",
+ __FUNCTION__, pQosContext);
+
+ mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+ list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList);
+ mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ smeStatus = sme_QosSetupReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ pTspec,
+ hdd_wmm_sme_callback,
+ pQosContext,
+ pTspec->ts_info.up,
+ &pQosContext->qosFlowId);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+ "%s: sme_QosSetupReq returned %d flowid %d",
+ __FUNCTION__, smeStatus, pQosContext->qosFlowId);
+
+ // need to check the return value and act appropriately
+ switch (smeStatus)
+ {
+ case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
+ status = HDD_WLAN_WMM_STATUS_SETUP_PENDING;
+ break;
+ case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+ status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD;
+ break;
+ case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
+ status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING;
+ break;
+ case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
+ status = HDD_WLAN_WMM_STATUS_SETUP_PENDING;
+ break;
+ case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP:
+ hdd_wmm_free_context(pQosContext);
+ return HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+ case SME_QOS_STATUS_SETUP_FAILURE_RSP:
+ // we can't tell the difference between when a request fails because
+ // AP rejected it versus when SME encounterd an internal error
+ hdd_wmm_free_context(pQosContext);
+ return HDD_WLAN_WMM_STATUS_SETUP_FAILED;
+ case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
+ hdd_wmm_free_context(pQosContext);
+ return HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
+ default:
+ // we didn't get back one of the SME_QOS_STATUS_SETUP_* status codes
+ hdd_wmm_free_context(pQosContext);
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: unexpected SME Status=%d\n", smeStatus );
+ VOS_ASSERT(0);
+ return HDD_WLAN_WMM_STATUS_SETUP_FAILED;
+ }
+#endif
+
+ // we were successful, save the status
+ pQosContext->lastStatus = status;
+
+ return status;
+}
+
+/**============================================================================
+ @brief hdd_wmm_delts() - Function which will delete a traffic spec at the
+ request of an application
+
+ @param pAdapter : [in] pointer to adapter context
+ @param handle : [in] handle to uniquely identify a TS
+
+ @return : HDD_WLAN_WMM_STATUS_*
+ ===========================================================================*/
+hdd_wlan_wmm_status_e hdd_wmm_delts( hdd_adapter_t* pAdapter,
+ v_U32_t handle )
+{
+ hdd_wmm_qos_context_t *pQosContext;
+ v_BOOL_t found = VOS_FALSE;
+ WLANTL_ACEnumType acType = 0;
+ v_U32_t qosFlowId = 0;
+ hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS ;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ sme_QosStatusType smeStatus;
+#endif
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered with handle 0x%x", __FUNCTION__, handle);
+
+ // locate the context with the given handle
+ mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+ list_for_each_entry(pQosContext,
+ &pAdapter->hddWmmStatus.wmmContextList,
+ node)
+ {
+ if (pQosContext->handle == handle)
+ {
+ found = VOS_TRUE;
+ acType = pQosContext->acType;
+ qosFlowId = pQosContext->qosFlowId;
+ break;
+ }
+ }
+ mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+
+ if (VOS_FALSE == found)
+ {
+ // we didn't find the handle
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: handle 0x%x not found", __FUNCTION__, handle);
+ return HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
+ }
+
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: found handle 0x%x, flow %d, AC %d, context %p",
+ __FUNCTION__, handle, qosFlowId, acType, pQosContext);
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+ smeStatus = sme_QosReleaseReq( WLAN_HDD_GET_HAL_CTX(pAdapter), qosFlowId );
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: SME flow %d released, SME status %d",
+ __FUNCTION__, qosFlowId, smeStatus);
+
+ switch(smeStatus)
+ {
+ case SME_QOS_STATUS_RELEASE_SUCCESS_RSP:
+ // this flow is the only one on that AC, so go ahead and update
+ // our TSPEC state for the AC
+ pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcTspecValid = VOS_FALSE;
+
+ // need to tell TL to stop trigger timer, etc
+ hdd_wmm_disable_tl_uapsd(pQosContext);
+
+#ifdef FEATURE_WLAN_CCX
+ // disable the inactivity timer
+ hdd_wmm_disable_inactivity_timer(pQosContext);
+#endif
+ // we are done with this context
+ hdd_wmm_free_context(pQosContext);
+
+ // SME must not fire any more callbacks for this flow since the context
+ // is no longer valid
+
+ return HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS;
+
+ case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP:
+ // do nothing as we will get a response from SME
+ status = HDD_WLAN_WMM_STATUS_RELEASE_PENDING;
+ break;
+
+ case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP:
+ // nothing we can do with the existing flow except leave it
+ status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
+ break;
+
+ case SME_QOS_STATUS_RELEASE_FAILURE_RSP:
+ // nothing we can do with the existing flow except leave it
+ status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
+
+ default:
+ // we didn't get back one of the SME_QOS_STATUS_RELEASE_* status codes
+ VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+ "%s: unexpected SME Status=%d\n", smeStatus );
+ VOS_ASSERT(0);
+ status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
+ }
+
+#endif
+ pQosContext->lastStatus = status;
+ return status;
+}
+
+/**============================================================================
+ @brief hdd_wmm_checkts() - Function which will return the status of a traffic
+ spec at the request of an application
+
+ @param pAdapter : [in] pointer to adapter context
+ @param handle : [in] handle to uniquely identify a TS
+
+ @return : HDD_WLAN_WMM_STATUS_*
+ ===========================================================================*/
+hdd_wlan_wmm_status_e hdd_wmm_checkts( hdd_adapter_t* pAdapter,
+ v_U32_t handle )
+{
+ hdd_wmm_qos_context_t *pQosContext;
+ hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_LOST;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: Entered with handle 0x%x", __FUNCTION__, handle);
+
+ // locate the context with the given handle
+ mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+ list_for_each_entry(pQosContext,
+ &pAdapter->hddWmmStatus.wmmContextList,
+ node)
+ {
+ if (pQosContext->handle == handle)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+ "%s: found handle 0x%x, context %p",
+ __FUNCTION__, handle, pQosContext);
+
+ status = pQosContext->lastStatus;
+ break;
+ }
+ }
+ mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+ return status;
+}
diff --git a/CORE/HDD/src/wlan_hdd_wowl.c b/CORE/HDD/src/wlan_hdd_wowl.c
new file mode 100644
index 0000000..fa41a23
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_wowl.c
@@ -0,0 +1,394 @@
+/*
+ * 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 wlan_hdd_wowl.c
+ *
+ * Copyright (c) 2009 QUALCOMM Incorporated.
+ * All Rights Reserved.
+ * Qualcomm Confidential and Proprietary
+ *
+ * ==========================================================================*/
+
+/*----------------------------------------------------------------------------
+ * Include Files
+ * -------------------------------------------------------------------------*/
+
+#include <wlan_hdd_includes.h>
+#include <wlan_hdd_wowl.h>
+
+/*----------------------------------------------------------------------------
+ * Preprocessor Definitions and Constants
+ * -------------------------------------------------------------------------*/
+
+#define WOWL_PTRN_MAX_SIZE 128
+#define WOWL_PTRN_MASK_MAX_SIZE 16
+#define WOWL_MAX_PTRNS_ALLOWED 8
+#define WOWL_INTER_PTRN_TOKENIZER ';'
+#define WOWL_INTRA_PTRN_TOKENIZER ':'
+
+/*----------------------------------------------------------------------------
+ * Type Declarations
+ * -------------------------------------------------------------------------*/
+
+static struct hdd_context_s *pAdapterHandle = NULL;
+
+char *g_hdd_wowl_ptrns[WOWL_MAX_PTRNS_ALLOWED]; //Patterns 0-7
+
+static int parse_hex(unsigned char c)
+{
+ if (c >= '0' && c <= '9')
+ return c-'0';
+ if (c >= 'a' && c <= 'f')
+ return c-'a'+10;
+ if (c >= 'A' && c <= 'F')
+ return c-'A'+10;
+
+ return 0;
+}
+
+static inline int find_ptrn_len(const char* ptrn)
+{
+ int len = 0;
+ while (*ptrn != '\0' && *ptrn != WOWL_INTER_PTRN_TOKENIZER)
+ {
+ len++; ptrn++;
+ }
+ return len;
+}
+
+static void hdd_wowl_callback( void *pContext, eHalStatus halStatus )
+{
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Return code = (%ld)\n", __FUNCTION__, halStatus );
+}
+
+static void dump_hdd_wowl_ptrn(tSirWowlAddBcastPtrn *ptrn)
+{
+ int i;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ucPatetrnId = 0x%x", __func__,
+ ptrn->ucPatternId);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ucPatternByteOffset = 0x%x", __func__,
+ ptrn->ucPatternByteOffset);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ucPatternSize = 0x%x", __func__,
+ ptrn->ucPatternSize);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ucPatternMaskSize = 0x%x", __func__,
+ ptrn->ucPatternMaskSize);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Pattern: ", __func__);
+ for(i = 0; i<ptrn->ucPatternSize; i++)
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO," %02X", ptrn->ucPattern[i]);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: PatternMask: ", __func__);
+ for(i = 0; i<ptrn->ucPatternMaskSize; i++)
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%02X", ptrn->ucPatternMask[i]);
+}
+
+
+/**============================================================================
+ @brief hdd_add_wowl_ptrn() - Function which will add the WoWL pattern to be
+ used when PBM filtering is enabled
+
+ @param ptrn : [in] pointer to the pattern string to be added
+
+ @return : FALSE if any errors encountered
+ : TRUE otherwise
+ ===========================================================================*/
+v_BOOL_t hdd_add_wowl_ptrn (const char * ptrn)
+{
+ tSirWowlAddBcastPtrn localPattern;
+ int i, first_empty_slot, len, offset;
+ eHalStatus halStatus;
+ const char *temp;
+
+ len = find_ptrn_len(ptrn);
+
+ /* There has to have atleast 1 byte for each field (pattern size, mask size,
+ * pattern, mask) e.g. PP:QQ:RR:SS ==> 11 chars */
+ while ( len >= 11 )
+ {
+ first_empty_slot = -1;
+
+ // Find an empty slot to store the pattern
+ for (i=0; i<WOWL_MAX_PTRNS_ALLOWED; i++)
+ {
+ if(g_hdd_wowl_ptrns[i] == NULL) {
+ first_empty_slot = i;
+ break;
+ }
+ }
+
+ // Maximum number of patterns have been configured already
+ if(first_empty_slot == -1)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Cannot add anymore patterns. No free slot!", __FUNCTION__);
+ return VOS_FALSE;
+ }
+
+ // Detect duplicate pattern
+ for (i=0; i<WOWL_MAX_PTRNS_ALLOWED; i++)
+ {
+ if(g_hdd_wowl_ptrns[i] == NULL) continue;
+
+ if(!memcmp(ptrn, g_hdd_wowl_ptrns[i], len))
+ {
+ // Pattern Already configured, skip to next pattern
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Trying to add duplicate WoWL pattern. Skip it!");
+ ptrn += len;
+ goto next_ptrn;
+ }
+ }
+
+ //Validate the pattern
+ if(ptrn[2] != WOWL_INTRA_PTRN_TOKENIZER ||
+ ptrn[5] != WOWL_INTRA_PTRN_TOKENIZER)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Malformed pattern string. Skip!\n", __FUNCTION__);
+ ptrn += len;
+ goto next_ptrn;
+ }
+
+ // Extract the pattern size
+ localPattern.ucPatternSize =
+ ( parse_hex( ptrn[0] ) * 0x10 ) + parse_hex( ptrn[1] );
+
+ // Extract the pattern mask size
+ localPattern.ucPatternMaskSize =
+ ( parse_hex( ptrn[3] ) * 0x10 ) + parse_hex( ptrn[4] );
+
+ if(localPattern.ucPatternSize > WOWL_PTRN_MAX_SIZE ||
+ localPattern.ucPatternMaskSize > WOWL_PTRN_MASK_MAX_SIZE)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid length specified. Skip!\n", __FUNCTION__);
+ ptrn += len;
+ goto next_ptrn;
+ }
+
+ //compute the offset of tokenizer after the pattern
+ offset = 5 + 2*localPattern.ucPatternSize + 1;
+ if(offset >= len || ptrn[offset] != WOWL_INTRA_PTRN_TOKENIZER)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Malformed pattern string..skip!\n", __FUNCTION__);
+ ptrn += len;
+ goto next_ptrn;
+ }
+
+ //compute the end of pattern sring
+ offset = offset + 2*localPattern.ucPatternMaskSize;
+ if(offset+1 != len) //offset begins with 0
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Malformed pattern string...skip!\n", __FUNCTION__);
+ ptrn += len;
+ goto next_ptrn;
+ }
+
+ temp = ptrn;
+
+ // Now advance to where pattern begins
+ ptrn += 6;
+
+ // Extract the pattern
+ for(i=0; i < localPattern.ucPatternSize; i++)
+ {
+ localPattern.ucPattern[i] =
+ (parse_hex( ptrn[0] ) * 0x10 ) + parse_hex( ptrn[1] );
+ ptrn += 2; //skip to next byte
+ }
+
+ ptrn++; // Skip over the ':' seperator after the pattern
+
+ // Extract the pattern Mask
+ for(i=0; i < localPattern.ucPatternMaskSize; i++)
+ {
+ localPattern.ucPatternMask[i] =
+ (parse_hex( ptrn[0] ) * 0x10 ) + parse_hex( ptrn[1] );
+ ptrn += 2; //skip to next byte
+ }
+
+ //All is good. Store the pattern locally
+ g_hdd_wowl_ptrns[first_empty_slot] = (char*) kmalloc(len+1, GFP_KERNEL);
+ if(g_hdd_wowl_ptrns[first_empty_slot] == NULL)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: kmalloc failure", __FUNCTION__);
+ return VOS_FALSE;
+ }
+
+ memcpy(g_hdd_wowl_ptrns[first_empty_slot], temp, len);
+ g_hdd_wowl_ptrns[first_empty_slot][len] = '\0';
+ localPattern.ucPatternId = first_empty_slot;
+ localPattern.ucPatternByteOffset = 0;
+
+ // Register the pattern downstream
+ halStatus = sme_WowlAddBcastPattern( pAdapterHandle->hHal, &localPattern );
+ if ( !HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ // Add failed, so invalidate the local storage
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "sme_WowlAddBcastPattern failed with error code (%ld)", halStatus );
+ kfree(g_hdd_wowl_ptrns[first_empty_slot]);
+ g_hdd_wowl_ptrns[first_empty_slot] = NULL;
+ }
+
+ dump_hdd_wowl_ptrn(&localPattern);
+
+ next_ptrn:
+ if (*ptrn == WOWL_INTER_PTRN_TOKENIZER)
+ {
+ ptrn += 1; // move past the tokenizer
+ len = find_ptrn_len(ptrn);
+ continue;
+ }
+ else
+ break;
+ }
+
+ return VOS_TRUE;
+}
+
+/**============================================================================
+ @brief hdd_del_wowl_ptrn() - Function which will remove a WoWL pattern
+
+ @param ptrn : [in] pointer to the pattern string to be removed
+
+ @return : FALSE if any errors encountered
+ : TRUE otherwise
+ ===========================================================================*/
+v_BOOL_t hdd_del_wowl_ptrn (const char * ptrn)
+{
+ tSirWowlDelBcastPtrn delPattern;
+ unsigned char id;
+ v_BOOL_t patternFound = VOS_FALSE;
+ eHalStatus halStatus;
+
+ // Detect pattern
+ for (id=0; id<WOWL_MAX_PTRNS_ALLOWED && g_hdd_wowl_ptrns[id] != NULL; id++)
+ {
+ if(!strcmp(ptrn, g_hdd_wowl_ptrns[id]))
+ {
+ patternFound = VOS_TRUE;
+ break;
+ }
+ }
+
+ // If pattern present, remove it from downstream
+ if(patternFound)
+ {
+ delPattern.ucPatternId = id;
+ halStatus = sme_WowlDelBcastPattern( pAdapterHandle->hHal, &delPattern );
+ if ( HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ // Remove from local storage as well
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Deleted pattern with id %d [%s]", id, g_hdd_wowl_ptrns[id]);
+
+ kfree(g_hdd_wowl_ptrns[id]);
+ g_hdd_wowl_ptrns[id] = NULL;
+ return VOS_TRUE;
+ }
+ }
+ return VOS_FALSE;
+}
+
+/**============================================================================
+ @brief hdd_enter_wowl() - Function which will enable WoWL. Atleast one
+ of MP and PBM must be enabled
+
+ @param enable_mp : [in] Whether to enable magic packet WoWL mode
+ @param enable_pbm : [in] Whether to enable pattern byte matching WoWL mode
+
+ @return : FALSE if any errors encountered
+ : TRUE otherwise
+ ===========================================================================*/
+v_BOOL_t hdd_enter_wowl (hdd_adapter_t *pAdapter, v_BOOL_t enable_mp, v_BOOL_t enable_pbm)
+{
+ tSirSmeWowlEnterParams wowParams;
+ eHalStatus halStatus;
+
+ wowParams.ucPatternFilteringEnable = enable_pbm;
+ wowParams.ucMagicPktEnable = enable_mp;
+ if(enable_mp)
+ {
+ vos_copy_macaddr( (v_MACADDR_t *)&(wowParams.magicPtrn),
+ &(pAdapter->macAddressCurrent) );
+ }
+
+ // Request to put Libra into WoWL
+ halStatus = sme_EnterWowl( pAdapterHandle->hHal, hdd_wowl_callback,
+ pAdapterHandle, &wowParams );
+
+ if ( !HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ if ( eHAL_STATUS_PMC_PENDING != halStatus )
+ {
+ // We failed to enter WoWL
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "sme_EnterWowl failed with error code (%ld)", halStatus );
+ return VOS_FALSE;
+ }
+ }
+ return VOS_TRUE;
+}
+
+/**============================================================================
+ @brief hdd_exit_wowl() - Function which will disable WoWL
+
+ @return : FALSE if any errors encountered
+ : TRUE otherwise
+ ===========================================================================*/
+v_BOOL_t hdd_exit_wowl (void)
+{
+ eHalStatus halStatus;
+
+ halStatus = sme_ExitWowl( pAdapterHandle->hHal );
+ if ( !HAL_STATUS_SUCCESS( halStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "sme_ExitWowl failed with error code (%ld)", halStatus );
+ return VOS_FALSE;
+ }
+
+ return VOS_TRUE;
+}
+
+/**============================================================================
+ @brief hdd_init_wowl() - Init function which will initialize the WoWL module
+ and perform any required intial configuration
+
+ @return : FALSE if any errors encountered
+ : TRUE otherwise
+ ===========================================================================*/
+v_BOOL_t hdd_init_wowl (void *pAdapter)
+{
+ pAdapterHandle = (struct hdd_context_s*)pAdapter;
+
+ memset(g_hdd_wowl_ptrns, 0, sizeof(g_hdd_wowl_ptrns));
+
+ //Add any statically configured patterns
+ hdd_add_wowl_ptrn(pAdapterHandle->cfg_ini->wowlPattern);
+
+ return VOS_TRUE;
+}