Newer
Older
mbed-os / connectivity / FEATURE_BLE / cordio / TARGET_CORDIO_LL / stack / controller / sources / ble / lctr / lctr_isr_init_master.c
@Paul Szczeanek Paul Szczeanek on 7 Aug 2020 8 KB remove generic, TPPs, nested namespaces
/*************************************************************************************************/
/*!
 *  \file
 *
 *  \brief  Link layer controller master advertising event ISR callbacks.
 *
 *  Copyright (c) 2013-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 "lctr_int_init_master.h"
#include "lctr_int_adv_master.h"
#include "lctr_int_conn_master.h"
#include "sch_api.h"
#include "sch_api_ble.h"
#include "wsf_assert.h"
#include "wsf_math.h"
#include "wsf_msg.h"
#include "wsf_trace.h"
#include "bb_ble_api.h"
#include "bb_ble_api_op.h"
#include "bb_ble_api_reslist.h"
#include "util/bstream.h"
#include <string.h>

/*************************************************************************************************/
/*!
 *  \brief  End an initiate scan operation in the master role.
 *
 *  \param  pOp     Completed operation.
 */
/*************************************************************************************************/
void lctrMstInitiateEndOp(BbOpDesc_t *pOp)
{
  lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(lctrMstInit.data.init.connHandle);
  BbOpDesc_t * pConnBod = &pCtx->connBod;

  if (lctrMstInit.selfTerm)    /* implies a LL_CONN_IND Tx completion */
  {
    uint16_t numIntervals = 0;
    uint32_t anchorPointUsec = pConnBod->dueUsec;

    while (TRUE)
    {
      if (SchInsertAtDueTime(pConnBod, lctrConnResolveConflict))
      {
        break;
      }

      LL_TRACE_WARN1("!!! Establish CE schedule conflict handle=%u", LCTR_GET_CONN_HANDLE(pCtx));

      numIntervals++;
      pCtx->eventCounter++;

      uint32_t connInterUsec = LCTR_CONN_IND_US(numIntervals * pCtx->connInterval);

      pConnBod->dueUsec = anchorPointUsec + connInterUsec;
    }
  }

  /* Same as discovery scan. */
  pOp->pCtx = &lctrMstInit;
  lctrMstDiscoverEndOp(pOp);
}

/*************************************************************************************************/
/*!
 *  \brief      Initiate state advertising packet receive completion handler.
 *
 *  \param      pOp     Originating operation.
 *  \param      pAdvBuf Received advertising buffer.
 *
 *  \return     TRUE if connection indication transmission is required, FALSE otherwise.
 */
/*************************************************************************************************/
bool_t lctrMstInitiateAdvPktHandler(BbOpDesc_t *pOp, const uint8_t *pAdvBuf)
{
  WSF_ASSERT(pOp->protId == BB_PROT_BLE);
  WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_ADV_EVENT);

  lctrConnCtx_t *pCtx = LCTR_GET_CONN_CTX(lctrMstInit.data.init.connHandle);
  BbOpDesc_t * const pConnBod = &pCtx->connBod;
  BbBleData_t * const pBle = pOp->prot.pBle;
  BbBleMstAdvEvent_t * const pScan = &pBle->op.mstAdv;

  uint32_t advEndTs = pScan->advStartTsUsec + LCTR_ADV_PKT_1M_US(pScan->filtResults.pduLen);
  uint32_t refTime = advEndTs;

  /*** Transmit response PDU processing. ***/

  bool_t txConnInd = FALSE;

  if (!pScan->filtResults.peerMatch)
  {
    /* Require peer match. */
  }
  else if (pScan->pTxReqBuf)
  {
    /* Update connection indication header with advertiser's address. */
    uint8_t *pConnIndAdvA = pScan->pTxReqBuf + LL_ADV_HDR_LEN + BDA_ADDR_LEN;
    Bda64ToBstream(pConnIndAdvA, pScan->filtResults.peerAddr);
    lctrMstInit.reqPduHdr.rxAddrRnd = pScan->filtResults.peerAddrRand;

    /* Update connection indication header with scanner's address. */
    if (lctrMstInit.scanParam.ownAddrType & LL_ADDR_IDENTITY_BIT)
    {
      bool_t  localAddrRand;
      uint64_t localAddr;

      if (pScan->filtResults.pduType == LL_PDU_ADV_DIRECT_IND)
      {
        /* If peer is using directed advertising then use the InitA from the    */
        /* ADV_DIRECT_IND as our local address in the connect indication.       */
        localAddrRand = ((pAdvBuf[0] >> LCTR_ADV_HDR_RX_ADD_SHIFT) & 1);
        localAddr     = BstreamToBda64(pAdvBuf + LL_ADV_HDR_LEN + BDA_ADDR_LEN);

        /* Update the local RPA if the received one is RPA. */
        if (BDA64_ADDR_IS_RPA(localAddr))
        {
          lctrMstInit.data.init.localRpa = localAddr;
          BbBleResListUpdateLocal(pScan->filtResults.peerIdAddrRand, pScan->filtResults.peerIdAddr, &localAddr);
        }
        else
        {
          lctrMstInit.data.init.localRpa = 0;
        }
      }
      else
      {
        localAddrRand = BB_BLE_PDU_FILT_FLAG_IS_SET(&pBle->pduFilt, LOCAL_ADDR_MATCH_RAND);
        localAddr     = pBle->pduFilt.localAddrMatch;
        if (BbBleResListReadLocal(pScan->filtResults.peerIdAddrRand, pScan->filtResults.peerIdAddr, &localAddr))
        {
          localAddrRand = TRUE;
          lctrMstInit.data.init.localRpa = localAddr;
        }
        else
        {
          lctrMstInit.data.init.localRpa = 0;
        }
      }
      uint8_t *pConnIndInitA = pScan->pTxReqBuf + LL_ADV_HDR_LEN;
      Bda64ToBstream(pConnIndInitA, localAddr);
      lctrMstInit.reqPduHdr.txAddrRnd = localAddrRand;
    }
    else
    {
      lctrMstInit.data.init.localRpa = 0;
    }

#if (LL_ENABLE_TESTER)
    if (llTesterCb.auxReq.len)
    {
      /* Overriding CONNECT_IND from test script. */
      memcpy(pScan->pTxReqBuf, llTesterCb.auxReq.buf, llTesterCb.auxReq.len);
      pScan->txReqLen = llTesterCb.auxReq.len;
    }
#endif

    lctrPackAdvbPduHdr(pScan->pTxReqBuf, &lctrMstInit.reqPduHdr);

    /* Update txWinOffset field in CONN_IND PDU. */
    refTime += LL_BLE_TIFS_US;
    refTime += LCTR_CONN_IND_PKT_1M_US;
    refTime += LCTR_CONN_IND_US(LCTR_DATA_CHAN_DLY);

    /* Now reference time is the start of transmitWindowOffset. */
    uint32_t txWinOffsetUsec = SchRmGetOffsetUsec(LCTR_CONN_IND_US(pCtx->connInterval), LCTR_GET_CONN_HANDLE(pCtx), refTime);
    uint16_t txWinOffset = LCTR_US_TO_CONN_IND(txWinOffsetUsec);

    UINT16_TO_BUF(pScan->pTxReqBuf + LCTR_CONN_IND_TX_WIN_OFFSET, txWinOffset);
    lctrMstInit.data.init.connInd.txWinOffset = txWinOffset;

    /*** Update due time of first CE. ***/
    pConnBod->dueUsec = refTime + txWinOffsetUsec;

#if (LL_ENABLE_TESTER)
    switch (llTesterCb.connFirstCePos)
    {
    case LL_TESTER_FIRST_CE_POS_BEGIN:
      /* BOD is not scheduled; force time adjustment here. */
      pCtx->connBod.dueUsec = advEndTs + LCTR_CONN_IND_US(LCTR_DATA_CHAN_DLY) + txWinOffsetUsec + LL_BLE_TIFS_US + LCTR_CONN_IND_PKT_1M_US;
      break;
    case LL_TESTER_FIRST_CE_POS_END:
      /* BOD is not scheduled; force time adjustment here. */
      pCtx->connBod.dueUsec = advEndTs + LCTR_CONN_IND_US(LCTR_DATA_CHAN_DLY) + txWinOffsetUsec + LCTR_CONN_IND_US(lctrMstInit.data.init.connInd.txWinSize - 1) + LL_BLE_TIFS_US + LCTR_CONN_IND_PKT_1M_US;
      break;
    case LL_TESTER_FIRST_CE_POS_NORMAL:
    default:
      break;
    }
    llTesterCb.connFirstCePos = LL_TESTER_FIRST_CE_POS_NORMAL;
#endif

    txConnInd = TRUE;

    /*** Received advertising PDU post-processing. ***/

    if ((lctrMstInit.reqPduHdr.chSel == LL_CH_SEL_2) &&   /* local initiator supports CS#2 */
        (pAdvBuf[0] & (1 << LCTR_ADV_HDR_CH_SEL_SHIFT)))  /* peer advertiser supports CS#2 */
    {
      lctrMstInit.data.init.usedChSel = LL_CH_SEL_2;
    }
    else
    {
      lctrMstInit.data.init.usedChSel = LL_CH_SEL_1;
    }
  }

  return txConnInd;
}

/*************************************************************************************************/
/*!
 *  \brief      Connection indication Tx completion handler.
 *
 *  \param      pOp     Originating operation.
 *  \param      pIndBuf Transmitted request buffer.
 *
 *  \return     FALSE to signal no scan response.
 */
/*************************************************************************************************/
bool_t lctrMstConnIndTxCompHandler(BbOpDesc_t *pOp, const uint8_t *pIndBuf)
{
#if (LL_ENABLE_TESTER == TRUE)
  if (llTesterCb.auxReq.len)
  {
    /* Do not establish connection when CONNECT_IND is overridden. */
    return FALSE;
  }
#endif

  WSF_ASSERT(pOp->protId == BB_PROT_BLE);
  WSF_ASSERT(pOp->prot.pBle->chan.opType == BB_BLE_OP_MST_ADV_EVENT);

  lctrMstInit.selfTerm = TRUE;
  BbSetBodTerminateFlag();
  return FALSE;
}