Host API C Bindings
The Host SDK includes a set of C bindings to interface with a black-box. Bindings are generated from the matching FSCI XML file that is available in the stack software package under tools\wireless\xml_fsci
. The bindings are designed to be platform agnostic, with a minimal set of OS abstraction symbols required for building. Thus, the files can be easily integrated on a wide range of host platforms.
Directory Tree
hsdk-c/
├── demo
│ ├── HeartRateSensor.c Source file that implements the Bluetooth LE Heart Sensor Profile.
│ └── Makefile
├── inc
│ ├── ble_sig_defines.h Standard Bluetooth SIG UUID values.
│ ├── cmd_<name>.h Generated from the matching FSCI <name>.xml file.
│ └── os_abstraction.h Provides OS dependent symbols for building the interface.
├── README.md
└── src
├── cmd_<name>.c Generated from the matching FSCI <name>.xml file.
├── evt_<name>.c Generated from the matching FSCI <name>.xml file.
└── evt_printer_<name>.c Generated from the matching FSCI <name>.xml file.
Tests and examples
Tests and examples that make use of the C bindings are placed in the hsdk-c/demo
directory. Example of usage:
$ cd hsdk-c/demo/
$ make
$ ./HeartRateSensor /dev/ttyACM0
[...]
--> Setup finished, please open IoT Toolbox -> Heart Rate -> HSDK_HRS
Development
Header file cmd_<name>.h is generated from the corresponding <name>.xml FSCI XML file.
Enumerations
/* Indicates whether the connection request is issued for a specific device or for all the devices in the White List - default specific device */ typedef enum GAPConnectRequest_FilterPolicy_tag { GAPConnectRequest_FilterPolicy_gUseDeviceAddress_c = 0x00, GAPConnectRequest_FilterPolicy_gUseWhiteList_c = 0x01 } GAPConnectRequest_FilterPolicy_t;
Structures
typedef PACKED_STRUCT GAPConnectRequest_tag { uint16_t ScanInterval; // Scanning interval - default 10ms uint16_t ScanWindow; // Scanning window - default 10ms GAPConnectRequest_FilterPolicy_t FilterPolicy; // Indicates whether the connection request is issued for a specific device or for all the devices in the White List - default specific device GAPConnectRequest_OwnAddressType_t OwnAddressType; // Indicates whether the address used in connection requests will be the public address or the random address - default public address GAPConnectRequest_PeerAddressType_t PeerAddressType; // When connecting to a specific device, this indicates that device's address type - default public address uint8_t PeerAddress[6]; // When connecting to a specific device, this indicates that device's address uint16_t ConnIntervalMin; // The minimum desired connection interval - default 100ms uint16_t ConnIntervalMax; // The maximum desired connection interval - default 200ms uint16_t ConnLatency; // The desired connection latency (the maximum number of consecutive connection events the Slave is allowed to ignore) - default 0 uint16_t SupervisionTimeout; // The maximum time interval between consecutive over-the-air packets; if this timer expires, the connection is dropped - default 10s uint16_t ConnEventLengthMin; // The minimum desired connection event length - default 0ms uint16_t ConnEventLengthMax; // The maximum desired connection event length - default maximum possible, ~41 s bool_t usePeerIdentityAddress; // TRUE if the address defined in the peerAddressType and peerAddress is an identity address } GAPConnectRequest_t;
Container for all possible event types
typedef struct bleEvtContainer_tag { uint16_t id; union { [...] GAPConnectionEventConnectedIndication_t GAPConnectionEventConnectedIndication; [...] } Data; } bleEvtContainer_t;
Prototypes for sending commands
memStatus_t GAPConnectRequest(GAPConnectRequest_t *req, void *arg, uint8_t fsciInterface);
Header file os_abstraction.h provides the required symbols for building the generated interface. When integrating in a project different that Host SDK, the user needs to provide the implementation for
void FSCI_transmitPayload ( void *arg, /* Optional argument passed to thefunction */ uint8_t og, /* FSCI operation group */ uint8_t oc, /* FSCI operation code */ void *msg, /* Pointer to payload */ uint16_t msgLen, /* Payload length */ uint8_t fsciInterface /* FSCI interface ID */ );
that creates and sends a FSCI packet (0x02 | og | oc | msgLen | msg | crc +- fsciInterface) on the serial interface. Source files cmd_<name>.c, evt_<name>.c and evt_printer_<name>.c are generated from the correspondent <NAME>.xml FSCI XML file.
Functions that handle command serialization in cmd_<name>.c
memStatus_t GAPConnectRequest(GAPConnectRequest_t *req, void *arg, uint8_t fsciInterface) { /* Sanity check */ if (!req) { return MEM_UNKNOWN_ERROR_c; } FSCI_transmitPayload(arg, 0x48, 0x1C, req, sizeof(GAPConnectRequest_t), fsciInterface); return MEM_SUCCESS_c; }
Event dispatcher in evt_<name>.c
void KHC_BLE_RX_MsgHandler(void *pData, void *param, uint8_t fsciInterface) { if (!pData || !param) { return; } fsciPacket_t *frame = (fsciPacket_t *)pData; bleEvtContainer_t *container = (bleEvtContainer_t *)param; uint8_t og = frame->opGroup; uint8_t oc = frame->opCode; uint8_t *pPayload = frame->data; uint16_t id = (og << 8) + oc, i; for (i = 0; i < sizeof(evtHandlerTbl) / sizeof(evtHandlerTbl[0]); i++) { if (evtHandlerTbl[i].id == id) { evtHandlerTbl[i].handlerFunc(container, pPayload); break; } } }
Handler functions to perform event de-serialization in evt_<name>.c
static memStatus_t Load_GAPConnectionEventConnectedIndication(bleEvtContainer_t *container, uint8_t *pPayload) { GAPConnectionEventConnectedIndication_t *evt = &(container->Data.GAPConnectionEventConnectedIndication); uint32_t idx = 0; /* Store (OG, OC) in ID */ container->id = 0x489D; evt->DeviceId = pPayload[idx]; idx++; FLib_MemCpy(&(evt->ConnectionParameters.ConnInterval), pPayload + idx, sizeof(evt->ConnectionParameters.ConnInterval)); idx += sizeof(evt->ConnectionParameters.ConnInterval); FLib_MemCpy(&(evt->ConnectionParameters.ConnLatency), pPayload + idx, sizeof(evt->ConnectionParameters.ConnLatency)); idx += sizeof(evt->ConnectionParameters.ConnLatency); FLib_MemCpy(&(evt->ConnectionParameters.SupervisionTimeout), pPayload + idx, sizeof(evt->ConnectionParameters.SupervisionTimeout)); idx += sizeof(evt->ConnectionParameters.SupervisionTimeout); evt->ConnectionParameters.MasterClockAccuracy = (GAPConnectionEventConnectedIndication_ConnectionParameters_MasterClockAccuracy_t)pPayload[idx]; idx++; evt->PeerAddressType = (GAPConnectionEventConnectedIndication_PeerAddressType_t)pPayload[idx]; idx++; FLib_MemCpy(evt->PeerAddress, pPayload + idx, 6); idx += 6; evt->peerRpaResolved = (bool_t)pPayload[idx]; idx++; evt->localRpaUsed = (bool_t)pPayload[idx]; idx++; return MEM_SUCCESS_c; }
Event status console printer in evt_printer_<name>.c
void SHELL_BleEventNotify(void *param) { bleEvtContainer_t *container = (bleEvtContainer_t *)param; switch (container->id) { [...] case 0x489D: shell_write("GAPConnectionEventConnectedIndication"); shell_write(" -> "); switch (container->Data.GAPConnectionEventConnectedIndication.PeerAddressType) { case GAPConnectionEventConnectedIndication_PeerAddressType_gPublic_c: shell_write(gPublic_c); break; case GAPConnectionEventConnectedIndication_PeerAddressType_gRandom_c: shell_write(gRandom_c); break; default: shell_printf("Unrecognized status 0x%02X", container->Data.GAPConnectionEventConnectedIndication.PeerAddressType); break; } break; [...] } }
Parent topic: Bluetooth Low Energy Host Stack FSCI Application Programming