blob: e7ba26676e618979205b366f27a1d6187d94b22f [file] [log] [blame]
/*
* Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*===========================================================================
b a p A p i D a t a . C
OVERVIEW:
This software unit holds the implementation of the WLAN BAP modules
"platform independent" Data path functions.
The functions externalized by this module are to be called ONLY by other
WLAN modules (HDD) that properly register with the BAP Layer initially.
DEPENDENCIES:
Are listed for each API below.
===========================================================================*/
/*===========================================================================
EDIT HISTORY FOR FILE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
$Header: /cygdrive/e/Builds/M7201JSDCAAPAD52240B/WM/platform/msm7200/Src/Drivers/SD/ClientDrivers/WLAN/QCT/CORE/BAP/src/bapApiData.c,v 1.4 2008/11/10 22:34:22 jzmuda Exp jzmuda $$DateTime$$Author: jzmuda $
when who what, where, why
---------- --- --------------------------------------------------------
2008-09-15 jez Created module
===========================================================================*/
/*----------------------------------------------------------------------------
* Include Files
* -------------------------------------------------------------------------*/
//#include "wlan_qct_tl.h"
#include "vos_trace.h"
//I need the TL types and API
#include "wlan_qct_tl.h"
#include "wlan_qct_hal.h"
/* BT-AMP PAL API header file */
#include "bapApi.h"
#include "bapInternal.h"
#include "bapApiTimer.h"
//#define BAP_DEBUG
/*----------------------------------------------------------------------------
* Preprocessor Definitions and Constants
* -------------------------------------------------------------------------*/
/*Endian-ness definitions*/
#undef BAP_LITTLE_BIT_ENDIAN
#define BAP_LITTLE_BIT_ENDIAN
/*LLC header definitions*/
/* Length of the LLC header*/
#define WLANBAP_LLC_HEADER_LEN 8
#if 0
/*Offset of the OUI field inside the LLC/SNAP header*/
#define WLANBAP_LLC_OUI_OFFSET 3
/*Size of the OUI type field inside the LLC/SNAP header*/
#define WLANBAP_LLC_OUI_SIZE 3
/*Offset of the protocol type field inside the LLC/SNAP header*/
#define WLANBAP_LLC_PROTO_TYPE_OFFSET (WLANBAP_LLC_OUI_OFFSET + WLANBAP_LLC_OUI_SIZE)
/*Size of the protocol type field inside the LLC/SNAP header*/
#define WLANBAP_LLC_PROTO_TYPE_SIZE 2
#endif
/*BT-AMP protocol type values*/
/*BT-AMP packet of type data*/
#define WLANBAP_BT_AMP_TYPE_DATA 0x0001
/*BT-AMP packet of type activity report*/
#define WLANBAP_BT_AMP_TYPE_AR 0x0002
/*BT-AMP packet of type security frame*/
#define WLANBAP_BT_AMP_TYPE_SEC 0x0003
/*802.3 header definitions*/
#define WLANBAP_802_3_HEADER_LEN 14
/* Offset of DA field in a 802.3 header*/
#define WLANBAP_802_3_HEADER_DA_OFFSET 0
//*BT-AMP packet LLC OUI value*/
const v_U8_t WLANBAP_BT_AMP_OUI[] = {0x00, 0x19, 0x58 };
/*LLC header value*/
static v_U8_t WLANBAP_LLC_HEADER[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 };
/* HCI header definitions*/
// Define the length of the ACL data packet HCI header
#define WLANBAP_HCI_ACL_HEADER_LEN 4
// Debug related defines
//#define DBGLOG printf
#define DUMPLOG_ON
#ifdef DUMPLOG_ON
#define DUMPLOG(n, name1, name2, aStr, size) do { \
int i; \
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,"%d. %s: %s = \n", n, name1, name2); \
for (i = 0; i < size; i++) \
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,"%2.2x%s", ((unsigned char *)aStr)[i], i % 16 == 15 ? "\n" : " "); \
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,"\n"); \
} while (0)
#else
#define DUMPLOG(n, name1, name2, aStr, size)
#endif
#if 0
// 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
#endif
/*----------------------------------------------------------------------------
* Type Declarations
* -------------------------------------------------------------------------*/
// Don't we have this type defined somewhere?
#if 0
/* 802.3 header */
typedef struct
{
/* Destination address field */
v_U8_t vDA[VOS_MAC_ADDR_SIZE];
/* Source address field */
v_U8_t vSA[VOS_MAC_ADDR_SIZE];
/* Length field */
v_U16_t usLenType; /* Num bytes in info field (i.e., exclude 802.3 hdr) */
/* Max length 1500 (0x5dc) (What about 0x5ee? That
* includes 802.3 Header and FCS.) */
}WLANBAP_8023HeaderType;
#endif
/**
* \brief HCI ACL Data packet format
*
* 0 7 8 15 16 23 24 31
* +--------+----+----+--------+--------+
* | phy_ |log_| PB/| Data Total |
* | link_ |lnk_| BC | Length |
* | handle |hndl|Flag| |
* +--------+----+----+--------+--------+
* | |
* | Data |
* ~ ~
* +--------+---------+--------+--------+
*
* NB:
* This is in little-endian
* 1) phy_link_handle is the first 8 bits
* 2) log_link_handle is the next 4 bits
* 3) PB flag is the next 2 bits
* 4) BC flags is the next 2 bits
* 5) Total length of the data field is the next 16 bits
*
*/
typedef struct
{
#ifndef BAP_LITTLE_BIT_ENDIAN
v_U8_t phyLinkHandle; /* do I have to reverse the byte? I think so... */
v_U8_t BCFlag :2;
v_U8_t PBFlag :2;
v_U8_t logLinkHandle :4;
v_U16_t dataLength; /* do I have to reverse each byte? and then reverse the two bytes? I think so... */
#else
v_U8_t phyLinkHandle;
v_U8_t logLinkHandle :4;
v_U8_t PBFlag :2;
v_U8_t BCFlag :2;
v_U16_t dataLength; /* Max length WLANBAP_MAX_80211_PAL_PDU_SIZE (1492) */
#endif
} WLANBAP_HCIACLHeaderType;
/*----------------------------------------------------------------------------
* Global Data Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Static Variable Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Static Function Declarations and Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Externalized Function Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Function Declarations and Documentation
* -------------------------------------------------------------------------*/
#define WLANBAP_DEBUG_FRAME_BYTE_PER_LINE 16
#define WLANBAP_DEBUG_FRAME_BYTE_PER_BYTE 4
/*===========================================================================
FUNCTION WLANBAP_XlateTxDataPkt
DESCRIPTION
HDD will call this API when it has a HCI Data Packet and it wants
to translate it into a 802.3 LLC frame - ready to send using TL.
PARAMETERS
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
phy_link_handle: Used by BAP to indentify the WLAN assoc. (StaId)
pucAC: Pointer to return the access category
vosDataBuff: The data buffer containing the BT-AMP packet to be
translated to an 802.3 LLC frame
tlMetaInfo: return meta info gleaned from the outgoing frame, here.
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: BAP handle is NULL
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANBAP_XlateTxDataPkt
(
ptBtampHandle btampHandle, /* Used by BAP to identify the actual session
and therefore addresses */
v_U8_t phy_link_handle, /* Used by BAP to indentify the WLAN assoc. (StaId) */
WLANTL_ACEnumType *pucAC, /* Return the AC here */
WLANTL_MetaInfoType *tlMetaInfo, /* Return the MetaInfo here. An assist to WLANBAP_STAFetchPktCBType */
vos_pkt_t *vosDataBuff
)
{
ptBtampContext pBtampCtx = (ptBtampContext) btampHandle;
tpBtampLogLinkCtx pLogLinkContext;
WLANBAP_8023HeaderType w8023Header;
WLANBAP_HCIACLHeaderType hciACLHeader;
v_U8_t aucLLCHeader[WLANBAP_LLC_HEADER_LEN];
VOS_STATUS vosStatus;
v_U8_t ucSTAId; /* The StaId (used by TL, PE, and HAL) */
v_PVOID_t pHddHdl; /* Handle to return BSL context in */
v_U16_t headerLength; /* The 802.3 frame length*/
v_U16_t protoType = WLANBAP_BT_AMP_TYPE_DATA; /* The protocol type bytes*/
uintptr_t value = 0;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*------------------------------------------------------------------------
Sanity check params
------------------------------------------------------------------------*/
if ( NULL == pBtampCtx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BAP handle value in %s", __func__);
return VOS_STATUS_E_FAULT;
}
// Here, I have to make the assumption that this is an
// HCI ACL Data packet that I am being handed.
vosStatus = vos_pkt_pop_head( vosDataBuff, &hciACLHeader, WLANBAP_HCI_ACL_HEADER_LEN);
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLAN BAP: Failed to pop HCI ACL header from packet %d",
vosStatus);
return vosStatus;
}
// JEZ081003: Remove this after debugging
// Sanity check the phy_link_handle value
if ( phy_link_handle != hciACLHeader.phyLinkHandle )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLAN BAP: phy_link_handle mismatch in %s phy_link_handle=%d hciACLHeader.phyLinkHandle=%d",
__func__, phy_link_handle, hciACLHeader.phyLinkHandle);
return VOS_STATUS_E_INVAL;
}
/* Lookup the StaId using the phy_link_handle and the BAP context */
vosStatus = WLANBAP_GetStaIdFromLinkCtx (
btampHandle, /* btampHandle value in */
phy_link_handle, /* phy_link_handle value in */
&ucSTAId, /* The StaId (used by TL, PE, and HAL) */
&pHddHdl); /* Handle to return BSL context */
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"Unable to retrieve STA Id from BAP context and phy_link_handle in %s", __func__);
return VOS_STATUS_E_FAULT;
}
// JEZ081003: Remove this after debugging
// Sanity check the log_link_handle value
if (!BTAMP_VALID_LOG_LINK( hciACLHeader.logLinkHandle))
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLAN BAP: Invalid logical link handle (%d) in %s. Corrected.",
hciACLHeader.logLinkHandle,
__func__);
// JEZ090123: Insure that the logical link value is good
hciACLHeader.logLinkHandle = 1;
//return VOS_STATUS_E_INVAL;
}
/* Use the log_link_handle to retrieve the logical link context */
/* JEZ081006: abstract this with a proc. So you can change the impl later */
pLogLinkContext = &(pBtampCtx->btampLogLinkCtx[ hciACLHeader.logLinkHandle ]);
// JEZ081003: Remove this after debugging
// Sanity check the log_link_handle value
// JEZ081113: I changed this to fail on an UNOCCUPIED entry
if ( pLogLinkContext->present != VOS_TRUE)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLAN BAP: Invalid logical link entry in %s",
__func__);
return VOS_STATUS_E_INVAL;
}
// Return the AC and MetaInfo
// Now copy the AC values from the Logical Link context
*pucAC = pLogLinkContext->btampAC;
// Now copy the values from the Logical Link context to the MetaInfo
tlMetaInfo->ac = *pucAC;
tlMetaInfo->ucTID = pLogLinkContext->ucTID;
tlMetaInfo->ucUP = pLogLinkContext->ucUP;
tlMetaInfo->ucIsEapol = VOS_FALSE;
tlMetaInfo->ucDisableFrmXtl = VOS_FALSE;
tlMetaInfo->ucBcast = VOS_FALSE; /* hciACLHeader.BCFlag; */ /* Don't I want to use the BCFlag? */
tlMetaInfo->ucMcast = VOS_FALSE;
tlMetaInfo->ucType = 0x00; /* What is this really ?? */
// tlMetaInfo->usTimeStamp = 0x00; /* Ravi, shouldn't you be setting this? It's in the VOS packet. */
// Form the 802.3 header
vos_mem_copy( w8023Header.vDA, pBtampCtx->peer_mac_addr, VOS_MAC_ADDR_SIZE);
vos_mem_copy( w8023Header.vSA, pBtampCtx->self_mac_addr, VOS_MAC_ADDR_SIZE);
/* Now this length passed down in HCI...is in little-endian */
headerLength = vos_le16_to_cpu(hciACLHeader.dataLength);
headerLength += WLANBAP_LLC_HEADER_LEN;
/* Now the 802.3 length field is big-endian?! */
w8023Header.usLenType = vos_cpu_to_be16(headerLength);
/* Now adjust the protocol type bytes*/
protoType = vos_cpu_to_be16( protoType);
/* Now form the LLC header */
vos_mem_copy(aucLLCHeader,
WLANBAP_LLC_HEADER,
sizeof(WLANBAP_LLC_HEADER));
vos_mem_copy(&aucLLCHeader[WLANBAP_LLC_OUI_OFFSET],
WLANBAP_BT_AMP_OUI,
WLANBAP_LLC_OUI_SIZE);
vos_mem_copy(&aucLLCHeader[WLANBAP_LLC_PROTO_TYPE_OFFSET],
&protoType, //WLANBAP_BT_AMP_TYPE_DATA
WLANBAP_LLC_PROTO_TYPE_SIZE);
/* Push on the LLC header */
vos_pkt_push_head(vosDataBuff,
aucLLCHeader,
WLANBAP_LLC_HEADER_LEN);
/* Push on the 802.3 header */
vos_pkt_push_head(vosDataBuff, &w8023Header, sizeof(w8023Header));
/*Set the logical link handle as user data so that we can retrieve it on
Tx Complete */
value = (uintptr_t)hciACLHeader.logLinkHandle;
vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_BAP,
(v_VOID_t *)value);
return VOS_STATUS_SUCCESS;
}/*WLANBAP_XlateTxDataPkt*/
/*===========================================================================
FUNCTION WLANBAP_GetAcFromTxDataPkt
DESCRIPTION
HDD will call this API when it has a HCI Data Packet (SKB) and it wants
to find AC type of the data frame from the HCI header on the data pkt
- to be send using TL.
PARAMETERS
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
pHciData: Pointer to the HCI data frame
pucAC: Pointer to return the access category
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: BAP handle is NULL
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANBAP_GetAcFromTxDataPkt
(
ptBtampHandle btampHandle, /* Used by BAP to identify the actual session
and therefore addresses */
void *pHciData, /* Pointer to the HCI data frame */
WLANTL_ACEnumType *pucAC /* Return the AC here */
)
{
ptBtampContext pBtampCtx;
tpBtampLogLinkCtx pLogLinkContext;
WLANBAP_HCIACLHeaderType hciACLHeader;
/*------------------------------------------------------------------------
Sanity check params
------------------------------------------------------------------------*/
if (( NULL == btampHandle) || (NULL == pHciData) || (NULL == pucAC))
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid params in %s", __func__);
return VOS_STATUS_E_FAULT;
}
pBtampCtx = (ptBtampContext) btampHandle;
vos_mem_copy( &hciACLHeader, pHciData, WLANBAP_HCI_ACL_HEADER_LEN);
// Sanity check the log_link_handle value
if (!BTAMP_VALID_LOG_LINK( hciACLHeader.logLinkHandle))
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLAN BAP: Invalid logical link handle (%d) in %s",
hciACLHeader.logLinkHandle,
__func__);
return VOS_STATUS_E_INVAL;
}
/* Use the log_link_handle to retrieve the logical link context */
/* JEZ081006: abstract this with a proc. So you can change the impl later */
pLogLinkContext = &(pBtampCtx->btampLogLinkCtx[ hciACLHeader.logLinkHandle ]);
// Sanity check the log_link_handle value
// JEZ081113: I changed this to fail on an UNOCCUPIED entry
if ( pLogLinkContext->present != VOS_TRUE)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLAN BAP: Invalid logical link entry in %s",
__func__);
return VOS_STATUS_E_INVAL;
}
// Return the AC
// Now copy the AC values from the Logical Link context
*pucAC = pLogLinkContext->btampAC;
return VOS_STATUS_SUCCESS;
}
/*===========================================================================
FUNCTION WLANBAP_XlateRxDataPkt
DESCRIPTION
HDD will call this API when it has received a 802.3 (TL/UMA has
Xlated from 802.11) frame from TL and it wants to form a
BT HCI Data Packet - ready to signal up to the BT stack application.
PARAMETERS
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
pucAC: Pointer to return the access category
vosDataBuff: The data buffer containing the 802.3 frame to be
translated to BT HCI Data Packet
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: BAP handle is NULL
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANBAP_XlateRxDataPkt
(
ptBtampHandle btampHandle,
v_U8_t phy_link_handle, /* Used by BAP to indentify the WLAN assoc. (StaId) */
WLANTL_ACEnumType *pucAC, /* Return the AC here. I don't think this is needed */
vos_pkt_t *vosDataBuff
)
{
WLANBAP_8023HeaderType w8023Header;
WLANBAP_HCIACLHeaderType hciACLHeader;
v_U8_t aucLLCHeader[WLANBAP_LLC_HEADER_LEN];
ptBtampContext pBtampCtx = (ptBtampContext) btampHandle;
VOS_STATUS vosStatus;
//v_PVOID_t pHddHdl; /* Handle to return BSL context in */
v_U16_t hciDataLength; /* The HCI packet data length*/
v_U16_t protoType = WLANBAP_BT_AMP_TYPE_DATA; /* The protocol type bytes*/
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*------------------------------------------------------------------------
Sanity check params
------------------------------------------------------------------------*/
if ( NULL == pBtampCtx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BAP handle value in %s", __func__);
return VOS_STATUS_E_FAULT;
}
// Here, I have to make the assumption that this is an
// 802.3 header followed by an LLC/SNAP packet.
vos_mem_set( &w8023Header, sizeof(w8023Header), 0 );
vosStatus = vos_pkt_pop_head( vosDataBuff, &w8023Header, sizeof(w8023Header));
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLAN BAP: Failed to pop 802.3 header from packet %d",
vosStatus);
return vosStatus;
}
// Here, is that LLC/SNAP header.
// With the BT SIG OUI that I am being handed.
vos_mem_set( aucLLCHeader, WLANBAP_LLC_HEADER_LEN, 0 );
vosStatus = vos_pkt_pop_head( vosDataBuff, aucLLCHeader, WLANBAP_LLC_HEADER_LEN);
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"WLAN BAP: Failed to pop LLC/SNAP header from packet %d",
vosStatus);
return vosStatus;
}
#ifdef BAP_DEBUG
// JEZ081003: Remove this after debugging
// Should I double check that I am getting the BT SIG OUI ?
if ( !(vos_mem_compare( aucLLCHeader,
WLANBAP_LLC_HEADER,
sizeof(WLANBAP_LLC_HEADER)
- WLANBAP_LLC_OUI_SIZE) /* Don't check the last three bytes here */
&& vos_mem_compare( &aucLLCHeader[WLANBAP_LLC_OUI_OFFSET],
(v_VOID_t*)WLANBAP_BT_AMP_OUI,
WLANBAP_LLC_OUI_SIZE))) /* check them here */
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid LLC header for BT-AMP packet in %s", __func__);
return VOS_STATUS_E_FAULT;
}
#endif //BAP_DEBUG
/* Now adjust the protocol type bytes*/
protoType = vos_cpu_to_be16( protoType);
// check if this is a data frame or other, internal to BAP, type...
// we are only handling data frames in here...
// The others (Security and AR) are handled by TLs BAP client API.
// (Verify with TL)
if ( !(vos_mem_compare( &aucLLCHeader[WLANBAP_LLC_PROTO_TYPE_OFFSET],
&protoType, //WLANBAP_BT_AMP_TYPE_DATA
WLANBAP_LLC_PROTO_TYPE_SIZE)))
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid (non-data) frame type in %s", __func__);
return VOS_STATUS_E_FAULT;
}
#ifdef BAP_DEBUG
// JEZ081003: Remove this after debugging
/*------------------------------------------------------------------------
Sanity check the MAC address in the physical link context
against the value in the incoming Rx Frame.
------------------------------------------------------------------------*/
if ( !(vos_mem_compare( w8023Header.vDA, pBtampCtx->self_mac_addr, VOS_MAC_ADDR_SIZE)
&& vos_mem_compare( w8023Header.vSA, pBtampCtx->peer_mac_addr, VOS_MAC_ADDR_SIZE)))
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"MAC address mismatch in %s", __func__);
return VOS_STATUS_E_FAULT;
}
#endif //BAP_DEBUG
/* No lookup is needed. Because TL has already told WLANBAP_STARxCB
* the StaId. And I told WLANBAP_STARxCBType the corresponding BSL context
* Which he used to lookup the phy_link_handle value.
*/
// Start filling in the HCI header
hciACLHeader.phyLinkHandle = phy_link_handle;
// Continue filling in the HCI header
//JEZ100913: On Rx the Logical Link is ALWAYS 0. See Vol 2, Sec E, 5.4.2 of spec.
hciACLHeader.logLinkHandle = 0;
hciACLHeader.PBFlag = WLANBAP_HCI_PKT_AMP;
hciACLHeader.BCFlag = 0;
/* Now the length field is big-endian?! */
hciDataLength = vos_be16_to_cpu(w8023Header.usLenType);
/* Max length WLANBAP_MAX_80211_PAL_PDU_SIZE (1492) */
hciDataLength -= WLANBAP_LLC_HEADER_LEN;
/* The HCI packet data length is Little-endian */
hciACLHeader.dataLength = vos_cpu_to_le16(hciDataLength);
/* Return the AC here.
* (I can't because there is no way to figure out what it is.)
*/
*pucAC = 0;
/* Push on the HCI header */
vos_pkt_push_head(vosDataBuff, &hciACLHeader, WLANBAP_HCI_ACL_HEADER_LEN);
return VOS_STATUS_SUCCESS;
} /* WLANBAP_XlateRxDataPkt */
/*----------------------------------------------------------------------------
FUNCTION WLANBAP_STAFetchPktCB
DESCRIPTION
The fetch packet callback registered with TL.
It is called by the TL when the scheduling algorithms allows for
transmission of another packet to the module.
It will be called in the context of the BAL fetch transmit packet
function, initiated by the bus lower layer.
PARAMETERS
IN
pvosGCtx: pointer to the global vos context; a handle
to TL's or HDD's control block can be extracted
from its context
IN/OUT
pucSTAId: the Id of the station for which TL is requesting a
packet, in case HDD does not maintain per station
queues it can give the next packet in its queue
and put in the right value for the
pucAC: 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
OUT
vosDataBuff: pointer to the VOSS data buffer that was transmitted
tlMetaInfo: meta info related to the data frame
RETURN VALUE
The result code associated with performing the operation
----------------------------------------------------------------------------*/
VOS_STATUS
WLANBAP_STAFetchPktCB
(
v_PVOID_t pvosGCtx,
v_U8_t* pucSTAId,
v_U8_t ucAC,
vos_pkt_t** vosDataBuff,
WLANTL_MetaInfoType* tlMetaInfo
)
{
VOS_STATUS vosStatus;
ptBtampHandle bapHdl; /* holds ptBtampHandle value returned */
ptBtampContext bapContext; /* Holds the btampContext value returned */
v_PVOID_t pHddHdl; /* Handle to return BSL context in */
/* Lookup the BSL and BAP contexts using the StaId */
vosStatus = WLANBAP_GetCtxFromStaId (
*pucSTAId, /* The StaId (used by TL, PE, and HAL) */
&bapHdl, /* "handle" to return ptBtampHandle value in */
&bapContext, /* "handle" to return ptBtampContext value in */
&pHddHdl); /* "handle" to return BSL context in */
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"Unable to retrieve BSL or BAP context from STA Id in WLANBAP_STAFetchPktCB");
return VOS_STATUS_E_FAULT;
}
/* Invoke the callback that BSL registered with me */
vosStatus = (*bapContext->pfnBtampFetchPktCB)(
pHddHdl,
(WLANTL_ACEnumType) ucAC, /* typecast it for now */
vosDataBuff,
tlMetaInfo);
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"Callback registered by BSL failed to fetch pkt in WLANNBAP_STAFetchPktCB");
return VOS_STATUS_E_FAULT;
}
return vosStatus;
} /* WLANBAP_STAFetchPktCB */
/*----------------------------------------------------------------------------
FUNCTION WLANBAP_STARxCB
DESCRIPTION
The receive callback registered with TL.
TL will call this to notify the client when a packet was received
for a registered STA.
PARAMETERS
IN
pvosGCtx: pointer to the global vos context; a handle to
TL's or HDD's control block can be extracted from
its context
vosDataBuff: pointer to the VOSS data buffer that was received
(it may be a linked list)
ucSTAId: station id
pRxMetaInfo: meta info for the received packet(s)
RETURN VALUE
The result code associated with performing the operation
----------------------------------------------------------------------------*/
VOS_STATUS
WLANBAP_STARxCB
(
v_PVOID_t pvosGCtx,
vos_pkt_t* vosDataBuff,
v_U8_t ucSTAId,
WLANTL_RxMetaInfoType* pRxMetaInfo
)
{
VOS_STATUS vosStatus;
ptBtampHandle bapHdl; /* holds ptBtampHandle value returned */
ptBtampContext bapContext; /* Holds the btampContext value returned */
v_PVOID_t pHddHdl; /* Handle to return BSL context in */
ptBtampHandle btampHandle;
WLANBAP_8023HeaderType w8023Header;
v_U8_t aucLLCHeader[WLANBAP_LLC_HEADER_LEN];
v_U16_t protoType ;
v_SIZE_t llcHeaderLen = WLANBAP_LLC_HEADER_LEN ;
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"In WLANBAP_STARxCB");
/* Lookup the BSL and BAP contexts using the StaId */
vosStatus = WLANBAP_GetCtxFromStaId (
ucSTAId, /* The StaId (used by TL, PE, and HAL) */
&bapHdl, /* "handle" to return ptBtampHandle value in */
&bapContext, /* "handle" to return ptBtampContext value in */
&pHddHdl); /* "handle" to return BSL context in */
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"Unable to retrieve BSL or BAP context from STA Id in WLANBAP_STARxCB");
/* Drop packet */
vos_pkt_return_packet(vosDataBuff);
return VOS_STATUS_E_FAULT;
}
vosStatus = vos_pkt_extract_data( vosDataBuff, sizeof(w8023Header), (v_VOID_t *)aucLLCHeader,
&llcHeaderLen);
if ( NULL == aucLLCHeader/*LLC Header*/ )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLANBAP_STARxCB:Cannot extract LLC header");
/* Drop packet */
vos_pkt_return_packet(vosDataBuff);
return VOS_STATUS_E_FAULT;
}
vos_mem_copy(&protoType,&aucLLCHeader[WLANBAP_LLC_PROTO_TYPE_OFFSET],WLANBAP_LLC_PROTO_TYPE_SIZE);
protoType = vos_be16_to_cpu(protoType);
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"%s: received : %d, => BAP",__func__,
protoType);
if(WLANBAP_BT_AMP_TYPE_DATA == protoType)
{
if (bapContext->bapLinkSupervisionTimerInterval)
{
/* Reset Link Supervision timer */
//vosStatus = WLANBAP_StopLinkSupervisionTimer(bapContext);
//vosStatus = WLANBAP_StartLinkSupervisionTimer(bapContext,7000);
bapContext->dataPktPending = VOS_TRUE;//Indication for LinkSupervision module that data is pending
/* Invoke the callback that BSL registered with me */
vosStatus = (*bapContext->pfnBtamp_STARxCB)(
pHddHdl,
vosDataBuff,
pRxMetaInfo);
}
else
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
"WLANBAP_STARxCB:bapLinkSupervisionTimerInterval is 0");
/* Drop packet */
vos_pkt_return_packet(vosDataBuff);
}
}
else
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"%s: link Supervision packet received over TL: %d, => BAP",
__func__,protoType);
btampHandle = (ptBtampHandle)bapContext;
vosStatus = WLANBAP_RxProcLsPkt(
btampHandle,
bapContext->phy_link_handle,
protoType,
vosDataBuff
);
}
return vosStatus;
} /* WLANBAP_STARxCB */
/*----------------------------------------------------------------------------
FUNCTION WLANBAP_TxCompCB
DESCRIPTION
The tx complete callback registered with TL.
TL will call this to notify the client when a transmission for a
packet has ended.
PARAMETERS
IN
pvosGCtx: pointer to the global vos context; a handle to
TL/HAL/PE/BAP/HDD control block can be extracted from
its context
vosDataBuff: pointer to the VOSS data buffer that was transmitted
wTxSTAtus: status of the transmission
RETURN VALUE
The result code associated with performing the operation
----------------------------------------------------------------------------*/
VOS_STATUS
WLANBAP_TxCompCB
(
v_PVOID_t pvosGCtx,
vos_pkt_t* vosDataBuff,
VOS_STATUS wTxSTAtus
)
{
VOS_STATUS vosStatus;
ptBtampHandle bapHdl; /* holds ptBtampHandle value returned */
ptBtampContext bapContext; /* Holds the btampContext value returned */
v_PVOID_t pHddHdl; /* Handle to return BSL context in */
v_PVOID_t pvlogLinkHandle = NULL;
uintptr_t value;
WLANBAP_HCIACLHeaderType hciACLHeader;
/* retrieve the BSL and BAP contexts */
/* I don't really know how to do this - in the general case. */
/* So, for now, I will just use something that works. */
/* (In general, I will have to keep a list of the outstanding transmit */
/* buffers, in order to determine which assoc they are with.) */
//vosStatus = WLANBAP_GetCtxFromStaId (
// ucSTAId, /* The StaId (used by TL, PE, and HAL) */
// &bapHdl, /* "handle" to return ptBtampHandle value in */
// &bapContext, /* "handle" to return ptBtampContext value in */
// &pHddHdl); /* "handle" to return BSL context in */
/* Temporarily we do the following*/
//bapHdl = &btampCtx;
bapHdl = (v_PVOID_t)gpBtampCtx;
/* Typecast the handle into a context. Works as we have only one link*/
bapContext = ((ptBtampContext) bapHdl);
/*------------------------------------------------------------------------
Sanity check params
------------------------------------------------------------------------*/
if ( NULL == vosDataBuff)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid vosDataBuff value in %s", __func__);
return VOS_STATUS_E_FAULT;
}
if ( NULL == bapContext)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid bapContext value in %s", __func__);
vos_pkt_return_packet( vosDataBuff );
return VOS_STATUS_E_FAULT;
}
pHddHdl = bapContext->pHddHdl;
vosStatus = VOS_STATUS_SUCCESS;
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"Unable to retrieve BSL or BAP context from STA Id in WLANBAP_TxCompCB");
vos_pkt_return_packet( vosDataBuff );
return VOS_STATUS_E_FAULT;
}
/*Get the logical link handle from the vos user data*/
vos_pkt_get_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_BAP,
&pvlogLinkHandle);
value = (uintptr_t)pvlogLinkHandle;
hciACLHeader.logLinkHandle = value;
#ifdef BAP_DEBUG
/* Trace the bapContext referenced. */
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,
"WLAN BAP Context Monitor: bapContext value = %pK in %s:%d. vosDataBuff=%pK", bapContext, __func__, __LINE__, vosDataBuff );
#endif //BAP_DEBUG
// Sanity check the log_link_handle value
// JEZ100722: Temporary changes.
if (BTAMP_VALID_LOG_LINK( hciACLHeader.logLinkHandle))
{
vos_atomic_increment_U32(
&bapContext->btampLogLinkCtx[hciACLHeader.logLinkHandle].uTxPktCompleted);
// &bapContext->btampLogLinkCtx[0].uTxPktCompleted);
// vos_atomic_increment_U32(
// &bapContext->btampLogLinkCtx[1].uTxPktCompleted);
} else
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"In %s:%d: Invalid logical link handle: %d", __func__, __LINE__, hciACLHeader.logLinkHandle);
}
/* Invoke the callback that BSL registered with me */
vosStatus = (*bapContext->pfnBtampTxCompCB)(
pHddHdl,
vosDataBuff,
wTxSTAtus);
return vosStatus;
} /* WLANBAP_TxCompCB */
/*==========================================================================
FUNCTION WLANBAP_RegisterDataPlane
DESCRIPTION
The HDD calls this routine to register the "data plane" routines
for Tx, Rx, and Tx complete with BT-AMP. For now, with only one
physical association supported at a time, this COULD be called
by HDD at the same time as WLANBAP_GetNewHndl. But, in general
it needs to be called upon each new physical link establishment.
This registration is really two part. The routines themselves are
registered here. But, the mapping between the BSL context and the
actual physical link takes place during WLANBAP_PhysicalLinkCreate.
DEPENDENCIES
PARAMETERS
IN
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_FAULT: pointer to BAP cb is NULL ; access would cause a page
fault
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANBAP_RegisterDataPlane
(
ptBtampHandle btampHandle, /* BTAMP context */
WLANBAP_STAFetchPktCBType pfnBtampFetchPktCB,
WLANBAP_STARxCBType pfnBtamp_STARxCB,
WLANBAP_TxCompCBType pfnBtampTxCompCB,
// phy_link_handle, of course, doesn't come until much later. At Physical Link create.
v_PVOID_t pHddHdl /* BSL specific context */
)
{
ptBtampContext pBtampCtx = (ptBtampContext) btampHandle;
/*------------------------------------------------------------------------
Sanity check params
------------------------------------------------------------------------*/
if ( NULL == pBtampCtx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BAP handle value in WLANBAP_RegisterDataPlane");
return VOS_STATUS_E_FAULT;
}
// Include the HDD BAP Shim Layer callbacks for Fetch, TxComp, and RxPkt
pBtampCtx->pfnBtampFetchPktCB = pfnBtampFetchPktCB;
pBtampCtx->pfnBtamp_STARxCB = pfnBtamp_STARxCB;
pBtampCtx->pfnBtampTxCompCB = pfnBtampTxCompCB;
// (Right now, there is only one)
pBtampCtx->pHddHdl = pHddHdl;
/* Set the default data transfer mode */
pBtampCtx->ucDataTrafficMode = WLANBAP_FLOW_CONTROL_MODE_BLOCK_BASED;
return VOS_STATUS_SUCCESS;
} /* WLANBAP_RegisterDataPlane */
/*===========================================================================
FUNCTION WLANBAP_STAPktPending
DESCRIPTION
HDD will call this API when a packet is pending transmission in its
queues. HDD uses this instead of WLANTL_STAPktPending because he is
not aware of the mapping from session to STA ID.
DEPENDENCIES
HDD must have called WLANBAP_GetNewHndl before calling this API.
PARAMETERS
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
BSL can obtain this from the physical handle value in the
downgoing HCI Data Packet. He, after all, was there
when the PhysicalLink was created. He knew the btampHandle
value returned by WLANBAP_GetNewHndl. He knows as well, his
own pHddHdl (see next).
phy_link_handle: Used by BAP to indentify the WLAN assoc. (StaId)
ucAc: The access category for the pending frame
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: BAP handle is NULL
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANBAP_STAPktPending
(
ptBtampHandle btampHandle, /* Used by BAP to identify the app context and VOSS ctx (!?) */
v_U8_t phy_link_handle, /* Used by BAP to indentify the WLAN assoc. (StaId) */
WLANTL_ACEnumType ucAc /* This is the first instance of a TL type in bapApi.h */
)
{
VOS_STATUS vosStatus;
ptBtampContext pBtampCtx = (ptBtampContext) btampHandle;
v_PVOID_t pvosGCtx;
v_U8_t ucSTAId; /* The StaId (used by TL, PE, and HAL) */
v_PVOID_t pHddHdl; /* Handle to return BSL context in */
#ifdef BAP_DEBUG
/* Trace the tBtampCtx being passed in. */
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH,
"WLAN BAP Context Monitor: pBtampCtx value = %pK in %s:%d", pBtampCtx, __func__, __LINE__ );
#endif //BAP_DEBUG
/*------------------------------------------------------------------------
Sanity check params
------------------------------------------------------------------------*/
if ( NULL == pBtampCtx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BAP handle value in WLANBAP_STAPktPending");
return VOS_STATUS_E_FAULT;
}
// Retrieve the VOSS context
pvosGCtx = pBtampCtx->pvosGCtx;
/* Lookup the StaId using the phy_link_handle and the BAP context */
vosStatus = WLANBAP_GetStaIdFromLinkCtx (
btampHandle, /* btampHandle value in */
phy_link_handle, /* phy_link_handle value in */
&ucSTAId, /* The StaId (used by TL, PE, and HAL) */
&pHddHdl); /* Handle to return BSL context */
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
"Unable to retrieve STA Id from BAP context and phy_link_handle in WLANBAP_STAPktPending");
return VOS_STATUS_E_FAULT;
}
// Let TL know we have a packet to send...
vosStatus = WLANTL_STAPktPending(
pvosGCtx,
ucSTAId,
ucAc);
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Tx: Packet rejected by TL in WLANBAP_STAPktPending");
return vosStatus;
}
pBtampCtx->dataPktPending = VOS_TRUE;//Indication for LinkSupervision module that data is pending
return VOS_STATUS_SUCCESS;
} /* WLANBAP_STAPktPending */
/*----------------------------------------------------------------------------
FUNCTION WLAN_BAPRegisterBAPCallbacks()
DESCRIPTION
Register the BAP "Event" callbacks.
Return the per instance handle.
DEPENDENCIES
NA.
PARAMETERS
IN
btampHandle: The BT-AMP PAL handle returned in WLANBAP_GetNewHndl.
pBapHCIEventCB: pointer to the Event callback
pAppHdl: The context passed in by caller. (I.E., BSL app specific context.)
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_FAULT: pointer to pBapHCIEventCB is NULL
VOS_STATUS_SUCCESS: Success
SIDE EFFECTS
----------------------------------------------------------------------------*/
VOS_STATUS
WLAN_BAPRegisterBAPCallbacks
(
ptBtampHandle btampHandle, /* BSL uses my handle to talk to me */
/* Returned from WLANBAP_GetNewHndl() */
/* It's like each of us is using the other */
/* guys reference when invoking him. */
tpWLAN_BAPEventCB pBapHCIEventCB, /*Implements the callback for ALL asynchronous events. */
v_PVOID_t pAppHdl // Per-app BSL context
)
{
ptBtampContext pBtampCtx = (ptBtampContext) btampHandle;
/*------------------------------------------------------------------------
Sanity check params
------------------------------------------------------------------------*/
if ( NULL == pBtampCtx)
{
VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
"Invalid BAP handle value in WLAN_BAPRegisterBAPCallbacks");
return VOS_STATUS_E_FAULT;
}
// Save the Event callback
pBtampCtx->pBapHCIEventCB = pBapHCIEventCB;
// (Right now, there is only one)
pBtampCtx->pAppHdl = pAppHdl;
return VOS_STATUS_SUCCESS;
} /* WLAN_BAPRegisterBAPCallbacks */