wlan: Add QCA copyright information in Tdls files newly added.
Update TDLS files with QCA copyright information.
Change-Id: I6c3f5eb31af192f439a9141626c43e64d2af02da
CR-Fixed: 426223
diff --git a/CORE/MAC/src/pe/lim/limProcessTdls.c b/CORE/MAC/src/pe/lim/limProcessTdls.c
new file mode 100644
index 0000000..cc2865f
--- /dev/null
+++ b/CORE/MAC/src/pe/lim/limProcessTdls.c
@@ -0,0 +1,4581 @@
+/*
+* Copyright (c) 2012 Qualcomm Atheros, Inc.
+* All Rights Reserved.
+* Qualcomm Atheros Confidential and Proprietary.
+*/
+
+/*===========================================================================
+
+ limProcessTdls.c
+
+ OVERVIEW:
+
+ DEPENDENCIES:
+
+ Are listed for each API below.
+
+
+ Copyright (c) 2010 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/05/2010 Ashwani Initial Creation, added TDLS action frame functionality,
+ TDLS message exchange with SME..etc..
+
+===========================================================================*/
+
+
+/**
+ * \file limProcessTdls.c
+ *
+ * \brief Code for preparing,processing and sending 802.11z action frames
+ *
+ */
+
+#ifdef FEATURE_WLAN_TDLS
+
+#include "sirApi.h"
+#include "aniGlobal.h"
+#include "sirMacProtDef.h"
+#include "cfgApi.h"
+#include "utilsApi.h"
+#include "limTypes.h"
+#include "limUtils.h"
+#include "limSecurityUtils.h"
+#include "dot11f.h"
+#include "limStaHashApi.h"
+#include "schApi.h"
+#include "limSendMessages.h"
+#include "utilsParser.h"
+#include "limAssocUtils.h"
+#include "dphHashTable.h"
+#include "wlan_qct_wda.h"
+
+
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+/* forword declarations */
+static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
+ tSirTdlsPeerInfo *peerInfo, tpPESession psessionEntry) ;
+static eHalStatus limSendSmeTdlsLinkSetupInd(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, tANI_U8 status);
+static eHalStatus limSendSmeTdlsDelPeerInd(tpAniSirGlobal pMac,
+ tANI_U8 sessionId, tDphHashNode *pStaDs, tANI_U8 status) ;
+static tSirTdlsPeerInfo *limTdlsFindDisPeerByState(tpAniSirGlobal pMac,
+ tANI_U8 state);
+static tANI_U8 limTdlsFindSetupPeerByState(tpAniSirGlobal pMac, tANI_U8 state,
+ tLimTdlsLinkSetupPeer **setupPeer) ;
+static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peer_mac);
+
+static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peer_mac);
+static tpDphHashNode limTdlsDelSta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
+ tpPESession psessionEntry) ;
+
+#endif
+static tSirRetStatus limTdlsSetupAddSta(tpAniSirGlobal pMac, tSirMacAddr,
+ tLimTdlsLinkSetupPeer *setupPeer, tpPESession psessionEntry) ;
+void PopulateDot11fLinkIden(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ tDot11fIELinkIdentifier *linkIden,
+ tSirMacAddr peerMac , tANI_U8 reqType) ;
+void PopulateDot11fTdlsExtCapability(tpAniSirGlobal pMac,
+ tDot11fIEExtCap *extCapability) ;
+/*
+ * TDLS data frames will go out/come in as non-qos data.
+ * so, eth_890d_header will be aligned access..
+ */
+static const tANI_U8 eth_890d_header[] =
+{
+ 0xaa, 0xaa, 0x03, 0x00,
+ 0x00, 0x00, 0x89, 0x0d,
+} ;
+
+/*
+ * type of links used in TDLS
+ */
+enum tdlsLinks
+{
+ TDLS_LINK_AP,
+ TDLS_LINK_DIRECT
+} eTdlsLink ;
+
+/*
+ * node status in node searching
+ */
+enum tdlsLinkNodeStatus
+{
+ TDLS_NODE_NOT_FOUND,
+ TDLS_NODE_FOUND
+} eTdlsLinkNodeStatus ;
+
+
+enum tdlsReqType
+{
+ TDLS_INITIATOR,
+ TDLS_RESPONDER
+} eTdlsReqType ;
+
+typedef enum tdlsLinkSetupStatus
+{
+ TDLS_SETUP_STATUS_SUCCESS = 0,
+ TDLS_SETUP_STATUS_FAILURE = 37
+}etdlsLinkSetupStatus ;
+
+/* some local defines */
+#define LINK_IDEN_BSSID_OFFSET (0)
+#define PEER_MAC_OFFSET (12)
+#define STA_MAC_OFFSET (6)
+#define LINK_IDEN_ELE_ID (101)
+//#define LINK_IDEN_LENGTH (18)
+#define LINK_IDEN_ADDR_OFFSET(x) (&x.LinkIdentifier)
+#define PTI_LINK_IDEN_OFFSET (5)
+#define PTI_BUF_STATUS_OFFSET (25)
+
+/* TODO, Move this parameters to configuration */
+#define PEER_PSM_SUPPORT (0)
+#define PEER_BUFFER_STA_SUPPORT (1)
+#define CH_SWITCH_SUPPORT (0)
+#define TDLS_SUPPORT (1)
+#define TDLS_PROHIBITED (0)
+#define TDLS_CH_SWITCH_PROHIBITED (1)
+
+#ifdef LIM_DEBUG_TDLS
+#define TDLS_CASE_RETURN_STRING(x) case (x): return( ((const tANI_U8*)#x) + 8); /* 8 = remove redundant SIR_MAC_ */
+
+#ifdef FEATURE_WLAN_TDLS
+#define WNI_CFG_TDLS_DISCOVERY_RSP_WAIT (100)
+#define WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT (800)
+#define WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT (200)
+#endif
+
+const tANI_U8* limTraceTdlsActionString( tANI_U8 tdlsActionCode )
+{
+ switch( tdlsActionCode )
+ {
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_REQ);
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_RSP);
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_CNF);
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_TEARDOWN);
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_IND);
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_REQ);
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_RSP);
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_RSP);
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_REQ);
+ TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_RSP);
+ }
+ return (const tANI_U8*)"UNKNOWN";
+}
+#endif
+#if 0
+static void printMacAddr(tSirMacAddr macAddr)
+{
+ int i = 0 ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, (" Mac Addr: "));
+
+ for(i = 0 ; i < 6; i++)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ (" %02x "), macAddr[i]);
+ }
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("\n"));
+ return ;
+}
+#endif
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+/*
+ * initialize TDLS setup list and related data structures.
+ */
+void limInitTdlsData(tpAniSirGlobal pMac, tpPESession sessionEntry)
+{
+ pMac->lim.gLimTdlsDisResultList = NULL ;
+ pMac->lim.gLimTdlsDisStaCount = 0 ;
+ palZeroMemory(pMac->hHdd, &pMac->lim.gLimTdlsDisReq,
+ sizeof(tSirTdlsDisReq));
+ palZeroMemory(pMac->hHdd, &pMac->lim.gLimTdlsLinkSetupInfo,
+ sizeof(tLimTdlsLinkSetupInfo));
+ pMac->lim.gAddStaDisRspWait = 0 ;
+
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+ /* when reassociated, negative behavior will not be kept */
+ /* you have to explicitly enable negative behavior per (re)association */
+ pMac->lim.gLimTdlsNegativeBehavior = 0;
+#endif
+ limInitAIDpool(pMac, sessionEntry) ;
+
+ return ;
+}
+#endif
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+void limTdlsSetNegativeBehavior(tpAniSirGlobal pMac, tANI_U8 value, tANI_BOOLEAN on)
+{
+ if(on) {
+ if(value == 255)
+ pMac->lim.gLimTdlsNegativeBehavior = 0XFFFFFFFF;
+ else
+ pMac->lim.gLimTdlsNegativeBehavior |= (1 << (value-1));
+ }
+ else {
+ if(value == 255)
+ pMac->lim.gLimTdlsNegativeBehavior = 0;
+ else
+ pMac->lim.gLimTdlsNegativeBehavior &= ~(1 << (value-1));
+ }
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("%d %d -> gLimTdlsNegativeBehavior= 0x%lx\n"), \
+ value, on, pMac->lim.gLimTdlsNegativeBehavior));
+}
+#endif
+#if 0
+/*
+ * This function is used for creating TDLS public Action frame to
+ * transmit on Direct link
+ */
+static void limPreparesActionFrameHdr(tpAniSirGlobal pMac, tANI_U8 *pFrame,
+ tANI_U8 type, tANI_U8 subType,
+ tANI_U8 *link_iden )
+{
+ tpSirMacMgmtHdr pMacHdr ;
+ tANI_U8 *bssid = link_iden ;
+#if 0
+ tANI_U8 *staMac = (tANI_U8 *)(bssid + sizeof(tSirMacAddr)) ;
+ tANI_U8 *peerMac = (tANI_U8 *) (staMac + sizeof(tSirMacAddr)) ;
+#else
+ tANI_U8 *peerMac = (tANI_U8 *) (bssid + sizeof(tSirMacAddr)) ;
+ tANI_U8 *staMac = (tANI_U8 *)(peerMac + sizeof(tSirMacAddr)) ;
+#endif
+ tANI_U8 toDs = ANI_TXDIR_IBSS ;
+
+ pMacHdr = (tpSirMacMgmtHdr) (pFrame);
+
+ /*
+ * prepare 802.11 header
+ */
+ pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
+ pMacHdr->fc.type = type ;
+ pMacHdr->fc.subType = subType ;
+ /*
+ * TL is not setting up below fields, so we are doing it here
+ */
+ pMacHdr->fc.toDS = toDs ;
+ pMacHdr->fc.powerMgmt = 0 ;
+
+
+ palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->da, peerMac,
+ sizeof( tSirMacAddr ));
+ palCopyMemory( pMac->hHdd,
+ (tANI_U8 *) pMacHdr->sa,
+ staMac, sizeof( tSirMacAddr ));
+
+ palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->bssId,
+ bssid, sizeof( tSirMacAddr ));
+
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS action frame\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n"), \
+ pMacHdr->da[0], pMacHdr->da[1], pMacHdr->da[2], pMacHdr->da[3], pMacHdr->da[4], pMacHdr->da[5], \
+ pMacHdr->sa[0], pMacHdr->sa[1], pMacHdr->sa[2], pMacHdr->sa[3], pMacHdr->sa[4], pMacHdr->sa[5], \
+ pMacHdr->bssId[0], pMacHdr->bssId[1], pMacHdr->bssId[2], \
+ pMacHdr->bssId[3], pMacHdr->bssId[4], pMacHdr->bssId[5]));
+
+ return ;
+}
+#endif
+/*
+ * prepare TDLS frame header, it includes
+ * | | | |
+ * |802.11 header|RFC1042 header|TDLS_PYLOAD_TYPE|PAYLOAD
+ * | | | |
+ */
+static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame,
+ tDot11fIELinkIdentifier *link_iden, tANI_U8 tdlsLinkType, tANI_U8 reqType, tpPESession psessionEntry )
+{
+ tpSirMacMgmtHdr pMacHdr ;
+ tANI_U32 header_offset = 0 ;
+ tANI_U8 *addr1 = NULL ;
+ tANI_U8 *addr3 = NULL ;
+ tANI_U8 toDs = (tdlsLinkType == TDLS_LINK_AP)
+ ? ANI_TXDIR_TODS :ANI_TXDIR_IBSS ;
+ tANI_U8 *peerMac = (reqType == TDLS_INITIATOR)
+ ? link_iden->RespStaAddr : link_iden->InitStaAddr;
+ tANI_U8 *staMac = (reqType == TDLS_INITIATOR)
+ ? link_iden->InitStaAddr : link_iden->RespStaAddr;
+
+ pMacHdr = (tpSirMacMgmtHdr) (pFrame);
+
+ /*
+ * if TDLS frame goes through the AP link, it follows normal address
+ * pattern, if TDLS frame goes thorugh the direct link, then
+ * A1--> Peer STA addr, A2-->Self STA address, A3--> BSSID
+ */
+ (tdlsLinkType == TDLS_LINK_AP) ? ((addr1 = (link_iden->bssid)),
+ (addr3 = (peerMac)))
+ : ((addr1 = (peerMac)),
+ (addr3 = (link_iden->bssid))) ;
+ /*
+ * prepare 802.11 header
+ */
+ pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
+ pMacHdr->fc.type = SIR_MAC_DATA_FRAME ;
+ pMacHdr->fc.subType = SIR_MAC_DATA_DATA ;
+ /*
+ * TL is not setting up below fields, so we are doing it here
+ */
+ pMacHdr->fc.toDS = toDs ;
+ pMacHdr->fc.powerMgmt = 0 ;
+ pMacHdr->fc.wep = (psessionEntry->encryptType == eSIR_ED_NONE)? 0 : 1;
+
+
+ palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->da, (tANI_U8 *)addr1,
+ sizeof( tSirMacAddr ));
+ palCopyMemory( pMac->hHdd,
+ (tANI_U8 *) pMacHdr->sa,
+ (tANI_U8 *) staMac,
+ sizeof( tSirMacAddr ));
+
+ palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->bssId,
+ (tANI_U8 *) (addr3), sizeof( tSirMacAddr ));
+
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS frame header to %s\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n"), \
+ (tdlsLinkType == TDLS_LINK_AP) ? "AP" : "TD", \
+ pMacHdr->da[0], pMacHdr->da[1], pMacHdr->da[2], pMacHdr->da[3], pMacHdr->da[4], pMacHdr->da[5], \
+ pMacHdr->sa[0], pMacHdr->sa[1], pMacHdr->sa[2], pMacHdr->sa[3], pMacHdr->sa[4], pMacHdr->sa[5], \
+ pMacHdr->bssId[0], pMacHdr->bssId[1], pMacHdr->bssId[2], \
+ pMacHdr->bssId[3], pMacHdr->bssId[4], pMacHdr->bssId[5]));
+
+ //printMacAddr(pMacHdr->bssId) ;
+ //printMacAddr(pMacHdr->sa) ;
+ //printMacAddr(pMacHdr->da) ;
+
+ header_offset += sizeof(tSirMacMgmtHdr) ;
+ /*
+ * Now form RFC1042 header
+ */
+ palCopyMemory(pMac->hHdd, (tANI_U8 *)(pFrame + header_offset),
+ (tANI_U8 *)eth_890d_header , sizeof(eth_890d_header)) ;
+
+ header_offset += sizeof(eth_890d_header) ;
+
+ /* add payload type as TDLS */
+ *(pFrame + header_offset) = PAYLOAD_TYPE_TDLS ;
+
+ return(header_offset += PAYLOAD_TYPE_TDLS_SIZE) ;
+}
+
+/*
+ * This function can be used for bacst or unicast discovery request
+ * We are not differentiating it here, it will all depnds on peer MAC address,
+ */
+tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac,
+ tANI_U8 dialog, tpPESession psessionEntry)
+{
+ tDot11fTDLSDisReq tdlsDisReq ;
+ tANI_U32 status = 0 ;
+ tANI_U32 nPayload = 0 ;
+ tANI_U32 size = 0 ;
+ tANI_U32 nBytes = 0 ;
+ tANI_U32 header_offset = 0 ;
+ tANI_U8 *pFrame;
+ void *pPacket;
+ eHalStatus halstatus;
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11fPackProbeRequest' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsDisReq,
+ sizeof( tDot11fTDLSDisReq ) );
+
+ /*
+ * setup Fixed fields,
+ */
+ tdlsDisReq.Category.category = SIR_MAC_ACTION_TDLS ;
+ tdlsDisReq.Action.action = SIR_MAC_TDLS_DIS_REQ ;
+ tdlsDisReq.DialogToken.token = dialog ;
+
+
+ size = sizeof(tSirMacAddr) ;
+
+ PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsDisReq.LinkIdentifier,
+ peer_mac, TDLS_INITIATOR) ;
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11fGetPackedTDLSDisReqSize( pMac, &tdlsDisReq, &nPayload);
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a discovery Request (0x%08x).\n"), status );
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof( tDot11fTDLSDisReq );
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while calculating"
+ "the packed size for a discovery Request ("
+ "0x%08x).\n"), status );
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+
+ nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ + sizeof( eth_890d_header )
+ + PAYLOAD_TYPE_TDLS_SIZE ;
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+
+ halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( tANI_U16 )nBytes, ( void** ) &pFrame,
+ ( void** ) &pPacket );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
+ "Discovery Request.\n"), nBytes );
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ palZeroMemory( pMac->hHdd, pFrame, nBytes );
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+
+ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET(tdlsDisReq), TDLS_LINK_AP, TDLS_INITIATOR, psessionEntry) ;
+
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+ if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_DSCV_REQ)
+ {
+ tdlsDisReq.LinkIdentifier.bssid[4] = 0xde;
+ tdlsDisReq.LinkIdentifier.bssid[5] = 0xad;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Req\n"), \
+ tdlsDisReq.LinkIdentifier.bssid[0],
+ tdlsDisReq.LinkIdentifier.bssid[1],
+ tdlsDisReq.LinkIdentifier.bssid[2],
+ tdlsDisReq.LinkIdentifier.bssid[3],
+ tdlsDisReq.LinkIdentifier.bssid[4],
+ tdlsDisReq.LinkIdentifier.bssid[5]);
+ }
+#endif
+ status = dot11fPackTDLSDisReq( pMac, &tdlsDisReq, pFrame
+ + header_offset, nPayload, &nPayload );
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
+ (0x%08x).\n"), status );
+ palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( void* ) pFrame, ( void* ) pPacket );
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
+ "Discovery Request (0x%08x).\n") );
+ }
+
+
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
+ SIR_MAC_TDLS_DIS_REQ, limTraceTdlsActionString(SIR_MAC_TDLS_DIS_REQ) ));
+
+ halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
+ HAL_TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ 7,
+ limTxComplete, pFrame, 0 );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
+ return eSIR_FAILURE;
+
+ }
+
+ return eSIR_SUCCESS;
+
+}
+
+/*
+ * Once Discovery response is sent successfully (or failure) on air, now send
+ * response to PE and send del STA to HAL.
+ */
+eHalStatus limTdlsDisRspTxComplete(tpAniSirGlobal pMac,
+ tANI_U32 txCompleteSuccess)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS ;
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+ tpDphHashNode pStaDs = NULL ;
+ tSirTdlsPeerInfo *peerInfo = 0 ;
+
+ /* find peer by looking into the list by expected state */
+ peerInfo = limTdlsFindDisPeerByState(pMac, TDLS_DIS_RSP_SENT_WAIT_STATE) ;
+
+ if(NULL == peerInfo)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("DisRspTxComplete: No TDLS state machine waits for this event\n"));
+ VOS_ASSERT(0) ;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ peerInfo->tdlsPeerState = TDLS_DIS_RSP_SENT_DONE_STATE ;
+
+ if(peerInfo->delStaNeeded)
+ {
+ tpPESession psessionEntry;
+
+ peerInfo->delStaNeeded = false ;
+ psessionEntry = peFindSessionBySessionId (pMac, peerInfo->sessionId);
+
+ if(NULL == psessionEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("DisRspTxComplete: sessionID %d is not found\n"), peerInfo->sessionId);
+ return eHAL_STATUS_FAILURE;
+ }
+ /* send del STA to remove context for this TDLS STA */
+ pStaDs = limTdlsDelSta(pMac, peerInfo->peerMac, psessionEntry) ;
+
+ /* now send indication to SME-->HDD->TL to remove STA from TL */
+ if(pStaDs)
+ {
+ limSendSmeTdlsDelPeerInd(pMac, psessionEntry->smeSessionId,
+ pStaDs, eSIR_SUCCESS) ;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("DisRspTxComplete: staDs not found for %02x:%02x:%02x:%02x:%02x:%02x\n"),
+ (peerInfo)->peerMac[0],
+ (peerInfo)->peerMac[1],
+ (peerInfo)->peerMac[2],
+ (peerInfo)->peerMac[3],
+ (peerInfo)->peerMac[4],
+ (peerInfo)->peerMac[5]) ;
+ VOS_ASSERT(0) ;
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+
+ if(!txCompleteSuccess)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TX complete failure for Dis RSP"));
+ limSendSmeTdlsDisRsp(pMac, eSIR_FAILURE,
+ eWNI_SME_TDLS_DISCOVERY_START_IND) ;
+ status = eHAL_STATUS_FAILURE;
+ }
+ else
+ {
+ limSendSmeTdlsDisRsp(pMac, eSIR_SUCCESS,
+ eWNI_SME_TDLS_DISCOVERY_START_IND) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("TX complete Success for Dis RSP"));
+ status = eHAL_STATUS_SUCCESS ;
+ }
+ //pMac->hal.pCBackFnTxComp = NULL ;
+#endif
+ return status ;
+
+}
+/*
+ * Once setup CNF is sent successfully (or failure) on air, now send
+ * response to PE and send del STA to HAL.
+ */
+eHalStatus limTdlsSetupCnfTxComplete(tpAniSirGlobal pMac,
+ tANI_U32 txCompleteSuccess)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS ;
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+ tLimTdlsLinkSetupPeer *peerInfo = 0 ;
+ /* find peer by looking into the list by expected state */
+ limTdlsFindSetupPeerByState(pMac,
+ TDLS_LINK_SETUP_RSP_WAIT_STATE, &peerInfo) ;
+
+ if(NULL == peerInfo)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("limTdlsSetupCnfTxComplete: No TDLS state machine waits for this event\n"));
+ VOS_ASSERT(0) ;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ (peerInfo)->tdls_prev_link_state = (peerInfo)->tdls_link_state ;
+ (peerInfo)->tdls_link_state = TDLS_LINK_SETUP_DONE_STATE ;
+
+ if(!txCompleteSuccess)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TX complete Failure for setup CNF"));
+ limSendSmeTdlsLinkStartRsp(pMac, eSIR_FAILURE, (peerInfo)->peerMac,
+ eWNI_SME_TDLS_LINK_START_RSP) ;
+ status = eHAL_STATUS_FAILURE;
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("RSP-->SME peer MAC = %02x,%02x,%02x,%02x,%02x,%02x\n"),
+ (peerInfo)->peerMac[0],
+ (peerInfo)->peerMac[1],
+ (peerInfo)->peerMac[2],
+ (peerInfo)->peerMac[3],
+ (peerInfo)->peerMac[4],
+ (peerInfo)->peerMac[5]) ;
+
+ limSendSmeTdlsLinkStartRsp(pMac, eSIR_SUCCESS, (peerInfo)->peerMac,
+ eWNI_SME_TDLS_LINK_START_RSP) ;
+
+ /* tdls_hklee: prepare PTI template and send it to HAL */
+ limTdlsLinkEstablish(pMac, (peerInfo)->peerMac);
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("TX complete Success for setup CNF"));
+ status = eHAL_STATUS_SUCCESS ;
+ }
+ //pMac->hal.pCBackFnTxComp = NULL ;
+#endif
+ return status ;
+
+}
+
+/*
+ * Tx Complete for Teardown frame
+ */
+eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac,
+ tANI_U32 txCompleteSuccess)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS ;
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+ tpDphHashNode pStaDs = NULL ;
+ tLimTdlsLinkSetupPeer *peerInfo = 0 ;
+ tpPESession psessionEntry = NULL ;
+ //tANI_U16 msgType = 0 ;
+
+ //tSirMacAddr peerMac = {0} ;
+ /* find peer by looking into the list by expected state */
+ limTdlsFindSetupPeerByState(pMac,
+ TDLS_LINK_TEARDOWN_START_STATE, &peerInfo) ;
+
+ if(NULL == peerInfo)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("limTdlsTeardownTxComplete: No TDLS state machine waits for this event\n"));
+ VOS_ASSERT(0) ;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("teardown peer Mac = %02x,%02x,%02x,%02x,%02x,%02x\n"),
+ (peerInfo)->peerMac[0] ,
+ (peerInfo)->peerMac[1] ,
+ (peerInfo)->peerMac[2] ,
+ (peerInfo)->peerMac[3] ,
+ (peerInfo)->peerMac[4] ,
+ (peerInfo)->peerMac[5] ) ;
+
+
+ //pMac->hal.pCBackFnTxComp = NULL ;
+
+ psessionEntry = peFindSessionBySessionId(pMac, (peerInfo)->tdls_sessionId);
+
+ if(NULL == psessionEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("limTdlsTeardownTxComplete: sessionID %d is not found\n"), (peerInfo)->tdls_sessionId);
+ VOS_ASSERT(0) ;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ if(!txCompleteSuccess)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TX complete failure for Teardown \n")) ;
+
+ /*
+ * we should be sending Teradown to AP with status code
+ * eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE, we are not worried if
+ * that is delivered or not, any way we removing this peer STA from our
+ * list
+ */
+ if(NULL != psessionEntry)
+ {
+ limSendTdlsTeardownFrame(pMac, (peerInfo)->peerMac,
+ eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE, psessionEntry, NULL, 0) ;
+ }
+ }
+
+ if(TDLS_LINK_SETUP_WAIT_STATE != (peerInfo)->tdls_prev_link_state)
+ {
+ (peerInfo)->tdls_prev_link_state = (peerInfo)->tdls_link_state ;
+ (peerInfo)->tdls_link_state = TDLS_LINK_TEARDOWN_DONE_STATE ;
+ /* send del STA to remove context for this TDLS STA */
+ if(NULL != psessionEntry)
+ {
+ /* tdls_hklee: send message to HAL before it is deleted */
+ limTdlsLinkTeardown(pMac, (peerInfo)->peerMac) ;
+
+ pStaDs = limTdlsDelSta(pMac, (peerInfo)->peerMac, psessionEntry) ;
+ }
+
+ /* now send indication to SME-->HDD->TL to remove STA from TL */
+ if(!pStaDs)
+ {
+ VOS_ASSERT(0) ;
+ return eSIR_FAILURE ;
+ }
+ limSendSmeTdlsDelPeerInd(pMac, psessionEntry->smeSessionId,
+ pStaDs, eSIR_SUCCESS) ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("TX complete SUCCESS for Teardown\n")) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Prev State = %d\n"), (peerInfo)->tdls_prev_link_state) ;
+ limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (peerInfo)->peerMac,
+ eWNI_SME_TDLS_TEARDOWN_RSP) ;
+ /* Delete Peer for Link Peer List */
+ limTdlsDelLinkPeer(pMac, (peerInfo)->peerMac) ;
+ }
+ else
+ {
+ (peerInfo)->tdls_prev_link_state = (peerInfo)->tdls_link_state ;
+ (peerInfo)->tdls_link_state = TDLS_LINK_TEARDOWN_DONE_STATE ;
+ limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (peerInfo)->peerMac,
+ eWNI_SME_TDLS_TEARDOWN_IND) ;
+ }
+
+
+#if 0
+ /* if previous state is link restart, then restart link setup again */
+ if(TDLS_LINK_SETUP_RESTART_STATE == (peerInfo)->tdls_prev_link_state)
+ {
+ tLimTdlsLinkSetupInfo *setupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
+ limTdlsPrepareSetupReqFrame(pMac, setupInfo, 37,
+ peerMac, psessionEntry) ;
+ }
+#endif
+ status = eHAL_STATUS_SUCCESS ;
+#endif
+ return status ;
+}
+
+/*
+ * Send TDLS discovery response frame on direct link.
+ */
+
+static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, tANI_U8 dialog, tpPESession psessionEntry)
+{
+ tDot11fTDLSDisRsp tdlsDisRsp ;
+ tANI_U16 caps = 0 ;
+ tANI_U32 status = 0 ;
+ tANI_U32 nPayload = 0 ;
+ tANI_U32 nBytes = 0 ;
+ tANI_U8 *pFrame;
+ void *pPacket;
+ eHalStatus halstatus;
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11fPackProbeRequest' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsDisRsp,
+ sizeof( tDot11fTDLSDisRsp ) );
+
+ /*
+ * setup Fixed fields,
+ */
+ tdlsDisRsp.Category.category = SIR_MAC_ACTION_PUBLIC_USAGE;
+ tdlsDisRsp.Action.action = SIR_MAC_TDLS_DIS_RSP ;
+ tdlsDisRsp.DialogToken.token = dialog ;
+
+ PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsDisRsp.LinkIdentifier,
+ peerMac, TDLS_RESPONDER) ;
+
+ if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS)
+ {
+ /*
+ * Could not get Capabilities value
+ * from CFG. Log error.
+ */
+ limLog(pMac, LOGP,
+ FL("could not retrieve Capabilities value\n"));
+ }
+ swapBitField16(caps, ( tANI_U16* )&tdlsDisRsp.Capabilities );
+
+ /* populate supported rate IE */
+ PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &tdlsDisRsp.SuppRates, psessionEntry );
+
+ /* Populate extended supported rates */
+ PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &tdlsDisRsp.ExtSuppRates, psessionEntry );
+
+ /* Populate extended supported rates */
+ PopulateDot11fTdlsExtCapability( pMac, &tdlsDisRsp.ExtCap );
+
+ /* Include HT Capability IE */
+ //This does not depend on peer capabilities. If it is supported then it should be included
+ PopulateDot11fHTCaps( pMac, psessionEntry, &tdlsDisRsp.HTCaps );
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11fGetPackedTDLSDisRspSize( pMac, &tdlsDisRsp, &nPayload);
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a discovery Request (0x%08x).\n"), status );
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof( tDot11fProbeRequest );
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while calculating"
+ "the packed size for a discovery Request ("
+ "0x%08x).\n"), status );
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+
+ nBytes = nPayload + sizeof( tSirMacMgmtHdr ) ;
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+
+ halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( tANI_U16 )nBytes, ( void** ) &pFrame,
+ ( void** ) &pPacket );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
+ "Discovery Request.\n"), nBytes );
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ palZeroMemory( pMac->hHdd, pFrame, nBytes );
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * response frame
+ */
+
+ /* Make public Action Frame */
+
+#if 0
+ limPreparesActionFrameHdr(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION,
+ LINK_IDEN_ADDR_OFFSET(tdlsDisRsp)) ;
+#endif
+ limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peerMac, psessionEntry->selfMacAddr);
+
+ {
+ tpSirMacMgmtHdr pMacHdr;
+ pMacHdr = ( tpSirMacMgmtHdr ) pFrame;
+ pMacHdr->fc.toDS = ANI_TXDIR_IBSS;
+ pMacHdr->fc.powerMgmt = 0 ;
+ sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId);
+ }
+
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+ if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_DSCV_RSP)
+ {
+ tdlsDisRsp.LinkIdentifier.bssid[4] = 0xde;
+ tdlsDisRsp.LinkIdentifier.bssid[5] = 0xad;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Rsp\n"), \
+ tdlsDisRsp.LinkIdentifier.bssid[0],
+ tdlsDisRsp.LinkIdentifier.bssid[1],
+ tdlsDisRsp.LinkIdentifier.bssid[2],
+ tdlsDisRsp.LinkIdentifier.bssid[3],
+ tdlsDisRsp.LinkIdentifier.bssid[4],
+ tdlsDisRsp.LinkIdentifier.bssid[5]);
+ }
+#endif
+ status = dot11fPackTDLSDisRsp( pMac, &tdlsDisRsp, pFrame +
+ sizeof( tSirMacMgmtHdr ),
+ nPayload, &nPayload );
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
+ (0x%08x).\n"), status );
+ palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( void* ) pFrame, ( void* ) pPacket );
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
+ "Discovery Request (0x%08x).\n") );
+ }
+
+#if 0
+ if(pMac->hal.pCBackFnTxComp == NULL)
+ {
+ pMac->hal.pCBackFnTxComp = (tpCBackFnTxComp)limTdlsDisRspTxComplete;
+
+ if(TX_SUCCESS != tx_timer_activate(&pMac->hal.txCompTimer))
+ {
+ status = eHAL_STATUS_FAILURE;
+ return status;
+
+ }
+ }
+#endif
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("transmitting Discovery response on direct link\n")) ;
+
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
+ SIR_MAC_TDLS_DIS_RSP, limTraceTdlsActionString(SIR_MAC_TDLS_DIS_RSP) ));
+
+
+ /*
+ * Transmit Discovery response and watch if this is delivered to
+ * peer STA.
+ */
+ halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
+ HAL_TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_IBSS,
+ 0,
+ limTxComplete, pFrame,
+ limTdlsDisRspTxComplete,
+ HAL_USE_SELF_STA_REQUESTED_MASK );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
+ return eSIR_FAILURE;
+
+ }
+
+ return eSIR_SUCCESS;
+
+}
+
+/*
+ * TDLS setup Request frame on AP link
+ */
+
+tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, tANI_U8 dialog, tpPESession psessionEntry,
+ tANI_U8 *addIe, tANI_U16 addIeLen)
+{
+ tDot11fTDLSSetupReq tdlsSetupReq ;
+ tANI_U16 caps = 0 ;
+ tANI_U32 status = 0 ;
+ tANI_U32 nPayload = 0 ;
+ tANI_U32 nBytes = 0 ;
+ tANI_U32 header_offset = 0 ;
+ tANI_U8 *pFrame;
+ void *pPacket;
+ eHalStatus halstatus;
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11fPackProbeRequest' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsSetupReq,
+ sizeof( tDot11fTDLSSetupReq ) );
+ tdlsSetupReq.Category.category = SIR_MAC_ACTION_TDLS ;
+ tdlsSetupReq.Action.action = SIR_MAC_TDLS_SETUP_REQ ;
+ tdlsSetupReq.DialogToken.token = dialog ;
+
+
+ PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsSetupReq.LinkIdentifier,
+ peerMac, TDLS_INITIATOR) ;
+
+ if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS)
+ {
+ /*
+ * Could not get Capabilities value
+ * from CFG. Log error.
+ */
+ limLog(pMac, LOGP,
+ FL("could not retrieve Capabilities value\n"));
+ }
+ swapBitField16(caps, ( tANI_U16* )&tdlsSetupReq.Capabilities );
+
+ /* populate supported rate IE */
+ PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &tdlsSetupReq.SuppRates, psessionEntry );
+
+ /* Populate extended supported rates */
+ PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &tdlsSetupReq.ExtSuppRates, psessionEntry );
+
+ /* Populate extended supported rates */
+ PopulateDot11fTdlsExtCapability( pMac, &tdlsSetupReq.ExtCap );
+
+ /*
+ * TODO: we need to see if we have to support conditions where we have
+ * EDCA parameter info element is needed a) if we need different QOS
+ * parameters for off channel operations or QOS is not supported on
+ * AP link and we wanted to QOS on direct link.
+ */
+ /* Populate QOS info, needed for Peer U-APSD session */
+ /* TODO: Now hardcoded, because PopulateDot11fQOSCapsStation() depends on AP's capability, and
+ TDLS doesn't want to depend on AP's capability */
+ tdlsSetupReq.QOSCapsStation.present = 1;
+ tdlsSetupReq.QOSCapsStation.max_sp_length = 0;
+ tdlsSetupReq.QOSCapsStation.qack = 0;
+ tdlsSetupReq.QOSCapsStation.acbe_uapsd = 0;
+ tdlsSetupReq.QOSCapsStation.acbk_uapsd = 0;
+ tdlsSetupReq.QOSCapsStation.acvi_uapsd = 0;
+ tdlsSetupReq.QOSCapsStation.acvo_uapsd = 0;
+
+
+ /*
+ * we will always try to init TDLS link with 11n capabilities
+ * let TDLS setup response to come, and we will set our caps based
+ * of peer caps
+ */
+
+ /* Include HT Capability IE */
+ PopulateDot11fHTCaps( pMac, psessionEntry, &tdlsSetupReq.HTCaps );
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11fGetPackedTDLSSetupReqSize( pMac, &tdlsSetupReq,
+ &nPayload);
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a discovery Request (0x%08x).\n"), status );
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof( tDot11fProbeRequest );
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while calculating"
+ "the packed size for a discovery Request ("
+ "0x%08x).\n"), status );
+ }
+
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+
+ nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ + sizeof( eth_890d_header )
+ + PAYLOAD_TYPE_TDLS_SIZE
+ + addIeLen;
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+
+ halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( tANI_U16 )nBytes , ( void** ) &pFrame,
+ ( void** ) &pPacket );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
+ "Discovery Request.\n"), nBytes );
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ palZeroMemory( pMac->hHdd, pFrame, nBytes );
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+
+ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET(tdlsSetupReq), TDLS_LINK_AP, TDLS_INITIATOR, psessionEntry) ;
+
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+ if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_REQ)
+ {
+ tdlsSetupReq.LinkIdentifier.bssid[4] = 0xde;
+ tdlsSetupReq.LinkIdentifier.bssid[5] = 0xad;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Req\n"), \
+ tdlsSetupReq.LinkIdentifier.bssid[0],
+ tdlsSetupReq.LinkIdentifier.bssid[1],
+ tdlsSetupReq.LinkIdentifier.bssid[2],
+ tdlsSetupReq.LinkIdentifier.bssid[3],
+ tdlsSetupReq.LinkIdentifier.bssid[4],
+ tdlsSetupReq.LinkIdentifier.bssid[5]);
+ }
+#endif
+ status = dot11fPackTDLSSetupReq( pMac, &tdlsSetupReq, pFrame
+ + header_offset, nPayload, &nPayload );
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
+ (0x%08x).\n"), status );
+ palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( void* ) pFrame, ( void* ) pPacket );
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
+ "Discovery Request (0x%08x).\n") );
+ }
+
+ //Copy the additional IE.
+ //TODO : addIe is added at the end of the frame. This means it doesnt
+ //follow the order. This should be ok, but we should consider changing this
+ //if there is any IOT issue.
+ if( addIeLen != 0 )
+ {
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"),
+ addIeLen ));
+ palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen );
+ }
+
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
+ SIR_MAC_TDLS_SETUP_REQ, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_REQ) ));
+
+ halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
+ HAL_TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ 7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
+ limTxComplete, pFrame, 0 );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
+ return eSIR_FAILURE;
+
+ }
+
+ return eSIR_SUCCESS;
+
+}
+/*
+ * Send TDLS Teardown frame on Direct link or AP link, depends on reason code.
+ */
+
+tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, tANI_U16 reason, tpPESession psessionEntry,
+ tANI_U8 *addIe, tANI_U16 addIeLen)
+{
+ tDot11fTDLSTeardown teardown ;
+ tANI_U32 status = 0 ;
+ tANI_U32 nPayload = 0 ;
+ tANI_U32 nBytes = 0 ;
+ tANI_U32 header_offset = 0 ;
+ tANI_U8 *pFrame;
+ void *pPacket;
+ eHalStatus halstatus;
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11fPackProbeRequest' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ palZeroMemory( pMac->hHdd, ( tANI_U8* )&teardown,
+ sizeof( tDot11fTDLSTeardown ) );
+ teardown.Category.category = SIR_MAC_ACTION_TDLS ;
+ teardown.Action.action = SIR_MAC_TDLS_TEARDOWN ;
+ teardown.Reason.code = reason ;
+
+ PopulateDot11fLinkIden( pMac, psessionEntry, &teardown.LinkIdentifier,
+ peerMac, TDLS_INITIATOR) ;
+
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11fGetPackedTDLSTeardownSize( pMac, &teardown, &nPayload);
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a discovery Request (0x%08x).\n"), status );
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof( tDot11fProbeRequest );
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while calculating"
+ "the packed size for a discovery Request ("
+ "0x%08x).\n"), status );
+ }
+
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+
+ nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ + sizeof( eth_890d_header )
+ + PAYLOAD_TYPE_TDLS_SIZE
+ + addIeLen;
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+
+ halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( tANI_U16 )nBytes, ( void** ) &pFrame,
+ ( void** ) &pPacket );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
+ "Discovery Request.\n"), nBytes );
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ palZeroMemory( pMac->hHdd, pFrame, nBytes );
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+
+ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET(teardown),
+ (reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE)
+ ? TDLS_LINK_AP : TDLS_LINK_DIRECT, TDLS_INITIATOR,
+ psessionEntry) ;
+
+ status = dot11fPackTDLSTeardown( pMac, &teardown, pFrame
+ + header_offset, nPayload, &nPayload );
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGE, FL("Failed to pack a TDLS Teardown req \
+ (0x%08x).\n"), status );
+ palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( void* ) pFrame, ( void* ) pPacket );
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
+ "Teardown Request (0x%08x).\n") );
+ }
+#if 0
+ if(pMac->hal.pCBackFnTxComp == NULL)
+ {
+ pMac->hal.pCBackFnTxComp = (tpCBackFnTxComp)limTdlsTeardownTxComplete;
+ if(TX_SUCCESS != tx_timer_activate(&pMac->hal.txCompTimer))
+ {
+ status = eHAL_STATUS_FAILURE;
+ return status;
+
+ }
+ }
+ else
+ {
+ VOS_ASSERT(0) ;
+ return status ;
+ }
+#endif
+
+ if( addIeLen != 0 )
+ {
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"),
+ addIeLen ));
+ palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen );
+ }
+
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
+ SIR_MAC_TDLS_TEARDOWN, limTraceTdlsActionString(SIR_MAC_TDLS_TEARDOWN) ));
+
+ halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
+ HAL_TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ 7,
+ limTxComplete, pFrame,
+ limTdlsTeardownTxComplete,
+ 0 );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
+ return eSIR_FAILURE;
+
+ }
+ return eSIR_SUCCESS;
+
+}
+
+/*
+ * Send Setup RSP frame on AP link.
+ */
+static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, tANI_U8 dialog, tpPESession psessionEntry,
+ etdlsLinkSetupStatus setupStatus, tANI_U8 *addIe, tANI_U16 addIeLen )
+{
+ tDot11fTDLSSetupRsp tdlsSetupRsp ;
+ tANI_U32 status = 0 ;
+ tANI_U16 caps = 0 ;
+ tANI_U32 nPayload = 0 ;
+ tANI_U32 header_offset = 0 ;
+ tANI_U32 nBytes = 0 ;
+ tANI_U8 *pFrame;
+ void *pPacket;
+ eHalStatus halstatus;
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11fPackProbeRequest' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsSetupRsp,
+ sizeof( tDot11fTDLSSetupRsp ) );
+
+ /*
+ * setup Fixed fields,
+ */
+ tdlsSetupRsp.Category.category = SIR_MAC_ACTION_TDLS;
+ tdlsSetupRsp.Action.action = SIR_MAC_TDLS_SETUP_RSP ;
+ tdlsSetupRsp.DialogToken.token = dialog;
+
+ PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsSetupRsp.LinkIdentifier,
+ peerMac, TDLS_RESPONDER) ;
+
+ if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS)
+ {
+ /*
+ * Could not get Capabilities value
+ * from CFG. Log error.
+ */
+ limLog(pMac, LOGP,
+ FL("could not retrieve Capabilities value\n"));
+ }
+ swapBitField16(caps, ( tANI_U16* )&tdlsSetupRsp.Capabilities );
+
+ /* ipopulate supported rate IE */
+ PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &tdlsSetupRsp.SuppRates, psessionEntry );
+
+ /* Populate extended supported rates */
+ PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &tdlsSetupRsp.ExtSuppRates, psessionEntry );
+
+ /* Populate extended supported rates */
+ PopulateDot11fTdlsExtCapability( pMac, &tdlsSetupRsp.ExtCap );
+
+ /*
+ * TODO: we need to see if we have to support conditions where we have
+ * EDCA parameter info element is needed a) if we need different QOS
+ * parameters for off channel operations or QOS is not supported on
+ * AP link and we wanted to QOS on direct link.
+ */
+ /* Populate QOS info, needed for Peer U-APSD session */
+ /* TODO: Now hardcoded, because PopulateDot11fQOSCapsStation() depends on AP's capability, and
+ TDLS doesn't want to depend on AP's capability */
+ tdlsSetupRsp.QOSCapsStation.present = 1;
+ tdlsSetupRsp.QOSCapsStation.max_sp_length = 0;
+ tdlsSetupRsp.QOSCapsStation.qack = 0;
+ tdlsSetupRsp.QOSCapsStation.acbe_uapsd = 1;
+ tdlsSetupRsp.QOSCapsStation.acbk_uapsd = 1;
+ tdlsSetupRsp.QOSCapsStation.acvi_uapsd = 1;
+ tdlsSetupRsp.QOSCapsStation.acvo_uapsd = 1;
+
+ /* Include HT Info IE */
+// if ( setupReq->HTCaps.present)
+// {
+ PopulateDot11fHTCaps( pMac, psessionEntry, &tdlsSetupRsp.HTCaps );
+// }
+
+ tdlsSetupRsp.Status.status = setupStatus ;
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11fGetPackedTDLSSetupRspSize( pMac, &tdlsSetupRsp,
+ &nPayload);
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a discovery Request (0x%08x).\n"), status );
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof( tDot11fProbeRequest );
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while calculating"
+ "the packed size for a discovery Request ("
+ "0x%08x).\n"), status );
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+
+ nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ + sizeof( eth_890d_header )
+ + PAYLOAD_TYPE_TDLS_SIZE
+ + addIeLen;
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+
+ halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( tANI_U16 )nBytes, ( void** ) &pFrame,
+ ( void** ) &pPacket );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
+ "Discovery Request.\n"), nBytes );
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ palZeroMemory( pMac->hHdd, pFrame, nBytes );
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+
+ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET(tdlsSetupRsp),
+ TDLS_LINK_AP, TDLS_RESPONDER,
+ psessionEntry) ;
+
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+ if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_RSP)
+ {
+ tdlsSetupRsp.LinkIdentifier.bssid[4] = 0xde;
+ tdlsSetupRsp.LinkIdentifier.bssid[5] = 0xad;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Rsp\n"), \
+ tdlsSetupRsp.LinkIdentifier.bssid[0],
+ tdlsSetupRsp.LinkIdentifier.bssid[1],
+ tdlsSetupRsp.LinkIdentifier.bssid[2],
+ tdlsSetupRsp.LinkIdentifier.bssid[3],
+ tdlsSetupRsp.LinkIdentifier.bssid[4],
+ tdlsSetupRsp.LinkIdentifier.bssid[5]);
+ }
+#endif
+ status = dot11fPackTDLSSetupRsp( pMac, &tdlsSetupRsp, pFrame
+ + header_offset, nPayload, &nPayload );
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
+ (0x%08x).\n"), status );
+ palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( void* ) pFrame, ( void* ) pPacket );
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
+ "Discovery Request (0x%08x).\n") );
+ }
+
+ //Copy the additional IE.
+ //TODO : addIe is added at the end of the frame. This means it doesnt
+ //follow the order. This should be ok, but we should consider changing this
+ //if there is any IOT issue.
+ if( addIeLen != 0 )
+ {
+ palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen );
+ }
+
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
+ SIR_MAC_TDLS_SETUP_RSP, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_RSP) ));
+
+ halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
+ HAL_TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ //ANI_TXDIR_IBSS,
+ 7,
+ limTxComplete, pFrame, 0 );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
+ return eSIR_FAILURE;
+
+ }
+
+ return eSIR_SUCCESS;
+
+}
+
+/*
+ * Send TDLS setup CNF frame on AP link
+ */
+
+tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peerMac,
+ tANI_U8 dialog, tpPESession psessionEntry, tANI_U8* addIe, tANI_U16 addIeLen)
+{
+ tDot11fTDLSSetupCnf tdlsSetupCnf ;
+ tANI_U32 status = 0 ;
+ tANI_U32 nPayload = 0 ;
+ tANI_U32 nBytes = 0 ;
+ tANI_U32 header_offset = 0 ;
+ tANI_U8 *pFrame;
+ void *pPacket;
+ eHalStatus halstatus;
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11fPackProbeRequest' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsSetupCnf,
+ sizeof( tDot11fTDLSSetupCnf ) );
+
+ /*
+ * setup Fixed fields,
+ */
+ tdlsSetupCnf.Category.category = SIR_MAC_ACTION_TDLS;
+ tdlsSetupCnf.Action.action = SIR_MAC_TDLS_SETUP_CNF ;
+ tdlsSetupCnf.DialogToken.token = dialog ;
+
+#if 1
+ PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsSetupCnf.LinkIdentifier,
+ peerMac, TDLS_INITIATOR) ;
+#else
+ palCopyMemory( pMac->hHdd, (tANI_U8 *)&tdlsSetupCnf.LinkIdentifier,
+ (tANI_U8 *)&setupRsp->LinkIdentifier, sizeof(tDot11fIELinkIdentifier)) ;
+#endif
+
+ /*
+ * TODO: we need to see if we have to support conditions where we have
+ * EDCA parameter info element is needed a) if we need different QOS
+ * parameters for off channel operations or QOS is not supported on
+ * AP link and we wanted to QOS on direct link.
+ */
+
+ /* Include HT Info IE */
+ //if ( tdlsSetupCnf.HTCaps.present)
+ //{
+ // PopulateDot11fHTInfo( pMac, &tdlsSetupCnf.HTInfo, psessionEntry );
+ // }
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11fGetPackedTDLSSetupCnfSize( pMac, &tdlsSetupCnf,
+ &nPayload);
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a discovery Request (0x%08x).\n"), status );
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof( tDot11fProbeRequest );
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while calculating"
+ "the packed size for a discovery Request ("
+ "0x%08x).\n"), status );
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+
+ nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ + sizeof( eth_890d_header )
+ + PAYLOAD_TYPE_TDLS_SIZE
+ + addIeLen;
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+
+ halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( tANI_U16 )nBytes, ( void** ) &pFrame,
+ ( void** ) &pPacket );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
+ "Discovery Request.\n"), nBytes );
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ palZeroMemory( pMac->hHdd, pFrame, nBytes );
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+
+ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET(tdlsSetupCnf), TDLS_LINK_AP, TDLS_INITIATOR,
+ psessionEntry) ;
+
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+ if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_STATUS_37_IN_SETUP_CNF) {
+ tdlsSetupCnf.StatusCode.statusCode = 37;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TDLS negative running: StatusCode = 37 in TDLS Setup Cnf\n"));
+ }
+#endif
+ status = dot11fPackTDLSSetupCnf( pMac, &tdlsSetupCnf, pFrame
+ + header_offset, nPayload, &nPayload );
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
+ (0x%08x).\n"), status );
+ palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( void* ) pFrame, ( void* ) pPacket );
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
+ "Discovery Request (0x%08x).\n") );
+ }
+#if 0
+ if(pMac->hal.pCBackFnTxComp == NULL)
+ {
+ pMac->hal.pCBackFnTxComp = (tpCBackFnTxComp)limTdlsSetupCnfTxComplete;
+ if(TX_SUCCESS != tx_timer_activate(&pMac->hal.txCompTimer))
+ {
+ status = eHAL_STATUS_FAILURE;
+ return status;
+
+ }
+ }
+ else
+ {
+ VOS_ASSERT(0) ;
+ return status ;
+ }
+#endif
+ //Copy the additional IE.
+ //TODO : addIe is added at the end of the frame. This means it doesnt
+ //follow the order. This should be ok, but we should consider changing this
+ //if there is any IOT issue.
+ if( addIeLen != 0 )
+ {
+ palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen );
+ }
+
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
+ SIR_MAC_TDLS_SETUP_CNF, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_CNF) ));
+
+ halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
+ HAL_TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ 7,
+ limTxComplete, pFrame,
+ limTdlsSetupCnfTxComplete,
+ 0 );
+
+
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
+ return eSIR_FAILURE;
+
+ }
+
+ return eSIR_SUCCESS;
+}
+
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+/*
+ * Convert HT caps to lim based HT caps
+ */
+static void limTdlsCovertHTCaps(tpAniSirGlobal pMac ,
+ tSirTdlsPeerInfo *peerInfo, tDot11fIEHTCaps *HTCaps)
+{
+
+ /* HT Capability Info */
+ peerInfo->tdlsPeerHtCaps.advCodingCap = HTCaps->advCodingCap ;
+ peerInfo->tdlsPeerHtCaps.supportedChannelWidthSet =
+ HTCaps->supportedChannelWidthSet ;
+ peerInfo->tdlsPeerHtCaps.mimoPowerSave = HTCaps->mimoPowerSave ;
+ peerInfo->tdlsPeerHtCaps.greenField = HTCaps->greenField ;
+ peerInfo->tdlsPeerHtCaps.shortGI20MHz = HTCaps->shortGI20MHz ;
+ peerInfo->tdlsPeerHtCaps.shortGI40MHz = HTCaps->shortGI40MHz ;
+ peerInfo->tdlsPeerHtCaps.txSTBC = HTCaps->txSTBC ;
+ peerInfo->tdlsPeerHtCaps.rxSTBC = HTCaps->rxSTBC ;
+ peerInfo->tdlsPeerHtCaps.delayedBA = HTCaps->delayedBA;
+ peerInfo->tdlsPeerHtCaps.maximalAMSDUsize = HTCaps->maximalAMSDUsize ;
+ peerInfo->tdlsPeerHtCaps.dsssCckMode40MHz = HTCaps->dsssCckMode40MHz ;
+ peerInfo->tdlsPeerHtCaps.psmp = HTCaps->stbcControlFrame ;
+ peerInfo->tdlsPeerHtCaps.stbcControlFrame = HTCaps->stbcControlFrame ;
+ peerInfo->tdlsPeerHtCaps.lsigTXOPProtection =
+ HTCaps->lsigTXOPProtection ;
+
+ /* HT Capa parameters */
+ peerInfo->tdlsPeerHtParams.maxRxAMPDUFactor = HTCaps->maxRxAMPDUFactor ;
+ peerInfo->tdlsPeerHtParams.mpduDensity = HTCaps->mpduDensity ;
+ peerInfo->tdlsPeerHtParams.reserved = HTCaps->reserved1 ;
+
+ /* Extended HT caps */
+ peerInfo->tdlsPeerHtExtCaps.pco = HTCaps->pco ;
+ peerInfo->tdlsPeerHtExtCaps.transitionTime = HTCaps->transitionTime ;
+ peerInfo->tdlsPeerHtExtCaps.mcsFeedback = HTCaps->mcsFeedback ;
+ palCopyMemory(pMac->hHdd, peerInfo->supportedMCSSet,
+ HTCaps->supportedMCSSet, SIZE_OF_SUPPORTED_MCS_SET) ;
+
+ return ;
+}
+
+/*
+ * update capability info..
+ */
+void tdlsUpdateCapInfo(tSirMacCapabilityInfo *capabilityInfo,
+ tDot11fFfCapabilities *Capabilities)
+{
+
+ capabilityInfo->ess = Capabilities->ess;
+ capabilityInfo->ibss = Capabilities->ibss;
+ capabilityInfo->cfPollable = Capabilities->cfPollable;
+ capabilityInfo->cfPollReq = Capabilities->cfPollReq;
+ capabilityInfo->privacy = Capabilities->privacy;
+ capabilityInfo->shortPreamble = Capabilities->shortPreamble;
+ capabilityInfo->pbcc = Capabilities->pbcc;
+ capabilityInfo->channelAgility = Capabilities->channelAgility;
+ capabilityInfo->spectrumMgt = Capabilities->spectrumMgt;
+ capabilityInfo->qos = Capabilities->qos;
+ capabilityInfo->shortSlotTime = Capabilities->shortSlotTime;
+ capabilityInfo->apsd = Capabilities->apsd;
+ capabilityInfo->rrm = Capabilities->rrm;
+ capabilityInfo->dsssOfdm = Capabilities->dsssOfdm;
+ capabilityInfo->immediateBA = Capabilities->immediateBA;
+
+ return ;
+}
+
+/*
+ * update Peer info from the link request frame recieved from Peer..
+ * in list of STA participating in TDLS link setup
+ */
+void limTdlsUpdateLinkReqPeerInfo(tpAniSirGlobal pMac,
+ tLimTdlsLinkSetupPeer *setupPeer,
+ tDot11fTDLSSetupReq *setupReq)
+{
+
+ /* Populate peer info of tdls discovery result */
+
+ tdlsUpdateCapInfo(&setupPeer->capabilityInfo , &setupReq->Capabilities) ;
+
+ if(setupReq->SuppRates.present)
+ {
+ ConvertSuppRates( pMac, &setupPeer->supportedRates,
+ &setupReq->SuppRates );
+ }
+
+ /* update QOS info, needed for Peer U-APSD session */
+ if(setupReq->QOSCapsStation.present)
+ {
+ ConvertQOSCapsStation(pMac->hHdd, &setupPeer->qosCaps,
+ &setupReq->QOSCapsStation) ;
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("setupReq->SPLen=%d (be %d %d %d %d vo) more %d qack %d.\n"), \
+ setupReq->QOSCapsStation.max_sp_length, setupReq->QOSCapsStation.acbe_uapsd, \
+ setupReq->QOSCapsStation.acbk_uapsd, setupReq->QOSCapsStation.acvi_uapsd, \
+ setupReq->QOSCapsStation.acvo_uapsd, setupReq->QOSCapsStation.more_data_ack, \
+ setupReq->QOSCapsStation.qack));
+ }
+
+ if(setupReq->ExtSuppRates.present)
+ {
+ setupPeer->ExtRatesPresent = 1;
+ ConvertExtSuppRates( pMac, &setupPeer->extendedRates,
+ &setupReq->ExtSuppRates );
+ }
+ /* update HT caps */
+ if(setupReq->HTCaps.present)
+ {
+ palCopyMemory(pMac->hHdd, &setupPeer->tdlsPeerHTCaps,
+ &setupReq->HTCaps, sizeof(tDot11fIEHTCaps)) ;
+ }
+ /* Update EXT caps */
+ if(setupReq->ExtCap.present)
+ {
+ palCopyMemory(pMac->hHdd, &setupPeer->tdlsPeerExtCaps,
+ &setupReq->ExtCap, sizeof(tDot11fIEExtCap)) ;
+ }
+
+ return ;
+}
+
+/*
+ * update peer Info recieved with TDLS setup RSP
+ */
+void limTdlsUpdateLinkRspPeerInfo(tpAniSirGlobal pMac,
+ tLimTdlsLinkSetupPeer *setupPeer,
+ tDot11fTDLSSetupRsp *setupRsp)
+{
+
+ /* Populate peer info of tdls discovery result */
+ tdlsUpdateCapInfo(&setupPeer->capabilityInfo , &setupRsp->Capabilities) ;
+
+ if(setupRsp->SuppRates.present)
+ {
+ tDot11fIESuppRates *suppRates = &setupRsp->SuppRates ;
+ ConvertSuppRates( pMac, &setupPeer->supportedRates, suppRates);
+ }
+
+ /* update QOS info, needed for Peer U-APSD session */
+ if(setupRsp->QOSCapsStation.present)
+ {
+ ConvertQOSCapsStation(pMac->hHdd, &setupPeer->qosCaps,
+ &setupRsp->QOSCapsStation) ;
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("setupRsp->SPLen=%d (be %d %d %d %d vo) more %d qack %d.\n"), \
+ setupRsp->QOSCapsStation.max_sp_length, setupRsp->QOSCapsStation.acbe_uapsd, \
+ setupRsp->QOSCapsStation.acbk_uapsd, setupRsp->QOSCapsStation.acvi_uapsd, \
+ setupRsp->QOSCapsStation.acvo_uapsd, setupRsp->QOSCapsStation.more_data_ack, \
+ setupRsp->QOSCapsStation.qack));
+ }
+
+ if(setupRsp->ExtSuppRates.present)
+ {
+ setupPeer->ExtRatesPresent = 1;
+ ConvertExtSuppRates( pMac, &setupPeer->extendedRates,
+ &setupRsp->ExtSuppRates );
+ }
+ /* update HT caps */
+ if(setupRsp->HTCaps.present)
+ {
+ palCopyMemory(pMac->hHdd, &setupPeer->tdlsPeerHTCaps,
+ &setupRsp->HTCaps, sizeof(tDot11fIEHTCaps)) ;
+ }
+
+ /* update EXT caps */
+ if(setupRsp->ExtCap.present)
+ {
+ palCopyMemory(pMac->hHdd, &setupPeer->tdlsPeerExtCaps,
+ &setupRsp->ExtCap, sizeof(tDot11fIEExtCap)) ;
+ }
+
+ return ;
+}
+#endif
+/*
+ * update HASH node entry info
+ */
+static void limTdlsUpdateHashNodeInfo(tpAniSirGlobal pMac, tDphHashNode *pStaDs,
+ tLimTdlsLinkSetupPeer *setupPeerInfo, tpPESession psessionEntry)
+{
+ //tDot11fIEHTCaps *htCaps = &setupPeerInfo->tdlsPeerHTCaps ;
+ tDot11fIEHTCaps htCap, *htCaps;
+ tpDphHashNode pSessStaDs = NULL;
+ tANI_U16 aid;
+
+ //HACK- to get the session's htcaps.
+ PopulateDot11fHTCaps(pMac, psessionEntry, &htCap);
+ htCaps = &htCap;
+ if(htCaps->present)
+ {
+ pStaDs->mlmStaContext.htCapability = 1 ;
+ pStaDs->htGreenfield = htCaps->greenField ;
+ pStaDs->htSupportedChannelWidthSet = htCaps->supportedChannelWidthSet ;
+ pStaDs->htMIMOPSState = htCaps->mimoPowerSave ;
+ pStaDs->htMaxAmsduLength = htCaps->maximalAMSDUsize;
+ pStaDs->htAMpduDensity = htCaps->mpduDensity;
+ pStaDs->htDsssCckRate40MHzSupport = htCaps->dsssCckMode40MHz ;
+ pStaDs->htShortGI20Mhz = htCaps->shortGI20MHz;
+ pStaDs->htShortGI40Mhz = htCaps->shortGI40MHz;
+ pStaDs->htMaxRxAMpduFactor = htCaps->maxRxAMPDUFactor;
+ limFillRxHighestSupportedRate(pMac,
+ &pStaDs->supportedRates.rxHighestDataRate,
+ htCaps->supportedMCSSet);
+ pStaDs->baPolicyFlag = 0xFF;
+
+ pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_N ;
+ }
+ else
+ {
+ pStaDs->mlmStaContext.htCapability = 0 ;
+ pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_BG ;
+ }
+
+ pSessStaDs = dphLookupHashEntry(pMac, psessionEntry->bssId, &aid,
+ &psessionEntry->dph.dphHashTable) ;
+
+ /* Lets enable QOS parameter */
+ pStaDs->qosMode = 1;
+ pStaDs->wmeEnabled = 1;
+ pStaDs->lleEnabled = 0;
+ pStaDs->qos.capability.qosInfo = pSessStaDs->qos.capability.qosInfo; //setupPeerInfo->qosCaps.qosInfo;
+
+ /* populate matching rate set */
+#if 0
+#ifdef WLAN_FEATURE_11AC
+ limPopulateMatchingRateSet(pMac, pStaDs, &setupPeerInfo->supportedRates,
+ &setupPeerInfo->extendedRates,
+ (tANI_U8 *)setupPeerInfo->tdlsPeerHTCaps.supportedMCSSet,
+ &pStaDs->mlmStaContext.propRateSet, psessionEntry, NULL);
+#else
+ limPopulateMatchingRateSet(pMac, pStaDs, &setupPeerInfo->supportedRates,
+ &setupPeerInfo->extendedRates,
+ (tANI_U8 *)setupPeerInfo->tdlsPeerHTCaps.supportedMCSSet,
+ &pStaDs->mlmStaContext.propRateSet, psessionEntry);
+#endif
+#else
+ palCopyMemory( pMac->hHdd, &pStaDs->supportedRates, &pSessStaDs->supportedRates, sizeof(pStaDs->supportedRates));
+#endif
+
+ pStaDs->mlmStaContext.capabilityInfo = pSessStaDs->mlmStaContext.capabilityInfo;// setupPeerInfo->capabilityInfo;
+
+ return ;
+}
+
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+/*
+ * find Peer in setup link list.
+ */
+
+tANI_U8 limTdlsFindLinkPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac,
+ tLimTdlsLinkSetupPeer **setupPeer)
+{
+ tLimTdlsLinkSetupInfo *setupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
+ tLimTdlsLinkSetupPeer *linkSetupList = setupInfo->tdlsLinkSetupList ;
+ tANI_U8 checkNode = TDLS_NODE_NOT_FOUND ;
+
+ while (linkSetupList != NULL)
+ {
+ if (palEqualMemory( pMac->hHdd,(tANI_U8 *) peerMac,
+ (tANI_U8 *) linkSetupList->peerMac,
+ sizeof(tSirMacAddr)) )
+ {
+ checkNode = TDLS_NODE_FOUND ;
+ *setupPeer = linkSetupList ;
+ break ;
+ }
+ linkSetupList = linkSetupList->next;
+ }
+
+ return ((TDLS_NODE_FOUND == checkNode) ? eSIR_SUCCESS : eSIR_FAILURE ) ;
+}
+
+/*
+ * find peer in Discovery list.
+ * Dicovery list get populated in two instances, a) Recieved responses in reply
+ * to discovery request b) If discover request is received from TDLS peer STA
+ */
+tSirTdlsPeerInfo *limTdlsFindDisPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac)
+{
+ tLimDisResultList *discoveryList = pMac->lim.gLimTdlsDisResultList ;
+ tSirTdlsPeerInfo *peerInfo = NULL ;
+
+ while (discoveryList != NULL)
+ {
+ peerInfo = &discoveryList->tdlsDisPeerInfo ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Peer in discovery list = %02x, %02x, %02x, %02x, %02x, %02x \n"),
+ peerInfo->peerMac[0],
+ peerInfo->peerMac[1],
+ peerInfo->peerMac[2],
+ peerInfo->peerMac[3],
+ peerInfo->peerMac[4],
+ peerInfo->peerMac[5]) ;
+
+ if (palEqualMemory( pMac->hHdd,(tANI_U8 *) peerMac,
+ (tANI_U8 *) &peerInfo->peerMac, sizeof(tSirMacAddr)) )
+ {
+ break ;
+ }
+ discoveryList = discoveryList->next;
+ }
+
+ return peerInfo ;
+}
+
+/*
+ * find peer in Discovery list by looking into peer state.
+ * Dicovery list get populated in two instances, a) Recieved responses in reply
+ * to discovery request b) If discover request is received from TDLS peer STA
+ */
+static tSirTdlsPeerInfo *limTdlsFindDisPeerByState(tpAniSirGlobal pMac,
+ tANI_U8 state)
+{
+ tLimDisResultList *discoveryList = pMac->lim.gLimTdlsDisResultList ;
+ tSirTdlsPeerInfo *peerInfo = NULL ;
+
+ while (discoveryList != NULL)
+ {
+ peerInfo = &discoveryList->tdlsDisPeerInfo ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("peerInfo Mac = %02x, %02x, %02x, %02x, %02x, %02x "),
+ peerInfo->peerMac[0],
+ peerInfo->peerMac[1],
+ peerInfo->peerMac[2],
+ peerInfo->peerMac[3],
+ peerInfo->peerMac[4],
+ peerInfo->peerMac[5]) ;
+
+ if (peerInfo->tdlsPeerState == state)
+ {
+ break ;
+ }
+ discoveryList = discoveryList->next;
+ }
+
+ return peerInfo ;
+}
+
+/*
+ * find peer in Setup list by looking into peer state.
+ * setup list get populated in two instances, a) Recieved responses in reply
+ * to setup request b) If discover request is received from TDLS peer STA
+ */
+static tANI_U8 limTdlsFindSetupPeerByState(tpAniSirGlobal pMac, tANI_U8 state,
+ tLimTdlsLinkSetupPeer **setupPeer)
+{
+
+ tLimTdlsLinkSetupInfo *setupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
+ tLimTdlsLinkSetupPeer *linkSetupList = setupInfo->tdlsLinkSetupList ;
+ tANI_U8 checkNode = TDLS_NODE_NOT_FOUND ;
+
+ while (linkSetupList != NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("peer state = %02x\n"), (linkSetupList)->tdls_link_state) ;
+ if((linkSetupList)->tdls_link_state == state)
+ {
+ checkNode = TDLS_NODE_FOUND ;
+ *setupPeer = linkSetupList ;
+ break ;
+ }
+ linkSetupList = (linkSetupList)->next;
+ }
+
+ return ((TDLS_NODE_FOUND == checkNode) ? eSIR_SUCCESS: eSIR_FAILURE) ;
+}
+
+
+/*
+ * delete Peer from Setup Link
+ */
+void limTdlsDelLinkPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac)
+{
+ tLimTdlsLinkSetupInfo *setupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
+ tLimTdlsLinkSetupPeer **linkSetupList = &setupInfo->tdlsLinkSetupList ;
+ tLimTdlsLinkSetupPeer *currentNode = NULL ;
+ tLimTdlsLinkSetupPeer *prevNode = NULL ;
+
+ for(currentNode = *linkSetupList ; currentNode != NULL ;
+ prevNode = currentNode, currentNode = currentNode->next)
+ {
+ if (palEqualMemory( pMac->hHdd,(tANI_U8 *) peerMac,
+ (tANI_U8 *) currentNode->peerMac,
+ sizeof(tSirMacAddr)) )
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Del Node for Peer = %02x,%02x,%02x,%02x,%02x,%02x\n"),
+ currentNode->peerMac[0],
+ currentNode->peerMac[1],
+ currentNode->peerMac[2],
+ currentNode->peerMac[3],
+ currentNode->peerMac[4],
+ currentNode->peerMac[5]) ;
+ /* if it's first Node */
+ if(NULL == prevNode)
+ {
+ *linkSetupList = currentNode->next ;
+ }
+ else
+ {
+ prevNode->next = currentNode->next ;
+ }
+ palFreeMemory(pMac, currentNode) ;
+ return ;
+ }
+ }
+
+ return ;
+}
+
+
+
+/*
+ * TDLS discovery request frame received from TDLS peer STA..
+ */
+static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac,
+ tANI_U8 *pBody, tANI_U32 frmLen )
+{
+ tDot11fTDLSDisReq tdlsDisReq = {{0}} ;
+ tANI_U32 status = 0 ;
+ tLimDisResultList *tdlsDisResult = NULL ;
+ tLimDisResultList **disResultList = &pMac->lim.gLimTdlsDisResultList ;
+ tSirMacAddr peerMac = {0} ;
+ tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+ tSirTdlsPeerInfo *peerInfo = NULL ;
+ tpPESession psessionEntry = NULL ;
+ tANI_U8 sessionId = 0 ;
+
+ status = dot11fUnpackTDLSDisReq(pMac, pBody, frmLen, &tdlsDisReq) ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN,
+ ("TDLS dis request dialog = %d\n"), tdlsDisReq.DialogToken.token);
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \
+ frame (0x%08x, %d bytes):\n"),status, frmLen);
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while unpacking an\
+ TDLS discovery Request frame (0x%08x," "%d bytes):\n"),
+ status, frmLen );
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ }
+
+ /*
+ * find session entry using BSSID in link identifier, not using MAC
+ * header beacuse, there is cases in TDLS, there may be BSSID will not
+ * be present in header
+ */
+ psessionEntry = peFindSessionByBssid(pMac,
+ &tdlsDisReq.LinkIdentifier.bssid[0], &sessionId) ;
+ if(NULL == psessionEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
+ ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
+ tdlsDisReq.LinkIdentifier.bssid[0],
+ tdlsDisReq.LinkIdentifier.bssid[1],
+ tdlsDisReq.LinkIdentifier.bssid[2],
+ tdlsDisReq.LinkIdentifier.bssid[3],
+ tdlsDisReq.LinkIdentifier.bssid[4],
+ tdlsDisReq.LinkIdentifier.bssid[5]) ;
+
+ //VOS_ASSERT(0) ;
+ return eSIR_FAILURE;
+ }
+
+ /* varify BSSID */
+ status = palEqualMemory(pMac->hHdd, &psessionEntry->bssId[0],
+ &tdlsDisReq.LinkIdentifier.bssid[0], sizeof(tSirMacAddr)) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("lim BSSID %02x, %02x, %02x, %02x, %02x, %02x\n"),
+ psessionEntry->bssId[0],
+ psessionEntry->bssId[1],
+ psessionEntry->bssId[2],
+ psessionEntry->bssId[3],
+ psessionEntry->bssId[4],
+ psessionEntry->bssId[5]) ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Dis req from BSSID %02x, %02x, %02x, %02x, %02x, %02x\n"),
+ tdlsDisReq.LinkIdentifier.bssid[0],
+ tdlsDisReq.LinkIdentifier.bssid[1],
+ tdlsDisReq.LinkIdentifier.bssid[2],
+ tdlsDisReq.LinkIdentifier.bssid[3],
+ tdlsDisReq.LinkIdentifier.bssid[4],
+ tdlsDisReq.LinkIdentifier.bssid[5]
+ ) ;
+ if(!status)
+ {
+ limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter\n")) ;
+
+ return eSIR_FAILURE ;
+ }
+
+ /*
+ * check if this is echo of our transmitted discovery request
+ * drop it here, TODO: better to drop this in TL.
+ */
+ status = palEqualMemory(pMac->hHdd, psessionEntry->selfMacAddr,
+ &tdlsDisReq.LinkIdentifier.InitStaAddr[0],
+ sizeof(tSirMacAddr)) ;
+ if(status)
+ {
+ limLog( pMac, LOGE, FL("Echo of our TDLS discovery request frame\n")) ;
+ return eSIR_FAILURE ;
+ }
+
+ /*
+ * while processing Discovery request from Peer,
+ * STA_MAC--> MAC of TDLS discovery initiator
+ * STA_PEER_MAC--> MAC of TDLS discovery responder.
+ */
+ palCopyMemory(pMac->hHdd, peerMac,
+ &tdlsDisReq.LinkIdentifier.InitStaAddr[0],
+ sizeof(tSirMacAddr)) ;
+ /* TODO, do more validation */
+
+ /* see if discovery is already in progress */
+ peerInfo = limTdlsFindDisPeer(pMac, peerMac) ;
+
+ if(NULL == peerInfo)
+ {
+ /*
+ * we are allocating peer info for individual peers found in TDLS
+ * discovery, we need to keep adding TDLS peers till we have timed
+ * out. We are freeing this memory at the time we are sending this
+ * collected peer info to SME.
+ */
+ status = palAllocateMemory(pMac->hHdd, (void **)&tdlsDisResult,
+ sizeof(tLimDisResultList)) ;
+
+ if(status != eHAL_STATUS_SUCCESS)
+ {
+ limLog(pMac, LOGP, FL("alloc fail for TDLS discovery \
+ reponse info\n")) ;
+ return eSIR_FAILURE ;
+ }
+
+
+ peerInfo = &tdlsDisResult->tdlsDisPeerInfo ;
+ peerInfo->tdlsPeerState = TDLS_DIS_REQ_PROCESS_STATE ;
+ peerInfo->dialog = tdlsDisReq.DialogToken.token ;
+
+ peerInfo->sessionId = psessionEntry->peSessionId;
+
+ /* Populate peer info of tdls discovery result */
+ status = palCopyMemory(pMac->hHdd, peerInfo->peerMac, peerMac,
+ sizeof(tSirMacAddr)) ;
+
+ /*
+ * Now, as per D13, there will not be any Supp rates, ext Supp rates
+ * info in Discovery request frames, so we are populating this info
+ * locally to pass it to ADD STA.
+ */
+ do
+ {
+ tDot11fIESuppRates suppRates = {0} ;
+ tDot11fIEExtSuppRates extSuppRates = {0} ;
+ tANI_U16 caps = 0 ;
+ tDot11fFfCapabilities capsInfo = {0} ;
+ tDot11fIEHTCaps HTCaps = {0} ;
+ /* populate supported rate IE */
+ PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &suppRates, psessionEntry );
+ ConvertSuppRates( pMac, &peerInfo->tdlsPeerSuppRates,
+ &suppRates);
+ /* Populate extended supported rates */
+ PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &extSuppRates, psessionEntry );
+
+ peerInfo->ExtRatesPresent = 1;
+ ConvertExtSuppRates( pMac, &peerInfo->tdlsPeerExtRates,
+ &extSuppRates);
+
+ if(cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS)
+ {
+ /*
+ * Could not get Capabilities value
+ * from CFG. Log error.
+ */
+ limLog(pMac, LOGP,
+ FL("could not retrieve Capabilities value\n"));
+ }
+ swapBitField16(caps, ( tANI_U16* )&capsInfo );
+ /* update Caps Info */
+ tdlsUpdateCapInfo(&peerInfo->capabilityInfo , &capsInfo) ;
+
+ PopulateDot11fHTCaps( pMac, psessionEntry, &HTCaps );
+ limTdlsCovertHTCaps(pMac, peerInfo, &HTCaps) ;
+
+ } while (0) ;
+
+ /* now add this new found discovery node into tdls discovery list */
+ tdlsDisResult->next = *disResultList ;
+ *disResultList = tdlsDisResult ;
+ pMac->lim.gLimTdlsDisStaCount++ ;
+
+ /* See if for this peer already entry in setup Link */
+ limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
+
+ /*
+ * if there is no entry for this peer in setup list, we need to
+ * do add sta for this peer to transmit discovery rsp.
+ */
+ if(NULL == setupPeer)
+ {
+ /* To start with, send add STA request to HAL */
+ pMac->lim.gLimAddStaTdls = true ;
+ peerInfo->delStaNeeded = true ;
+
+ if(eSIR_FAILURE == limTdlsDisAddSta(pMac, peerMac,
+ peerInfo, psessionEntry))
+ {
+ VOS_ASSERT(0) ;
+ limLog(pMac, LOGE, "Add STA for dis response is failed \n") ;
+ return eSIR_FAILURE ;
+ }
+ } /* use setup link sta ID for discovery rsp */
+ else
+ {
+ peerInfo->delStaNeeded = false ;
+ limSendTdlsDisRspFrame(pMac, peerInfo->peerMac, peerInfo->dialog, psessionEntry) ;
+ peerInfo->tdlsPeerState = TDLS_DIS_RSP_SENT_WAIT_STATE ;
+ }
+
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("discovery procedure in progress for this peer\n")) ;
+ }
+
+ return eSIR_SUCCESS ;
+}
+
+/* Process TDLS setup Request Frame */
+
+static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac,
+ tANI_U8 *pBody, tANI_U32 frmLen)
+{
+
+ tDot11fTDLSSetupReq tdlsSetupReq = {{0}} ;
+ tANI_U32 status = 0 ;
+ tpPESession psessionEntry = NULL ;
+ tANI_U8 sessionId = 0 ;
+ tANI_U8 currentState = TDLS_LINK_SETUP_WAIT_STATE ;
+ tANI_U8 previousState = TDLS_LINK_IDLE_STATE ;
+ /* create node for Link setup */
+ tLimTdlsLinkSetupInfo *linkSetupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
+ tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+ tLimTdlsLinkSetupPeer *tmpSetupPeer = NULL ;
+
+ status = dot11fUnpackTDLSSetupReq(pMac, pBody, frmLen, &tdlsSetupReq) ;
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \
+ frame (0x%08x, %d bytes):\n"),status, frmLen);
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while unpacking an\
+ TDLS setup Request frame (0x%08x," "%d bytes):\n"),
+ status, pBody );
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ }
+ /*
+ * find session entry using BSSID in link identifier, not using MAC
+ * header beacuse, there is cases in TDLS, there may be BSSID will not
+ * be present in header
+ */
+ psessionEntry = peFindSessionByBssid(pMac,
+ &tdlsSetupReq.LinkIdentifier.bssid[0], &sessionId) ;
+ if(NULL == psessionEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
+ ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
+ tdlsSetupReq.LinkIdentifier.bssid[0],
+ tdlsSetupReq.LinkIdentifier.bssid[1],
+ tdlsSetupReq.LinkIdentifier.bssid[2],
+ tdlsSetupReq.LinkIdentifier.bssid[3],
+ tdlsSetupReq.LinkIdentifier.bssid[4],
+ tdlsSetupReq.LinkIdentifier.bssid[5]) ;
+
+ //VOS_ASSERT(0) ;
+ return eSIR_FAILURE ;
+ }
+ /* TODO: we don;t need this check now, varify BSSID */
+ status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
+ &tdlsSetupReq.LinkIdentifier.bssid[0],
+ sizeof(tSirMacAddr)) ;
+
+ if(!status)
+ {
+ limLog( pMac, LOGE, FL("TDLS setup request frame from other BSS -> something wrong. Check RXP filter\n")) ;
+
+ limSendTdlsSetupRspFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr, tdlsSetupReq.DialogToken.token , psessionEntry,
+ TDLS_SETUP_STATUS_FAILURE, NULL, 0 ) ;
+ return eSIR_FAILURE ;
+ }
+
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+ if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_RSP_TIMEOUT_TO_SETUP_REQ)
+ {
+ /* simply ignore this setup request packet */
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TDLS negative running: ignore TDLS Setup Req packet\n"));
+ return eSIR_SUCCESS ;
+ }
+ if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_SEND_REQ_TO_SETUP_REQ)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("TDLS negative running: send TDLS Setup Req to peer TDLS Setup Req\n"));
+ /* format TDLS discovery request frame and transmit it */
+ limSendTdlsLinkSetupReqFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr, tdlsSetupReq.DialogToken.token, psessionEntry,
+ NULL, 0) ;
+ }
+#endif
+ /* TODO, do more validation */
+
+ if(!limTdlsFindLinkPeer(pMac,
+ &tdlsSetupReq.LinkIdentifier.InitStaAddr[0],
+ &tmpSetupPeer))
+ {
+ tANI_U32 tdlsStateStatus = TDLS_LINK_SETUP_START_STATE ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("Link is already setup with this peer\n" )) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("state = %d\n"), tmpSetupPeer->tdls_link_state) ;
+ //return eSIR_FAILURE ;
+
+ if(tmpSetupPeer == NULL)
+ {
+ VOS_ASSERT(0) ;
+ return eSIR_FAILURE ;
+
+ }
+ switch(tmpSetupPeer->tdls_link_state)
+ {
+
+ case TDLS_LINK_SETUP_START_STATE:
+ {
+ v_SINT_t macCompare = 0 ;
+ macCompare= vos_mem_compare2(tmpSetupPeer->peerMac,
+ psessionEntry->selfMacAddr, sizeof(tSirMacAddr)) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("MAC comparison Rslt = %d\n"), macCompare ) ;
+ if(0 > macCompare)
+ {
+ /*
+ * Delete our Setup Request/Peer info and honour Peer
+ * Setup Request, go ahead and respond for this
+ */
+ /* Deactivate the timer */
+ tx_timer_deactivate(&tmpSetupPeer->gLimTdlsLinkSetupRspTimeoutTimer) ;
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+ if((pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_SEND_REQ_TO_SETUP_REQ)
+ != LIM_TDLS_NEGATIVE_SEND_REQ_TO_SETUP_REQ)
+#endif
+ limSendSmeTdlsLinkStartRsp(pMac, eSIR_FAILURE,
+ tmpSetupPeer->peerMac, eWNI_SME_TDLS_LINK_START_RSP);
+
+ limTdlsDelLinkPeer(pMac, tmpSetupPeer->peerMac) ;
+ tdlsStateStatus = TDLS_LINK_IDLE_STATE ;
+ }
+ else if(0 < macCompare)
+ {
+ /*
+ * Go ahead with current setup as peer is going to
+ * respond for setup request
+ */
+ tdlsStateStatus = TDLS_LINK_SETUP_START_STATE ;
+ }
+ else
+ {
+ /* same MAC, not possible */
+ VOS_ASSERT(0) ;
+ }
+
+ break ;
+ }
+#if 1
+ case TDLS_LINK_SETUP_DONE_STATE:
+ {
+ tpDphHashNode pStaDs = NULL ;
+
+ previousState = TDLS_LINK_SETUP_WAIT_STATE ;
+ currentState = TDLS_LINK_TEARDOWN_START_STATE ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("link Setup Done state " )) ;
+ tmpSetupPeer->tdls_prev_link_state = previousState ;
+ tmpSetupPeer->tdls_link_state = currentState ;
+ setupPeer = tmpSetupPeer ;
+#if 0
+ /* Send Teardown to this Peer and Initiate new TDLS Setup */
+ limSendTdlsTeardownFrame(pMac,
+ &tdlsSetupReq.LinkIdentifier.InitStaAddr[0],
+ eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON, psessionEntry) ;
+#else
+
+ /* tdls_hklee: send message to HAL before it is deleted, cause */
+ limTdlsLinkTeardown(pMac, (setupPeer)->peerMac) ;
+
+ /* send del STA to remove context for this TDLS STA */
+ pStaDs = limTdlsDelSta(pMac, (setupPeer)->peerMac, psessionEntry) ;
+
+ /* now send indication to SME-->HDD->TL to remove STA from TL */
+
+ if(pStaDs)
+ {
+ limSendSmeTdlsDelPeerInd(pMac, psessionEntry->smeSessionId,
+ pStaDs, eSIR_SUCCESS) ;
+
+ /* send Teardown Ind to SME */
+ limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (setupPeer)->peerMac,
+ eWNI_SME_TDLS_TEARDOWN_IND) ;
+ /* remove node from setup list */
+ limTdlsDelLinkPeer(pMac, (setupPeer)->peerMac) ;
+ }
+#endif
+ //setupPeer->tdls_prev_link_state = TDLS_LINK_SETUP_RESTART_STATE;
+ tdlsStateStatus = TDLS_LINK_IDLE_STATE ;
+ break ;
+
+ }
+ default:
+ {
+ VOS_ASSERT(0) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("link Setup is Recieved in unknown state\n" )) ;
+ break ;
+ }
+#endif
+ }
+ if(tdlsStateStatus == TDLS_LINK_SETUP_START_STATE)
+ return eSIR_FAILURE ;
+ }
+
+ if(currentState != TDLS_LINK_TEARDOWN_START_STATE)
+ {
+ /*
+ * Now we are sure to send discovery response frame to TDLS discovery
+ * initiator, we don't care, if this request is unicast ro broadcast,
+ * we simply, send discovery response frame on direct link.
+ */
+ if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd,
+ (void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer )))
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ( "Unable to allocate memory during ADD_STA\n" ));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ setupPeer->dialog = tdlsSetupReq.DialogToken.token ;
+ //setupPeer->tdls_prev_link_state = setupPeer->tdls_link_state ;
+ //setupPeer->tdls_link_state = TDLS_LINK_SETUP_WAIT_STATE ;
+ setupPeer->tdls_prev_link_state = previousState ;
+ setupPeer->tdls_link_state = currentState ;
+ /* TDLS_sessionize: remember sessionId for future */
+ setupPeer->tdls_sessionId = psessionEntry->peSessionId;
+ setupPeer->tdls_bIsResponder = 0;
+
+ palCopyMemory(pMac->hHdd, setupPeer->peerMac,
+ &tdlsSetupReq.LinkIdentifier.InitStaAddr[0],
+ sizeof(tSirMacAddr)) ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x\n"),
+ setupPeer->peerMac[0],
+ setupPeer->peerMac[1],
+ setupPeer->peerMac[2],
+ setupPeer->peerMac[3],
+ setupPeer->peerMac[4],
+ setupPeer->peerMac[5] ) ;
+
+ limTdlsUpdateLinkReqPeerInfo(pMac, setupPeer, &tdlsSetupReq) ;
+ pMac->lim.gLimAddStaTdls = true ;
+
+ /* To start with, send add STA request to HAL */
+ if(eSIR_FAILURE == limTdlsSetupAddSta(pMac, setupPeer->peerMac,
+ setupPeer, psessionEntry))
+ {
+ VOS_ASSERT(0) ;
+ palFreeMemory(pMac->hHdd, (void **) &setupPeer) ;
+ return eSIR_FAILURE ;
+ }
+
+ limSendTdlsSetupRspFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr,
+ tdlsSetupReq.DialogToken.token , psessionEntry,
+ TDLS_SETUP_STATUS_SUCCESS, NULL, 0) ;
+
+ limStartTdlsTimer(pMac, psessionEntry->peSessionId,
+ &setupPeer->gLimTdlsLinkSetupCnfTimeoutTimer,
+ (tANI_U32)setupPeer->peerMac,
+ WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT,
+ SIR_LIM_TDLS_LINK_SETUP_CNF_TIMEOUT) ;
+
+ /* update setup peer list */
+ setupPeer->next = linkSetupInfo->tdlsLinkSetupList ;
+ linkSetupInfo->tdlsLinkSetupList = setupPeer ;
+ }
+ else
+ {
+ setupPeer->dialog = tdlsSetupReq.DialogToken.token ;
+ //setupPeer->tdls_prev_link_state = setupPeer->tdls_link_state ;
+ //setupPeer->tdls_link_state = TDLS_LINK_SETUP_WAIT_STATE ;
+ setupPeer->tdls_prev_link_state = previousState ;
+ setupPeer->tdls_link_state = currentState ;
+ /* TDLS_sessionize: remember sessionId for future */
+ setupPeer->tdls_sessionId = psessionEntry->peSessionId;
+ setupPeer->tdls_bIsResponder = 0;
+
+ palCopyMemory(pMac->hHdd, setupPeer->peerMac,
+ &tdlsSetupReq.LinkIdentifier.InitStaAddr[0],
+ sizeof(tSirMacAddr)) ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x\n"),
+ setupPeer->peerMac[0],
+ setupPeer->peerMac[1],
+ setupPeer->peerMac[2],
+ setupPeer->peerMac[3],
+ setupPeer->peerMac[4],
+ setupPeer->peerMac[5] ) ;
+
+ limTdlsUpdateLinkReqPeerInfo(pMac, setupPeer, &tdlsSetupReq) ;
+ limSendTdlsSetupRspFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr,
+ tdlsSetupReq.DialogToken.token , psessionEntry,
+ TDLS_SETUP_STATUS_SUCCESS, NULL, 0) ;
+
+ limStartTdlsTimer(pMac, psessionEntry->peSessionId,
+ &setupPeer->gLimTdlsLinkSetupCnfTimeoutTimer,
+ (tANI_U32)setupPeer->peerMac,
+ WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT,
+ SIR_LIM_TDLS_LINK_SETUP_CNF_TIMEOUT) ;
+ }
+
+
+ return eSIR_SUCCESS ;
+
+}
+
+/*
+ * TDLS discovery request frame received from TDLS peer STA..
+ */
+static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac,
+ tANI_U8 *pBody, tANI_U32 frmLen )
+{
+ tDot11fTDLSSetupRsp tdlsSetupRsp = {{0}} ;
+ tANI_U32 status = 0 ;
+ tSirMacAddr peerMac = {0} ;
+ tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+ tpPESession psessionEntry = NULL ;
+ tANI_U8 sessionId = 0 ;
+
+ status = dot11fUnpackTDLSSetupRsp(pMac, pBody, frmLen, &tdlsSetupRsp) ;
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \
+ frame (0x%08x, %d bytes):\n"),status, frmLen);
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while unpacking an\
+ TDLS discovery Request frame (0x%08x," "%d bytes):\n"),
+ status, frmLen );
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ }
+
+ /*
+ * find session entry using BSSID in link identifier, not using MAC
+ * header beacuse, there is cases in TDLS, there may be BSSID will not
+ * be present in header
+ */
+ psessionEntry = peFindSessionByBssid(pMac,
+ &tdlsSetupRsp.LinkIdentifier.bssid[0], &sessionId) ;
+ if(NULL == psessionEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
+ ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
+ tdlsSetupRsp.LinkIdentifier.bssid[0],
+ tdlsSetupRsp.LinkIdentifier.bssid[1],
+ tdlsSetupRsp.LinkIdentifier.bssid[2],
+ tdlsSetupRsp.LinkIdentifier.bssid[3],
+ tdlsSetupRsp.LinkIdentifier.bssid[4],
+ tdlsSetupRsp.LinkIdentifier.bssid[5]) ;
+
+ //VOS_ASSERT(0) ;
+ return eSIR_FAILURE;
+ }
+
+ /* varify BSSID */
+ status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
+ &tdlsSetupRsp.LinkIdentifier.bssid[0],
+ sizeof(tSirMacAddr)) ;
+
+ if(!status)
+ {
+ limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter\n")) ;
+
+ VOS_ASSERT(0) ;
+ return eSIR_FAILURE ;
+ }
+ palCopyMemory(pMac->hHdd, peerMac,
+ &tdlsSetupRsp.LinkIdentifier.RespStaAddr[0],
+ sizeof(tSirMacAddr)) ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("TDLS setup RSP peer = %02x,%02x,%02x,%02x,%02x,%02x\n"),
+ peerMac[0],
+ peerMac[1],
+ peerMac[2],
+ peerMac[3],
+ peerMac[4],
+ peerMac[5]) ;
+ limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
+
+ if(NULL == setupPeer)
+ {
+ limLog( pMac, LOGE, FL(" unknown setup Response frame \
+ other BSS\n")) ;
+ return eSIR_FAILURE ;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("deactivating Setup RSP timer\n")) ;
+
+ /* Deactivate the timer */
+ tx_timer_deactivate(&(setupPeer)->gLimTdlsLinkSetupRspTimeoutTimer) ;
+
+ /*
+ * TDLS Setup RSP is recieved with Failure, Delete this STA entry
+ * don't respond with TDLS CNF frame.
+ */
+ if(TDLS_SETUP_STATUS_SUCCESS != tdlsSetupRsp.Status.status)
+ {
+ limTdlsDelLinkPeer(pMac, (setupPeer)->peerMac) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("setup RSP with Failure Code\n")) ;
+ return eSIR_FAILURE ;
+ }
+
+ /* update Link Info */
+ limTdlsUpdateLinkRspPeerInfo(pMac, setupPeer, &tdlsSetupRsp) ;
+
+ /* TODO, do more validation */
+
+
+ /*
+ * Now we are sure to send link setup CNF frame to TDLS link setup
+ * reponded, now we will create dph hash entry and send add STA to HAL
+ */
+
+ pMac->lim.gLimAddStaTdls = true ;
+ if(eSIR_FAILURE == limTdlsSetupAddSta(pMac, peerMac,
+ setupPeer, psessionEntry))
+ {
+ /* through error */
+ VOS_ASSERT(0) ;
+ return eSIR_FAILURE ;
+ }
+ /* TDLS_HKLEE_FIXME: now we add some delay for AddSta_Rsp comes */
+
+
+ /* send TDLS confim frame to TDLS Peer STA */
+ limSendTdlsLinkSetupCnfFrame(pMac, peerMac, tdlsSetupRsp.DialogToken.token, psessionEntry, NULL, 0) ;
+
+ /*
+ * set the tdls_link_state to TDLS_LINK_SETUP_RSP_WAIT_STATE, and
+ * wait for Setup CNF transmission on air, once we receive tx complete
+ * message, we will change the peer state and send message to SME
+ * callback..
+ */
+ (setupPeer)->tdls_prev_link_state = (setupPeer)->tdls_link_state ;
+ (setupPeer)->tdls_link_state = TDLS_LINK_SETUP_RSP_WAIT_STATE ;
+
+ return eSIR_SUCCESS ;
+}
+/*
+ * TDLS setup CNF frame processing ..
+ */
+
+static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac,
+ tANI_U8 *pBody, tANI_U32 frmLen)
+{
+ tDot11fTDLSSetupCnf tdlsSetupCnf = {{0}} ;
+ tANI_U32 status = 0 ;
+ tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+ tpPESession psessionEntry = NULL ;
+ tANI_U8 sessionId = 0 ;
+
+ status = dot11fUnpackTDLSSetupCnf(pMac, pBody, frmLen, &tdlsSetupCnf) ;
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \
+ frame (0x%08x, %d bytes):\n"),status, frmLen);
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while unpacking an\
+ TDLS discovery Response frame (0x%08x," "%d bytes):\n"),
+ status, frmLen );
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ }
+ /*
+ * find session entry using BSSID in link identifier, not using MAC
+ * header beacuse, there is cases in TDLS, there may be BSSID will not
+ * be present in header
+ */
+ psessionEntry = peFindSessionByBssid(pMac,
+ &tdlsSetupCnf.LinkIdentifier.bssid[0], &sessionId) ;
+ if(NULL == psessionEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
+ ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
+ tdlsSetupCnf.LinkIdentifier.bssid[0],
+ tdlsSetupCnf.LinkIdentifier.bssid[1],
+ tdlsSetupCnf.LinkIdentifier.bssid[2],
+ tdlsSetupCnf.LinkIdentifier.bssid[3],
+ tdlsSetupCnf.LinkIdentifier.bssid[4],
+ tdlsSetupCnf.LinkIdentifier.bssid[5]) ;
+
+ //VOS_ASSERT(0) ;
+ return eSIR_FAILURE;
+ }
+
+ /* varify BSSID */
+ status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
+ &tdlsSetupCnf.LinkIdentifier.bssid[0],
+ sizeof(tSirMacAddr)) ;
+
+ if(!status)
+ {
+ limLog( pMac, LOGE, FL("TDLS setup CNF frame other BSS -> something wrong. Check RXP filter\n")) ;
+
+ VOS_ASSERT(0) ;
+ return eSIR_FAILURE ;
+ }
+ /* TODO, do more validation */
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("setup Cnf peer MAc = %02x,%02x,%02x,%02x,%02x,%02x\n"),
+ tdlsSetupCnf.LinkIdentifier.InitStaAddr[0],
+ tdlsSetupCnf.LinkIdentifier.InitStaAddr[1],
+ tdlsSetupCnf.LinkIdentifier.InitStaAddr[2],
+ tdlsSetupCnf.LinkIdentifier.InitStaAddr[3],
+ tdlsSetupCnf.LinkIdentifier.InitStaAddr[4],
+ tdlsSetupCnf.LinkIdentifier.InitStaAddr[5]
+ ) ;
+
+ limTdlsFindLinkPeer(pMac,
+ &tdlsSetupCnf.LinkIdentifier.InitStaAddr[0],
+ &setupPeer) ;
+
+ if(NULL == setupPeer)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ (" unknown setup CNF frame\n")) ;
+ VOS_ASSERT(0) ;
+ return eSIR_FAILURE ;
+ }
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("setup CNF peer MAC = %02x,%02x,%02x,%02x,%02x,%02x\n"),
+ (setupPeer)->peerMac[0],
+ (setupPeer)->peerMac[1],
+ (setupPeer)->peerMac[2],
+ (setupPeer)->peerMac[3],
+ (setupPeer)->peerMac[4],
+ (setupPeer)->peerMac[5]) ;
+ /*T match dialog token, before proceeding further */
+ if((setupPeer)->dialog != tdlsSetupCnf.DialogToken.token)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("setup CNF frame not matching with setup RSP\n")) ;
+ VOS_ASSERT(0) ;
+ return eSIR_FAILURE ;
+ }
+
+ /*
+ * Now we are sure that, this set CNF is for us, now stop
+ * the running timer..
+ */
+ tx_timer_deactivate(&(setupPeer)->gLimTdlsLinkSetupCnfTimeoutTimer) ;
+
+ /* change TDLS peer State */
+ (setupPeer)->tdls_prev_link_state = (setupPeer)->tdls_link_state ;
+ (setupPeer)->tdls_link_state = TDLS_LINK_SETUP_DONE_STATE ;
+
+ /* send indication to SME that, new link is setup */
+ limSendSmeTdlsLinkSetupInd(pMac, (setupPeer)->peerMac, eSIR_SUCCESS) ;
+
+ /* tdls_hklee: prepare PTI template and send it to HAL */
+ limTdlsLinkEstablish(pMac, (setupPeer)->peerMac);
+
+ return eSIR_SUCCESS ;
+
+}
+
+/*
+ * TDLS discovery response frame processing ..
+ */
+
+static tSirRetStatus limProcessTdlsDisRspFrame(tpAniSirGlobal pMac,
+ tANI_U8 *pBody, tANI_U32 frmLen,
+ tANI_S8 rssi, tpPESession psessionEntry)
+{
+ tDot11fTDLSDisRsp tdlsDisRsp = {{0}} ;
+ tANI_U32 status = 0 ;
+ tLimDisResultList *tdlsDisResult = NULL ;
+ tLimDisResultList **disResultList = &pMac->lim.gLimTdlsDisResultList ;
+ tSirTdlsDisReq *prevDisReq = &pMac->lim.gLimTdlsDisReq ;
+
+ status = dot11fUnpackTDLSDisRsp(pMac, pBody, frmLen, &tdlsDisRsp) ;
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \
+ frame (0x%08x, %d bytes):\n"),status, frmLen);
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while unpacking an\
+ TDLS discovery Response frame (0x%08x," "%d bytes):\n"),
+ status, frmLen );
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);)
+ }
+ /*TODO: match dialog token, before proceeding further */
+
+ /* varify BSSID */
+ status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
+ &tdlsDisRsp.LinkIdentifier.bssid[0],
+ sizeof(tSirMacAddr)) ;
+
+ if(!status)
+ {
+ limLog( pMac, LOGW, FL(" TDLS discovery Response frame other BSS\n")) ;
+ return eSIR_FAILURE ;
+ }
+ /* TODO, do more validation */
+
+ if(tdlsDisRsp.DialogToken.token != prevDisReq->dialog)
+ {
+ limLog( pMac, LOGW, FL(" wrong TDLS discovery Response frame\n")) ;
+ return eSIR_FAILURE ;
+ }
+
+ pMac->lim.gLimTdlsDisStaCount++ ;
+
+ /*
+ * we are allocating peer info for individual peers found in TDLS
+ * discovery, we need to keep adding TDLS peers till we have timed
+ * out. We are freeing this memory at the time we are sending this
+ * collected peer info to SME.
+ */
+ status = palAllocateMemory(pMac->hHdd, (void **)&tdlsDisResult,
+ sizeof(tLimDisResultList)) ;
+
+ if(status != eHAL_STATUS_SUCCESS)
+ {
+ limLog(pMac, LOGP, FL("alloc fail for TDLS discovery reponse info\n")) ;
+ return eSIR_FAILURE ;
+ }
+
+ do
+ {
+ tSirTdlsPeerInfo *peerInfo = &tdlsDisResult->tdlsDisPeerInfo ;
+
+ /* Populate peer info of tdls discovery result */
+ peerInfo->sessionId = psessionEntry->peSessionId;
+ /*
+ * When we receive DIS RSP from peer MAC,
+ * STA_MAC_OFFSET will carry peer MAC address and PEER MAC OFFSET
+ * will carry our MAC.
+ */
+ status = palCopyMemory(pMac->hHdd, peerInfo->peerMac,
+ &tdlsDisRsp.LinkIdentifier.RespStaAddr[0],
+ sizeof(tSirMacAddr)) ;
+
+ /* update RSSI for this TDLS peer STA */
+ peerInfo->tdlsPeerRssi = rssi ;
+
+ /* update Caps Info */
+ tdlsUpdateCapInfo(&peerInfo->capabilityInfo ,
+ &tdlsDisRsp.Capabilities) ;
+
+ /* update Supp rates */
+ if(tdlsDisRsp.SuppRates.present)
+ {
+ ConvertSuppRates( pMac, &peerInfo->tdlsPeerSuppRates,
+ &tdlsDisRsp.SuppRates );
+ }
+
+ /* update EXT supp rates */
+ if(tdlsDisRsp.ExtSuppRates.present)
+ {
+ peerInfo->ExtRatesPresent = 1;
+ ConvertExtSuppRates( pMac, &peerInfo->tdlsPeerExtRates,
+ &tdlsDisRsp.ExtSuppRates );
+ }
+ /* update HT caps */
+ if (tdlsDisRsp.HTCaps.present)
+ {
+ palCopyMemory( pMac, &peerInfo->tdlsPeerHtCaps, &tdlsDisRsp.HTCaps,
+ sizeof( tDot11fIEHTCaps ) );
+ }
+ /* update EXT caps */
+ if (tdlsDisRsp.ExtCap.present)
+ {
+ //palCopyMemory( pMac, &peerInfo->tdlsPeerExtenCaps,
+ // &tdlsDisRsp.ExtCap,
+ // sizeof( tDot11fIEExtCap ) );
+ }
+ } while(0) ;
+
+ /* now add this new found discovery node into tdls discovery list */
+ tdlsDisResult->next = *disResultList ;
+ *disResultList = tdlsDisResult ;
+
+ return eSIR_SUCCESS ;
+}
+
+/*
+ * Process TDLS Teardown request frame from TDLS peer STA
+ */
+static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac,
+ tANI_U8 *pBody, tANI_U32 frmLen )
+{
+ tDot11fTDLSTeardown tdlsTeardown = {{0}} ;
+ tANI_U32 status = 0 ;
+ tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+ tpPESession psessionEntry = NULL ;
+ tANI_U8 sessionId = 0 ;
+
+ status = dot11fUnpackTDLSTeardown(pMac, pBody, frmLen, &tdlsTeardown) ;
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \
+ frame (0x%08x, %d bytes):\n"),status, frmLen);
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while unpacking an\
+ TDLS discovery Response frame (0x%08x," "%d bytes):\n"),
+ status, frmLen );
+ PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
+ }
+
+ /*
+ * find session entry using BSSID in link identifier, not using MAC
+ * header beacuse, there is cases in TDLS, there may be BSSID will not
+ * be present in header
+ */
+ psessionEntry = peFindSessionByBssid(pMac,
+ &tdlsTeardown.LinkIdentifier.bssid[0], &sessionId) ;
+ if(NULL == psessionEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
+ ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
+ tdlsTeardown.LinkIdentifier.bssid[0],
+ tdlsTeardown.LinkIdentifier.bssid[1],
+ tdlsTeardown.LinkIdentifier.bssid[2],
+ tdlsTeardown.LinkIdentifier.bssid[3],
+ tdlsTeardown.LinkIdentifier.bssid[4],
+ tdlsTeardown.LinkIdentifier.bssid[5]) ;
+
+ //VOS_ASSERT(0) ;
+ return eSIR_FAILURE;
+ }
+
+ /* varify BSSID */
+ status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
+ &tdlsTeardown.LinkIdentifier.bssid[0],
+ sizeof(tSirMacAddr)) ;
+
+
+ if(!status)
+ {
+ limLog( pMac, LOGE, FL("Teardown from other BSS -> something wrong. Check RXP filter\n")) ;
+ VOS_ASSERT(0) ;
+ return eSIR_FAILURE ;
+ }
+
+ limTdlsFindLinkPeer(pMac,
+ &tdlsTeardown.LinkIdentifier.InitStaAddr[0],
+ &setupPeer) ;
+
+ if(NULL == setupPeer)
+ {
+ //ignore
+ //VOS_ASSERT(0) ;
+ limLog( pMac, LOGE, FL("Teardown from unknown peer. --> ignored\n") );
+
+ return eSIR_FAILURE ;
+ }
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("teardown for peer %02x,%02x,%02x,%02x,%02x,%02x\n"),
+ (setupPeer)->peerMac[0],
+ (setupPeer)->peerMac[1],
+ (setupPeer)->peerMac[2],
+ (setupPeer)->peerMac[3],
+ (setupPeer)->peerMac[4],
+ (setupPeer)->peerMac[5]) ;
+
+ switch(tdlsTeardown.Reason.code)
+ {
+ case eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON:
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("teardown with unspecified reason\n")) ;
+ break ;
+ }
+ case eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE:
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ (" Teardown from AP, TDLS peer unreachable\n")) ;
+ break ;
+ }
+ default:
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ (" unknown teardown\n")) ;
+ break ;
+ }
+ }
+
+ /* change TDLS peer State */
+ (setupPeer)->tdls_prev_link_state = (setupPeer)->tdls_link_state ;
+ (setupPeer)->tdls_link_state = TDLS_LINK_TEARDOWN_START_STATE ;
+
+ do
+ {
+ tpDphHashNode pStaDs = NULL ;
+
+ /* tdls_hklee: send message to HAL before it is deleted, cause */
+ limTdlsLinkTeardown(pMac, (setupPeer)->peerMac) ;
+
+ /* send del STA to remove context for this TDLS STA */
+ pStaDs = limTdlsDelSta(pMac, (setupPeer)->peerMac, psessionEntry) ;
+
+ /* now send indication to SME-->HDD->TL to remove STA from TL */
+
+ if(pStaDs)
+ {
+ limSendSmeTdlsDelPeerInd(pMac, psessionEntry->smeSessionId,
+ pStaDs, eSIR_SUCCESS) ;
+
+ /* send Teardown Ind to SME */
+ limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (setupPeer)->peerMac,
+ eWNI_SME_TDLS_TEARDOWN_IND) ;
+ /* remove node from setup list */
+ limTdlsDelLinkPeer(pMac, (setupPeer)->peerMac) ;
+ }
+
+ }while(0) ;
+
+ return status ;
+}
+
+/*
+ * Common processing of TDLS action frames recieved
+ */
+void limProcessTdlsFrame(tpAniSirGlobal pMac, tANI_U32 *pBd)
+{
+ tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pBd);
+ tANI_U8 pOffset = ((0 == WDA_GET_RX_FT_DONE(pBd))
+ ? (( sizeof( eth_890d_header ))) :(0)) ;
+
+ tANI_U8 category = (pBody + pOffset + PAYLOAD_TYPE_TDLS_SIZE)[0] ;
+ tANI_U8 action = (pBody + pOffset + PAYLOAD_TYPE_TDLS_SIZE)[1] ;
+ tANI_U32 frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd) ;
+ tANI_U8 *tdlsFrameBody = (pBody + pOffset + PAYLOAD_TYPE_TDLS_SIZE) ;
+ //tANI_S8 rssi = (tANI_S8)SIR_MAC_BD_TO_RSSI_DB(pBd);
+
+ if(category != SIR_MAC_ACTION_TDLS)
+ {
+ limLog( pMac, LOGE, FL("Invalid TDLS action frame=(%d). Ignored\n"), category );
+ return ;
+ }
+
+ frameLen -= (pOffset + PAYLOAD_TYPE_TDLS_SIZE) ;
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Received TDLS action %d (%s)"), \
+ action, limTraceTdlsActionString(action) ));
+
+ switch(action)
+ {
+
+ case SIR_MAC_TDLS_SETUP_REQ:
+ {
+ limProcessTdlsSetupReqFrame(pMac, tdlsFrameBody, frameLen) ;
+ break ;
+ }
+ case SIR_MAC_TDLS_SETUP_RSP:
+ {
+ limProcessTdlsSetupRspFrame(pMac, tdlsFrameBody, frameLen) ;
+ break ;
+ }
+ case SIR_MAC_TDLS_SETUP_CNF:
+ {
+ limProcessTdlsSetupCnfFrame(pMac, tdlsFrameBody, frameLen) ;
+ break ;
+ }
+ case SIR_MAC_TDLS_TEARDOWN:
+ {
+ limProcessTdlsTeardownFrame(pMac, tdlsFrameBody, frameLen) ;
+ break ;
+ }
+ case SIR_MAC_TDLS_DIS_REQ:
+ {
+ limProcessTdlsDisReqFrame(pMac, tdlsFrameBody, frameLen) ;
+ break ;
+ }
+ case SIR_MAC_TDLS_PEER_TRAFFIC_IND:
+ case SIR_MAC_TDLS_CH_SWITCH_REQ:
+ case SIR_MAC_TDLS_CH_SWITCH_RSP:
+ case SIR_MAC_TDLS_PEER_TRAFFIC_RSP:
+ default:
+ {
+ break ;
+ }
+ }
+
+ return ;
+}
+
+/*
+ * ADD sta for dis response fame sent on direct link
+ */
+static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
+ tSirTdlsPeerInfo *peerInfo, tpPESession psessionEntry)
+{
+ tpDphHashNode pStaDs = NULL ;
+ tSirRetStatus status = eSIR_SUCCESS ;
+ tANI_U16 aid = 0 ;
+
+ if(NULL == peerInfo)
+ {
+ VOS_ASSERT(0) ;
+ return status ;
+
+ }
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("ADD STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x\n"),
+ peerMac[0],
+ peerMac[1],
+ peerMac[2],
+ peerMac[3],
+ peerMac[4],
+ peerMac[5]) ;
+
+
+ if(NULL != dphLookupHashEntry(pMac, peerMac,
+ &aid, &psessionEntry->dph.dphHashTable))
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ (" there is hash entry for this client\n")) ;
+ status = eSIR_FAILURE ;
+ VOS_ASSERT(0) ;
+ return status ;
+ }
+
+ aid = limAssignAID(pMac) ;
+
+ pStaDs = dphGetHashEntry(pMac, aid, &psessionEntry->dph.dphHashTable);
+
+ if (pStaDs)
+ {
+ (void) limDelSta(pMac, pStaDs, false /*asynchronous*/, psessionEntry);
+ limDeleteDphHashEntry(pMac, pStaDs->staAddr, aid, psessionEntry);
+ }
+ pStaDs = dphAddHashEntry(pMac, peerMac, aid,
+ &psessionEntry->dph.dphHashTable) ;
+
+ if(NULL == pStaDs)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ (" add hash entry failed\n")) ;
+ status = eSIR_FAILURE ;
+ VOS_ASSERT(0) ;
+ return status;
+ }
+ if(eSIR_SUCCESS == status)
+ {
+#ifdef TDLS_RATE_DEBUG
+ tSirMacRateSet *suppRates = &peerInfo->tdlsPeerSuppRates ;
+ tSirMacRateSet *extRates = &peerInfo->tdlsPeerExtRates ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("pSta DS [%p] \n"), pStaDs) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("peerInfo->tdlsPeerSuppRates = [%p]\n"),
+ (tANI_U8 *)&peerInfo->tdlsPeerSuppRates) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("peerInfo->tdlsPeerExtRates = [%p]\n"),
+ (tANI_U8 *)&peerInfo->tdlsPeerExtRates) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("peerInfo->tdlsPeerPropRates = [%p]\n"),
+ (tANI_U8 *)&pStaDs->mlmStaContext.propRateSet) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("peerInfo->mcs = [%p]\n"),
+ (tANI_U8 *)peerInfo->supportedMCSSet) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("num of supp rates = %02x\n"), suppRates->numRates) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("num of ext rates = %01x\n"), extRates->numRates) ;
+#endif
+
+ /* Populate matching rate set */
+#ifdef WLAN_FEATURE_11AC
+ if(eSIR_FAILURE == limPopulateMatchingRateSet(pMac, pStaDs,
+ &peerInfo->tdlsPeerSuppRates,
+ &peerInfo->tdlsPeerExtRates,
+ peerInfo->supportedMCSSet,
+ &pStaDs->mlmStaContext.propRateSet,
+ psessionEntry, NULL))
+#else
+ if(eSIR_FAILURE == limPopulateMatchingRateSet(pMac, pStaDs,
+ &peerInfo->tdlsPeerSuppRates,
+ &peerInfo->tdlsPeerExtRates,
+ peerInfo->supportedMCSSet,
+ &pStaDs->mlmStaContext.propRateSet,
+ psessionEntry))
+#endif
+ {
+ VOS_ASSERT(0) ;
+ }
+
+
+ pStaDs->mlmStaContext.capabilityInfo = peerInfo->capabilityInfo;
+ palCopyMemory(pMac->hHdd, pStaDs->staAddr, peerMac,
+ sizeof(tSirMacAddr)) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Add STA for Peer: %02x, %02x, %02x, %02x, %02x, %02x\n"),
+ pStaDs->staAddr[0],
+ pStaDs->staAddr[1],
+ pStaDs->staAddr[2],
+ pStaDs->staAddr[3],
+ pStaDs->staAddr[4],
+ pStaDs->staAddr[5]) ;
+
+
+ pStaDs->staType = STA_ENTRY_TDLS_PEER ;
+
+ status = limAddSta(pMac, pStaDs, psessionEntry);
+
+ if(eSIR_SUCCESS != status)
+ {
+ /* should not fail */
+ VOS_ASSERT(0) ;
+ }
+ }
+
+ return status ;
+}
+#endif
+/*
+ * Add STA for TDLS setup procedure
+ */
+static tSirRetStatus limTdlsSetupAddSta(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, tLimTdlsLinkSetupPeer *setupPeer,
+ tpPESession psessionEntry)
+{
+ tpDphHashNode pStaDs = NULL ;
+ tSirRetStatus status = eSIR_SUCCESS ;
+ tANI_U16 aid = 0 ;
+
+ if(NULL != dphLookupHashEntry(pMac, peerMac, &aid,
+ &psessionEntry->dph.dphHashTable))
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ (" there is hash entry for this client\n")) ;
+ status = eSIR_FAILURE ;
+ /* TDLS_TODO: I have seen this VOS ASSERT happened. must handle this (called from limProcessTdlsSetupReqFrame) */
+ VOS_ASSERT(0) ;
+ return status ;
+ }
+ aid = limAssignAID(pMac) ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Aid = %d, for peer = %02x,%02x,%02x,%02x,%02x,%02x\n"),
+ aid, peerMac[0],peerMac[1],peerMac[2],
+ peerMac[3],peerMac[4],peerMac[5]) ;
+ pStaDs = dphGetHashEntry(pMac, aid, &psessionEntry->dph.dphHashTable);
+
+ if (pStaDs)
+ {
+ (void) limDelSta(pMac, pStaDs, false /*asynchronous*/, psessionEntry);
+ limDeleteDphHashEntry(pMac, pStaDs->staAddr, aid, psessionEntry);
+ }
+
+ pStaDs = dphAddHashEntry(pMac, peerMac, aid,
+ &psessionEntry->dph.dphHashTable) ;
+
+ if(NULL == pStaDs)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ (" add hash entry failed\n")) ;
+ status = eSIR_FAILURE ;
+ VOS_ASSERT(0) ;
+ }
+
+ limTdlsUpdateHashNodeInfo(pMac, pStaDs, setupPeer, psessionEntry) ;
+
+ pStaDs->staType = STA_ENTRY_TDLS_PEER ;
+
+ status = limAddSta(pMac, pStaDs, psessionEntry);
+
+ if(eSIR_SUCCESS != status)
+ {
+ /* should not fail */
+ VOS_ASSERT(0) ;
+ }
+ return status ;
+}
+
+/*
+ * Del STA, after Link is teardown or discovery response sent on direct link
+ */
+static tpDphHashNode limTdlsDelSta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
+ tpPESession psessionEntry)
+{
+ tSirRetStatus status = eSIR_SUCCESS ;
+ tANI_U16 aid = 0 ;
+ tpDphHashNode pStaDs = NULL ;
+
+ pStaDs = dphLookupHashEntry(pMac, peerMac, &aid,
+ &psessionEntry->dph.dphHashTable) ;
+
+ if(pStaDs)
+ {
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("DEL STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x \n"),
+ pStaDs->staAddr[0],
+ pStaDs->staAddr[1],
+ pStaDs->staAddr[2],
+ pStaDs->staAddr[3],
+ pStaDs->staAddr[4],
+ pStaDs->staAddr[5]
+ ) ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("STA type = %x, sta idx = %x\n"),pStaDs->staType,
+ pStaDs->staIndex) ;
+
+ status = limDelSta(pMac, pStaDs, false, psessionEntry) ;
+ if(eSIR_SUCCESS == status)
+ {
+ limDeleteDphHashEntry(pMac, pStaDs->staAddr, aid, psessionEntry) ;
+ limReleaseAID(pMac, aid) ;
+ }
+ else
+ {
+ VOS_ASSERT(0) ;
+ }
+ }
+
+ return pStaDs ;
+}
+
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+/*
+* Prepare link establish message for HAL, construct PTI template.
+*
+*/
+static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerMac)
+{
+ tANI_U8 pFrame[64] ;
+ tDot11fTDLSPeerTrafficInd tdlsPtiTemplate ;
+ tANI_U32 status = 0 ;
+ tANI_U32 nPayload = 0 ;
+ tANI_U32 nBytes = 0 ;
+ tANI_U32 header_offset = 0 ;
+ tANI_U16 aid = 0 ;
+ tDphHashNode *pStaDs = NULL ;
+ tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+ tpPESession psessionEntry = NULL ;
+
+
+ limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
+ if(NULL == setupPeer) {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("limTdlsLinkEstablish: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X\n"), \
+ peerMac[0], peerMac[1], peerMac[2], \
+ peerMac[3], peerMac[4], peerMac[5]);
+ return eSIR_FAILURE;
+ }
+
+ psessionEntry = peFindSessionBySessionId(pMac,
+ setupPeer->tdls_sessionId) ;
+
+ if(NULL == psessionEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("limTdlsLinkEstablish: sessionID %d is not found\n"), setupPeer->tdls_sessionId);
+ VOS_ASSERT(0) ;
+ return eHAL_STATUS_FAILURE;
+ }
+
+ /* */
+ pStaDs = dphLookupHashEntry(pMac, peerMac, &aid, &psessionEntry->dph.dphHashTable) ;
+ if(pStaDs == NULL) {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("limTdlsLinkEstablish: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X\n"), \
+ peerMac[0], peerMac[1], peerMac[2], \
+ peerMac[3], peerMac[4], peerMac[5]);
+ return eSIR_FAILURE;
+ }
+
+ palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsPtiTemplate,
+ sizeof( tDot11fTDLSPeerTrafficInd ) );
+
+ /*
+ * setup Fixed fields,
+ */
+ tdlsPtiTemplate.Category.category = SIR_MAC_ACTION_TDLS;
+ tdlsPtiTemplate.Action.action = SIR_MAC_TDLS_PEER_TRAFFIC_IND;
+ tdlsPtiTemplate.DialogToken.token = 0 ; /* filled by firmware at the time of transmission */
+#if 1
+ /* CHECK_PTI_LINK_IDENTIFIER_INITIATOR_ADDRESS: initator address should be TDLS link setup's initiator address,
+ then below code makes such an way */
+ PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsPtiTemplate.LinkIdentifier,
+ peerMac, !setupPeer->tdls_bIsResponder) ;
+#else
+ /* below code will make PTI's linkIdentifier's initiator address be selfAddr */
+ PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsPtiTemplate.LinkIdentifier,
+ peerMac, TDLS_INITIATOR) ;
+#endif
+
+ /* PUBufferStatus will be filled by firmware at the time of transmission */
+ tdlsPtiTemplate.PUBufferStatus.present = 1;
+
+ /* TODO: get ExtendedCapabilities IE */
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11fGetPackedTDLSPeerTrafficIndSize ( pMac, &tdlsPtiTemplate, &nPayload);
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to calculate the packed size for a PTI template (0x%08x).\n"), status );
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof( tdlsPtiTemplate );
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while calculating the packed size for a PTI template (0x%08x).\n"), status );
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+ nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ + sizeof( eth_890d_header )
+ + PAYLOAD_TYPE_TDLS_SIZE ;
+
+ if(nBytes > 64) {
+ limLog( pMac, LOGE, FL("required memory for PTI frame is %ld, but reserved only 64.\n"), nBytes);
+ nBytes = 64;
+ }
+ /* zero out the memory */
+ palZeroMemory( pMac->hHdd, pFrame, sizeof(pFrame) );
+
+ /* fill out the buffer descriptor */
+
+ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET(tdlsPtiTemplate), TDLS_LINK_AP, !setupPeer->tdls_bIsResponder, psessionEntry) ;
+
+ status = dot11fPackTDLSPeerTrafficInd ( pMac, &tdlsPtiTemplate, pFrame
+ + header_offset, nPayload, &nPayload );
+
+ if ( DOT11F_FAILED( status ) )
+ {
+ limLog( pMac, LOGE, FL("Failed to pack a PTI template \
+ (0x%08x).\n"), status );
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( status ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
+ "Peer Traffic Indication (0x%08x).\n") );
+ }
+
+ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("bIsResponder=%d, header_offset=%ld, linkIdenOffset=%d, ptiBufStatusOffset=%d \n"), \
+ setupPeer->tdls_bIsResponder, header_offset, PTI_LINK_IDEN_OFFSET, PTI_BUF_STATUS_OFFSET));
+
+ limSendTdlsLinkEstablish(pMac, setupPeer->tdls_bIsResponder,
+ header_offset+PTI_LINK_IDEN_OFFSET, header_offset+PTI_BUF_STATUS_OFFSET,
+ nBytes, pFrame, (tANI_U8 *)&setupPeer->tdlsPeerExtCaps);
+
+ return eSIR_SUCCESS;
+}
+
+/*
+* Prepare link teardown message for HAL from peer_mac
+*
+*/
+static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peerMac)
+{
+ tDphHashNode *pStaDs = NULL ;
+ tANI_U16 aid = 0 ;
+ tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+ tpPESession psessionEntry = NULL ;
+
+
+ limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
+ if(NULL == setupPeer) {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("limTdlsLinkTeardown: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X\n"), \
+ peerMac[0], peerMac[1], peerMac[2], \
+ peerMac[3], peerMac[4], peerMac[5]);
+ return eSIR_FAILURE;
+ }
+
+ psessionEntry = peFindSessionBySessionId(pMac,
+ setupPeer->tdls_sessionId) ;
+
+ if(NULL == psessionEntry)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("limTdlsLinkTeardown: sessionID %d is not found\n"), setupPeer->tdls_sessionId);
+ VOS_ASSERT(0) ;
+ return eHAL_STATUS_FAILURE;
+ }
+
+
+ /* */
+ pStaDs = dphLookupHashEntry(pMac, peerMac, &aid, &psessionEntry->dph.dphHashTable);
+
+ if(pStaDs == NULL) {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("limTdlsLinkTeardown: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X\n"), \
+ peerMac[0], peerMac[1], peerMac[2], \
+ peerMac[3], peerMac[4], peerMac[5]);
+ return eSIR_FAILURE;
+ }
+
+ limSendTdlsLinkTeardown(pMac, pStaDs->staIndex);
+
+ return eSIR_SUCCESS;
+}
+
+/*
+ * Prepare Discovery RSP message for SME, collect peerINfo for all the
+ * peers discovered and delete/clean discovery lists in PE.
+ */
+
+static tSirTdlsDisRsp *tdlsPrepareTdlsDisRsp(tpAniSirGlobal pMac,
+ tSirTdlsDisRsp *disRsp, tANI_U8 disStaCount)
+{
+ tANI_U32 disMsgRspSize = sizeof(tSirTdlsDisRsp);
+ tANI_U8 status = eHAL_STATUS_SUCCESS ;
+
+ /*
+ * allocate memory for tdls discovery response, allocated memory should
+ * be alloc_mem = tdlsStaCount * sizeof(peerinfo)
+ * + siezeof tSirTdlsDisRsp.
+ */
+ disMsgRspSize += (disStaCount * sizeof(tSirTdlsPeerInfo));
+
+ /* now allocate memory */
+ status = palAllocateMemory( pMac->hHdd, (void **)&disRsp, disMsgRspSize ) ;
+
+ if(eHAL_STATUS_FAILURE == status)
+ {
+ limLog(pMac, LOGP, FL("palAllocateMemory failed for DIS RSP"));
+ return NULL ;
+ }
+
+ if(disStaCount)
+ {
+ tLimDisResultList *tdlsDisRspList = pMac->lim.gLimTdlsDisResultList ;
+ tSirTdlsPeerInfo *peerInfo = &disRsp->tdlsDisPeerInfo[0] ;
+
+ tLimDisResultList *currentNode = tdlsDisRspList ;
+ while(tdlsDisRspList != NULL)
+ {
+
+ palCopyMemory( pMac->hHdd, (tANI_U8 *)peerInfo,
+ (tANI_U8 *) &tdlsDisRspList->tdlsDisPeerInfo,
+ sizeof(tSirTdlsPeerInfo));
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Msg Sent to PE, peer MAC: %02x, %02x, %02x, %02x, %02x, %02x\n"),
+ peerInfo->peerMac[0] ,
+ peerInfo->peerMac[1] ,
+ peerInfo->peerMac[2] ,
+ peerInfo->peerMac[3] ,
+ peerInfo->peerMac[4] ,
+ peerInfo->peerMac[5]) ;
+ disStaCount-- ;
+ peerInfo++ ;
+ currentNode = tdlsDisRspList ;
+ tdlsDisRspList = tdlsDisRspList->next ;
+ palFreeMemory(pMac->hHdd, currentNode) ;
+ /* boundary condition check, may be fatal */
+ if(((!disStaCount) && (tdlsDisRspList))
+ || ((!tdlsDisRspList) && disStaCount))
+ {
+ limLog(pMac, LOG1, FL("mismatch in dis sta count and\
+ and number of nodes in list\n")) ;
+ VOS_ASSERT(0) ;
+ return NULL ;
+ }
+ } /* end of while */
+
+ /* All discovery STA processed */
+ pMac->lim.gLimTdlsDisResultList = NULL ;
+
+ } /* end of if dis STA count */
+
+ return (disRsp) ;
+}
+
+/* Send Teardown response back to PE */
+
+void limSendSmeTdlsTeardownRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode,
+ tSirMacAddr peerMac, tANI_U16 msgType)
+{
+ tSirMsgQ mmhMsg = {0} ;
+ tSirTdlsTeardownRsp *teardownRspMsg = NULL ;
+ tANI_U8 status = eHAL_STATUS_SUCCESS ;
+
+ mmhMsg.type = msgType ;
+
+ status = palAllocateMemory( pMac->hHdd, (void **)&teardownRspMsg,
+ sizeof(tSirTdlsTeardownRsp)) ;
+
+ if(eHAL_STATUS_SUCCESS != status)
+ {
+ VOS_ASSERT(0) ;
+ }
+ palCopyMemory( pMac->hHdd, teardownRspMsg->peerMac, (tANI_U8 *)peerMac,
+ sizeof(tSirMacAddr)) ;
+ teardownRspMsg->statusCode = statusCode ;
+ mmhMsg.bodyptr = teardownRspMsg ;
+ mmhMsg.bodyval = 0;
+ limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+
+ return ;
+
+}
+
+/*
+ * Send Link start RSP back to SME after link is setup or failed
+ */
+void limSendSmeTdlsLinkStartRsp(tpAniSirGlobal pMac,
+ tSirResultCodes statusCode,
+ tSirMacAddr peerMac,
+ tANI_U16 msgType)
+{
+ tSirMsgQ mmhMsg = {0} ;
+ tSirTdlsLinksetupRsp *setupRspMsg = NULL ;
+ tANI_U8 status = eHAL_STATUS_SUCCESS ;
+
+ mmhMsg.type = msgType ;
+
+ status = palAllocateMemory( pMac->hHdd, (void **)&setupRspMsg,
+ sizeof(tSirTdlsLinksetupRsp)) ;
+
+ if(eHAL_STATUS_SUCCESS != status)
+ {
+ VOS_ASSERT(0) ;
+ }
+
+ palCopyMemory( pMac->hHdd, setupRspMsg->peerMac, (tANI_U8 *)peerMac,
+ sizeof(tSirMacAddr)) ;
+ setupRspMsg->statusCode = statusCode ;
+ mmhMsg.bodyptr = setupRspMsg ;
+ mmhMsg.bodyval = 0;
+ limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+
+ return ;
+}
+
+/*
+ * Send TDLS discovery RSP back to SME
+ */
+void limSendSmeTdlsDisRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode,
+ tANI_U16 msgType)
+{
+ tSirMsgQ mmhMsg = {0} ;
+ tSirTdlsDisRsp *tdlsDisRsp = NULL ;
+
+ mmhMsg.type = msgType ;
+
+ if(eSIR_SME_SUCCESS == statusCode)
+ {
+ tANI_U8 tdlsStaCount = pMac->lim.gLimTdlsDisStaCount ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("no of TDLS STA discovered: %d\n"), tdlsStaCount) ;
+ tdlsDisRsp = tdlsPrepareTdlsDisRsp(pMac, tdlsDisRsp, tdlsStaCount) ;
+
+ if(tdlsDisRsp)
+ {
+ tdlsDisRsp->numDisSta = tdlsStaCount ;
+ }
+ else
+ {
+ limLog(pMac, LOGP, FL("fatal failure for TDLS DIS RSP\n"));
+ VOS_ASSERT(0) ;
+ return ;
+ }
+ /* all Discovery STA is processed */
+ pMac->lim.gLimTdlsDisStaCount = 0 ;
+ }
+ else
+ {
+ tdlsDisRsp = tdlsPrepareTdlsDisRsp(pMac, tdlsDisRsp, 0) ;
+ }
+
+ tdlsDisRsp->statusCode = statusCode ;
+ mmhMsg.bodyptr = tdlsDisRsp ;
+ mmhMsg.bodyval = 0;
+ limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+
+ return ;
+}
+
+/*
+ * Once Link is setup with PEER, send Add STA ind to SME
+ */
+static eHalStatus limSendSmeTdlsAddPeerInd(tpAniSirGlobal pMac,
+ tANI_U8 sessionId, tDphHashNode *pStaDs, tANI_U8 status)
+{
+ tSirMsgQ mmhMsg = {0} ;
+ tSirTdlsPeerInd *peerInd = NULL ;
+ mmhMsg.type = eWNI_SME_ADD_TDLS_PEER_IND ;
+ if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &peerInd,
+ (sizeof(tSirTdlsPeerInd))))
+ {
+ PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
+ return eSIR_FAILURE;
+ }
+
+ palCopyMemory( pMac->hHdd, peerInd->peerMac,
+ (tANI_U8 *) pStaDs->staAddr, sizeof(tSirMacAddr));
+ peerInd->sessionId = sessionId;
+ peerInd->staId = pStaDs->staIndex ;
+ peerInd->ucastSig = pStaDs->ucUcastSig ;
+ peerInd->bcastSig = pStaDs->ucBcastSig ;
+ peerInd->length = sizeof(tSmeIbssPeerInd) ;
+
+ mmhMsg.bodyptr = peerInd ;
+ mmhMsg.bodyval = 0;
+ limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+
+ return eSIR_SUCCESS ;
+
+}
+
+/*
+ * Once link is teardown, send Del Peer Ind to SME
+ */
+static eHalStatus limSendSmeTdlsDelPeerInd(tpAniSirGlobal pMac,
+ tANI_U8 sessionId, tDphHashNode *pStaDs, tANI_U8 status)
+{
+ tSirMsgQ mmhMsg = {0} ;
+ tSirTdlsPeerInd *peerInd = NULL ;
+ mmhMsg.type = eWNI_SME_DELETE_TDLS_PEER_IND ;
+ if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &peerInd,
+ (sizeof(tSirTdlsPeerInd))))
+ {
+ PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
+ return eSIR_FAILURE;
+ }
+
+ palCopyMemory( pMac->hHdd, peerInd->peerMac,
+ (tANI_U8 *) pStaDs->staAddr, sizeof(tSirMacAddr));
+ peerInd->sessionId = sessionId;
+ peerInd->staId = pStaDs->staIndex ;
+ peerInd->ucastSig = pStaDs->ucUcastSig ;
+ peerInd->bcastSig = pStaDs->ucBcastSig ;
+ peerInd->length = sizeof(tSmeIbssPeerInd) ;
+
+ mmhMsg.bodyptr = peerInd ;
+
+ //peerInd->statusCode = status ;
+ mmhMsg.bodyval = 0;
+ limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+ return eSIR_SUCCESS ;
+
+}
+
+/*
+ * Send Link setup Ind to SME, This is the case where, link setup is
+ * initiated by peer STA
+ */
+static eHalStatus limSendSmeTdlsLinkSetupInd(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, tANI_U8 status)
+{
+ tSirMsgQ mmhMsg = {0} ;
+ tSirTdlsLinkSetupInd *setupInd = NULL ;
+
+ mmhMsg.type = eWNI_SME_TDLS_LINK_START_IND ;
+ if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &setupInd,
+ (sizeof(tSirTdlsLinkSetupInd))))
+ {
+ PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
+ return eSIR_FAILURE;
+ }
+
+ palCopyMemory( pMac->hHdd, setupInd->peerMac,
+ (tANI_U8 *) peerMac, sizeof(tSirMacAddr));
+ setupInd->length = sizeof(tSirTdlsLinkSetupInd);
+ setupInd->statusCode = status ;
+ mmhMsg.bodyptr = setupInd ;
+ mmhMsg.bodyval = 0;
+ limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+
+ return eSIR_SUCCESS ;
+
+}
+
+/*
+ * Setup RSP timer handler
+ */
+void limTdlsLinkSetupRspTimerHandler(void *pMacGlobal, tANI_U32 timerId)
+{
+
+ tANI_U32 statusCode;
+ tSirMsgQ msg;
+ tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal;
+
+ /* Prepare and post message to LIM Message Queue */
+
+ msg.type = SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT;
+ msg.bodyptr = NULL ;
+ msg.bodyval = timerId ;
+
+ if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS)
+ limLog(pMac, LOGE,
+ FL("posting message %X to LIM failed, reason=%d\n"),
+ msg.type, statusCode);
+ return ;
+}
+
+/*
+ * Link setup CNF timer
+ */
+void limTdlsLinkSetupCnfTimerHandler(void *pMacGlobal, tANI_U32 timerId)
+{
+
+ tANI_U32 statusCode;
+ tSirMsgQ msg;
+ tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal;
+
+ // Prepare and post message to LIM Message Queue
+
+ msg.type = SIR_LIM_TDLS_LINK_SETUP_CNF_TIMEOUT;
+ msg.bodyptr = NULL ;
+ msg.bodyval = timerId ;
+
+ if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS)
+ limLog(pMac, LOGE,
+ FL("posting message %X to LIM failed, reason=%d\n"),
+ msg.type, statusCode);
+ return ;
+}
+
+/*
+ * start TDLS timer
+ */
+void limStartTdlsTimer(tpAniSirGlobal pMac, tANI_U8 sessionId, TX_TIMER *timer,
+ tANI_U32 timerId, tANI_U16 timerType, tANI_U32 timerMsg)
+{
+ tANI_U32 cfgValue = (timerMsg == SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT)
+ ? WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT
+ : WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT ;
+
+ void *timerFunc = (timerMsg == SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT)
+ ? (limTdlsLinkSetupRspTimerHandler)
+ : limTdlsLinkSetupCnfTimerHandler ;
+
+ /* TODO: Read timer vals from CFG */
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ /*
+ * create TDLS discovery response wait timer and activate it
+ */
+ if (tx_timer_create(timer, "TDLS link setup timers", timerFunc,
+ timerId, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS)
+ {
+ limLog(pMac, LOGP,
+ FL("could not create TDLS discovery response wait timer\n"));
+ return;
+ }
+
+ //assign appropriate sessionId to the timer object
+ timer->sessionId = sessionId;
+
+ MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0,
+ eLIM_TDLS_DISCOVERY_RSP_WAIT));
+ if (tx_timer_activate(timer) != TX_SUCCESS)
+ {
+ limLog(pMac, LOGP, FL("TDLS link setup timer activation failed!\n"));
+ return ;
+ }
+
+ return ;
+
+}
+#endif
+
+/*
+ * Once Link is setup with PEER, send Add STA ind to SME
+ */
+static eHalStatus limSendSmeTdlsAddStaRsp(tpAniSirGlobal pMac,
+ tANI_U8 sessionId, tSirMacAddr peerMac, tDphHashNode *pStaDs,
+ tANI_U8 status)
+{
+ tSirMsgQ mmhMsg = {0} ;
+ tSirTdlsAddStaRsp *addStaRsp = NULL ;
+ mmhMsg.type = eWNI_SME_TDLS_ADD_STA_RSP ;
+ if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &addStaRsp,
+ (sizeof(tSirTdlsAddStaRsp))))
+ {
+ PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
+ return eSIR_FAILURE;
+ }
+
+ addStaRsp->sessionId = sessionId;
+ addStaRsp->statusCode = status;
+ if( pStaDs )
+ {
+ addStaRsp->staId = pStaDs->staIndex ;
+ addStaRsp->ucastSig = pStaDs->ucUcastSig ;
+ addStaRsp->bcastSig = pStaDs->ucBcastSig ;
+ }
+ if( peerMac )
+ {
+ palCopyMemory( pMac->hHdd, addStaRsp->peerMac,
+ (tANI_U8 *) peerMac, sizeof(tSirMacAddr));
+ }
+ addStaRsp->length = sizeof(tSirTdlsAddStaRsp) ;
+ addStaRsp->messageType = eWNI_SME_TDLS_ADD_STA_RSP ;
+
+ mmhMsg.bodyptr = addStaRsp;
+ mmhMsg.bodyval = 0;
+ limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+
+ return eSIR_SUCCESS ;
+
+}
+/*
+ * STA RSP received from HAL
+ */
+eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg,
+ tpPESession psessionEntry)
+{
+ tAddStaParams *pAddStaParams = (tAddStaParams *) msg ;
+ tANI_U8 status = eSIR_SUCCESS ;
+ tDphHashNode *pStaDs = NULL ;
+ tANI_U16 aid = 0 ;
+
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("ADD_STA_RSP received :staIdx=%d, staMac=%02x:%02x:%02x:%02x:%02x:%02x"), pAddStaParams->staIdx, \
+ pAddStaParams->staMac[0],
+ pAddStaParams->staMac[1],
+ pAddStaParams->staMac[2],
+ pAddStaParams->staMac[3],
+ pAddStaParams->staMac[4],
+ pAddStaParams->staMac[5] ) ;
+
+ if (pAddStaParams->status != eHAL_STATUS_SUCCESS)
+ {
+ VOS_ASSERT(0) ;
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("Add sta failed \n")) ;
+ status = eSIR_FAILURE;
+ goto add_sta_error;
+ }
+
+ pStaDs = dphLookupHashEntry(pMac, pAddStaParams->staMac, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if(NULL == pStaDs)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("pStaDs is NULL \n")) ;
+ status = eSIR_FAILURE;
+ goto add_sta_error;
+ }
+
+ pStaDs->bssId = pAddStaParams->bssIdx;
+ pStaDs->staIndex = pAddStaParams->staIdx;
+ pStaDs->ucUcastSig = pAddStaParams->ucUcastSig;
+ pStaDs->ucBcastSig = pAddStaParams->ucBcastSig;
+ pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
+ pStaDs->valid = 1 ;
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+ status = limSendSmeTdlsAddPeerInd(pMac, psessionEntry->smeSessionId,
+ pStaDs, eSIR_SUCCESS ) ;
+ if(eSIR_FAILURE == status)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("Peer IND msg to SME failed\n")) ;
+ palFreeMemory( pMac->hHdd, (void *) pAddStaParams );
+ return eSIR_FAILURE ;
+ }
+
+ /*
+ * Now, there is two things a) ADD STA RSP for ADD STA request sent
+ * after recieving discovery request from Peer.
+ * now we have to send discovery response, if there is any pending
+ * discovery equest..
+ */
+ do
+ {
+ tSirTdlsPeerInfo *peerInfo = limTdlsFindDisPeer(pMac,
+ pAddStaParams->staMac) ;
+
+
+ if(peerInfo)
+ {
+ /*
+ * send TDLS discovery response frame on direct link, state machine
+ * is rolling.., once discovery response is get Acked, we will
+ * send response to SME based on TxComplete callback results
+ */
+ limSendTdlsDisRspFrame(pMac, peerInfo->peerMac, peerInfo->dialog, psessionEntry) ;
+ peerInfo->tdlsPeerState = TDLS_DIS_RSP_SENT_WAIT_STATE ;
+ }
+ } while(0) ;
+#else
+ status = limSendSmeTdlsAddStaRsp(pMac, psessionEntry->smeSessionId,
+ pAddStaParams->staMac, pStaDs, status) ;
+ if(eSIR_FAILURE == status)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ ("Peer IND msg to SME failed\n")) ;
+ palFreeMemory( pMac->hHdd, (void *) pAddStaParams );
+ }
+ return status;
+
+#endif
+add_sta_error:
+ status = limSendSmeTdlsAddStaRsp(pMac, psessionEntry->smeSessionId,
+ pAddStaParams->staMac, NULL, status) ;
+ palFreeMemory( pMac->hHdd, (void *) pAddStaParams );
+ return status ;
+}
+
+/*
+ * FUNCTION: Populate Link Identifier element IE
+ *
+ */
+
+
+void PopulateDot11fLinkIden(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ tDot11fIELinkIdentifier *linkIden,
+ tSirMacAddr peerMac, tANI_U8 reqType)
+{
+ //tANI_U32 size = sizeof(tSirMacAddr) ;
+ tANI_U8 *initStaAddr = NULL ;
+ tANI_U8 *respStaAddr = NULL ;
+
+ (reqType == TDLS_INITIATOR) ? ((initStaAddr = linkIden->InitStaAddr),
+ (respStaAddr = linkIden->RespStaAddr))
+ : ((respStaAddr = linkIden->InitStaAddr ),
+ (initStaAddr = linkIden->RespStaAddr)) ;
+ palCopyMemory( pMac->hHdd, (tANI_U8 *)linkIden->bssid,
+ (tANI_U8 *) psessionEntry->bssId, sizeof(tSirMacAddr)) ;
+
+ palCopyMemory( pMac->hHdd, (tANI_U8 *)initStaAddr,
+ psessionEntry->selfMacAddr, sizeof(tSirMacAddr)) ;
+
+ palCopyMemory( pMac->hHdd, (tANI_U8 *)respStaAddr, (tANI_U8 *) peerMac,
+ sizeof( tSirMacAddr ));
+
+ linkIden->present = 1 ;
+ return ;
+
+}
+
+void PopulateDot11fTdlsExtCapability(tpAniSirGlobal pMac,
+ tDot11fIEExtCap *extCapability)
+{
+ extCapability->TDLSPeerPSMSupp = PEER_PSM_SUPPORT ;
+ extCapability->TDLSPeerUAPSDBufferSTA = PEER_BUFFER_STA_SUPPORT ;
+ extCapability->TDLSChannelSwitching = CH_SWITCH_SUPPORT ;
+ extCapability->TDLSSupport = TDLS_SUPPORT ;
+ extCapability->TDLSProhibited = TDLS_PROHIBITED ;
+ extCapability->TDLSChanSwitProhibited = TDLS_CH_SWITCH_PROHIBITED ;
+ extCapability->present = 1 ;
+ return ;
+}
+
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+/*
+ * Public Action frame common processing
+ * This Function will be moved/merged to appropriate place
+ * once other public action frames (particularly 802.11k)
+ * is in place
+ */
+void limProcessTdlsPublicActionFrame(tpAniSirGlobal pMac, tANI_U32 *pBd,
+ tpPESession psessionEntry)
+{
+ tANI_U32 frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd) ;
+ tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pBd) ;
+ tANI_S8 rssi = (tANI_S8)WDA_GET_RX_RSSI_DB(pBd) ;
+
+ limProcessTdlsDisRspFrame(pMac, pBody, frameLen, rssi, psessionEntry) ;
+ return ;
+}
+
+eHalStatus limTdlsPrepareSetupReqFrame(tpAniSirGlobal pMac,
+ tLimTdlsLinkSetupInfo *linkSetupInfo,
+ tANI_U8 dialog, tSirMacAddr peerMac,
+ tpPESession psessionEntry)
+{
+ tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+
+ /*
+ * we allocate the TDLS setup Peer Memory here, we will free'd this
+ * memory after teardown, if the link is successfully setup or
+ * free this memory if any timeout is happen in link setup procedure
+ */
+ if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd,
+ (void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer )))
+ {
+ limLog( pMac, LOGP,
+ FL( "Unable to allocate memory during ADD_STA\n" ));
+ VOS_ASSERT(0) ;
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ setupPeer->dialog = dialog ;
+ setupPeer->tdls_prev_link_state = setupPeer->tdls_link_state ;
+ setupPeer->tdls_link_state = TDLS_LINK_SETUP_START_STATE ;
+
+ /* TDLS_sessionize: remember sessionId for future */
+ setupPeer->tdls_sessionId = psessionEntry->peSessionId;
+ setupPeer->tdls_bIsResponder = 1;
+
+ /*
+ * we only populate peer MAC, so it can assit us to find the
+ * TDLS peer after response/or after response timeout
+ */
+ palCopyMemory(pMac->hHdd, setupPeer->peerMac, peerMac,
+ sizeof(tSirMacAddr)) ;
+ /* format TDLS discovery request frame and transmit it */
+ limSendTdlsLinkSetupReqFrame(pMac, peerMac, dialog, psessionEntry, NULL, 0) ;
+
+ limStartTdlsTimer(pMac, psessionEntry->peSessionId,
+ &setupPeer->gLimTdlsLinkSetupRspTimeoutTimer,
+ (tANI_U32)setupPeer->peerMac,
+ WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT,
+ SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT) ;
+ /* update setup peer list */
+ setupPeer->next = linkSetupInfo->tdlsLinkSetupList ;
+ linkSetupInfo->tdlsLinkSetupList = setupPeer ;
+
+ /* in case of success, eWNI_SME_TDLS_LINK_START_RSP is sent back to
+ * SME later when TDLS setup cnf TX complete is successful. --> see
+ * limTdlsSetupCnfTxComplete()
+ */
+ return eSIR_SUCCESS ;
+}
+#endif
+
+/*
+ * Process Send Mgmt Request from SME and transmit to AP.
+ */
+tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac,
+ tANI_U32 *pMsgBuf)
+{
+ /* get all discovery request parameters */
+ tSirTdlsSendMgmtReq *pSendMgmtReq = (tSirTdlsSendMgmtReq*) pMsgBuf ;
+ tpPESession psessionEntry;
+ tANI_U8 sessionId;
+ tSirResultCodes resultCode = eSIR_SME_INVALID_PARAMETERS;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Send Mgmt Recieved\n")) ;
+
+ if((psessionEntry = peFindSessionByBssid(pMac, pSendMgmtReq->bssid, &sessionId))
+ == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ "PE Session does not exist for given sme sessionId %d\n",
+ pSendMgmtReq->sessionId);
+ goto lim_tdls_send_mgmt_error;
+ }
+
+ /* check if we are in proper state to work as TDLS client */
+ if (psessionEntry->limSystemRole != eLIM_STA_ROLE)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ "send mgmt received in wrong system Role %d\n",
+ psessionEntry->limSystemRole);
+ goto lim_tdls_send_mgmt_error;
+ }
+
+ /*
+ * if we are still good, go ahead and check if we are in proper state to
+ * do TDLS discovery req/rsp/....frames.
+ */
+ if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE))
+ {
+
+ limLog(pMac, LOGE, "send mgmt received in invalid LIMsme \
+ state (%d)\n", psessionEntry->limSmeState);
+ goto lim_tdls_send_mgmt_error;
+ }
+
+ switch( pSendMgmtReq->reqType )
+ {
+ case SIR_MAC_TDLS_DIS_REQ:
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ "Transmit Discovery Request Frame\n") ;
+ /* format TDLS discovery request frame and transmit it */
+ limSendTdlsDisReqFrame(pMac, pSendMgmtReq->peerMac, pSendMgmtReq->dialog,
+ psessionEntry) ;
+ resultCode = eSIR_SME_SUCCESS;
+ break;
+ case SIR_MAC_TDLS_DIS_RSP:
+ {
+ //Send a response mgmt action frame
+ limSendTdlsDisRspFrame(pMac, pSendMgmtReq->peerMac,
+ pSendMgmtReq->dialog, psessionEntry) ;
+ resultCode = eSIR_SME_SUCCESS;
+ }
+ break;
+ case SIR_MAC_TDLS_SETUP_REQ:
+ {
+ limSendTdlsLinkSetupReqFrame(pMac,
+ pSendMgmtReq->peerMac, pSendMgmtReq->dialog, psessionEntry,
+ &pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq)));
+ resultCode = eSIR_SME_SUCCESS;
+ }
+ break;
+ case SIR_MAC_TDLS_SETUP_RSP:
+ {
+ limSendTdlsSetupRspFrame(pMac,
+ pSendMgmtReq->peerMac, pSendMgmtReq->dialog, psessionEntry, pSendMgmtReq->statusCode,
+ &pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq)));
+ resultCode = eSIR_SME_SUCCESS;
+ }
+ break;
+ case SIR_MAC_TDLS_SETUP_CNF:
+ {
+ limSendTdlsLinkSetupCnfFrame(pMac, pSendMgmtReq->peerMac, pSendMgmtReq->dialog,
+ psessionEntry, &pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq)));
+ resultCode = eSIR_SME_SUCCESS;
+ }
+ break;
+ case SIR_MAC_TDLS_TEARDOWN:
+ {
+ limSendTdlsTeardownFrame(pMac,
+ pSendMgmtReq->peerMac, pSendMgmtReq->statusCode, psessionEntry,
+ &pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq)));
+ resultCode = eSIR_SME_SUCCESS;
+ }
+ break;
+ case SIR_MAC_TDLS_PEER_TRAFFIC_IND:
+ {
+ }
+ break;
+ case SIR_MAC_TDLS_CH_SWITCH_REQ:
+ {
+ }
+ break;
+ case SIR_MAC_TDLS_CH_SWITCH_RSP:
+ {
+ }
+ break;
+ case SIR_MAC_TDLS_PEER_TRAFFIC_RSP:
+ {
+ }
+ break;
+ default:
+ break;
+ }
+
+lim_tdls_send_mgmt_error:
+
+ limSendSmeRsp( pMac, eWNI_SME_TDLS_SEND_MGMT_RSP,
+ resultCode, pSendMgmtReq->sessionId, pSendMgmtReq->transactionId);
+
+ return eSIR_SUCCESS;
+}
+
+/*
+ * Once link is teardown, send Del Peer Ind to SME
+ */
+static eHalStatus limSendSmeTdlsDelStaRsp(tpAniSirGlobal pMac,
+ tANI_U8 sessionId, tSirMacAddr peerMac, tDphHashNode *pStaDs,
+ tANI_U8 status)
+{
+ tSirMsgQ mmhMsg = {0} ;
+ tSirTdlsDelStaRsp *pDelSta = NULL ;
+ mmhMsg.type = eWNI_SME_TDLS_DEL_STA_RSP ;
+ if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &pDelSta,
+ (sizeof(tSirTdlsDelStaRsp))))
+ {
+ PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
+ return eSIR_FAILURE;
+ }
+
+ pDelSta->sessionId = sessionId;
+ pDelSta->statusCode = status ;
+ if( pStaDs )
+ {
+ pDelSta->staId = pStaDs->staIndex ;
+ }
+ if( peerMac )
+ {
+ palCopyMemory(pMac->hHdd, pDelSta->peerMac, peerMac, sizeof(tSirMacAddr));
+ }
+
+ pDelSta->length = sizeof(tSirTdlsDelStaRsp) ;
+ pDelSta->messageType = eWNI_SME_TDLS_DEL_STA_RSP ;
+
+ mmhMsg.bodyptr = pDelSta;
+
+ mmhMsg.bodyval = 0;
+ limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+ return eSIR_SUCCESS ;
+
+}
+
+/*
+ * Process Send Mgmt Request from SME and transmit to AP.
+ */
+tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac,
+ tANI_U32 *pMsgBuf)
+{
+ /* get all discovery request parameters */
+ tSirTdlsAddStaReq *pAddStaReq = (tSirTdlsAddStaReq*) pMsgBuf ;
+ tpPESession psessionEntry;
+ tANI_U8 sessionId;
+ tLimTdlsLinkSetupPeer setupPeer = {0};
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Send Mgmt Recieved\n")) ;
+
+ if((psessionEntry = peFindSessionByBssid(pMac, pAddStaReq->bssid, &sessionId))
+ == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ "PE Session does not exist for given sme sessionId %d\n",
+ pAddStaReq->sessionId);
+ goto lim_tdls_add_sta_error;
+ }
+
+ /* check if we are in proper state to work as TDLS client */
+ if (psessionEntry->limSystemRole != eLIM_STA_ROLE)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ "send mgmt received in wrong system Role %d\n",
+ psessionEntry->limSystemRole);
+ goto lim_tdls_add_sta_error;
+ }
+
+ /*
+ * if we are still good, go ahead and check if we are in proper state to
+ * do TDLS discovery req/rsp/....frames.
+ */
+ if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE))
+ {
+
+ limLog(pMac, LOGE, "send mgmt received in invalid LIMsme \
+ state (%d)\n", psessionEntry->limSmeState);
+ goto lim_tdls_add_sta_error;
+ }
+
+ pMac->lim.gLimAddStaTdls = true ;
+
+ /* To start with, send add STA request to HAL */
+ if(eSIR_FAILURE == limTdlsSetupAddSta(pMac, pAddStaReq->peerMac,
+ &setupPeer, psessionEntry))
+ {
+ VOS_ASSERT(0) ;
+ goto lim_tdls_add_sta_error;
+ }
+ return eSIR_SUCCESS;
+lim_tdls_add_sta_error:
+ limSendSmeTdlsAddStaRsp(pMac,
+ pAddStaReq->sessionId, pAddStaReq->peerMac, NULL, eSIR_FAILURE );
+
+ return eSIR_SUCCESS;
+}
+/*
+ * Process Del Sta Request from SME .
+ */
+tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac,
+ tANI_U32 *pMsgBuf)
+{
+ /* get all discovery request parameters */
+ tSirTdlsDelStaReq *pDelStaReq = (tSirTdlsDelStaReq*) pMsgBuf ;
+ tpPESession psessionEntry;
+ tANI_U8 sessionId;
+ tpDphHashNode pStaDs = NULL ;
+
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+ ("Send Mgmt Recieved\n")) ;
+
+ if((psessionEntry = peFindSessionByBssid(pMac, pDelStaReq->bssid, &sessionId))
+ == NULL)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ "PE Session does not exist for given sme sessionId %d\n",
+ pDelStaReq->sessionId);
+ limSendSmeTdlsDelStaRsp(pMac, 0, pDelStaReq->peerMac,
+ NULL, eSIR_FAILURE) ;
+ return eSIR_FAILURE;
+ }
+
+ /* check if we are in proper state to work as TDLS client */
+ if (psessionEntry->limSystemRole != eLIM_STA_ROLE)
+ {
+ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+ "Del sta received in wrong system Role %d\n",
+ psessionEntry->limSystemRole);
+ goto lim_tdls_del_sta_error;
+ }
+
+ /*
+ * if we are still good, go ahead and check if we are in proper state to
+ * do TDLS discovery req/rsp/....frames.
+ */
+ if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE))
+ {
+
+ limLog(pMac, LOGE, "Del Sta received in invalid LIMsme \
+ state (%d)\n", psessionEntry->limSmeState);
+ goto lim_tdls_del_sta_error;
+ }
+
+ pStaDs = limTdlsDelSta(pMac, pDelStaReq->peerMac, psessionEntry) ;
+
+ /* now send indication to SME-->HDD->TL to remove STA from TL */
+
+ if(pStaDs)
+ {
+ limSendSmeTdlsDelStaRsp(pMac, psessionEntry->smeSessionId, pDelStaReq->peerMac,
+ pStaDs, eSIR_SUCCESS) ;
+ return eSIR_SUCCESS;
+
+ }
+
+lim_tdls_del_sta_error:
+ limSendSmeTdlsDelStaRsp(pMac, psessionEntry->smeSessionId, pDelStaReq->peerMac,
+ NULL, eSIR_FAILURE) ;
+
+ return eSIR_SUCCESS;
+}
+#endif