text: /*************************************************************************************************/
  /*!
   *  \file
   *
   *  \brief  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 "ll_api.h"
  #include "ll_defs.h"
  #include "wsf_msg.h"
  #include "util/bstream.h"
  #include <string.h>
  
  /*************************************************************************************************/
  /*!
   *  \brief  Pack a read resolving list size event.
   *
   *  \param  pBuf        Packed packet buffer.
   *  \param  status      Status code.
   *  \param  size        Resolving list size.
   *
   *  \return Packet length.
   */
  /*************************************************************************************************/
  static uint8_t lhciPackReadResListSizeEvt(uint8_t *pBuf, uint8_t status, uint16_t size)
  {
    const uint8_t len = LHCI_LEN_LE_READ_RES_LIST_SIZE_EVT;
  
    UINT8_TO_BSTREAM (pBuf, status);
    UINT16_TO_BSTREAM(pBuf, size);
  
    return len;
  }
  
  /*************************************************************************************************/
  /*!
   *  \brief  Build and send a command complete event packet.
   *
   *  \param  pCmdHdr     Command HCI header.
   *  \param  status      Status value.
   *  \param  paramLen    Parameter length of the command status event.
   */
  /*************************************************************************************************/
  static void lhciPrivAdvSendCmdCmplEvt(LhciHdr_t *pCmdHdr, uint8_t status, uint8_t paramLen)
  {
    uint8_t *pBuf;
    uint8_t *pEvtBuf;
  
    if ((pEvtBuf = lhciAllocCmdCmplEvt(paramLen, pCmdHdr->opCode)) == NULL)
    {
      return;
    }
    pBuf = pEvtBuf;
  
    switch (pCmdHdr->opCode)
    {
      /* --- command completion with status only parameter --- */
  
      case HCI_OPCODE_LE_ADD_DEV_RES_LIST:
      case HCI_OPCODE_LE_REMOVE_DEV_RES_LIST:
      case HCI_OPCODE_LE_CLEAR_RES_LIST:
      case HCI_OPCODE_LE_SET_ADDR_RES_ENABLE:
      case HCI_OPCODE_LE_SET_RES_PRIV_ADDR_TO:
      case HCI_OPCODE_LE_SET_PRIVACY_MODE:
        lhciPackCmdCompleteEvtStatus(pBuf, status);
        break;
  
      case HCI_OPCODE_LE_READ_RES_LIST_SIZE:
      {
        uint8_t size = 0;
        status = LlReadResolvingListSize(&size);
        lhciPackReadResListSizeEvt(pBuf, status, size);
        break;
      }
  
      /* --- default --- */
  
      default:
        break;
    }
  
    lhciSendCmdCmplEvt(pEvtBuf);
  }
  
  /*************************************************************************************************/
  /*!
   *  \brief  Decode an HCI command packet.
   *
   *  \param  pHdr    Decoded packet header.
   *  \param  pBuf    Packed HCI packet buffer.
   *
   *  \return TRUE if opcode handled, FALSE otherwise.
   */
  /*************************************************************************************************/
  bool_t lhciPrivAdvDecodeCmdPkt(LhciHdr_t *pHdr, uint8_t *pBuf)
  {
    uint8_t status = HCI_SUCCESS;
    uint8_t paramLen = 0;
  
    switch (pHdr->opCode)
    {
      case HCI_OPCODE_LE_ADD_DEV_RES_LIST:
      {
        status = LlAddDeviceToResolvingList(pBuf[0], pBuf + 1, pBuf + 7, pBuf + 23);
        paramLen = LHCI_LEN_LE_ADD_DEV_RES_LIST_EVT;
        break;
      }
      case HCI_OPCODE_LE_REMOVE_DEV_RES_LIST:
      {
        status = LlRemoveDeviceFromResolvingList(pBuf[0], pBuf + 1);
        paramLen = LHCI_LEN_LE_REMOVE_DEV_RES_LIST_EVT;
        break;
      }
      case HCI_OPCODE_LE_CLEAR_RES_LIST:
      {
        status = LlClearResolvingList();
        paramLen = LHCI_LEN_LE_CLEAR_RES_LIST_EVT;
        break;
      }
      case HCI_OPCODE_LE_READ_RES_LIST_SIZE:
      {
        paramLen = LHCI_LEN_LE_READ_RES_LIST_SIZE_EVT;
        break;
      }
      case HCI_OPCODE_LE_SET_ADDR_RES_ENABLE:
      {
        status = LlSetAddrResolutionEnable(pBuf[0]);
        paramLen = LHCI_LEN_LE_SET_ADDR_RES_ENABLE_EVT;
        break;
      }
      case HCI_OPCODE_LE_SET_RES_PRIV_ADDR_TO:
      {
        uint16_t rpaTimeout;
        BSTREAM_TO_UINT16(rpaTimeout, pBuf);
        status = LlSetResolvablePrivateAddrTimeout(rpaTimeout);
        paramLen = LHCI_LEN_LE_SET_RES_PRIV_ADDR_TO_EVT;
        break;
      }
      case HCI_OPCODE_LE_SET_PRIVACY_MODE:
      {
        status = LlSetPrivacyMode(pBuf[0], pBuf + 1, pBuf[7]);
        paramLen = LHCI_LEN_LE_SET_PRIVACY_MODE;
        break;
      }
  
      default:
        return FALSE;     /* exit dispatcher routine */
    }
  
    lhciPrivAdvSendCmdCmplEvt(pHdr, status, paramLen);
  
    return TRUE;
  }
  