Newer
Older
mbed-os / features / FEATURE_BLE / targets / TARGET_CORDIO_LL / stack / controller / sources / ble / lhci / lhci_cmd_vs_iso.c
@Paul Szczeanek Paul Szczeanek on 2 Jul 2020 4 KB update cordio LL files to 20.05r
/*************************************************************************************************/
/*!
 *  \file
 *
 *  \brief  Arm Ltd. vendor specific HCI command module implementation file.
 *
 *  Copyright (c) 2013-2018 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 "lhci_int.h"
#include "hci_defs.h"
#include "bb_ble_api.h"
#include "ll_api.h"
#include "wsf_msg.h"
#include "wsf_trace.h"
#include "util/bstream.h"
#include <string.h>

/*! \brief      Control block for ISO generation. */
lhciIsoCb_t lhciIsoCb;

/*************************************************************************************************/
/*!
 *  \brief  Decode Arm Ltd. connection vendor specific HCI command packet.
 *
 *  \param  pHdr    Unpacked command header.
 *  \param  pBuf    Packed HCI packet buffer.
 *
 *  Command processing for vendor specific commands.
 *
 *  \return TRUE if opcode handled, FALSE otherwise.
 */
/*************************************************************************************************/
bool_t lhciIsoVsStdDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf)
{
  uint8_t status = HCI_SUCCESS;
  uint8_t evtParamLen = 1;      /* default is status field only */

  /* Decode and consume command packet. */
  switch (pHdr->opCode)
  {
    /* --- ISO --- */

    case LHCI_OPCODE_VS_GET_ISO_TEST_REPORT:
      evtParamLen += sizeof(uint32_t) * 4;
      break;
    case LHCI_OPCODE_VS_ENA_ISO_SINK:
      lhciIsoCb.recvIsoSink = pBuf[0];
      break;
    case LHCI_OPCODE_VS_ENA_AUTO_GEN_ISO:
      BSTREAM_TO_UINT16(lhciIsoCb.genPktLen, pBuf);
      break;
    case LHCI_OPCODE_VS_GENERATE_ISO:
    {
      uint16_t handle;
      uint16_t pktLen;
      uint8_t numPkts;

      BSTREAM_TO_UINT16(handle, pBuf);
      BSTREAM_TO_UINT16(pktLen, pBuf);
      numPkts = *pBuf++;

      lhciGenerateIso(handle, pktLen, numPkts);
      break;
    }
    case LHCI_OPCODE_VS_GET_CIS_STATS:
      evtParamLen += sizeof(BbBleDataPktStats_t);
      break;

    /* --- default --- */

    default:
      return FALSE;       /* exit dispatcher routine */
  }

  uint8_t *pEvtBuf;

  /* Encode and send command complete event packet. */
  if ((pEvtBuf = lhciAllocCmdCmplEvt(evtParamLen, pHdr->opCode)) != NULL)
  {
    pBuf  = pEvtBuf;
    pBuf += lhciPackCmdCompleteEvtStatus(pBuf, status);

    switch (pHdr->opCode)
    {
      case LHCI_OPCODE_VS_GET_ISO_TEST_REPORT:
        UINT32_TO_BSTREAM(pBuf, lhciIsoCb.recvIsoPktCnt);
        UINT32_TO_BSTREAM(pBuf, lhciIsoCb.recvIsoOctetCnt);
        UINT32_TO_BSTREAM(pBuf, lhciIsoCb.genPktCnt);
        UINT32_TO_BSTREAM(pBuf, lhciIsoCb.genOctetCnt);
        break;

      case LHCI_OPCODE_VS_GET_CIS_STATS:
      {
        BbBleDataPktStats_t stats;
        BbBleGetCisStats(&stats);
        memcpy(pBuf, (uint8_t *)&stats, sizeof(stats));
        break;
      }

      /* --- default --- */

      default:
        break;
    }

    lhciSendCmdCmplEvt(pEvtBuf);
  }

  return TRUE;
}

/*************************************************************************************************/
/*!
 *  \brief  Generate ISO packets.
 *
 *  \param  handle      Connection handle.
 *  \param  pktLen      Packet length.
 *  \param  numPkts     Number of packets.
 */
/*************************************************************************************************/
void lhciGenerateIso(uint16_t handle, uint16_t pktLen, uint8_t numPkts)
{
  if (lhciIsoCb.genEnaFlag)
  {
    /* Prevent re-entrance. */
    return;
  }

  lhciIsoCb.genEnaFlag = TRUE;

  while (numPkts--)
  {
    uint8_t *pIsoBuf;
    if ((pIsoBuf = (uint8_t*)WsfMsgAlloc(LL_ISO_PDU_MAX_LEN)) == NULL)
    {
      break;
    }

    uint8_t *pBuf = pIsoBuf;
    UINT16_TO_BSTREAM(pBuf, handle & 0xFFF);   /* BTS=0 and BF=0 */
    UINT16_TO_BSTREAM(pBuf, pktLen);
    memset(pBuf, lhciIsoCb.genPldCnt++, pktLen);

    LlSendIsoData(pIsoBuf);
  }

  lhciIsoCb.genEnaFlag = FALSE;
}