blob: aa6e3b7936bb55680a22c91b876d7041d184a6dc [file] [log] [blame]
/*
* Copyright (c) 2012-2014, 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.
*/
/**========================================================================
\file bap_hdd_main.c
\brief 802.11 BT-AMP PAL Host Device Driver implementation
========================================================================*/
/**=========================================================================
EDIT HISTORY FOR FILE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
$Header: /prj/qct/asw/engbuilds/scl/users02/jzmuda/gb-bluez/vendor/qcom/proprietary/wlan/libra/CORE/HDD/src/bap_hdd_main.c,v 1.63 2011/04/01 15:24:20 jzmuda Exp jzmuda $ $DateTime: $ $Author: jzmuda $
when who what, where, why
-------- --- --------------------------------------------------------
12/1/09 JZmuda Created module.
==========================================================================*/
/*--------------------------------------------------------------------------
Include Files
------------------------------------------------------------------------*/
#ifdef WLAN_BTAMP_FEATURE
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/spinlock.h>
//#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/io.h>
//#include <wlan_qct_driver.h>
#include <wlan_hdd_includes.h>
#include <wlan_hdd_dp_utils.h>
/* -------------------------------------------------------------------------*/
#include <bap_hdd_main.h>
#include <vos_api.h>
#include <bapApi.h>
#include <btampHCI.h>
/* -------------------------------------------------------------------------*/
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <wlan_hdd_misc.h>
/*----------------------------------------------------------------------------
* Preprocessor Definitions and Constants
* -------------------------------------------------------------------------*/
// the difference between the next two is that the first is the max
// number we support in our current implementation while the second is
// the max allowed by the spec
#define BSL_MAX_PHY_LINKS ( BSL_MAX_CLIENTS * BSL_MAX_PHY_LINK_PER_CLIENT )
#define BSL_MAX_ALLOWED_PHY_LINKS 255
// these likely will need tuning based on experiments
#define BSL_MAX_RX_PKT_DESCRIPTOR 100
#define BSL_MAX_TX_PKT_DESCRIPTOR 100
// these caps are in place to not have run-away queues, again needs empirical tuning
#define BSL_MAX_SIZE_TX_ACL_QUEUE 50
#define BSL_MAX_SIZE_RX_ACL_QUEUE 50
#define BSL_MAX_SIZE_RX_EVT_QUEUE 50
#if 0
What are the maximum sizes of a command packet, an event packet and an ACL
data packet?
[JimZ]: Sizes:
1. Cmd Maximum size is slightly greater than 672 btyes. But I am pretty sure
right now that I will never have more than 240 bytes to send down at a time. And
that is good. Because some rather unpleasant things happen at the HCI interface
if I exceed that. ( Think 8-bit CPUs. And the limitations of an 8-bit length
field. )
2. Event - Ditto.
3. Data 1492 bytes
#endif
// jimz
// TLV related defines
#define USE_FINAL_FRAMESC
//#undef USE_FINAL_FRAMESC
// jimz
// TLV related defines
#ifndef USE_FINAL_FRAMESC //USE_FINAL_FRAMESC
// AMP ASSOC TLV related defines
#define AMP_ASSOC_TLV_TYPE_SIZE 2
#define AMP_ASSOC_TLV_LEN_SIZE 2
#define AMP_ASSOC_TLV_TYPE_AND_LEN_SIZE (AMP_ASSOC_TLV_TYPE_SIZE + AMP_ASSOC_TLV_LEN_SIZE)
// FLOW SPEC TLV related defines
#define FLOWSPEC_TYPE_SIZE 2
#define FLOWSPEC_LEN_SIZE 2
#define FLOWSPEC_TYPE_AND_LEN_SIZE (FLOWSPEC_TYPE_SIZE + FLOWSPEC_LEN_SIZE)
// CMD TLV related defines
#define CMD_TLV_TYPE_SIZE 2
#define CMD_TLV_LEN_SIZE 2
#define CMD_TLV_TYPE_AND_LEN_SIZE (CMD_TLV_TYPE_SIZE + CMD_TLV_LEN_SIZE)
// Event TLV related defines
#define EVENT_TLV_TYPE_SIZE 2
#define EVENT_TLV_LEN_SIZE 2
#define EVENT_TLV_TYPE_AND_LEN_SIZE (EVENT_TLV_TYPE_SIZE + EVENT_TLV_LEN_SIZE)
// Data header size related defines
#define DATA_HEADER_SIZE 4
#else //USE_FINAL_FRAMESC
// AMP ASSOC TLV related defines
#define AMP_ASSOC_TLV_TYPE_SIZE 1
#define AMP_ASSOC_TLV_LEN_SIZE 2
#define AMP_ASSOC_TLV_TYPE_AND_LEN_SIZE (AMP_ASSOC_TLV_TYPE_SIZE + AMP_ASSOC_TLV_LEN_SIZE)
// FLOW SPEC TLV related defines
#define FLOWSPEC_TYPE_SIZE 1
#define FLOWSPEC_LEN_SIZE 1
#define FLOWSPEC_TYPE_AND_LEN_SIZE (FLOWSPEC_TYPE_SIZE + FLOWSPEC_LEN_SIZE)
// CMD TLV related defines
#define CMD_TLV_TYPE_SIZE 2
#define CMD_TLV_LEN_SIZE 1
#define CMD_TLV_TYPE_AND_LEN_SIZE (CMD_TLV_TYPE_SIZE + CMD_TLV_LEN_SIZE)
// Event TLV related defines
#define EVENT_TLV_TYPE_SIZE 1
#define EVENT_TLV_LEN_SIZE 1
#define EVENT_TLV_TYPE_AND_LEN_SIZE (EVENT_TLV_TYPE_SIZE + EVENT_TLV_LEN_SIZE)
// Data header size related defines
#define DATA_HEADER_SIZE 4
#endif // USE_FINAL_FRAMESC
// jimz
#define BSL_MAX_EVENT_SIZE 700
#define BSL_DEV_HANDLE 0x1234
// Debug related defines
#define DBGLOG printf
//#define DUMPLOG
#if defined DUMPLOG
#define DUMPLOG(n, name1, name2, aStr, size) do { \
int i; \
DBGLOG("%d. %s: %s = \n", n, name1, name2); \
for (i = 0; i < size; i++) \
DBGLOG("%2.2x%s", ((unsigned char *)aStr)[i], i % 16 == 15 ? "\n" : " "); \
DBGLOG("\n"); \
} while (0)
#else
#define DUMPLOG(n, name1, name2, aStr, size)
#endif
// These are required to replace some Microsoft specific specifiers
//#define UNALIGNED __align
#define UNALIGNED
#define INFINITE 0
#define BT_AMP_HCI_CTX_MAGIC 0x48434949 // "HCII"
/*----------------------------------------------------------------------------
* Type Declarations
* -------------------------------------------------------------------------*/
// Temporary Windows types
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef void * HANDLE;
typedef char TCHAR;
typedef void *LPVOID;
typedef const void *LPCVOID;
typedef struct
{
BOOL used; // is this a valid context?
vos_event_t ReadableEvt; // the event a ReadFile can block on
ptBtampHandle bapHdl; // our handle in BAP
vos_list_t PhyLinks; // a list of all associations setup by this client
// Newly added for BlueZ
struct hci_dev *hdev; // the BlueZ HCI device structure
/* I don't know how many of these Tx fields we need */
spinlock_t lock; /* For serializing operations */
struct sk_buff_head txq; /* We need the ACL Data Tx queue */
/* We definitely need some of these rx_skb fields */
unsigned long rx_state;
unsigned long rx_count;
struct sk_buff *rx_skb;
struct net_device *p_dev; // Our parent wlan network device
} BslClientCtxType;
typedef struct
{
BslClientCtxType* pctx;
/* Tx skb queue and the workstructure for handling Tx as deferred work. */
struct sk_buff *tx_skb;
struct work_struct hciInterfaceProcessing;
v_U32_t magic;
} BslHciWorkStructure;
typedef struct
{
TCHAR* ValueName; // name of the value
DWORD Type; // type of value
DWORD DwordValue; // DWORD value
TCHAR* StringValue; // string value
} BslRegEntry;
typedef struct
{
BOOL used; // is this a valid context?
hdd_list_t ACLTxQueue[WLANTL_MAX_AC]; // the TX ACL queues
BslClientCtxType* pClientCtx; // ptr to application context that spawned
// this association
v_U8_t PhyLinkHdl; // BAP handle for this association
void* pPhyLinkDescNode; // ptr to node in list of assoc in client ctx
// real type BslPhyLinksNodeType*
} BslPhyLinkCtxType;
typedef struct
{
vos_list_node_t node; // MUST be first element
BslPhyLinkCtxType* pPhy; // ptr to an association context
} BslPhyLinksNodeType;
typedef struct
{
vos_list_node_t node; // MUST be first element
vos_pkt_t* pVosPkt; // ptr to a RX VoS pkt which can hold an HCI event or ACL data
} BslRxListNodeType;
// Borrowed from wlan_hdd_dp_utils.h
typedef struct
{
hdd_list_node_t node; // MUST be first element
struct sk_buff * skb; // ptr to the ACL data
} BslTxListNodeType;
typedef struct
{
BslPhyLinkCtxType* ptr; // ptr to the association context for this phy_link_handle
} BslPhyLinkMapEntryType;
/*----------------------------------------------------------------------------
* Global Data Definitions
* -------------------------------------------------------------------------*/
BslClientCtxType* gpBslctx;
/*----------------------------------------------------------------------------
* Static Variable Definitions
* -------------------------------------------------------------------------*/
// Temporary (until multi-phy link) pointer to BT-AMP context
static void *gpCtx;
// an efficient lookup from phy_link_handle to phy link context
static BslPhyLinkMapEntryType BslPhyLinkMap[BSL_MAX_ALLOWED_PHY_LINKS];
//static HANDLE hBsl = NULL; //INVALID_HANDLE_VALUE;
static BOOL bBslInited = FALSE;
static BslClientCtxType BslClientCtx[BSL_MAX_CLIENTS];
//static vos_lock_t BslClientLock;
static BslPhyLinkCtxType BslPhyLinkCtx[BSL_MAX_PHY_LINKS];
//static vos_lock_t BslPhyLock;
// the pool for association contexts
static vos_list_t BslPhyLinksDescPool;
static BslPhyLinksNodeType BslPhyLinksDesc[BSL_MAX_PHY_LINKS];
//static v_U32_t Eventlen = 0;
/*---------------------------------------------------------------------------
* Forward declarations
*-------------------------------------------------------------------------*/
static void bslWriteFinish(struct work_struct *work);
/*---------------------------------------------------------------------------
* Driver Entry points and Structure definitions
*-------------------------------------------------------------------------*/
static int BSL_Open (struct hci_dev *hdev);
static int BSL_Close (struct hci_dev *hdev);
static int BSL_Flush(struct hci_dev *hdev);
static int BSL_IOControl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
static int BSL_Write(struct sk_buff *skb);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
static void BSL_Destruct(struct hci_dev *hdev);
#endif
/*----------------------------------------------------------------------------
* Static Function Declarations and Definitions
* -------------------------------------------------------------------------*/
static v_BOOL_t WLANBAP_AmpConnectionAllowed(void)
{
v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
hdd_context_t *pHddCtx;
v_BOOL_t retVal = VOS_FALSE;
if (NULL != pVosContext)
{
pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
if (NULL != pHddCtx)
{
return pHddCtx->isAmpAllowed;
}
else
{
return retVal;
}
}
return retVal;
}
/**
@brief WLANBAP_STAFetchPktCB() - The fetch packet callback registered
with BAP by HDD.
It is called by the BAP immediately upon the underlying
WLANTL_STAFetchPktCBType routine being called. Which is called by
TL when the scheduling algorithms allows for transmission of another
packet to the module.
This function is here to "wrap" or abstract WLANTL_STAFetchPktCBType.
Because the BAP-specific HDD "shim" layer (BSL) doesn't know anything
about STAIds, or other parameters required by TL.
@param pHddHdl: [in] The HDD(BSL) specific context for this association.
Use the STAId passed to me by TL in WLANTL_STAFetchCBType to retreive
this value.
@param pucAC: [inout] access category requested by TL, if HDD does not
have packets on this AC it can choose to service another AC queue in
the order of priority
@param vosDataBuff: [out] pointer to the VOSS data buffer that was
transmitted
@param tlMetaInfo: [out] meta info related to the data frame
@return
The result code associated with performing the operation
*/
static VOS_STATUS WLANBAP_STAFetchPktCB
(
v_PVOID_t pHddHdl,
WLANTL_ACEnumType ucAC,
vos_pkt_t** vosDataBuff,
WLANTL_MetaInfoType* tlMetaInfo
)
{
BslPhyLinkCtxType* pPhyCtx;
VOS_STATUS VosStatus;
v_U8_t AcIdxStart;
v_U8_t AcIdx;
hdd_list_node_t *pLink;
BslTxListNodeType *pNode;
struct sk_buff * skb;
BslClientCtxType* pctx;
WLANTL_ACEnumType Ac;
vos_pkt_t* pVosPkt;
WLANTL_MetaInfoType TlMetaInfo;
pctx = &BslClientCtx[0];
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "WLANBAP_STAFetchPktCB" );
// sanity checking
if( pHddHdl == NULL || vosDataBuff == NULL ||
tlMetaInfo == NULL || ucAC >= WLANTL_MAX_AC || ucAC < 0 )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STAFetchPktCB bad input" );
return VOS_STATUS_E_FAILURE;
}
// Initialize the VOSS packet returned to NULL - in case of error
*vosDataBuff = NULL;
pPhyCtx = (BslPhyLinkCtxType *)pHddHdl;
AcIdx = AcIdxStart = ucAC;
spin_lock_bh(&pPhyCtx->ACLTxQueue[AcIdx].lock);
VosStatus = hdd_list_remove_front( &pPhyCtx->ACLTxQueue[AcIdx], &pLink );
spin_unlock_bh(&pPhyCtx->ACLTxQueue[AcIdx].lock);
if ( VOS_STATUS_E_EMPTY == VosStatus )
{
do
{
AcIdx = (AcIdx + 1) % WLANTL_MAX_AC;
spin_lock_bh(&pPhyCtx->ACLTxQueue[AcIdx].lock);
VosStatus = hdd_list_remove_front( &pPhyCtx->ACLTxQueue[AcIdx], &pLink );
spin_unlock_bh(&pPhyCtx->ACLTxQueue[AcIdx].lock);
}
while ( VosStatus == VOS_STATUS_E_EMPTY && AcIdx != AcIdxStart );
if ( VosStatus == VOS_STATUS_E_EMPTY )
{
// Queue is empty. This can happen. Just return NULL back to TL...
return(VOS_STATUS_E_EMPTY);
}
else if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_ASSERT( 0 );
}
}
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_ASSERT( 0 );
}
pNode = (BslTxListNodeType *)pLink;
skb = pNode->skb;
// I will access the skb in a VOSS packet
// Wrap the OS provided skb in a VOSS packet
// Attach skb to VOS packet.
VosStatus = vos_pkt_wrap_data_packet( &pVosPkt,
VOS_PKT_TYPE_TX_802_3_DATA,
skb,
NULL,
NULL);
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STAFetchPktCB vos_pkt_wrap_data_packet "
"failed status =%d", VosStatus );
kfree_skb(skb);
return VosStatus;
}
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, "%s: pVosPkt(vos_pkt_t *)=%pK", __func__,
pVosPkt );
VosStatus = WLANBAP_XlateTxDataPkt( pctx->bapHdl, pPhyCtx->PhyLinkHdl,
&Ac, &TlMetaInfo, pVosPkt);
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STAFetchPktCB WLANBAP_XlateTxDataPkt "
"failed status =%d", VosStatus );
// return the packet
VosStatus = vos_pkt_return_packet( pVosPkt );
kfree_skb(skb);
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return VosStatus;
}
// give TL the VoS pkt
*vosDataBuff = pVosPkt;
// provide the meta-info BAP provided previously
*tlMetaInfo = TlMetaInfo;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: *vosDataBuff(vos_pkt_t *)=%pK", __func__, *vosDataBuff );
return(VOS_STATUS_SUCCESS);
} // WLANBAP_STAFetchPktCB()
/**
@brief WLANBAP_STARxCB() - The receive callback registered with BAP by HDD.
It is called by the BAP immediately upon the underlying
WLANTL_STARxCBType routine being called. Which is called by
TL to notify when a packet was received for a registered STA.
@param pHddHdl: [in] The HDD(BSL) specific context for this association.
Use the STAId passed to me by TL in WLANTL_STARxCBType to retrieve this value.
@param vosDataBuff: [in] pointer to the VOSS data buffer that was received
(it may be a linked list)
@param pRxMetaInfo: [in] Rx meta info related to the data frame
@return
The result code associated with performing the operation
*/
static VOS_STATUS WLANBAP_STARxCB
(
v_PVOID_t pHddHdl,
vos_pkt_t* vosDataBuff,
WLANTL_RxMetaInfoType* pRxMetaInfo
)
{
BslPhyLinkCtxType* pctx;
BslClientCtxType* ppctx;
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
WLANTL_ACEnumType Ac; // this is not needed really
struct sk_buff *skb = NULL;
vos_pkt_t* pVosPacket;
vos_pkt_t* pNextVosPacket;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "WLANBAP_STARxCB" );
// sanity checking
if ( pHddHdl == NULL || vosDataBuff == NULL || pRxMetaInfo == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STARxCB bad input" );
if(NULL != vosDataBuff)
{
VosStatus = vos_pkt_return_packet( vosDataBuff );
}
return VOS_STATUS_E_FAILURE;
}
pctx = (BslPhyLinkCtxType *)pHddHdl;
ppctx = pctx->pClientCtx;
if( NULL == ppctx )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_STARxCB ClientCtx is NULL" );
VosStatus = vos_pkt_return_packet( vosDataBuff );
return VOS_STATUS_E_FAILURE;
}
// walk the chain until all are processed
pVosPacket = vosDataBuff;
do
{
// get the pointer to the next packet in the chain
// (but don't unlink the packet since we free the entire chain later)
VosStatus = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
// both "success" and "empty" are acceptable results
if (!((VosStatus == VOS_STATUS_SUCCESS) || (VosStatus == VOS_STATUS_E_EMPTY)))
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,"%s: Failure walking packet chain", __func__);
return VOS_STATUS_E_FAILURE;
}
// process the packet
VosStatus = WLANBAP_XlateRxDataPkt( ppctx->bapHdl, pctx->PhyLinkHdl,
&Ac, pVosPacket );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_FATAL, "WLANBAP_STARxCB WLANBAP_XlateRxDataPkt "
"failed status = %d", VosStatus );
VosStatus = VOS_STATUS_E_FAILURE;
break;
}
// Extract the OS packet (skb).
// Tell VOS to detach the OS packet from the VOS packet
VosStatus = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
if(!VOS_IS_STATUS_SUCCESS( VosStatus ))
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: Failure extracting skb from vos pkt. "
"VosStatus = %d", __func__, VosStatus );
VosStatus = VOS_STATUS_E_FAILURE;
break;
}
//JEZ100809: While an skb is being handled by the kernel, is "skb->dev" de-ref'd?
skb->dev = (struct net_device *) gpBslctx->hdev;
bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
//skb->protocol = eth_type_trans(skb, skb->dev);
//skb->ip_summed = CHECKSUM_UNNECESSARY;
// This is my receive skb pointer
gpBslctx->rx_skb = skb;
// This is how data and events are passed up to BlueZ
hci_recv_frame(gpBslctx->rx_skb);
// now process the next packet in the chain
pVosPacket = pNextVosPacket;
} while (pVosPacket);
//JEZ100922: We are free to return the enclosing VOSS packet.
VosStatus = vos_pkt_return_packet( vosDataBuff );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_SUCCESS);
} // WLANBAP_STARxCB()
/**
@brief WLANBAP_TxCompCB() - The Tx complete callback registered with BAP by HDD.
It is called by the BAP immediately upon the underlying
WLANTL_TxCompCBType routine being called. Which is called by
TL to notify when a transmission for a packet has ended.
@param pHddHdl: [in] The HDD(BSL) specific context for this association
@param vosDataBuff: [in] pointer to the VOSS data buffer that was transmitted
@param wTxSTAtus: [in] status of the transmission
@return
The result code associated with performing the operation
*/
extern v_VOID_t WLANBAP_TxPacketMonitorHandler ( v_PVOID_t ); // our handle in BAP
static VOS_STATUS WLANBAP_TxCompCB
(
v_PVOID_t pHddHdl,
vos_pkt_t* vosDataBuff,
VOS_STATUS wTxSTAtus
)
{
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
//BslTxListNodeType* pTxNode;
void* pOsPkt = NULL;
BslPhyLinkCtxType* pctx;
BslClientCtxType* ppctx;
static int num_packets;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, "WLANBAP_TxCompCB. vosDataBuff(vos_pkt_t *)=%pK", vosDataBuff );
// be aware that pHddHdl can be NULL or can point to the per association
// BSL context from the register data plane. In either case it does not
// matter since we will simply free the VoS pkt and reclaim the TX
// descriptor
// sanity checking
if ( vosDataBuff == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_TxCompCB bad input" );
return VOS_STATUS_E_FAILURE;
}
//Return the skb to the OS
VosStatus = vos_pkt_get_os_packet( vosDataBuff, &pOsPkt, VOS_TRUE );
if(!VOS_IS_STATUS_SUCCESS( VosStatus ))
{
//This is bad but still try to free the VOSS resources if we can
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __func__);
vos_pkt_return_packet( vosDataBuff );
return VOS_STATUS_E_FAILURE;
}
kfree_skb((struct sk_buff *)pOsPkt);
//Return the VOS packet resources.
VosStatus = vos_pkt_return_packet( vosDataBuff );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_ASSERT(0);
}
// JEZ110330: Now signal the layer above me...that I have released some packets.
pctx = (BslPhyLinkCtxType *)pHddHdl;
ppctx = pctx->pClientCtx;
num_packets = (num_packets + 1) % 4;
if (num_packets == 0 )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, "%s: Sending up number of completed packets. num_packets = %d.", __func__, num_packets );
WLANBAP_TxPacketMonitorHandler ( (v_PVOID_t) ppctx->bapHdl ); // our handle in BAP
}
return(VOS_STATUS_SUCCESS);
} // WLANBAP_TxCompCB()
/**
@brief BslFlushTxQueues() - flush the Tx queues
@param pPhyCtx : [in] ptr to the phy context whose queues need to be flushed
@return
VOS_STATUS
*/
static VOS_STATUS BslFlushTxQueues
(
BslPhyLinkCtxType* pPhyCtx
)
{
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
v_SINT_t i = -1;
hdd_list_node_t* pLink;
BslTxListNodeType *pNode;
if(TRUE == pPhyCtx->used)
{
while (++i != WLANTL_MAX_AC)
{
//Free up any packets in the Tx queue
spin_lock_bh(&pPhyCtx->ACLTxQueue[i].lock);
while (true)
{
VosStatus = hdd_list_remove_front(&pPhyCtx->ACLTxQueue[i], &pLink );
if(VOS_STATUS_E_EMPTY != VosStatus)
{
pNode = (BslTxListNodeType *)pLink;
kfree_skb(pNode->skb);
continue;
}
break;
}
spin_unlock_bh(&pPhyCtx->ACLTxQueue[i].lock);
}
}
return(VOS_STATUS_SUCCESS);
} // BslFlushTxQueues
/**
@brief BslReleasePhyCtx() - this function will free up an association context
@param pPhyCtx : [in] ptr to the phy context to release
@return
None
*/
static void BslReleasePhyCtx
(
BslPhyLinkCtxType* pPhyCtx
)
{
uintptr_t OldMapVal;
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslReleasePhyCtx" );
pPhyCtx->used = FALSE;
if (BslPhyLinkMap[pPhyCtx->PhyLinkHdl].ptr == NULL) return;
// update the phy link handle based map so TX data is stopped from flowing through
OldMapVal = vos_atomic_set( (uintptr_t *) (BslPhyLinkMap[pPhyCtx->PhyLinkHdl].ptr),
(uintptr_t) 0 );
// clear out the Tx Queues
VosStatus = BslFlushTxQueues(pPhyCtx);
// clear out the parent ptr
// pPhyCtx->pClientCtx = NULL;//commented to debug exception
// we also need to remove this assocation from the list of active
// associations maintained in the application context
if( pPhyCtx->pPhyLinkDescNode )
{
VosStatus = vos_list_remove_node( &pPhyCtx->pClientCtx->PhyLinks,
&((BslPhyLinksNodeType*)pPhyCtx->pPhyLinkDescNode)->node);
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
//Return the PhyLink handle to the free pool
VosStatus = vos_list_insert_front(&BslPhyLinksDescPool,&((BslPhyLinksNodeType*)pPhyCtx->pPhyLinkDescNode)->node);
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
pPhyCtx->pPhyLinkDescNode = NULL;
}
pPhyCtx->pClientCtx = NULL;//Moved here to bebug the exception
pPhyCtx->used = FALSE;
} // BslReleasePhyCtx()
/**
@brief WLAN_BAPEventCB() - Implements the callback for ALL asynchronous events.
Including Events resulting from:
* HCI Create Physical Link,
* Disconnect Physical Link,
* Create Logical Link,
* Flow Spec Modify,
* HCI Reset,
* HCI Flush,...
Also used to return sync events locally by BSL
@param pHddHdl: [in] The HDD(BSL) specific context for this association.
BSL gets this from the downgoing packets Physical handle value.
@param pBapHCIEvent: [in] pointer to the union of "HCI Event" structures.
Contains all info needed for HCI event.
@param AssocSpecificEvent: [in] flag indicates assoc-specific (1) or
global (0) event
@return
The result code associated with performing the operation
VOS_STATUS_E_FAULT: pointer to pBapHCIEvent is NULL
VOS_STATUS_SUCCESS: Success
*/
static VOS_STATUS WLANBAP_EventCB
(
v_PVOID_t pHddHdl, /* this could refer to either the BSL per
association context which got passed in during
register data plane OR the BSL per application
context passed in during register BAP callbacks
based on setting of the Boolean flag below */
tpBtampHCI_Event pBapHCIEvent, /* This now encodes ALL event types including
Command Complete and Command Status*/
v_BOOL_t AssocSpecificEvent /* Flag to indicate global or assoc-specific event */
)
{
BslClientCtxType* pctx;
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
vos_pkt_t* pVosPkt;
v_U32_t PackStatus;
static v_U8_t Buff[BSL_MAX_EVENT_SIZE]; // stack overflow?
v_U32_t Written = 0; // FramesC REQUIRES this
v_U32_t OldMapVal;
struct sk_buff *skb = NULL;
// sanity checking
if ( pBapHCIEvent == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB bad input" );
return VOS_STATUS_E_FAILURE;
}
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB event=%d "
"assoc_specific=%d", pBapHCIEvent->bapHCIEventCode, AssocSpecificEvent );
if ( pHddHdl == NULL )
{
/* Consider the following error scenarios to bypass the NULL check:
- create LL without a call for create PL before
- delete LL or PL when no AMP connection has been established yet
Client context is unimportant from HCI point of view, only needed by the TLV API in BAP
TODO: Change the TLV APIs to not to carry the client context; it doesn't use it anyway
*/
if (( AssocSpecificEvent ) &&
(BTAMP_TLV_HCI_PHYSICAL_LINK_COMPLETE_EVENT != pBapHCIEvent->bapHCIEventCode) &&
(BTAMP_TLV_HCI_DISCONNECT_PHYSICAL_LINK_COMPLETE_EVENT != pBapHCIEvent->bapHCIEventCode))
{
pctx = gpBslctx;
}
else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_FATAL, "WLANBAP_EventCB bad input" );
return VOS_STATUS_E_FAILURE;
}
}
if(NULL != pHddHdl)
{
if ( AssocSpecificEvent )
{
// get the app context from the assoc context
pctx = ((BslPhyLinkCtxType *)pHddHdl)->pClientCtx;
}
else
{
pctx = (BslClientCtxType *)pHddHdl;
}
}
if(NULL == pctx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"pctx is NULL in %s", __func__);
return VOS_STATUS_E_FAULT;
}
VosStatus = vos_pkt_get_packet( &pVosPkt, VOS_PKT_TYPE_RX_RAW,
BSL_MAX_EVENT_SIZE, 1, 0, NULL, NULL);
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB vos_pkt_get_packet "
"failed status=%d", VosStatus );
return(VosStatus);
}
switch ( pBapHCIEvent->bapHCIEventCode )
{
/** BT events */
case BTAMP_TLV_HCI_COMMAND_COMPLETE_EVENT:
{
/*
BTAMP_TLV_HCI_RESET_CMD:
BTAMP_TLV_HCI_FLUSH_CMD:
BTAMP_TLV_HCI_LOGICAL_LINK_CANCEL_CMD:
BTAMP_TLV_HCI_SET_EVENT_MASK_CMD:
BTAMP_TLV_HCI_READ_CONNECTION_ACCEPT_TIMEOUT_CMD:
BTAMP_TLV_HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT_CMD:
BTAMP_TLV_HCI_READ_LINK_SUPERVISION_TIMEOUT_CMD:
BTAMP_TLV_HCI_WRITE_LINK_SUPERVISION_TIMEOUT_CMD:
BTAMP_TLV_HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT_CMD:
BTAMP_TLV_HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT_CMD:
BTAMP_TLV_HCI_SET_EVENT_MASK_PAGE_2_CMD:
BTAMP_TLV_HCI_READ_LOCATION_DATA_CMD:
BTAMP_TLV_HCI_WRITE_LOCATION_DATA_CMD:
BTAMP_TLV_HCI_READ_FLOW_CONTROL_MODE_CMD:
BTAMP_TLV_HCI_WRITE_FLOW_CONTROL_MODE_CMD:
BTAMP_TLV_HCI_READ_BEST_EFFORT_FLUSH_TO_CMD:
BTAMP_TLV_HCI_WRITE_BEST_EFFORT_FLUSH_TO_CMD:
BTAMP_TLV_HCI_SET_SHORT_RANGE_MODE_CMD:
BTAMP_TLV_HCI_READ_LOCAL_VERSION_INFORMATION_CMD:
BTAMP_TLV_HCI_READ_LOCAL_SUPPORTED_COMMANDS_CMD:
BTAMP_TLV_HCI_READ_BUFFER_SIZE_CMD:
BTAMP_TLV_HCI_READ_DATA_BLOCK_SIZE_CMD:
BTAMP_TLV_HCI_READ_FAILED_CONTACT_COUNTER_CMD:
BTAMP_TLV_HCI_RESET_FAILED_CONTACT_COUNTER_CMD:
BTAMP_TLV_HCI_READ_LINK_QUALITY_CMD:
BTAMP_TLV_HCI_READ_RSSI_CMD:
BTAMP_TLV_HCI_READ_LOCAL_AMP_INFORMATION_CMD:
BTAMP_TLV_HCI_READ_LOCAL_AMP_ASSOC_CMD:
BTAMP_TLV_HCI_WRITE_REMOTE_AMP_ASSOC_CMD:
BTAMP_TLV_HCI_READ_LOOPBACK_MODE_CMD:
BTAMP_TLV_HCI_WRITE_LOOPBACK_MODE_CMD:
BTAMP_TLV_HCI_VENDOR_SPECIFIC_CMD_0:
*/
// pack
PackStatus = btampPackTlvHCI_Command_Complete_Event( pctx,
&pBapHCIEvent->u.btampCommandCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Command_Complete_Event failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_COMMAND_STATUS_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Command_Status_Event( pctx,
&pBapHCIEvent->u.btampCommandStatusEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Command_Status_Event failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_NUM_OF_COMPLETED_PKTS_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Num_Completed_Pkts_Event( pctx,
&pBapHCIEvent->u.btampNumOfCompletedPktsEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Num_Completed_Pkts_Event failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_NUM_OF_COMPLETED_DATA_BLOCKS_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Num_Completed_Data_Blocks_Event( pctx,
&pBapHCIEvent->u.btampNumOfCompletedDataBlocksEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Num_Completed_Data_Blocks_Event failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_HARDWARE_ERROR_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Hardware_Error_Event( pctx,
&pBapHCIEvent->u.btampHardwareErrorEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_FLUSH_OCCURRED_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Flush_Occurred_Event( pctx,
&pBapHCIEvent->u.btampFlushOccurredEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Flush_Occurred_Event failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_ENHANCED_FLUSH_COMPLETE_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Enhanced_Flush_Complete_Event( pctx,
&pBapHCIEvent->u.btampEnhancedFlushCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampPackTlvHCI_Enhanced_Flush_Complete_Event failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_LOOPBACK_COMMAND_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Loopback_Command_Event( pctx,
&pBapHCIEvent->u.btampLoopbackCommandEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_DATA_BUFFER_OVERFLOW_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Data_Buffer_Overflow_Event( pctx,
&pBapHCIEvent->u.btampDataBufferOverflowEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_QOS_VIOLATION_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Qos_Violation_Event( pctx,
&pBapHCIEvent->u.btampQosViolationEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
/** BT v3.0 events */
case BTAMP_TLV_HCI_GENERIC_AMP_LINK_KEY_NOTIFICATION_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Generic_AMP_Link_Key_Notification_Event( pctx,
&pBapHCIEvent->u.btampGenericAMPLinkKeyNotificationEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_PHYSICAL_LINK_COMPLETE_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Physical_Link_Complete_Event( pctx,
&pBapHCIEvent->u.btampPhysicalLinkCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
// look at this event to determine whether to cleanup the PHY context
if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
WLANBAP_STATUS_SUCCESS )
{
// register the data plane now
VosStatus = WLANBAP_RegisterDataPlane( pctx->bapHdl,
WLANBAP_STAFetchPktCB,
WLANBAP_STARxCB,
WLANBAP_TxCompCB,
(BslPhyLinkCtxType *)pHddHdl );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB WLANBAP_RegisterDataPlane "
"failed status = %d", VosStatus );
// we still want to send the event upto app so do not bail
}
else
{
// update the phy link handle based map so TX data can start flowing through
OldMapVal = vos_atomic_set( (uintptr_t*)BslPhyLinkMap+pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.phy_link_handle,
(uintptr_t) pHddHdl );
// VOS_ASSERT( OldMapVal == 0 );//Commented to test reconnect
}
}
else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
WLANBAP_ERROR_HOST_REJ_RESOURCES )
{
BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
}
else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
WLANBAP_ERROR_HOST_TIMEOUT )
{
//We need to update the phy link handle here to be able to reissue physical link accept
// update the phy link handle based map so TX data can start flowing through
OldMapVal = vos_atomic_set( (uintptr_t*)BslPhyLinkMap+pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.phy_link_handle,
(uintptr_t) pHddHdl );
// VOS_ASSERT( OldMapVal == 0 );//Commented to test reconnect
BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
}
else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
WLANBAP_ERROR_MAX_NUM_CNCTS )
{
//We need to update the phy link handle here to be able to reissue physical link /create/accept
// update the phy link handle based map so TX data can start flowing through
OldMapVal = vos_atomic_set( (uintptr_t*)BslPhyLinkMap+pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.phy_link_handle,
(uintptr_t) pHddHdl );
// VOS_ASSERT( OldMapVal == 0 );//Commented to test reconnect
BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
}
else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
WLANBAP_ERROR_HOST_TIMEOUT )
{
BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
}
else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
0x16 /* WLANBAP_ERROR_FAILED_CONNECTION? */ )
{
BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
}
else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
0x8 /* WLANBAP_ERROR_AUTH_FAILED? */ )
{
BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
}
else if ( pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status ==
WLANBAP_ERROR_NO_CNCT )
{
BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
}
else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB unexpected HCI Phy Link Comp Evt "
"status =%d", pBapHCIEvent->u.btampPhysicalLinkCompleteEvent.status );
}
break;
}
case BTAMP_TLV_HCI_CHANNEL_SELECTED_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Channel_Selected_Event( pctx,
&pBapHCIEvent->u.btampChannelSelectedEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_DISCONNECT_PHYSICAL_LINK_COMPLETE_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Disconnect_Physical_Link_Complete_Event( pctx,
&pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
// we need to cleanup the PHY context always but have these checks to make
// sure we catch unexpected behavior, strangely enough even when peer triggers
// the disconnect the reason code is still 0x16, weird
if ( pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent.status == WLANBAP_STATUS_SUCCESS &&
pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent.reason == WLANBAP_ERROR_TERM_BY_LOCAL_HOST )
{
BslReleasePhyCtx( (BslPhyLinkCtxType *)pHddHdl );
}
else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB unexpected HCI Dis Phy Link Comp Evt "
"status =%d reason =%d", pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent.status,
pBapHCIEvent->u.btampDisconnectPhysicalLinkCompleteEvent.reason );
}
break;
}
case BTAMP_TLV_HCI_PHYSICAL_LINK_LOSS_WARNING_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Physical_Link_Loss_Warning_Event( pctx,
&pBapHCIEvent->u.btampPhysicalLinkLossWarningEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_PHYSICAL_LINK_RECOVERY_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Physical_Link_Recovery_Event( pctx,
&pBapHCIEvent->u.btampPhysicalLinkRecoveryEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_LOGICAL_LINK_COMPLETE_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Logical_Link_Complete_Event( pctx,
&pBapHCIEvent->u.btampLogicalLinkCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_DISCONNECT_LOGICAL_LINK_COMPLETE_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Disconnect_Logical_Link_Complete_Event( pctx,
&pBapHCIEvent->u.btampDisconnectLogicalLinkCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_FLOW_SPEC_MODIFY_COMPLETE_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Flow_Spec_Modify_Complete_Event( pctx,
&pBapHCIEvent->u.btampFlowSpecModifyCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
case BTAMP_TLV_HCI_SHORT_RANGE_MODE_CHANGE_COMPLETE_EVENT:
{
// pack
PackStatus = btampPackTlvHCI_Short_Range_Mode_Change_Complete_Event( pctx,
&pBapHCIEvent->u.btampShortRangeModeChangeCompleteEvent, Buff, BSL_MAX_EVENT_SIZE, &Written );
if ( !BTAMP_SUCCEEDED( PackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANBAP_EventCB: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", PackStatus);
// handle the error
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
break;
}
default:
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB unexpected event" );
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
break;
}
}
VOS_ASSERT(Written <= BSL_MAX_EVENT_SIZE);
// stick the event into a VoS pkt
VosStatus = vos_pkt_push_head( pVosPkt, Buff, Written );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_EventCB vos_pkt_push_head "
"status =%d", VosStatus );
// return the packet
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
// Extract the OS packet (skb).
// Tell VOS to detach the OS packet from the VOS packet
VosStatus = vos_pkt_get_os_packet( pVosPkt, (v_VOID_t **)&skb, VOS_TRUE );
if(!VOS_IS_STATUS_SUCCESS( VosStatus ))
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: Failure extracting skb from vos pkt. "
"VosStatus = %d", __func__, VosStatus );
// return the packet
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
return(VOS_STATUS_E_FAILURE);
}
//JEZ100922: We are free to return the enclosing VOSS packet.
VosStatus = vos_pkt_return_packet( pVosPkt );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ));
//JEZ100809: While an skb is being handled by the kernel, is "skb->dev" de-ref'd?
skb->dev = (struct net_device *) gpBslctx->hdev;
bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
//skb->protocol = eth_type_trans(skb, skb->dev);
//skb->ip_summed = CHECKSUM_UNNECESSARY;
// This is my receive skb pointer
gpBslctx->rx_skb = skb;
// This is how data and events are passed up to BlueZ
hci_recv_frame(gpBslctx->rx_skb);
return(VOS_STATUS_SUCCESS);
} // WLANBAP_EventCB()
static VOS_STATUS
WLANBAP_PhyLinkFailure
(
BslClientCtxType* pctx,
v_U8_t phy_link_handle
)
{
VOS_STATUS vosStatus;
tBtampHCI_Event bapHCIEvent;
/* Format the Physical Link Complete event to return... */
bapHCIEvent.bapHCIEventCode = BTAMP_TLV_HCI_PHYSICAL_LINK_COMPLETE_EVENT;
bapHCIEvent.u.btampPhysicalLinkCompleteEvent.present = 1;
bapHCIEvent.u.btampPhysicalLinkCompleteEvent.status = WLANBAP_ERROR_UNSPECIFIED_ERROR;
bapHCIEvent.u.btampPhysicalLinkCompleteEvent.phy_link_handle
= phy_link_handle;
bapHCIEvent.u.btampPhysicalLinkCompleteEvent.ch_number
= 0;
//TBD: Could be a cleaner way to get the PhyLinkCtx handle; For now works
BslPhyLinkCtx[0].pClientCtx = pctx;
vosStatus = WLANBAP_EventCB( &BslPhyLinkCtx[0], &bapHCIEvent, TRUE );
return vosStatus;
}
/**
@brief BslFindAndInitClientCtx() - This function will find and initialize a client
a.k.a app context
@param pctx : [inout] ptr to the client context
@return
TRUE if all OK, FALSE otherwise
*/
static BOOL BslFindAndInitClientCtx
(
BslClientCtxType** pctx_
)
{
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
BslClientCtxType* pctx;
v_U8_t i;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslFindAndInitClientCtx" );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,"%s:BslClientLock already inited",__func__);
// return(0);
}
for ( i=0; i < BSL_MAX_CLIENTS; i++ )
{
if ( !BslClientCtx[i].used )
{
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,"%s:BslClientCtx[%d] selected",__func__, i);
BslClientCtx[i].used = TRUE;
break;
}
}
if ( i == BSL_MAX_CLIENTS )
{
// no more clients can be supported
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslFindAndInitClientCtx no more "
"clients can be supported MAX=%d", BSL_MAX_CLIENTS );
return FALSE;
}
//pctx = BslClientCtx + i;
pctx = gpBslctx;
// get a handle from BAP
VosStatus = WLANBAP_GetNewHndl(&pctx->bapHdl);
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
pctx->used = FALSE;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s:WLAN_GetNewHndl Failed",__func__);
return(FALSE);
}
// register the event cb with BAP, this cb is used for BOTH association
// specific and non-association specific event notifications by BAP.
// However association specific events will be called with a different
// cookie that is passed in during the physical link create/accept
VosStatus = WLAN_BAPRegisterBAPCallbacks( pctx->bapHdl, WLANBAP_EventCB, pctx );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
pctx->used = FALSE;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s:WLAN_BAPRegsiterBAPCallaback Failed",__func__);
return(FALSE);
}
// init the PhyLinks queue to keep track of the assoc's of this client
VosStatus = vos_list_init( &pctx->PhyLinks );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
*pctx_ = pctx;
return(TRUE);
} //BslFindAndInitClientCtx()
/**
@brief BslReleaseClientCtx() - This function will release a client a.k.a. app
context
@param pctx : [in] ptr to the client context
@return
None
*/
//#if 0
static void BslReleaseClientCtx
(
BslClientCtxType* pctx
)
{
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
vos_list_node_t* pLink;
BslPhyLinksNodeType *pPhyNode;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslReleaseClientCtx" );
// an app can do this without cleaning up after itself i.e. it can have active associations and
// data pending, we need to cleanup its mess
// first tell BAP we dont want the handle anymore, BAP will cleanup all the associations and
// consume resulting HCI events, so after this we will not get any HCI events. we will also
// not see any FetchPktCB and RxPktCB. We can still expect TxCompletePktCB
VosStatus = WLANBAP_ReleaseHndl( pctx->bapHdl );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
// find and free all of the association contexts belonging to this app
while ( VOS_IS_STATUS_SUCCESS( VosStatus = vos_list_remove_front( &pctx->PhyLinks, &pLink ) ) )
{
pPhyNode = (BslPhyLinksNodeType *)pLink;
// since the phy link has already been removed from the list of active
// associations, make sure we dont attempt to do this again
pPhyNode->pPhy->pPhyLinkDescNode = NULL;
BslReleasePhyCtx( pPhyNode->pPhy );
}
VOS_ASSERT( VosStatus == VOS_STATUS_E_EMPTY );
// destroy the PhyLinks queue
VosStatus = vos_list_destroy( &pctx->PhyLinks );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
pctx->used = FALSE;
} // BslReleaseClientCtx()
//#endif
/**
@brief BslInitPhyCtx() - Initialize the Phy Context array.
@return
TRUE if all OK, FALSE otherwise
*/
static BOOL BslInitPhyCtx (void)
{
v_U16_t i;
// free PHY context
for ( i=0; i<BSL_MAX_PHY_LINKS; i++ )
{
BslPhyLinkCtx[i].used = FALSE;
}
return (TRUE);
} // BslInitPhyCtx()
/**
@brief BslFindAndInitPhyCtx() - This function will try to find a free physical
link a.k.a assocation context and if successful, then init that context
@param pctx : [in] the client context
@param PhyLinkHdl : [in] the physical link handle chosen by application
@param ppPhyCtx : [inout] ptr to the physical link context
@return
TRUE if all OK, FALSE otherwise
*/
static BOOL BslFindAndInitPhyCtx
(
BslClientCtxType* pctx,
v_U8_t PhyLinkHdl,
BslPhyLinkCtxType** ppPhyCtx
)
{
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
v_U16_t i;
v_U16_t j;
vos_list_node_t* pLink;
BslPhyLinksNodeType *pNode;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslFindAndInitPhyCtx" );
for ( i=0; i<BSL_MAX_PHY_LINKS; i++ )
{
if ( !BslPhyLinkCtx[i].used )
{
BslPhyLinkCtx[i].used = TRUE;
break;
}
}
if ( i==BSL_MAX_PHY_LINKS )
{
return(FALSE);
}
else
{
// now init this context
*ppPhyCtx = BslPhyLinkCtx + i;
// setup a ptr to the app context that this assocation specific context lives in
BslPhyLinkCtx[i].pClientCtx = pctx;
// Mark as used
(*ppPhyCtx)->used = TRUE;
// store the PHY link handle
BslPhyLinkCtx[i].PhyLinkHdl = PhyLinkHdl;
// init the TX queues
for ( j=0; j<WLANTL_MAX_AC; j++ )
{
hdd_list_init( &BslPhyLinkCtx[i].ACLTxQueue[j], HDD_TX_QUEUE_MAX_LEN );
//VosStatus = vos_list_init( &BslPhyLinkCtx[i].ACLTxQueue[j] );
//VosStatus = vos_list_init( &(BslPhyLinkCtx+i)->ACLTxQueue );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
}
// need to add this Phy context to the client list of associations,
// useful during Close operation
// get a pkt desc
VosStatus = vos_list_remove_front( &BslPhyLinksDescPool, &pLink );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
// this could happen due to pool not being big enough, etc
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslFindAndInitPhyCtx failed to "
"get node from BslPhyLinksDescPool vstatus=%d", VosStatus );
BslReleasePhyCtx( *ppPhyCtx );
return FALSE;
}
// stick the VOS pkt into the node
pNode = (BslPhyLinksNodeType *) pLink;
pNode->node = *pLink;
pNode->pPhy = *ppPhyCtx;
// now queue the pkt into the correct queue
VosStatus = vos_list_insert_back( &pctx->PhyLinks, pLink );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_ASSERT(0);
}
// need to record the desc for this assocation in the list of
// active assocations in client context to allow cleanup later
(*ppPhyCtx)->pPhyLinkDescNode = pNode;
return(TRUE);
}
} // BslFindAndInitPhyCtx()
/**
@brief BslProcessHCICommand() - This function will process an HCI command i.e
take an HCI command buffer, unpack it and then call the appropriate BAP API
@param pctx : [in] ptr to the client context
@param pBuffer_ : [in] the input buffer containing the HCI command
@param Count_ : [in] size of the HCI command buffer
@return
TRUE if all OK, FALSE otherwise
*/
static BOOL BslProcessHCICommand
(
BslClientCtxType* pctx,
LPCVOID pBuffer_,
DWORD Count_
)
{
LPVOID pBuffer = (LPVOID) pBuffer_; // castaway the const-ness of the ptr
v_U16_t Count = (v_U16_t) Count_; // this should be OK max size < 1500
v_U32_t UnpackStatus;
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
BOOL Status;
BslPhyLinkCtxType* pPhyCtx;
tBtampHCI_Event HCIEvt;
v_U16_t x = 1;
int i = 0;
// the opcode is in LE, if we are LE too then this is fine else we need some
// byte swapping
v_U16_t cmdOpcode = *(UNALIGNED v_U16_t *)pBuffer;
v_U8_t *pBuf = (v_U8_t *)pBuffer;
v_U8_t *pTmp = (v_U8_t *)pBuf;
// TODO: do we really need to do this per call even though the op is quite cheap
if(*(v_U8_t *)&x == 0)
{
// BE
cmdOpcode = ( cmdOpcode & 0xFF ) << 8 | ( cmdOpcode & 0xFF00 ) >> 8;
}
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslProcessHCICommand: cmdOpcode = %hx", cmdOpcode );
for(i=0; i<4; i++)
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: *pBuf before advancepTmp[%x] = %x", i,pTmp[i] );
pBuf+=CMD_TLV_TYPE_AND_LEN_SIZE;
switch ( cmdOpcode )
{
/** BT v3.0 Link Control commands */
case BTAMP_TLV_HCI_CREATE_PHYSICAL_LINK_CMD:
{
tBtampTLVHCI_Create_Physical_Link_Cmd CreatePhysicalLinkCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Create_Physical_Link_Cmd( NULL,
pBuf, Count, &CreatePhysicalLinkCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Create_Physical_Link_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
if(VOS_FALSE == WLANBAP_AmpConnectionAllowed())
{
VosStatus = WLANBAP_PhyLinkFailure(pctx, CreatePhysicalLinkCmd.phy_link_handle);
if ( VOS_STATUS_SUCCESS != VosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLANBAP_PhyLinkFailure failed");
// handle the error
return(FALSE);
}
break;
}
// setup the per PHY link BAP context
Status = BslFindAndInitPhyCtx( pctx, CreatePhysicalLinkCmd.phy_link_handle,
&pPhyCtx );
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "CreatePhysicalLinkCmd.phy_link_handle=%d",CreatePhysicalLinkCmd.phy_link_handle);
if ( !Status )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: BslFindAndInitPhyCtx failed");
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPPhysicalLinkCreate( pctx->bapHdl,
&CreatePhysicalLinkCmd, pPhyCtx, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPPhysicalLinkCreate failed status %d", VosStatus);
// handle the error
BslReleasePhyCtx( pPhyCtx );
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pPhyCtx, &HCIEvt, TRUE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
BslReleasePhyCtx( pPhyCtx );
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_ACCEPT_PHYSICAL_LINK_CMD:
{
tBtampTLVHCI_Accept_Physical_Link_Cmd AcceptPhysicalLinkCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Accept_Physical_Link_Cmd( NULL,
pBuf, Count, &AcceptPhysicalLinkCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Accept_Physical_Link_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
if(VOS_FALSE == WLANBAP_AmpConnectionAllowed())
{
VosStatus = WLANBAP_PhyLinkFailure(pctx, AcceptPhysicalLinkCmd.phy_link_handle);
if ( VOS_STATUS_SUCCESS != VosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLANBAP_PhyLinkFailure failed");
// handle the error
return(FALSE);
}
break;
}
// setup the per PHY link BAP context
Status = BslFindAndInitPhyCtx( pctx, AcceptPhysicalLinkCmd.phy_link_handle,
&pPhyCtx );
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "AcceptPhysicalLinkCmd.phy_link_handle=%d",AcceptPhysicalLinkCmd.phy_link_handle);
if ( !Status )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: BslFindAndInitPhyCtx failed");
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPPhysicalLinkAccept( pctx->bapHdl,
&AcceptPhysicalLinkCmd, pPhyCtx, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPPhysicalLinkAccept failed status %d", VosStatus);
// handle the error
BslReleasePhyCtx( pPhyCtx );
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pPhyCtx, &HCIEvt, TRUE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
BslReleasePhyCtx( pPhyCtx );
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_DISCONNECT_PHYSICAL_LINK_CMD:
{
tBtampTLVHCI_Disconnect_Physical_Link_Cmd DisconnectPhysicalLinkCmd;
Count = Count - 3;//Type and length field lengths are not needed
pTmp = pBuf;
for(i=0; i<4; i++)
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: *pBuf in Disconnect phy link pTmp[%x] = %x", i,pTmp[i] );
// unpack
UnpackStatus = btampUnpackTlvHCI_Disconnect_Physical_Link_Cmd( NULL,
pBuf, Count, &DisconnectPhysicalLinkCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Disconnect_Physical_Link_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPPhysicalLinkDisconnect( pctx->bapHdl,
&DisconnectPhysicalLinkCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPPhysicalLinkDisconnect failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_CREATE_LOGICAL_LINK_CMD:
{
tBtampTLVHCI_Create_Logical_Link_Cmd CreateLogicalLinkCmd;
Count -= 3; //To send the correct length to unpack event
// unpack
UnpackStatus = btampUnpackTlvHCI_Create_Logical_Link_Cmd( NULL,
pBuf, Count, &CreateLogicalLinkCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Create_Logical_Link_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPLogicalLinkCreate( pctx->bapHdl,
&CreateLogicalLinkCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPLogicalLinkCreate failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_ACCEPT_LOGICAL_LINK_CMD:
{
tBtampTLVHCI_Accept_Logical_Link_Cmd AcceptLogicalLinkCmd;
Count = Count - 3;//Subtract Type and Length fields
// unpack
UnpackStatus = btampUnpackTlvHCI_Accept_Logical_Link_Cmd( NULL,
pBuf, Count, &AcceptLogicalLinkCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Accept_Logical_Link_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPLogicalLinkAccept( pctx->bapHdl,
&AcceptLogicalLinkCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPLogicalLinkAccept failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_DISCONNECT_LOGICAL_LINK_CMD:
{
tBtampTLVHCI_Disconnect_Logical_Link_Cmd DisconnectLogicalLinkCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Disconnect_Logical_Link_Cmd( NULL,
pBuf, Count, &DisconnectLogicalLinkCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Disconnect_Logical_Link_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPLogicalLinkDisconnect( pctx->bapHdl,
&DisconnectLogicalLinkCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPLogicalLinkDisconnect failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_LOGICAL_LINK_CANCEL_CMD:
{
tBtampTLVHCI_Logical_Link_Cancel_Cmd LogicalLinkCancelCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Logical_Link_Cancel_Cmd( NULL,
pBuf, Count, &LogicalLinkCancelCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Logical_Link_Cancel_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPLogicalLinkCancel( pctx->bapHdl,
&LogicalLinkCancelCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPLogicalLinkCancel failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_FLOW_SPEC_MODIFY_CMD:
{
tBtampTLVHCI_Flow_Spec_Modify_Cmd FlowSpecModifyCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Flow_Spec_Modify_Cmd( NULL,
pBuf, Count, &FlowSpecModifyCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Flow_Spec_Modify_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPFlowSpecModify( pctx->bapHdl,
&FlowSpecModifyCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPFlowSpecModify failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
/*
Host Controller and Baseband Commands
*/
case BTAMP_TLV_HCI_RESET_CMD:
{
VosStatus = WLAN_BAPReset( pctx->bapHdl );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReset failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_SET_EVENT_MASK_CMD:
{
tBtampTLVHCI_Set_Event_Mask_Cmd SetEventMaskCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Set_Event_Mask_Cmd( NULL,
pBuf, Count, &SetEventMaskCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Set_Event_Mask_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPSetEventMask( pctx->bapHdl,
&SetEventMaskCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPSetEventMask failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_FLUSH_CMD:
{
tBtampTLVHCI_Flush_Cmd FlushCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Flush_Cmd( NULL,
pBuf, Count, &FlushCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Flush_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
/* Flush the TX queue */
//#ifdef BAP_DEBUG
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s:HCI Flush command - will flush Tx Queue", __func__);
//#endif //BAP_DEBUG
// JEZ100604: Temporary short cut
pPhyCtx = &BslPhyLinkCtx[0];
VosStatus = BslFlushTxQueues ( pPhyCtx);
/* Acknowledge the command */
VosStatus = WLAN_BAPFlush( pctx->bapHdl, &FlushCmd );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLAN_BAPFlush failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_ENHANCED_FLUSH_CMD:
{
tBtampTLVHCI_Enhanced_Flush_Cmd FlushCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Enhanced_Flush_Cmd( NULL,
pBuf, Count, &FlushCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: btampUnpackTlvHCI_Enhanced_Flush_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
/* Flush the TX queue */
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s:HCI Flush command - will flush Tx Queue for pkt type %d", __func__, FlushCmd.packet_type);
// We support BE traffic only
if(WLANTL_AC_BE == FlushCmd.packet_type)
{
pPhyCtx = &BslPhyLinkCtx[0];
VosStatus = BslFlushTxQueues ( pPhyCtx);
}
/* Acknowledge the command */
VosStatus = WLAN_EnhancedBAPFlush( pctx->bapHdl, &FlushCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLAN_EnahncedBAPFlush failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_CONNECTION_ACCEPT_TIMEOUT_CMD:
{
VosStatus = WLAN_BAPReadConnectionAcceptTimeout( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadConnectionAcceptTimeout failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT_CMD:
{
tBtampTLVHCI_Write_Connection_Accept_Timeout_Cmd WriteConnectionAcceptTimeoutCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Write_Connection_Accept_Timeout_Cmd( NULL,
pBuf, Count, &WriteConnectionAcceptTimeoutCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Connection_Accept_Timeout_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPWriteConnectionAcceptTimeout( pctx->bapHdl,
&WriteConnectionAcceptTimeoutCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteConnectionAcceptTimeout failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_LINK_SUPERVISION_TIMEOUT_CMD:
{
tBtampTLVHCI_Read_Link_Supervision_Timeout_Cmd ReadLinkSupervisionTimeoutCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Read_Link_Supervision_Timeout_Cmd( NULL,
pBuf, Count, &ReadLinkSupervisionTimeoutCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Link_Supervision_Timeout_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPReadLinkSupervisionTimeout( pctx->bapHdl,
&ReadLinkSupervisionTimeoutCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLinkSupervisionTimeout failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_WRITE_LINK_SUPERVISION_TIMEOUT_CMD:
{
tBtampTLVHCI_Write_Link_Supervision_Timeout_Cmd WriteLinkSupervisionTimeoutCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Write_Link_Supervision_Timeout_Cmd( NULL,
pBuf, Count, &WriteLinkSupervisionTimeoutCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Link_Supervision_Timeout_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPWriteLinkSupervisionTimeout( pctx->bapHdl,
&WriteLinkSupervisionTimeoutCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteLinkSupervisionTimeout failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
/* v3.0 Host Controller and Baseband Commands */
case BTAMP_TLV_HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT_CMD:
{
VosStatus = WLAN_BAPReadLogicalLinkAcceptTimeout( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLogicalLinkAcceptTimeout failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT_CMD:
{
tBtampTLVHCI_Write_Logical_Link_Accept_Timeout_Cmd WriteLogicalLinkAcceptTimeoutCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Write_Logical_Link_Accept_Timeout_Cmd( NULL,
pBuf, Count, &WriteLogicalLinkAcceptTimeoutCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Logical_Link_Accept_Timeout_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPWriteLogicalLinkAcceptTimeout( pctx->bapHdl,
&WriteLogicalLinkAcceptTimeoutCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteLogicalLinkAcceptTimeout failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_SET_EVENT_MASK_PAGE_2_CMD:
{
tBtampTLVHCI_Set_Event_Mask_Page_2_Cmd SetEventMaskPage2Cmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Set_Event_Mask_Page_2_Cmd( NULL,
pBuf, Count, &SetEventMaskPage2Cmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Set_Event_Mask_Page_2_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPSetEventMaskPage2( pctx->bapHdl,
&SetEventMaskPage2Cmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPSetEventMaskPage2 failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_LOCATION_DATA_CMD:
{
VosStatus = WLAN_BAPReadLocationData( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocationData failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_WRITE_LOCATION_DATA_CMD:
{
tBtampTLVHCI_Write_Location_Data_Cmd WriteLocationDataCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Write_Location_Data_Cmd( NULL,
pBuf, Count, &WriteLocationDataCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Location_Data_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPWriteLocationData( pctx->bapHdl,
&WriteLocationDataCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteLocationData failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_FLOW_CONTROL_MODE_CMD:
{
VosStatus = WLAN_BAPReadFlowControlMode( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadFlowControlMode failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_WRITE_FLOW_CONTROL_MODE_CMD:
{
tBtampTLVHCI_Write_Flow_Control_Mode_Cmd WriteFlowControlModeCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Write_Flow_Control_Mode_Cmd( NULL,
pBuf, Count, &WriteFlowControlModeCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Flow_Control_Mode_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPWriteFlowControlMode( pctx->bapHdl,
&WriteFlowControlModeCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteFlowControlMode failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT_CMD:
{
tBtampTLVHCI_Read_Best_Effort_Flush_Timeout_Cmd ReadBestEffortFlushTimeoutCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Read_Best_Effort_Flush_Timeout_Cmd( NULL,
pBuf, Count, &ReadBestEffortFlushTimeoutCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Best_Effort_Flush_Timeout_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPReadBestEffortFlushTimeout( pctx->bapHdl,
&ReadBestEffortFlushTimeoutCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadBestEffortFlushTimeout failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT_CMD:
{
tBtampTLVHCI_Write_Best_Effort_Flush_Timeout_Cmd WriteBestEffortFlushTimeoutCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Write_Best_Effort_Flush_Timeout_Cmd( NULL,
pBuf, Count, &WriteBestEffortFlushTimeoutCmd);
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Best_Effort_Flush_Timeout_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPWriteBestEffortFlushTimeout( pctx->bapHdl,
&WriteBestEffortFlushTimeoutCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteBestEffortFlushTimeout failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
/** opcode definition for this command from AMP HCI CR D9r4 markup */
case BTAMP_TLV_HCI_SET_SHORT_RANGE_MODE_CMD:
{
tBtampTLVHCI_Set_Short_Range_Mode_Cmd SetShortRangeModeCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Set_Short_Range_Mode_Cmd( NULL,
pBuf, Count, &SetShortRangeModeCmd);
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Set_Short_Range_Mode_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPSetShortRangeMode( pctx->bapHdl,
&SetShortRangeModeCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPSetShortRangeMode failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
/* End of v3.0 Host Controller and Baseband Commands */
/*
Informational Parameters
*/
case BTAMP_TLV_HCI_READ_LOCAL_VERSION_INFO_CMD:
{
VosStatus = WLAN_BAPReadLocalVersionInfo( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocalVersionInfo failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_LOCAL_SUPPORTED_CMDS_CMD:
{
VosStatus = WLAN_BAPReadLocalSupportedCmds( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocalSupportedCmds failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_BUFFER_SIZE_CMD:
{
VosStatus = WLAN_BAPReadBufferSize( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadBufferSize failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
/* v3.0 Informational commands */
case BTAMP_TLV_HCI_READ_DATA_BLOCK_SIZE_CMD:
{
VosStatus = WLAN_BAPReadDataBlockSize( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadDataBlockSize failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
/*
Status Parameters
*/
case BTAMP_TLV_HCI_READ_FAILED_CONTACT_COUNTER_CMD:
{
tBtampTLVHCI_Read_Failed_Contact_Counter_Cmd ReadFailedContactCounterCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Read_Failed_Contact_Counter_Cmd( NULL,
pBuf, Count, &ReadFailedContactCounterCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Failed_Contact_Counter_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPReadFailedContactCounter( pctx->bapHdl,
&ReadFailedContactCounterCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadFailedContactCounter failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_RESET_FAILED_CONTACT_COUNTER_CMD:
{
tBtampTLVHCI_Reset_Failed_Contact_Counter_Cmd ResetFailedContactCounterCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Reset_Failed_Contact_Counter_Cmd( NULL,
pBuf, Count, &ResetFailedContactCounterCmd);
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Reset_Failed_Contact_Counter_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPResetFailedContactCounter( pctx->bapHdl,
&ResetFailedContactCounterCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPResetFailedContactCounter failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_LINK_QUALITY_CMD:
{
tBtampTLVHCI_Read_Link_Quality_Cmd ReadLinkQualityCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Read_Link_Quality_Cmd( NULL,
pBuf, Count, &ReadLinkQualityCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Link_Quality_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPReadLinkQuality( pctx->bapHdl,
&ReadLinkQualityCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLinkQuality failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_RSSI_CMD:
{
tBtampTLVHCI_Read_RSSI_Cmd ReadRssiCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Read_RSSI_Cmd( NULL,
pBuf, Count, &ReadRssiCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_RSSI_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPReadRSSI( pctx->bapHdl,
&ReadRssiCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadRSSI failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_LOCAL_AMP_INFORMATION_CMD:
{
tBtampTLVHCI_Read_Local_AMP_Information_Cmd ReadLocalAmpInformationCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Read_Local_AMP_Information_Cmd( NULL,
pBuf, Count, &ReadLocalAmpInformationCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Local_AMP_Information_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPReadLocalAMPInfo( pctx->bapHdl,
&ReadLocalAmpInformationCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocalAMPInfo failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_READ_LOCAL_AMP_ASSOC_CMD:
{
tBtampTLVHCI_Read_Local_AMP_Assoc_Cmd ReadLocalAmpAssocCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Read_Local_AMP_Assoc_Cmd( NULL,
pBuf, Count, &ReadLocalAmpAssocCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Local_AMP_Assoc_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPReadLocalAMPAssoc( pctx->bapHdl,
&ReadLocalAmpAssocCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLocalAMPAssoc failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_WRITE_REMOTE_AMP_ASSOC_CMD:
{
tBtampTLVHCI_Write_Remote_AMP_ASSOC_Cmd WriteRemoteAmpAssocCmd;
// unpack
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: HCI_Write_Remote_AMP_ASSOC_Cmd Count = %d", Count);
DUMPLOG(1, __func__, "HCI_Write_Remote_AMP_ASSOC cmd",
pBuf,
Count);
UnpackStatus = btampUnpackTlvHCI_Write_Remote_AMP_ASSOC_Cmd( NULL,
pBuf, Count, &WriteRemoteAmpAssocCmd );
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WriteRemoteAmpAssocCmd.amp_assoc_remaining_length = %d",
WriteRemoteAmpAssocCmd.amp_assoc_remaining_length
);
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Remote_AMP_ASSOC_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
//#define BAP_UNIT_TEST
#ifdef BAP_UNIT_TEST
{
unsigned char test_amp_assoc_fragment[] =
{
0x01, 0x00, 0x06, 0x00, 0x00, 0xde, 0xad, 0xbe,
0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
0x0c, 0x00, 0x55, 0x53, 0x20, 0xc9, 0x0c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x00, 0x06, 0x00, 0x55, 0x53,
0x20, 0xc9, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00,
0x00, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
WriteRemoteAmpAssocCmd.present = 1;
WriteRemoteAmpAssocCmd.phy_link_handle = 1;
WriteRemoteAmpAssocCmd.length_so_far = 0;
WriteRemoteAmpAssocCmd.amp_assoc_remaining_length = 74;
/* Set the amp_assoc_fragment to the right values of MAC addr and
* channels
*/
vos_mem_copy(
WriteRemoteAmpAssocCmd.amp_assoc_fragment,
test_amp_assoc_fragment,
sizeof( test_amp_assoc_fragment));
}
#endif
VosStatus = WLAN_BAPWriteRemoteAMPAssoc( pctx->bapHdl,
&WriteRemoteAmpAssocCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteRemoteAMPAssoc failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
/*
Debug Commands
*/
case BTAMP_TLV_HCI_READ_LOOPBACK_MODE_CMD:
{
tBtampTLVHCI_Read_Loopback_Mode_Cmd ReadLoopbackModeCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Read_Loopback_Mode_Cmd( NULL,
pBuf, Count, &ReadLoopbackModeCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Read_Loopback_Mode_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPReadLoopbackMode( pctx->bapHdl,
&ReadLoopbackModeCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPReadLoopbackMode failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_WRITE_LOOPBACK_MODE_CMD:
{
tBtampTLVHCI_Write_Loopback_Mode_Cmd WriteLoopbackModeCmd;
// unpack
UnpackStatus = btampUnpackTlvHCI_Write_Loopback_Mode_Cmd( NULL,
pBuf, Count, &WriteLoopbackModeCmd );
if ( !BTAMP_SUCCEEDED( UnpackStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: btampUnpackTlvHCI_Write_Loopback_Mode_Cmd failed status %d", UnpackStatus);
// handle the error
return(FALSE);
}
VosStatus = WLAN_BAPWriteLoopbackMode( pctx->bapHdl,
&WriteLoopbackModeCmd, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPWriteLoopbackMode failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_VENDOR_SPECIFIC_CMD_0:
{
VosStatus = WLAN_BAPVendorSpecificCmd0( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPVendorSpecificCmd0 failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
case BTAMP_TLV_HCI_VENDOR_SPECIFIC_CMD_1:
{
VosStatus = WLAN_BAPVendorSpecificCmd1( pctx->bapHdl, &HCIEvt );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLAN_BAPVendorSpecificCmd1 failed status %d", VosStatus);
// handle the error
return(FALSE);
}
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
default:
{
/* Unknow opcode. Return a command status event...with "Unknown Opcode" status */
/* Format the command status event to return... */
HCIEvt.bapHCIEventCode = BTAMP_TLV_HCI_COMMAND_STATUS_EVENT;
HCIEvt.u.btampCommandStatusEvent.present = 1;
HCIEvt.u.btampCommandStatusEvent.status = WLANBAP_ERROR_UNKNOWN_HCI_CMND;
HCIEvt.u.btampCommandStatusEvent.num_hci_command_packets = 1;
HCIEvt.u.btampCommandStatusEvent.command_opcode
= cmdOpcode;
// this may look strange as this is the function registered
// with BAP for the EventCB but we are also going to use it
// as a helper function. The difference is that this invocation
// runs in HCI command sending caller context while the callback
// will happen in BAP's context whatever that may be
VosStatus = WLANBAP_EventCB( pctx, &HCIEvt, FALSE );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BslProcessHCICommand: WLANBAP_EventCB failed status %d", VosStatus);
// handle the error
return(FALSE);
}
break;
}
}
return(TRUE);
} // BslProcessHCICommand()
/**
@brief BslProcessACLDataTx() - This function will process an egress ACL data packet
@param pctx : [in] ptr to the client context
@param pBuffer_ : [in] ptr to the buffer containing the ACL data packet
@param pCount : [in] size of the ACL data packet buffer
@return
TRUE if all OK, FALSE otherwise
*/
#define BTAMP_USE_VOS_WRAPPER
//#undef BTAMP_USE_VOS_WRAPPER
#ifdef BTAMP_USE_VOS_WRAPPER
static BOOL BslProcessACLDataTx
(
BslClientCtxType* pctx,
struct sk_buff *skb,
v_SIZE_t* pCount
)
#else
static BOOL BslProcessACLDataTx
(
BslClientCtxType* pctx,
LPCVOID pBuffer_,
v_SIZE_t* pCount
)
#endif
{
#ifndef BTAMP_USE_VOS_WRAPPER
LPVOID pBuffer = (LPVOID) pBuffer_; // castaway const-ness of ptr
#endif
BOOL findPhyStatus;
BslPhyLinkCtxType* pPhyCtx;
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
WLANTL_ACEnumType Ac;
hdd_list_node_t* pLink;
BslTxListNodeType *pNode;
v_SIZE_t ListSize;
// I will access the skb in a VOSS packet
#ifndef BTAMP_USE_VOS_WRAPPER
struct sk_buff *skb;
#endif
#if 0
static int num_packets;
#endif
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BslProcessACLDataTx" );
// need to find the PHY link for this ACL data pkt based on phy_link_handle
// TODO need some endian-ness check?
////findPhyStatus = BslFindPhyCtx( pctx, *(v_U8_t *)skb->data, &pPhyCtx );
//findPhyStatus = BslFindPhyCtx( pctx, *(v_U8_t *)pBuffer, &pPhyCtx );
// JEZ100604: Temporary short cut
pPhyCtx = &BslPhyLinkCtx[0];
findPhyStatus = VOS_TRUE;
if ( findPhyStatus )
{
//Use the skb->cb field to hold the list node information
pNode = (BslTxListNodeType *) &skb->cb;
// This list node info includes the VOS pkt
pNode->skb = skb;
// stick the SKB into the node
pLink = (hdd_list_node_t *) pNode;
VosStatus = WLANBAP_GetAcFromTxDataPkt(pctx->bapHdl, skb->data, &Ac);
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessACLDataTx WLANBAP_GetAcFromTxDataPkt "
"failed status =%d", VosStatus );
Ac = WLANTL_AC_BE;
}
// now queue the pkt into the correct queue
// We will want to insert a node of type BslTxListNodeType (was going to be vos_pkt_list_node_t)
spin_lock_bh(&pPhyCtx->ACLTxQueue[Ac].lock);
VosStatus = hdd_list_insert_back( &pPhyCtx->ACLTxQueue[Ac], pLink );
spin_unlock_bh(&pPhyCtx->ACLTxQueue[Ac].lock);
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_ASSERT(0);
}
// determine if there is a need to signal TL through BAP
hdd_list_size( &pPhyCtx->ACLTxQueue[Ac], &ListSize );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_ASSERT(0);
}
if ( ListSize == 1 )
{
// Let TL know we have a packet to send for this AC
VosStatus = WLANBAP_STAPktPending( pctx->bapHdl, pPhyCtx->PhyLinkHdl, Ac );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessACLDataTx WLANBAP_STAPktPending "
"failed status =%d", VosStatus );
VOS_ASSERT(0);
}
}
return(TRUE);
}
else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BslProcessACLDataTx attempting to send "
"data for a non-existant assocation" );
return(FALSE);
}
} // BslProcessACLDataTx()
static inline void *hci_get_drvdata(struct hci_dev *hdev)
{
return hdev->driver_data;
}
static inline void hci_set_drvdata(struct hci_dev *hdev, void *data)
{
hdev->driver_data = data;
}
/*---------------------------------------------------------------------------
* Function definitions
*-------------------------------------------------------------------------*/
/**---------------------------------------------------------------------------
\brief BSL_Init() - Initialize the BSL Misc char driver
This is called in vos_open(), right after WLANBAP_Open(), as part of
bringing up the BT-AMP PAL (BAP)
vos_open() will pass in the VOS context. In which a BSL context can be created.
\param - NA
\return - 0 for success non-zero for failure
--------------------------------------------------------------------------*/
//int BSL_Init (void *pCtx)
int BSL_Init ( v_PVOID_t pvosGCtx )
{
BslClientCtxType* pctx = NULL;
ptBtampHandle bapHdl = NULL; // our handle in BAP
//ptBtampContext pBtampCtx = NULL;
int err = 0;
struct hci_dev *hdev = NULL;
//struct net_device *dev = NULL; // Our parent wlan network device
hdd_adapter_t *pAdapter = NULL; // Used to retrieve the parent WLAN device
hdd_context_t *pHddCtx = NULL;
hdd_config_t *pConfig = NULL;
hdd_adapter_list_node_t *pAdapterNode = NULL;
VOS_STATUS status;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Init");
/*------------------------------------------------------------------------
Allocate (and sanity check?!) BSL control block
------------------------------------------------------------------------*/
//vos_alloc_context(pvosGCtx, VOS_MODULE_ID_BSL, (v_VOID_t**)&pctx, sizeof(BslClientCtxType));
pctx = &BslClientCtx[0];
bapHdl = vos_get_context( VOS_MODULE_ID_BAP, pvosGCtx);
if ( NULL == bapHdl )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BAP pointer from pvosGCtx on BSL_Init");
return VOS_STATUS_E_FAULT;
}
// Save away the btamp (actually the vos) context
gpCtx = pvosGCtx;
/* Save away the pointer to the BT-AMP PAL context in the BSL driver context */
pctx->bapHdl = bapHdl;
/* Save away the pointer to the BSL driver context in a global (fix this) */
gpBslctx = pctx;
/* Initialize all the Phy Contexts to un-used */
BslInitPhyCtx();
/* Initialize the Rx fields in the HCI driver context */
//pctx->rx_state = RECV_WAIT_PACKET_TYPE;
pctx->rx_count = 0;
pctx->rx_skb = NULL;
/* JEZ100713: Temporarily the Tx skb queue will have depth one.*/
// Don't disturb tx_skb
//pctx->tx_skb = NULL;
//pctx->tx_skb = alloc_skb(WLANBAP_MAX_80211_PAL_PDU_SIZE+12, GFP_ATOMIC);
pctx->hdev = NULL;
//Get the HDD context.
pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, pvosGCtx );
if(NULL != pHddCtx)
{
pConfig = pHddCtx->cfg_ini;
}
if(NULL == pConfig)
{
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"Didn't register as HCI device");
return 0;
}
else if(0 == pConfig->enableBtAmp)
{
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"Didn't register as HCI device, user option(gEnableBtAmp) is set to 0");
return 0;
}
if (VOS_STA_SAP_MODE == hdd_get_conparam())
{
status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
if ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
{
if ( WLAN_HDD_SOFTAP == pAdapterNode->pAdapter->device_mode)
{
pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP);
}
else if (WLAN_HDD_P2P_GO == pAdapterNode->pAdapter->device_mode)
{
pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
}
}
}
else
pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
if ( NULL == pAdapter )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid HDD Adapter pointer from pvosGCtx on BSL_Init");
return VOS_STATUS_E_FAULT;
}
/* Save away the pointer to the parent WLAN device in BSL driver context */
pctx->p_dev = pAdapter->dev;
/* Initialize HCI device */
hdev = hci_alloc_dev();
if (!hdev)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Can't allocate HCI device in BSL_Init");
return VOS_STATUS_E_FAULT;
}
/* Save away the HCI device pointer in the BSL driver context */
pctx->hdev = hdev;
#if defined HCI_80211 || defined HCI_AMP
#define BUILD_FOR_BLUETOOTH_NEXT_2_6
#else
#undef BUILD_FOR_BLUETOOTH_NEXT_2_6
#endif
#ifdef BUILD_FOR_BLUETOOTH_NEXT_2_6
/* HCI "bus type" of HCI_VIRTUAL should apply */
hdev->bus = HCI_VIRTUAL;
/* Set the dev_type to BT-AMP 802.11 */
#ifdef HCI_80211
hdev->dev_type = HCI_80211;
#else
hdev->dev_type = HCI_AMP;
#endif
#ifdef FEATURE_WLAN_BTAMP_UT
/* For the "real" BlueZ build, DON'T Set the device "quirks" to indicate RAW */
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
#endif
#else //BUILD_FOR_BLUETOOTH_NEXT_2_6
/* HCI "bus type" of HCI_VIRTUAL should apply */
hdev->type = HCI_VIRTUAL;
/* Set the dev_type to BT-AMP 802.11 */
//hdev->dev_type = HCI_80211;
////hdev->dev_type = HCI_AMP;
/* For the "temporary" BlueZ build, Set the device "quirks" to indicate RAW */
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
#endif //BUILD_FOR_BLUETOOTH_NEXT_2_6
/* Save away the BSL driver pointer in the HCI device context */
hci_set_drvdata(hdev, pctx);
/* Set the parent device for this HCI device. This is our WLAN net_device */
SET_HCIDEV_DEV(hdev, &pctx->p_dev->dev);
hdev->open = BSL_Open;
hdev->close = BSL_Close;
hdev->flush = BSL_Flush;
hdev->send = BSL_Write;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
hdev->destruct = BSL_Destruct;
hdev->owner = THIS_MODULE;
#endif
hdev->ioctl = BSL_IOControl;
/* Timeout before it is safe to send the first HCI packet */
msleep(1000);
/* Register HCI device */
err = hci_register_dev(hdev);
if (err < 0)
{
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Unable to register HCI device, err=%d", err);
pctx->hdev = NULL;
hci_free_dev(hdev);
return -ENODEV;
}
pHddCtx->isAmpAllowed = VOS_TRUE;
return 0;
} // BSL_Init()
/**---------------------------------------------------------------------------
\brief BSL_Deinit() - De-initialize the BSL Misc char driver
This is called in by WLANBAP_Close() as part of bringing down the BT-AMP PAL (BAP)
\param - NA
\return - 0 for success non-zero for failure
--------------------------------------------------------------------------*/
int BSL_Deinit( v_PVOID_t pvosGCtx )
{
//int err = 0;
struct hci_dev *hdev;
BslClientCtxType* pctx = NULL;
//pctx = vos_get_context( VOS_MODULE_ID_BSL, pvosGCtx);
pctx = gpBslctx;
if ( NULL == pctx )
{
//VOS_TRACE( VOS_MODULE_ID_BSL, VOS_TRACE_LEVEL_ERROR,
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BSL pointer from pvosGCtx on BSL_Init");
return VOS_STATUS_E_FAULT;
}
/* Retrieve the HCI device pointer from the BSL driver context */
hdev = pctx->hdev;
if (!hdev)
return 0;
/* hci_unregister_dev is called again here, in case user didn't call it */
/* Unregister device from BlueZ; fcn sends us HCI commands before it returns */
/* And then the registered hdev->close fcn should be called by BlueZ (BSL_Close) */
hci_unregister_dev(hdev);
/* BSL_Close is called again here, in case BlueZ didn't call it */
BSL_Close(hdev);
hci_free_dev(hdev);
pctx->hdev = NULL;
return 0;
} // BSL_Deinit()
/**
@brief BSL_Open() - This function opens a device for reading, and writing.
An application indirectly invokes this function when it calls the fopen()
system call to open a special device file names.
@param *hdev : [in] pointer to the open HCI device structure.
BSL_Init (Device Manager) function creates and stores this HCI
device context in the BSL context.
@return
This function returns a status code. Negative codes are failures.
NB: I don't seem to be following this convention.
*/
//static int BSL_Open(struct inode *pInode, struct file *pFile)
static int BSL_Open( struct hci_dev *hdev )
{
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
BslClientCtxType* pctx = (BslClientCtxType *)(hci_get_drvdata(hdev));
v_U16_t i;
BOOL rval;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Open");
/* you can only open a btamp device one time */
if (bBslInited)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "BSL_Open: Already Opened.");
return -EPERM; /* Operation not permitted */
}
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSLClientLock already inited");
// return -EIO; /* I/O error */
return 0;
}
VosStatus = vos_list_init( &BslPhyLinksDescPool );
if ( !VOS_IS_STATUS_SUCCESS( VosStatus ) )
{
//return -EIO; /* I/O error */
return 0;
}
// now we need to populate this pool with the free pkt desc from the array
for ( i=0; i<BSL_MAX_PHY_LINKS; i++ )
{
VosStatus = vos_list_insert_front( &BslPhyLinksDescPool, &BslPhyLinksDesc[i].node );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
}
// This is redundent. See the check above on (fp->private_data != NULL)
bBslInited = TRUE;
rval = BslFindAndInitClientCtx( &pctx );
if(rval != TRUE)
{
// Where is the clean-up in case the above BslFindAndInitClientCtx() call
// fails?
//return -EIO; /* I/O error */
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSLFindAndInitClientContext failed");
return 0;
}
/* Let Linux fopen() know everything is all right */
return 0;
} // BSL_Open()
/**
@brief BSL_Close() - This function closes a device context created by
BSL_Open(). May be called more than once during AMP PAL shut down.
@param *hdev : [in] pointer to the open HCI device structure.
BSL_Init (Device Manager) function creates and stores this HCI
device context in the BSL context.
@return
TRUE indicates success. FALSE indicates failure.
*/
//static int BSL_Close (struct inode *pInode, struct file *pFile)
static int BSL_Close ( struct hci_dev *hdev )
{
VOS_STATUS VosStatus = VOS_STATUS_SUCCESS;
BslClientCtxType* pctx;
vos_list_node_t* pLink;
v_U16_t i;
v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
hdd_context_t *pHddCtx;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Close");
if (NULL != pVosContext)
{
pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
if (NULL != pHddCtx)
{
pHddCtx->isAmpAllowed = VOS_FALSE;
}
}
// it may seem there is some risk here because we are using a value
// passed into us as a pointer. what if this pointer is 0 or points to
// someplace bad? as it turns out the caller is device manager and not
// the application. kernel should trap such invalid access but we will check
// for NULL pointer
if ( hdev == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Close: NULL hdev specified");
return FALSE;
}
pctx = (BslClientCtxType *)(hci_get_drvdata(hdev));
if ( pctx == NULL || !bBslInited)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_LOW, "BSL_Close: %s is not open", hdev->name);
return TRUE;
}
// need to cleanup any per PHY state and the common RX state
BslReleaseClientCtx( pctx );
for ( i=0; i<BslPhyLinksDescPool.count; i++ )
{
VosStatus = vos_list_remove_front( &BslPhyLinksDescPool, &pLink );
//nothing to free as the nodes came from BslPhyLinksDesc, which is a static
//this is needed to allow vos_list_destroy() to go through
}
VosStatus = vos_list_destroy( &BslPhyLinksDescPool );
VOS_ASSERT(VOS_IS_STATUS_SUCCESS( VosStatus ) );
bBslInited = FALSE;
// The next line is temporary
return(0);
} //BSL_Close()
/**
@brief BSL_IOControl() - This function sends a command to a device.
@param *hdev : [in] pointer to the open HCI device structure.
@param cmd : [in] I/O control operation to perform. These codes are
device-specific and are usually exposed to developers through a header file.
@param arg : [in] Additional input parameter.
@return
TRUE indicates success. FALSE indicates failure.
*/
//static long BSL_IOControl(struct file *pFile, unsigned int cmd, unsigned long arg)
static int BSL_IOControl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_IOControl - not supported");
return(TRUE);
} // BSL_IOControl()
/**
@brief BSL_Flush() - This function flushes all pending commands on a device.
@param *hdev : [in] pointer to the open HCI device structure.
@return
TRUE indicates success. FALSE indicates failure.
*/
static int BSL_Flush(struct hci_dev *hdev)
{
VOS_STATUS VosStatus;
BslPhyLinkCtxType* pPhyCtx;
//VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Flush - will flush ALL Tx Queues");
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s - will flush ALL Tx Queues", __func__);
/* Flush the TX queue */
// JEZ100604: Temporary short cut
pPhyCtx = &BslPhyLinkCtx[0];
VosStatus = BslFlushTxQueues ( pPhyCtx);
//return(TRUE);
return(0);
} // BSL_Flush()
/**
@brief BSL_Destruct() - This function destroys an HCI device.
@param *hdev : [in] pointer to the open HCI device structure.
@return
TRUE indicates success. FALSE indicates failure.
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
static void BSL_Destruct(struct hci_dev *hdev)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "BSL_Destruct - not supported");
return; //(TRUE);
} // BSL_Destruct()
#endif
/**
@brief BSL_Write() - This function writes data to the device.
An application indirectly invokes this function when it calls the fwrite()
system call to write to a special device file.
@param *skb : [in] pointer to the skb being transmitted. This skb contains
the HCI command or HCI data. Also a pointer (hdev) to the HCI device struct
@return
The number of bytes written indicates success.
Negative values indicate various failures.
*/
//static ssize_t BSL_Write(struct file *pFile, const char __user *pBuffer,
// size_t Count, loff_t *pOff)
static int BSL_Write(struct sk_buff *skb)
{
struct hci_dev *hdev;
BslClientCtxType* pctx;
v_SIZE_t written = 0;
BOOL status;
//char *bslBuff = NULL;
BslHciWorkStructure *pHciContext;
//VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s", __func__);
// Sanity check inputs
if ( skb == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: skb is bad i/p", __func__);
//return -EFAULT; /* Bad address */
return 0;
}
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Count (skb->len)=%d", __func__, skb->len);
// Sanity check inputs
if ( 0 == skb->len )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: skb is empty", __func__);
//return -EFAULT; /* Bad address */
return 0;
}
hdev = (struct hci_dev *)(skb->dev);
// Sanity check the HCI device in the skb
if ( hdev == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Frame for Unknown HCI device (hdev=NULL)", __func__);
//return -ENODEV; /* no device */
return 0;
}
pctx = (BslClientCtxType *)hci_get_drvdata(hdev);
// Sanity check inputs
if ( pctx == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: pctx is bad i/p", __func__);
//return -EFAULT; /* Bad address */
return 0;
/* Maybe I should return "no device" */
//return -ENODEV; /* no device */
}
// Switch for each case of packet type
switch (bt_cb(skb)->pkt_type)
{
case HCI_ACLDATA_PKT:
// Directly execute the data write
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,
"%s: HCI ACL data tx, skb=%pK",
__func__, skb);
// ACL data
hdev->stat.acl_tx++;
// Correct way of doing this...
written = skb->len;
#ifdef BTAMP_USE_VOS_WRAPPER
status = BslProcessACLDataTx( pctx, skb, &written );
#else
status = BslProcessACLDataTx( pctx, skb->data, &written );
// Free up the skb
kfree_skb(skb);
#endif //BTAMP_USE_VOS_WRAPPER
break;
case HCI_COMMAND_PKT:
// Defer the HCI command writes
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: HCI command", __func__);
hdev->stat.cmd_tx++;
// Allocate an HCI context. To use as a "container" for the "work" to be deferred.
pHciContext = kmalloc(sizeof(*pHciContext), GFP_ATOMIC);
if (NULL == pHciContext)
{
// no memory for HCI context. Nothing we can do but drop
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"%s: Unable to allocate context", __func__);
kfree_skb(skb);
return 0;
}
// save away the tx skb in the HCI context...so it can be
// retrieved by the work procedure.
pHciContext->tx_skb = skb;
// save away the pctx context...so it can be retrieved by the work procedure.
pHciContext->pctx = pctx;
pHciContext->magic = BT_AMP_HCI_CTX_MAGIC;
vos_init_work(&pHciContext->hciInterfaceProcessing,
bslWriteFinish);
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,
"%s: Scheduling work for skb %pK, BT-AMP Client context %pK, work %pK",
__func__, skb, pctx, pHciContext);
status = schedule_work(&pHciContext->hciInterfaceProcessing);
// Check result
if ( 0 == status )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: hciInterfaceProcessing work already queued. This should never happen.", __func__);
}
// Temporary way of doing this
//written = skb->len-CMD_TLV_TYPE_AND_LEN_SIZE;
written = skb->len;
break;
case HCI_SCODATA_PKT:
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: unknown type", __func__);
hdev->stat.sco_tx++;
// anything else including HCI events and SCO data
status = FALSE;
// Free up the skb
kfree_skb(skb);
break;
default:
// anything else including HCI events and SCO data
status = FALSE;
// Free up the skb
kfree_skb(skb);
break;
};
// JEZ100809: For the HCI command, will the caller need to wait until the work takes place and
// return the ACTUAL amount of data written.
// The next line is temporary
//written = skb->len;
return(written);
} // BSL_Write()
/**
@brief bslWriteFinish() - This function finished the writes operation
started by BSL_Write().
@param work : [in] pointer to work structure
@return : void
*/
static void bslWriteFinish(struct work_struct *work)
{
//BslClientCtxType* pctx =
// container_of(work, BslClientCtxType, hciInterfaceProcessing);
BslHciWorkStructure *pHciContext =
container_of(work, BslHciWorkStructure, hciInterfaceProcessing);
BslClientCtxType* pctx = pHciContext->pctx;
VOS_STATUS status;
struct sk_buff *skb;
struct hci_dev *hdev;
//char *bslBuff = NULL;
v_SIZE_t written = 0;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
"%s: Entered, context %pK",
__func__, pctx);
// Sanity check inputs
if ( pctx == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: pctx is bad i/p", __func__);
return; // -EFAULT; /* Bad address */
}
//skb = pctx->tx_skb;
skb = pHciContext->tx_skb;
kfree( pHciContext);
// Sanity check inputs
if ( skb == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: skb is bad i/p", __func__);
return; // -EFAULT; /* Bad address */
}
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Count (skb->len)=%d", __func__, skb->len);
hdev = (struct hci_dev *)(skb->dev);
// Sanity check the HCI device in the skb
if ( hdev == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Frame for Unknown HCI device (hdev=NULL)", __func__);
return; // -ENODEV; /* no device */
}
// Sanity check inputs
if ( pctx != (BslClientCtxType *)hci_get_drvdata(hdev));
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: pctx and hdev not consistent - bad i/p", __func__);
return; // -EFAULT; /* Bad address */
/* Maybe I should return "no device" */
//return -ENODEV; /* no device */
}
// Switch for each case of packet type
switch (bt_cb(skb)->pkt_type)
{
case HCI_COMMAND_PKT:
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: HCI command", __func__);
hdev->stat.cmd_tx++;
// HCI command
status = BslProcessHCICommand( pctx, skb->data, skb->len-CMD_TLV_TYPE_AND_LEN_SIZE);
// Temporary way of doing this
//written = skb->len-CMD_TLV_TYPE_AND_LEN_SIZE;
written = skb->len;
break;
case HCI_SCODATA_PKT:
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: unknown type", __func__);
hdev->stat.sco_tx++;
// anything else including HCI events and SCO data
status = FALSE;
break;
default:
// anything else including HCI events and SCO data
status = FALSE;
break;
};
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,
"%s: Freeing skb %pK",
__func__, skb);
consume_skb(skb);
// How do I return the actual number of bytes written to the caller?
// return(written);
return;
} //bslWriteFinish()
VOS_STATUS WLANBAP_SetConfig
(
WLANBAP_ConfigType *pConfig
)
{
BslClientCtxType* pctx;
VOS_STATUS status;
// sanity checking
if ( pConfig == NULL )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_SetConfig bad input" );
return VOS_STATUS_E_FAILURE;
}
pctx = gpBslctx;
if ( NULL == pctx )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BSL pointer from pctx on WLANBAP_SetConfig");
return VOS_STATUS_E_FAULT;
}
// get a handle from BAP
status = WLANBAP_GetNewHndl(&pctx->bapHdl);
if ( !VOS_IS_STATUS_SUCCESS( status ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_SetConfig can't get BAP handle" );
return VOS_STATUS_E_FAILURE;
}
status = WLAN_BAPSetConfig(pctx->bapHdl, pConfig);
if ( !VOS_IS_STATUS_SUCCESS( status ) )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "WLANBAP_SetConfig can't set BAP config" );
return VOS_STATUS_E_FAILURE;
}
return(VOS_STATUS_SUCCESS);
}
VOS_STATUS WLANBAP_RegisterWithHCI(hdd_adapter_t *pAdapter)
{
struct hci_dev *hdev = NULL;
BslClientCtxType* pctx = NULL;
int err = 0;
v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
hdd_context_t *pHddCtx;
pctx = gpBslctx;
if ( NULL == pctx )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BSL pointer from pctx on WLANBAP_RegisterWithHCI");
return VOS_STATUS_E_FAULT;
}
if ( NULL == pAdapter )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid HDD Adapter pointer from pvosGCtx on WLANBAP_RegisterWithHCI");
return VOS_STATUS_E_FAULT;
}
if(NULL != pctx->hdev)
{
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_WARN,
"Already registered as HCI device");
return VOS_STATUS_SUCCESS;
}
/* Save away the pointer to the parent WLAN device in BSL driver context */
pctx->p_dev = pAdapter->dev;
/* Initialize HCI device */
hdev = hci_alloc_dev();
if (!hdev)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Can't allocate HCI device in WLANBAP_RegisterWithHCI");
return VOS_STATUS_E_FAULT;
}
/* Save away the HCI device pointer in the BSL driver context */
pctx->hdev = hdev;
#if defined HCI_80211 || defined HCI_AMP
#define BUILD_FOR_BLUETOOTH_NEXT_2_6
#else
#undef BUILD_FOR_BLUETOOTH_NEXT_2_6
#endif
#ifdef BUILD_FOR_BLUETOOTH_NEXT_2_6
/* HCI "bus type" of HCI_VIRTUAL should apply */
hdev->bus = HCI_VIRTUAL;
/* Set the dev_type to BT-AMP 802.11 */
#ifdef HCI_80211
hdev->dev_type = HCI_80211;
#else
hdev->dev_type = HCI_AMP;
#endif
#ifdef FEATURE_WLAN_BTAMP_UT
/* For the "real" BlueZ build, DON'T Set the device "quirks" to indicate RAW */
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
#endif
#else //BUILD_FOR_BLUETOOTH_NEXT_2_6
/* HCI "bus type" of HCI_VIRTUAL should apply */
hdev->type = HCI_VIRTUAL;
/* Set the dev_type to BT-AMP 802.11 */
//hdev->dev_type = HCI_80211;
////hdev->dev_type = HCI_AMP;
/* For the "temporary" BlueZ build, Set the device "quirks" to indicate RAW */
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
#endif //BUILD_FOR_BLUETOOTH_NEXT_2_6
/* Save away the BSL driver pointer in the HCI device context */
hci_set_drvdata(hdev, pctx);
/* Set the parent device for this HCI device. This is our WLAN net_device */
SET_HCIDEV_DEV(hdev, &pctx->p_dev->dev);
hdev->open = BSL_Open;
hdev->close = BSL_Close;
hdev->flush = BSL_Flush;
hdev->send = BSL_Write;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
hdev->owner = THIS_MODULE;
hdev->destruct = BSL_Destruct;
#endif
hdev->ioctl = BSL_IOControl;
/* Timeout before it is safe to send the first HCI packet */
msleep(1000);
/* Register HCI device */
err = hci_register_dev(hdev);
if (err < 0)
{
VOS_TRACE(VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Unable to register HCI device, err=%d", err);
pctx->hdev = NULL;
hci_free_dev(hdev);
return VOS_STATUS_E_FAULT;
}
if (NULL != pVosContext)
{
pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
if (NULL != pHddCtx)
{
pHddCtx->isAmpAllowed = VOS_TRUE;
}
}
return VOS_STATUS_SUCCESS;
}
VOS_STATUS WLANBAP_DeregisterFromHCI(void)
{
struct hci_dev *hdev;
BslClientCtxType* pctx = NULL;
pctx = gpBslctx;
if ( NULL == pctx )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BSL pointer from pvosGCtx on WLANBAP_DeregisterFromHCI");
return VOS_STATUS_E_FAULT;
}
/* Retrieve the HCI device pointer from the BSL driver context */
hdev = pctx->hdev;
if (!hdev)
return VOS_STATUS_E_FAULT;
/* Unregister device from BlueZ; fcn sends us HCI commands before it returns */
/* And then the registered hdev->close fcn should be called by BlueZ (BSL_Close) */
hci_unregister_dev(hdev);
/* BSL_Close is called again here, in case BlueZ didn't call it */
BSL_Close(hdev);
hci_free_dev(hdev);
pctx->hdev = NULL;
return VOS_STATUS_SUCCESS;
}
VOS_STATUS WLANBAP_StopAmp(void)
{
BslClientCtxType* pctx;
VOS_STATUS status = VOS_STATUS_SUCCESS;
pctx = gpBslctx;
if(NULL == pctx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BSL pointer from pvosGCtx on WLANBAP_StopAmp");
status = VOS_STATUS_E_FAULT;
}
else
{
//is AMP session on, if so disconnect
if(VOS_TRUE == WLAN_BAPSessionOn(pctx->bapHdl))
{
status = WLAN_BAPDisconnect(pctx->bapHdl);
}
}
return status;
}
v_BOOL_t WLANBAP_AmpSessionOn(void)
{
BslClientCtxType* pctx;
pctx = gpBslctx;
if(NULL == pctx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BSL pointer from pvosGCtx on WLANBAP_AmpSessionOn");
return VOS_FALSE;
}
else
{
return( WLAN_BAPSessionOn(pctx->bapHdl));
}
}
#endif // WLAN_BTAMP_FEATURE