Newer
Older
mbed-os / features / FEATURE_BLE / targets / TARGET_CORDIO_LL / stack / controller / sources / ble / bb / bb_ble_sniffer.c
@Paul Szczeanek Paul Szczeanek on 2 Jul 2020 12 KB update cordio LL files to 20.05r
/*************************************************************************************************/
/*!
 *  \file
 *
 *  \brief  BB BLE Sniffer utility function definition file.
 *
 *  Copyright (c) 2019 Arm Ltd. All Rights Reserved.
 *
 *  Copyright (c) 2019-2020 Packetcraft, Inc.
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/*************************************************************************************************/

#include "bb_ble_sniffer_api.h"
#include "wsf_types.h"
#include "pal_bb_ble.h"
#include "bb_api.h"
#include "ll_api.h"
#include "bb_ble_api_op.h"
#include "wsf_trace.h"
#include "wsf_assert.h"
#include "pal_bb.h"
#include "bb_ble_int.h"
#include <string.h>

/**************************************************************************************************
  Global Variables
**************************************************************************************************/

/*! brief   Sniffer VS output packet function placeholder. */
static void bbSnifferOutputVendorSpec(BbBleSnifferPkt_t * pPktData);

/*! brief   Sniffer output table. */
bbSnifferFn_t bbSnifferOutTbl[BB_SNIFFER_OUTPUT_TOTAL_METHODS] =
{
  bbSnifferOutputVendorSpec                    /* BB_SNIFFER_OUTPUT_HCI_TOKEN */
};

/*! brief   Sniffer VS get packet function placeholder. */
static BbBleSnifferPkt_t * bbSnifferGetPktVendorSpec();

/*! brief   Sniffer get packet table. */
bbSnifferGetPktFn_t bbSnifferGetPktTbl[BB_SNIFFER_OUTPUT_TOTAL_METHODS] =
{
  bbSnifferGetPktVendorSpec                    /* BB_SNIFFER_OUTPUT_HCI_TOKEN */
};
/*! brief   Sniffer context. */
bbSnifferCtx_t bbSnifferCtx;

/**************************************************************************************************
  Packet retrival methods
**************************************************************************************************/

/*************************************************************************************************/
/*!
 *  \brief      Retrive packet for processing.
 *
 *  \return     Pointer to packet to be packed.
 *
 */
/*************************************************************************************************/
static BbBleSnifferPkt_t * bbSnifferGetPktVendorSpec()
{
  BbBleSnifferHciCtx_t * pHci = &bbSnifferCtx.outputCtx.hci;

  if ((pHci->bufIdx == BB_SNIFFER_MAX_NUM_BUF) ||
      (bbSnifferCtx.enabled == FALSE))
  {
    return NULL;
  }

  return &pHci->pktBuf[pHci->bufIdx];
}


/**************************************************************************************************
  Output methods
**************************************************************************************************/

/*************************************************************************************************/
/*!
 *  \brief      Finalize sniffer packet by incrementing index.
 *
 *  \param      pPktData    Packet to be pushed.
 *
 */
/*************************************************************************************************/
static void bbSnifferOutputVendorSpec(BbBleSnifferPkt_t * pPktData)
{
  BbBleSnifferHciCtx_t * pHci = &bbSnifferCtx.outputCtx.hci;

  pHci->bufIdx++;
}
/*************************************************************************************************/
/*!
 *  \brief      Master primary scan sniffer packet handler.
 *
 *  \param      pBod            Pointer to BOD.
 *  \param      pPktData        Pointer to sniffer packet.
 *
 *  Pack sniffer packet and call to output method function.
 */
/*************************************************************************************************/
void bbBleSnifferMstScanPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData)
{
  BbBleMstAdvEvent_t * pScan = &pBod->prot.pBle->op.mstAdv;

  /* Pack channelization data. */
  memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan));

  /* Pack metadata. */
  pPktData->pktType.meta.timeStamp   =  bbSnifferCtx.packetCtr++;

  /* Pack header. */
  switch (pPktData->pktType.meta.state)
  {
    case BB_EVT_STATE_RX_ADV_IND:
      /* Handled in the Rx Callback. */
      break;

    case BB_EVT_STATE_TX_SCAN_OR_CONN_INIT:
      memcpy(pPktData->pktType.advPkt.hdr, pScan->pTxReqBuf, LL_ADV_HDR_LEN);
      break;

    case BB_EVT_STATE_RX_SCAN_OR_CONN_RSP:
      /* Handled in the Rx Callback. */
      break;

    default:
      break;
  }

  WSF_ASSERT(bbSnifferCtx.snifferOutCb);

  bbSnifferCtx.snifferOutCb(pPktData);
}

/*************************************************************************************************/
/*!
 *  \brief      Master auxiliary scan sniffer packet handler
 *
 *  \param      pBod            Pointer to BOD.
 *  \param      pPktData        Pointer to sniffer packet.
 *
 *  Pack sniffer packet and call to output method function.
 */
/*************************************************************************************************/
void bbBleSnifferMstAuxScanPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t *pPktData)
{
  BbBleMstAuxAdvEvent_t * pScan = &pBod->prot.pBle->op.mstAuxAdv;

  /* Pack channelization data. */
  memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan));

  /* Pack metadata. */
  pPktData->pktType.meta.timeStamp   =  bbSnifferCtx.packetCtr++;

  /* Pack header. */
  switch (pPktData->pktType.meta.state)
  {
    case BB_EVT_STATE_RX_ADV_IND:
      /* Handled in the Rx Callback. */
      break;

    case BB_EVT_STATE_TX_SCAN_OR_CONN_INIT:
      memcpy(pPktData->pktType.advPkt.hdr, pScan->pTxAuxReqBuf, LL_ADV_HDR_LEN);
      break;

    case BB_EVT_STATE_RX_SCAN_OR_CONN_RSP:
      /* Handled in the Rx Callback. */
      break;

    case BB_EVT_STATE_RX_CHAIN_IND:
      /* Handled in the Rx callback. */
      break;

    default:
      break;
  }

  WSF_ASSERT(bbSnifferCtx.snifferOutCb);

  bbSnifferCtx.snifferOutCb(pPktData);
}

/*************************************************************************************************/
/*!
 *  \brief      Master periodic scan sniffer packet handler.
 *
 *  \param      pBod            Pointer to BOD.
 *  \param      pPktData        Pointer to sniffer packet.
 *
 *  Pack sniffer packet and call to output method function.
 */
/*************************************************************************************************/
void bbBleSnifferMstPerScanPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t *pPktData)
{
  /* Pack channelization data. */
  memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan));

  /* Pack metadata. */
  pPktData->pktType.meta.timeStamp   =  bbSnifferCtx.packetCtr++;

  /* Pack header. */
  switch (pPktData->pktType.meta.state)
  {
    case BB_EVT_STATE_RX_ADV_IND:
      /* Handled in the Rx Callback. */
      break;

    case BB_EVT_STATE_RX_CHAIN_IND:
      /* Handled in the Rx callback. */
      break;

    default:
      break;
  }

  WSF_ASSERT(bbSnifferCtx.snifferOutCb);

  bbSnifferCtx.snifferOutCb(pPktData);
}

/*************************************************************************************************/
/*!
 *  \brief      Slave primary advertising sniffer packet handler.
 *
 *  \param      pBod            Pointer to BOD.
 *  \param      pPktData        Pointer to sniffer packet.
 *
 *  Pack sniffer packet and call to output method function.
 */
/*************************************************************************************************/
void bbBleSnifferSlvAdvPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData)
{
  BbBleSlvAdvEvent_t * pAdv = &pBod->prot.pBle->op.slvAdv;

  /* Pack channelization data. */
  memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan));

  /* Pack saved channel index. */
  pPktData->pktType.meta.chan.chanIdx = bbSnifferCtx.chanIdx;

  /* Pack metadata. */
  pPktData->pktType.meta.timeStamp = bbSnifferCtx.packetCtr++;

  /* Pack header. */
  switch (pPktData->pktType.meta.state)
  {
    case BB_EVT_STATE_TX_ADV_IND:
      memcpy(pPktData->pktType.advPkt.hdr, pAdv->pTxAdvBuf, LL_ADV_HDR_LEN);
      break;

    case BB_EVT_STATE_RX_SCAN_OR_CONN_INIT:
      /* Handled in the Rx Callback. */
      break;

    case BB_EVT_STATE_TX_SCAN_OR_CONN_RSP:
      memcpy(pPktData->pktType.advPkt.hdr, pAdv->pTxRspBuf, LL_ADV_HDR_LEN);
      break;

    default:
      break;
  }

  WSF_ASSERT(bbSnifferCtx.snifferOutCb);

  bbSnifferCtx.snifferOutCb(pPktData);
}

/*************************************************************************************************/
/*!
 *  \brief      Slave auxiliary advertising sniffer packet handler.
 *
 *  \param      pBod            Pointer to BOD.
 *  \param      pPktData        Pointer to sniffer packet.
 *
 *  Pack sniffer packet and call to output method function.
 */
/*************************************************************************************************/
void bbBleSnifferSlvAuxAdvPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData)
{
  BbBleSlvAuxAdvEvent_t * pAdv = &pBod->prot.pBle->op.slvAuxAdv;

  /* Pack channelization data. */
  memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan));

  /* Pack metadata. */
  pPktData->pktType.meta.timeStamp = bbSnifferCtx.packetCtr++;

  /* Pack header. */
  switch (pPktData->pktType.meta.state)
  {
    case BB_EVT_STATE_TX_ADV_IND:
      /* Handled in the Tx Callback. */
      break;

    case BB_EVT_STATE_RX_SCAN_OR_CONN_INIT:
      /* Handled in the Rx Callback. */
      break;

    case BB_EVT_STATE_TX_SCAN_OR_CONN_RSP:
      memcpy(pPktData->pktType.advPkt.hdr, pAdv->txAuxRspPdu[0].pBuf, LL_ADV_HDR_LEN);
      break;

    case BB_EVT_STATE_TX_CHAIN_IND:
      /* Handled in the Tx Callback. */
      break;

    default:
      break;
  }

  WSF_ASSERT(bbSnifferCtx.snifferOutCb);

  bbSnifferCtx.snifferOutCb(pPktData);
}

/*************************************************************************************************/
/*!
 *  \brief      Connection sniffer packet handler.
 *
 *  \param      pBod            Pointer to BOD.
 *  \param      pPktData        Pointer to sniffer packet.
 *
 *  Pack sniffer packet and call to output method function.
 */
/*************************************************************************************************/
void bbBleSnifferConnPktHandler(BbOpDesc_t * pBod, BbBleSnifferPkt_t * pPktData)
{
  /* BbBleMstConnEvent_t * pConn = &pBod->prot.pBle->op.mstConn; */

  /* Pack channelization data. */
  memcpy(&pPktData->pktType.meta.chan, &pBod->prot.pBle->chan, sizeof(pPktData->pktType.meta.chan));

  /* Pack metadata. */
  pPktData->pktType.meta.timeStamp = bbSnifferCtx.packetCtr++;

  /* Pack Header. */
  if (pPktData->pktType.meta.type == BB_SNIFF_PKT_TYPE_TX)
  {
    memcpy(pPktData->pktType.dataPkt.hdr, bbSnifferCtx.txBuf, LL_DATA_HDR_MAX_LEN);
  }
  else /* (type == BB_SNIFF_PKT_TYPE_RX) */
  {
    /* Header copy is done in the Rx comp callback. */
  }

  WSF_ASSERT(bbSnifferCtx.snifferOutCb);

  bbSnifferCtx.snifferOutCb(pPktData);
}

/*************************************************************************************************/
/*!
 *  \brief      Initialize packet sniffer
 *
 *  \param      outMethod     Output method.
 *  \param      enable        Enable.
 *
 *  \return     Status error code.
 *
 *  Initialize packet sniffer with specified output method.
 */
/*************************************************************************************************/
uint8_t BbBleInitSniffer(uint8_t outMethod, bool_t enable)
{
  memset(&bbSnifferCtx, 0, sizeof(bbSnifferCtx));

  if (enable == FALSE)
  {
    return LL_SUCCESS;
  }

  if (outMethod >= BB_SNIFFER_OUTPUT_TOTAL_METHODS)
  {
    return LL_ERROR_CODE_INVALID_HCI_CMD_PARAMS;
  }

  bbSnifferCtx.snifferGetPktFn = bbSnifferGetPktTbl[outMethod];
  bbSnifferCtx.snifferOutCb = bbSnifferOutTbl[outMethod];
  bbSnifferCtx.enabled = enable;

  return LL_SUCCESS;
}