Custom HCI command

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Custom HCI command

Custom HCI command

HCI Application is a Host Controller Interface application which provides a serial communication to interface with the KW40/KW41/KW3x/QN9080 BLE radio part.

 

It enables the user to have a way to control the radio through serial commands.

 

The format of the HCI Command Packet it’s composed by the following parts.

 

HCI_packet.pngFigure 1. HCI Command Packet

 

Each command is assigned a 2 byte Opcode which it’s divided into two fields, called the OpCode Group Field (OGF) and OpCode Command Field (OCF).

 

The OGF uses the upper 6 bits of the Opcode, while the OCF corresponds to the remaining 10 bits.

 

The OGF of 0x3F is reserved for vendor-specific debug commands. The organization of the opcodes allows additional information to be inferred without fully decoding the entire Opcode. 

 

For further information regarding this, please check the BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E, 5.4 EXCHANGE OF HCI-SPECIFIC INFORMATION. 

 

This document will guide you through the implementation of custom HCI commands in the KW36, but it can be applied as well for the rest of the NXP Bluetooth LE MCU’s that support HCI.

 

The following changes were made and tested in the FREEDOM KW38 and will generate a continuous with both channel and power configurable. 

   

You will need to perform the following changes to the HCI black box demo.

 

Modify the hci_transport.h public constants and macros section by adding:

 

#define gHciCustomCommandOpcodeUpper (0xFC90)
 #define gHciCustomCommandOpcodeLower (0xFC00)
 #define gHciInCustomVendorCommandsRange(x) (((x) <= gHciCustomCommandOpcodeUpper) && \
 ((x) >= gHciCustomCommandOpcodeLower))‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

In this case, the opcodes 0xFC90 to 0xFC00 are not used by our stack. These opcodes meet the requirements for vendor specific commands (OCF = 3F).

 

Then you will need to declare the handler for the custom command.

 

void Hcit_InstallCustomCommandHandler(hciTransportInterface_t mCustomInterfaceHandler);‍‍‍‍‍

 

 

In the  hcit_serial_interface.c modify the following :

 

Add in the private memory declarations section

 

static hciTransportInterface_t mCustomTransportInterface = NULL;‍‍‍‍‍


Change the Hcit_SendMessage as it is shown:

 

static inline void Hcit_SendMessage(void)
 {
    uint16_t opcode = 0;
    /* verify if this is an event packet */
    if(mHcitData.pktHeader.packetTypeMarker == gHciEventPacket_c)
    {
       /* verify if this is a command complete event */
       if(mHcitData.pPacket->raw[0] == gHciCommandCompleteEvent_c)
       {
          /* extract the first opcode to verify if it is a custom command */
          opcode = mHcitData.pPacket->raw[3] + (mHcitData.pPacket->raw[4] << 8);
       }
    }
    /* verify if command packet */
    else if(mHcitData.pktHeader.packetTypeMarker == gHciCommandPacket_c)
    {
       /* extract opcode */
       opcode = mHcitData.pPacket->raw[0] + (mHcitData.pPacket->raw[1] << 8);
    }

    if(gHciInCustomVendorCommandsRange(opcode))
    {
       if(mCustomTransportInterface)
       {
          mCustomTransportInterface( mHcitData.pktHeader.packetTypeMarker,
                                                         mHcitData.pPacket,
                                                         mHcitData.bytesReceived);
       }
    }
    else
    {
       /* Send the message to HCI */
       mTransportInterface( mHcitData.pktHeader.packetTypeMarker,
                                          mHcitData.pPacket,
                                          mHcitData.bytesReceived);
    }
   MEM_BufferFree( mHcitData.pPacket );
   mHcitData.pPacket = NULL;
    mPacketDetectStep = mDetectMarker_c; 
 }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

Implement the registration of the handler

void Hcit_InstallCustomCommandHandler(hciTransportInterface_t mCustomInterfaceHandler)
{
   OSA_EXT_InterruptDisable();
   mCustomTransportInterface = mCustomInterfaceHandler;
   OSA_EXT_InterruptEnable();
   return;
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

 Once those changes are done, we will need to modify the  hci_black_box.c with the following changes. 

 

Add the files to support HCI Custom commands.

 

#include "hci_transport.h"
#include "fsl_xcvr.h"‍‍‍‍‍‍‍‍‍‍

 

Define the custom commands, in this case, we will create some to turn ON/OFF the continuous wave as well as to set up the channel and power. 

 

//@CC custom command
#define CUSTOM_HCI_CW_EVENT_SIZE (0x04)
#define CUSTOM_HCI_EVENT_SUCCESS (0x00)
#define CUSTOM_HCI_EVENT_FAIL (0x01)
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Also, adding some app auxiliar variables 

static uint16_t channelCC = 2402;
static uint8_t powerCC = 0x3E;

 

Create the custom event packet 

 

uint8_t  eventPacket[6] = {gHciCommandCompleteEvent_c, CUSTOM_HCI_CW_EVENT_SIZE, 1, 0, 0, 0 };‍‍‍‍‍

 

In the main_task() after the BleApp_Init() register the callback for the custom commands.

 

/* Initialize peripheral drivers specific to the application */
BleApp_Init();
//Register the callback for the custom commands.
Hcit_InstallCustomCommandHandler(BleApp_CustomCommandsHandle);‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

Once that it’s added, add the handler for the command

 

bleResult_t BleApp_CustomCommandsHandle(hciPacketType_t packetType, void* pPacket, uint16_t packetSize)
{
   uint16_t opcode = 0;

   uint8_t error=0;
   switch(packetType)
   {
      case gHciCommandPacket_c:
      opcode = ((uint8_t*)pPacket)[0] + (((uint8_t*)pPacket)[1] << 8);
if (opcode >= 0xfc00 & opcode <= 0xfc50)
      {
        channelCC = 2400+(opcode - 0xfc00);
        eventPacket[5] = CUSTOM_HCI_EVENT_SUCCESS;        
      }
      else if (opcode <= 0xfc70)
      {
        powerCC = (opcode-0xfc50)*2;
        if (gXcvrSuccess_c ==XCVR_ForcePAPower(powerCC)
            eventPacket[5] = CUSTOM_HCI_EVENT_SUCCESS;
        else  eventPacket[5] = CUSTOM_HCI_EVENT_FAIL;
      }
      else if (opcode == 0xfc80)
      {
        if (gXcvrSuccess_c == XCVR_DftTxCW(channelCC*1000000))
        {
         eventPacket[5] = CUSTOM_HCI_EVENT_SUCCESS;
        }
        else eventPacket[5] = CUSTOM_HCI_EVENT_FAIL;
      }
      else if(opcode == 0xfc90)
      {
        XCVR_ForceTxWd();
        /* Initialize the PHY as BLE */
        XCVR_Init(BLE_MODE, DR_1MBPS);
        eventPacket[5] = CUSTOM_HCI_EVENT_SUCCESS;
      }
      else 
      {
        eventPacket[5] = CUSTOM_HCI_EVENT_FAIL;
      }


      eventPacket[3] = (uint8_t)opcode;
      eventPacket[4] = (uint8_t)(opcode >> 8);

      Hcit_SendPacket(gHciEventPacket_c, eventPacket, sizeof(eventPacket));

      break;

      default:
      break;
}
 ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍}

The format of this HCI command is:

01 XX FC 00

Where:

When 0<=XX<=50: set the transmitting channel. The transmitting frequency is (2400+XX (in hexadecimal) )*1000MHz

When 50<xx<70: set the transmitting power. 51 is the minimum Tx power and 69 corresponds to the maximum Tx power.

When XX = 80: start the CW transmission

When XX = 90: Stop the CW transmission

 

For example, if you want to transmit a CW on the frequency 2420MHz at maximum frequency, you should send the following command:

01 14 FC 00

01 69 FC 00

01 80 FC 00

 

whenever you want to change the channel or Tx power, please stop the ongoing Tx first by sending

01 90 FC 00

Then repeat the previous step.

 

If you want to add some parameter to it, please consider that the fourth byte of the packet will correspond to the number of parameters to enter and you will need to indicate it there. 

No ratings
Version history
Last update:
‎10-22-2024 07:00 AM
Updated by: