blob: c2d08b69a8465d85c713e5897792afc3005fdb2e [file] [log] [blame]
/*
* Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*===========================================================================
b a p A p i LinkSupervision . C
OVERVIEW:
This software unit holds the implementation of the WLAN BAP modules
"platform independent" Data path functions.
The functions externalized by this module are to be called ONLY by other
WLAN modules (HDD) that properly register with the BAP Layer initially.
DEPENDENCIES:
Are listed for each API below.
===========================================================================*/
/*===========================================================================
EDIT HISTORY FOR FILE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
when who what, where, why
---------- --- --------------------------------------------------------
2008-03-25 arulv Created module
===========================================================================*/
/*----------------------------------------------------------------------------
* Include Files
* -------------------------------------------------------------------------*/
//#include "wlan_qct_tl.h"
#include "vos_trace.h"
//I need the TL types and API
#include "wlan_qct_tl.h"
/* BT-AMP PAL API header file */
#include "bapApi.h"
#include "bapInternal.h"
#include "bapApiTimer.h"
/*----------------------------------------------------------------------------
* Preprocessor Definitions and Constants
* -------------------------------------------------------------------------*/
#if 1
//*BT-AMP packet LLC OUI value*/
static const v_U8_t WLANBAP_BT_AMP_OUI[] = {0x00, 0x19, 0x58 };
/*LLC header value*/
static v_U8_t WLANBAP_LLC_HEADER[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 };
#endif
/*----------------------------------------------------------------------------
* Global Data Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Static Variable Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Static Function Declarations and Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Externalized Function Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Function Declarations and Documentation
* -------------------------------------------------------------------------*/
VOS_STATUS
WLANBAP_AcquireLSPacket( ptBtampContext pBtampCtx, vos_pkt_t **ppPacket, v_U16_t size, tANI_BOOLEAN isLsReq )
{
VOS_STATUS vosStatus;
vos_pkt_t *pPacket;
WLANBAP_8023HeaderType w8023Header;
v_U8_t aucLLCHeader[WLANBAP_LLC_HEADER_LEN];
v_U16_t headerLength; /* The 802.3 frame length*/
v_U16_t protoType;
v_U8_t *pData = NULL;
if(isLsReq)
{
protoType = WLANTL_BT_AMP_TYPE_LS_REQ;
}
else
{
protoType = WLANTL_BT_AMP_TYPE_LS_REP;
}
//If success, vosTxLsPacket is the packet and pData points to the head.
vosStatus = vos_pkt_get_packet( &pPacket, VOS_PKT_TYPE_TX_802_11_MGMT,size, 1,
VOS_TRUE, NULL, NULL );
if( VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
vosStatus = vos_pkt_reserve_head( pPacket, (v_VOID_t *)&pData, size );
if( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"%s: failed to reserve size = %d\n",__func__, size );
vos_pkt_return_packet( pPacket );
}
}
if( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLANBAP_LinkSupervisionTimerHandler failed to get vos_pkt\n" );
return vosStatus;
}
// Form the 802.3 header
vos_mem_copy( w8023Header.vDA, pBtampCtx->peer_mac_addr, VOS_MAC_ADDR_SIZE);
vos_mem_copy( w8023Header.vSA, pBtampCtx->self_mac_addr, VOS_MAC_ADDR_SIZE);
headerLength = WLANBAP_LLC_HEADER_LEN;
/* Now the 802.3 length field is big-endian?! */
w8023Header.usLenType = vos_cpu_to_be16(headerLength);
/* Now adjust the protocol type bytes*/
protoType = vos_cpu_to_be16( protoType);
/* Now form the LLC header */
vos_mem_copy(aucLLCHeader,
WLANBAP_LLC_HEADER,
sizeof(WLANBAP_LLC_HEADER));
vos_mem_copy(&aucLLCHeader[WLANBAP_LLC_OUI_OFFSET],
WLANBAP_BT_AMP_OUI,
WLANBAP_LLC_OUI_SIZE);
vos_mem_copy(&aucLLCHeader[WLANBAP_LLC_PROTO_TYPE_OFFSET],
&protoType, //WLANBAP_BT_AMP_TYPE_LS_REQ
WLANBAP_LLC_PROTO_TYPE_SIZE);
/* Push on the LLC header */
vos_pkt_push_head(pPacket,
aucLLCHeader,
WLANBAP_LLC_HEADER_LEN);
/* Push on the 802.3 header */
vos_pkt_push_head(pPacket, &w8023Header, sizeof(w8023Header));
*ppPacket = pPacket;
return vosStatus;
}
/*===========================================================================
FUNCTION WLANBAP_InitLinkSupervision
DESCRIPTION
This API will be called when Link Supervision module is to be initialized when connected at BAP
PARAMETERS
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: BAP handle is NULL
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
#define TX_LS_DATALEN 32
VOS_STATUS
WLANBAP_InitLinkSupervision
(
ptBtampHandle btampHandle
)
{
VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
ptBtampContext pBtampCtx = (ptBtampContext) btampHandle;
vos_pkt_t *pLSReqPacket;
vos_pkt_t *pLSRepPacket;
v_U16_t lsPktln;
if ( NULL == pBtampCtx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BAP handle value in %s", __func__);
return VOS_STATUS_E_FAULT;
}
#if 0
/* Initialize Link supervision data structure */
vos_mem_set(pLsInfo, sizeof(tBtampLS),0);
/* Allocate memory for Static Tx Data */
pLsInfo->pTxPktData = vos_mem_malloc(sizeof(tBtampLsPktData)+TX_LS_DATALEN);
/* Initialize Static data for LS pkt Tx */
pLsInfo->pTxPktData->BufLen = TX_LS_DATALEN;
vos_mem_copy (&pLsInfo->pTxPktData->pBuf, LsTxData, pLsInfo->pTxPktData->BufLen);
#endif
pBtampCtx->lsReqPktPending = VOS_FALSE;
pBtampCtx->retries = 0;
vosStatus = WLANBAP_AcquireLSPacket( pBtampCtx, &pLSReqPacket,32, TRUE );
if( VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
pBtampCtx->lsReqPacket = pLSReqPacket;
}
else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"%s:AcquireLSPacket failed\n",__func__);
pBtampCtx->lsReqPacket = NULL;
return vosStatus;
}
vosStatus = WLANBAP_AcquireLSPacket( pBtampCtx, &pLSRepPacket,32,FALSE );
if( VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
pBtampCtx->lsRepPacket = pLSRepPacket;
}
else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"%s:AcquireLSPacket failed\n",__func__);
pBtampCtx->lsRepPacket = NULL;
return vosStatus;
}
vosStatus = vos_pkt_get_packet_length(pBtampCtx->lsRepPacket,&lsPktln);
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"%s:vos_pkt_get_length error",__func__);
return VOS_STATUS_E_FAULT;
}
pBtampCtx->lsPktln = lsPktln;
/* Start Link Supervision Timer if not configured for infinite */
if (pBtampCtx->bapLinkSupervisionTimerInterval)
{
vosStatus = WLANBAP_StartLinkSupervisionTimer (pBtampCtx,
pBtampCtx->bapLinkSupervisionTimerInterval * WLANBAP_BREDR_BASEBAND_SLOT_TIME);
}
else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"%s:No LS configured for infinite",__func__);
}
return vosStatus;
}
/*===========================================================================
FUNCTION WLANBAP_DeInitLinkSupervision
DESCRIPTION
This API will be called when Link Supervision module is to be stopped after disconnected at BAP
PARAMETERS
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: BAP handle is NULL
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANBAP_DeInitLinkSupervision
(
ptBtampHandle btampHandle
)
{
VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
ptBtampContext pBtampCtx = (ptBtampContext) btampHandle;
if ( NULL == pBtampCtx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BAP handle value in %s", __func__);
return VOS_STATUS_E_FAULT;
}
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"In: %s", __func__);
vosStatus = WLANBAP_StopLinkSupervisionTimer(pBtampCtx);
/*Free the vos packet*/
if ( pBtampCtx->lsRepPacket )
{
vosStatus = vos_pkt_return_packet(pBtampCtx->lsRepPacket);
pBtampCtx->lsRepPacket = NULL;
}
if ( pBtampCtx->lsReqPacket )
{
vosStatus = vos_pkt_return_packet(pBtampCtx->lsReqPacket);
pBtampCtx->lsReqPacket = NULL;
}
return vosStatus;
}
/*===========================================================================
FUNCTION WLANBAP_RxProcLsPkt
DESCRIPTION
This API will be called when Link Supervision frames are received at BAP
PARAMETERS
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
pucAC: Pointer to return the access category
vosDataBuff: The data buffer containing the 802.3 frame to be
translated to BT HCI Data Packet
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: BAP handle is NULL
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANBAP_RxProcLsPkt
(
ptBtampHandle btampHandle,
v_U8_t phy_link_handle, /* Used by BAP to indentify the WLAN assoc. (StaId) */
v_U16_t RxProtoType, /* Protocol Type from the frame received */
vos_pkt_t *vosRxLsBuff
)
{
VOS_STATUS vosStatus;
ptBtampContext pBtampCtx = (ptBtampContext) btampHandle;
WLANBAP_8023HeaderType w8023Header;
v_SIZE_t HeaderLen = sizeof(w8023Header);
/*------------------------------------------------------------------------
Sanity check params
------------------------------------------------------------------------*/
if ( NULL == pBtampCtx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BAP handle value in %s", __func__);
return VOS_STATUS_E_FAULT;
}
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"In %s Received RxProtoType=%x", __func__,RxProtoType);
vos_pkt_extract_data(vosRxLsBuff,0,(v_VOID_t*)&w8023Header,&HeaderLen);
if ( !(vos_mem_compare( w8023Header.vDA, pBtampCtx->self_mac_addr, VOS_MAC_ADDR_SIZE)
&& vos_mem_compare( w8023Header.vSA, pBtampCtx->peer_mac_addr, VOS_MAC_ADDR_SIZE)))
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"MAC address mismatch in %s", __func__);
return VOS_STATUS_E_FAULT;
}
/*Free the vos packet*/
vosStatus = vos_pkt_return_packet( vosRxLsBuff );
if ( VOS_STATUS_SUCCESS != vosStatus)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Failed to free VOS packet in %s", __func__);
return VOS_STATUS_E_FAULT;
}
/* Reset Link Supervision timer */
if (RxProtoType == WLANTL_BT_AMP_TYPE_LS_REP)
{
pBtampCtx->lsReqPktPending = FALSE;
pBtampCtx->retries = 0;
if (pBtampCtx->bapLinkSupervisionTimerInterval)
{
/* Restart the LS timer */
WLANBAP_StopLinkSupervisionTimer(pBtampCtx);
vosStatus = WLANBAP_StartLinkSupervisionTimer (pBtampCtx,
pBtampCtx->bapLinkSupervisionTimerInterval * WLANBAP_BREDR_BASEBAND_SLOT_TIME);
}
}
else if(RxProtoType == WLANTL_BT_AMP_TYPE_LS_REQ)
{
if (pBtampCtx->bapLinkSupervisionTimerInterval)
{
/* Restart the LS timer */
WLANBAP_StopLinkSupervisionTimer(pBtampCtx);
vosStatus = WLANBAP_StartLinkSupervisionTimer (pBtampCtx,
pBtampCtx->bapLinkSupervisionTimerInterval * WLANBAP_BREDR_BASEBAND_SLOT_TIME);
}
pBtampCtx->pPacket = pBtampCtx->lsRepPacket;
// Handle LS rep frame
vosStatus = WLANBAP_TxLinkSupervision( btampHandle, phy_link_handle, pBtampCtx->pPacket, WLANTL_BT_AMP_TYPE_LS_REP);
}
return vosStatus;
}
/* Tx callback function for LS packet */
static VOS_STATUS WLANBAP_TxLinkSupervisionCB
(
v_PVOID_t pvosGCtx,
vos_pkt_t *pPacket,
VOS_STATUS retStatus
)
{
VOS_STATUS vosStatus;
ptBtampContext bapContext; /* Holds the btampContext value returned */
vos_pkt_t *pLSPacket;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"TxCompCB reached for LS Pkt");
/* Get the BT AMP context from the global */
bapContext = gpBtampCtx;
if (!VOS_IS_STATUS_SUCCESS (retStatus))
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"TxCompCB:Transmit status Failure");
}
if ( pPacket == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLANBAP_TxCompCB bad input\n" );
return VOS_STATUS_E_FAILURE;
}
/* Return the packet & reallocate */
if( pPacket == bapContext->lsReqPacket )
{
vosStatus = WLANBAP_AcquireLSPacket( bapContext, &pLSPacket,32, TRUE );
if( VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
bapContext->lsReqPacket = pLSPacket;
}
else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"%s:AcquireLSPacket failed\n",__func__);
bapContext->lsReqPacket = NULL;
return vosStatus;
}
}
else
{
vosStatus = WLANBAP_AcquireLSPacket( bapContext, &pLSPacket,32, FALSE );
if( VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
bapContext->lsRepPacket = pLSPacket;
}
else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"%s:AcquireLSPacket failed\n",__func__);
bapContext->lsRepPacket = NULL;
return vosStatus;
}
}
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"%s:Returned Vos Packet:%pK\n", __func__, pPacket );
vos_pkt_return_packet( pPacket );
return (VOS_STATUS_SUCCESS );
}
/*===========================================================================
FUNCTION WLANBAP_TxLinkSupervision
DESCRIPTION
This API will be called to process Link Supervision Request received
PARAMETERS
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
pucAC: Pointer to return the access category
vosDataBuff: The data buffer containing the 802.3 frame to be
translated to BT HCI Data Packet
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: BAP handle is NULL
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANBAP_TxLinkSupervision
(
ptBtampHandle btampHandle,
v_U8_t phy_link_handle, /* Used by BAP to indentify the WLAN assoc. (StaId) */
vos_pkt_t *pPacket,
v_U16_t protoType
)
{
ptBtampContext pBtampCtx = (ptBtampContext)btampHandle;
VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
v_PVOID_t pvosGCtx;
v_U8_t ucSTAId; /* The StaId (used by TL, PE, and HAL) */
v_PVOID_t pHddHdl; /* Handle to return BSL context in */
WLANTL_MetaInfoType metaInfo;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"In : %s protoType=%x", __func__,protoType);
// Retrieve the VOSS context
pvosGCtx = pBtampCtx->pvosGCtx;
/* Lookup the StaId using the phy_link_handle and the BAP context */
vosStatus = WLANBAP_GetStaIdFromLinkCtx (
btampHandle, /* btampHandle value in */
phy_link_handle, /* phy_link_handle value in */
&ucSTAId, /* The StaId (used by TL, PE, and HAL) */
&pHddHdl); /* Handle to return BSL context */
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Unable to retrieve STA Id from BAP context and phy_link_handle in WLANBAP_TxLinKSupervisionReq");
return VOS_STATUS_E_FAULT;
}
vos_mem_zero( &metaInfo, sizeof( WLANTL_MetaInfoType ) );
metaInfo.ucTID = 0x00 ;
metaInfo.ucUP = 0x00;
metaInfo.ucIsEapol = VOS_FALSE;//Notify TL that this is NOT an EAPOL frame
metaInfo.ucDisableFrmXtl = VOS_FALSE;
metaInfo.ucType = 0x00;
pBtampCtx->metaInfo = metaInfo;
vosStatus = WLANTL_TxBAPFrm( pvosGCtx, pPacket, &metaInfo, WLANBAP_TxLinkSupervisionCB );
if( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Tx: Packet rejected by TL in WLANBAP_TxLinkSupervisionReq");
return vosStatus;
}
if(protoType == WLANTL_BT_AMP_TYPE_LS_REQ)
{
pBtampCtx->lsReqPktPending = TRUE;
pBtampCtx->retries++;
}
if (pBtampCtx->bapLinkSupervisionTimerInterval)
{
/* Restart the LS timer */
WLANBAP_StopLinkSupervisionTimer(pBtampCtx);
vosStatus = WLANBAP_StartLinkSupervisionTimer (pBtampCtx,
pBtampCtx->bapLinkSupervisionTimerInterval * WLANBAP_BREDR_BASEBAND_SLOT_TIME);
}
if( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLANBAP_TxLinkSupervisionReq failed to Start LinkSupervision Timer\n" );
return vosStatus;
}
return vosStatus;
} /* WLANBAP_RxLinkSupervisionReq */