6#include "dawn/proto/nimble/prph_ess.hxx"
11#include "dawn/io/common.hxx"
12#include "dawn/io/sdata.hxx"
13#include "dawn/proto/nimble/gatt_runtime.hxx"
14#include "host/ble_hs_mbuf.h"
15#include "os/os_mbuf.h"
19#ifdef CONFIG_DAWN_PROTO_NIMBLE_EXTENDED_METADATA
20# if defined(CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_USER_DESCRIPTION) || \
21 defined(CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_VALID_RANGE) || \
22 defined(CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_MEASUREMENT) || \
23 defined(CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_CONFIGURATION) || \
24 defined(CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_TRIGGER_SETTING)
25# define DAWN_PROTO_NIMBLE_ESS_ANY_DESCRIPTOR 1
28# ifdef DAWN_PROTO_NIMBLE_ESS_ANY_DESCRIPTOR
29static ble_uuid_any_t *essMakeUuid16(uint16_t value)
31 ble_uuid_any_t *uuid =
new (std::nothrow) ble_uuid_any_t{};
37 uuid->u.type = BLE_UUID_TYPE_16;
38 uuid->u16.value = value;
42static void essFreeUuid(
const ble_uuid_t *uuid)
46 delete reinterpret_cast<const ble_uuid_any_t *
>(uuid);
51# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_VALID_RANGE
52static uint8_t essValueBytes(uint8_t type)
95 *value = data->
get<uint8_t>(0);
99 *value = data->
get<uint16_t>(0);
103 *value = data->
get<uint32_t>(0);
123 if (io->
getDataSize() > CProtoNimblePrphEss::ESS_RAW_DESCRIPTOR_MAX)
140#ifdef CONFIG_DAWN_IO_NOTIFY
141int CProtoNimblePrphEss::notifierCb(
void *priv,
io_ddata_t *data)
143 SPrphNotiferCb *ncb = (SPrphNotiferCb *)priv;
147 DAWNERR(
"NULL ncb pointer in notifier\n");
155 DAWNERR(
"NULL io pointer in notifier\n");
161 std::memcpy(ncb->data->getDataPtr(), data->
getDataPtr(), ncb->data->getDataSize());
165 ble_gatts_chr_updated(ncb->handle);
171#ifdef CONFIG_DAWN_PROTO_NIMBLE_EXTENDED_METADATA
172int CProtoNimblePrphEss::descriptorCb(uint16_t conn_handle,
173 uint16_t attr_handle,
174 struct ble_gatt_access_ctxt *ctxt,
177 SEssDscCb *dcb =
static_cast<SEssDscCb *
>(arg);
183 if (dcb ==
nullptr || ctxt->op != BLE_GATT_ACCESS_OP_READ_DSC)
185 return BLE_ATT_ERR_UNLIKELY;
188 if (dcb->kind == ESS_DESC_MEASUREMENT)
192 for (
size_t i = 0; i < 6; i++)
194 ret = essReadFieldU32(dcb->measurement[i].io, dcb->measurement[i].data, &values[i]);
197 DAWNERR(
"ESS measurement descriptor field read failed %d\n", ret);
198 return BLE_ATT_ERR_UNLIKELY;
202 dcb->data[0] =
static_cast<uint8_t
>(values[0] & 0xff);
203 dcb->data[1] =
static_cast<uint8_t
>((values[0] >> 8) & 0xff);
204 dcb->data[2] =
static_cast<uint8_t
>(values[1] & 0xff);
205 dcb->data[3] =
static_cast<uint8_t
>(values[2] & 0xff);
206 dcb->data[4] =
static_cast<uint8_t
>((values[2] >> 8) & 0xff);
207 dcb->data[5] =
static_cast<uint8_t
>((values[2] >> 16) & 0xff);
208 dcb->data[6] =
static_cast<uint8_t
>(values[3] & 0xff);
209 dcb->data[7] =
static_cast<uint8_t
>((values[3] >> 8) & 0xff);
210 dcb->data[8] =
static_cast<uint8_t
>((values[3] >> 16) & 0xff);
211 dcb->data[9] =
static_cast<uint8_t
>(values[4] & 0xff);
212 dcb->data[10] =
static_cast<uint8_t
>(values[5] & 0xff);
214 else if (dcb->kind == ESS_DESC_CONFIGURATION || dcb->kind == ESS_DESC_TRIGGER_SETTING)
216 ret = essReadFieldRaw(dcb->field.io, dcb->field.data, dcb->data, &dcb->len);
219 DAWNERR(
"ESS raw descriptor field read failed %d\n", ret);
220 return BLE_ATT_ERR_UNLIKELY;
224 ret = os_mbuf_append(ctxt->om, dcb->data, dcb->len);
227 DAWNERR(
"ESS descriptor append failed %d\n", ret);
228 return BLE_ATT_ERR_UNLIKELY;
237template<
typename T,
size_t WriteBytes>
238int CProtoNimblePrphEss::callback(uint16_t conn_handle,
239 uint16_t attr_handle,
240 struct ble_gatt_access_ctxt *ctxt,
243 SPrphNotiferCb *ncb =
static_cast<SPrphNotiferCb *
>(arg);
245 uint16_t uuid16 = ble_uuid_u16(ctxt->chr->uuid);
250 case BLE_GATT_ACCESS_OP_READ_CHR:
254#ifdef CONFIG_DAWN_IO_NOTIFY
260 ret = io->
getData(*ncb->data, 1);
263 return BLE_ATT_ERR_UNLIKELY;
283 DAWNERR(
"ESS data type not supported yet\n");
284 return BLE_ATT_ERR_UNLIKELY;
290 ret = os_mbuf_append(ctxt->om, &retval, WriteBytes);
293 DAWNERR(
"os_mbuf_append failed %d\n", ret);
301 DAWNERR(
"ESS GATT operation not supported\n");
302 return BLE_ATT_ERR_UNLIKELY;
307int CProtoNimblePrphEss::allocESS()
311 svc.type = BLE_GATT_SVC_TYPE_PRIMARY;
313 svc.includes =
nullptr;
321 svc.characteristics =
new (std::nothrow) ble_gatt_chr_def[noChar]();
323 if (svc.characteristics ==
nullptr)
325 DAWNERR(
"Failed to allocate characteristics\n");
332int CProtoNimblePrphEss::createESS()
334 const uint32_t *char_uuid =
nullptr;
338 if (svc.characteristics ==
nullptr)
340 DAWNERR(
"Failed to allocate characteristics\n");
346 svc.type = BLE_GATT_SVC_TYPE_PRIMARY;
348 svc.includes =
nullptr;
350 for (
auto const objid :
vio)
358 struct ble_gatt_chr_def *chr =
const_cast<struct ble_gatt_chr_def *
>(&svc.characteristics[j]);
362 DAWNERR(
"ESS IO not found\n");
370 DAWNERR(
"seekable IO not supported by ESS"
371 " (objid=0x%08" PRIx32
")\n",
376 SPrphNotiferCb *ncb = nimbleGattNotifierCreate(io);
379 DAWNERR(
"ESS notifier allocation failed\n");
385 nimbleGattChrInit(*chr, ncb);
390#ifdef CONFIG_DAWN_IO_NOTIFY
391 ret = nimbleGattChrNotifySet(*chr, *io, *ncb, notifierCb, objid);
394 DAWNERR(
"ESS notifier setup failed\n");
398 nimbleGattChrAccessSet(*chr, *io);
402 switch (ioTypeMap[objid])
406 chr->access_cb = CProtoNimblePrphEss::callback<int16_t>;
413 chr->access_cb = CProtoNimblePrphEss::callback<int16_t>;
420 chr->access_cb = CProtoNimblePrphEss::callback<uint32_t>;
427 chr->access_cb = CProtoNimblePrphEss::callback<uint8_t>;
436 chr->access_cb = CProtoNimblePrphEss::callback<int16_t>;
445 chr->access_cb = CProtoNimblePrphEss::callback<uint32_t, 3>;
452 DAWNERR(
"unknown ESS type %d\n", ioTypeMap[objid]);
453 nimbleGattChrNotifierFree(*chr);
460 if (char_uuid ==
nullptr)
462 DAWNERR(
"No UUID for ESS IO\n");
463 nimbleGattChrNotifierFree(*chr);
467 ret = nimbleGattChrUuid128Set(*chr, char_uuid);
470 DAWNERR(
"ESS UUID allocation failed\n");
471 nimbleGattChrNotifierFree(*chr);
475 ret = configureDescriptors(chr, objid, ioTypeMap[objid]);
478 nimbleGattChrUuidFree(*chr);
479 nimbleGattChrNotifierFree(*chr);
491void CProtoNimblePrphEss::deleteESS()
495 if (svc.characteristics)
497 for (
size_t i = 0; i < noChar - 1; i++)
499 if (svc.characteristics[i].uuid)
501 nimbleGattChrUuidFree(
const_cast<struct ble_gatt_chr_def &
>(svc.characteristics[i]));
504#ifdef DAWN_PROTO_NIMBLE_ESS_ANY_DESCRIPTOR
505 if (svc.characteristics[i].descriptors)
507 struct ble_gatt_dsc_def *dsc =
508 const_cast<struct ble_gatt_dsc_def *
>(svc.characteristics[i].descriptors);
510 for (
size_t j = 0; dsc[j].uuid !=
nullptr; j++)
512 SEssDscCb *dcb =
static_cast<SEssDscCb *
>(dsc[j].arg);
514 essFreeUuid(dsc[j].uuid);
517 if (dcb->field.data !=
nullptr)
519 delete dcb->field.data;
521 for (
size_t k = 0; k < 6; k++)
523 if (dcb->measurement[k].data !=
nullptr)
525 delete dcb->measurement[k].data;
536 nimbleGattChrNotifierFree(
const_cast<struct ble_gatt_chr_def &
>(svc.characteristics[i]));
539 delete[]
const_cast<ble_gatt_chr_def *
>(svc.characteristics);
541 svc.characteristics =
nullptr;
546int CProtoNimblePrphEss::configureDescriptors(
struct ble_gatt_chr_def *chr,
550#ifndef CONFIG_DAWN_PROTO_NIMBLE_EXTENDED_METADATA
556 const auto metaIt = ioMetaMap.find(objid);
558 struct ble_gatt_dsc_def *dsc;
563 if (metaIt == ioMetaMap.end())
568 meta =
const_cast<SEssMeta *
>(&metaIt->second);
570# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_USER_DESCRIPTION
571 if (meta->desc & ESS_DESC_USER_DESCRIPTION)
577# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_VALID_RANGE
578 if (meta->desc & ESS_DESC_VALID_RANGE)
580 if (essValueBytes(type) == 0)
582 DAWNERR(
"ESS valid range unsupported for type %u\n", type);
589# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_MEASUREMENT
590 if (meta->desc & ESS_DESC_MEASUREMENT)
596# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_CONFIGURATION
597 if (meta->desc & ESS_DESC_CONFIGURATION)
603# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_TRIGGER_SETTING
604 if (meta->desc & ESS_DESC_TRIGGER_SETTING)
615 dsc =
new (std::nothrow) ble_gatt_dsc_def[count + 1]();
621# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_USER_DESCRIPTION
622 if (meta->desc & ESS_DESC_USER_DESCRIPTION)
624 SEssDscCb *dcb =
new (std::nothrow) SEssDscCb{};
625 ble_uuid_any_t *uuid = essMakeUuid16(UUID16_CHR_USER_DESCRIPTION);
626 if (dcb ==
nullptr || uuid ==
nullptr)
629 essFreeUuid(uuid ? &uuid->u : nullptr);
634 dcb->kind = ESS_DESC_USER_DESCRIPTION;
636 while (dcb->len < ESS_USER_DESCRIPTION_MAX && meta->userDescription[dcb->len] !=
'\0')
638 dcb->data[dcb->len] =
static_cast<uint8_t
>(meta->userDescription[dcb->len]);
642 dsc[idx].uuid = &uuid->u;
643 dsc[idx].att_flags = BLE_ATT_F_READ;
644 dsc[idx].access_cb = descriptorCb;
650# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_VALID_RANGE
651 if (meta->desc & ESS_DESC_VALID_RANGE)
653 SEssDscCb *dcb =
new (std::nothrow) SEssDscCb{};
654 ble_uuid_any_t *uuid = essMakeUuid16(UUID16_VALID_RANGE);
655 uint8_t width = essValueBytes(type);
656 if (dcb ==
nullptr || uuid ==
nullptr)
659 essFreeUuid(uuid ? &uuid->u : nullptr);
664 dcb->kind = ESS_DESC_VALID_RANGE;
665 dcb->len = width * 2;
666 for (uint8_t i = 0; i < width; i++)
668 dcb->data[i] =
static_cast<uint8_t
>((meta->validMin >> (8 * i)) & 0xff);
669 dcb->data[width + i] =
static_cast<uint8_t
>((meta->validMax >> (8 * i)) & 0xff);
672 dsc[idx].uuid = &uuid->u;
673 dsc[idx].att_flags = BLE_ATT_F_READ;
674 dsc[idx].access_cb = descriptorCb;
680# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_CONFIGURATION
681 if (meta->desc & ESS_DESC_CONFIGURATION)
683 SEssDscCb *dcb =
new (std::nothrow) SEssDscCb{};
684 ble_uuid_any_t *uuid = essMakeUuid16(UUID16_ES_CONFIGURATION);
685 if (dcb ==
nullptr || uuid ==
nullptr)
688 essFreeUuid(uuid ? &uuid->u : nullptr);
693 dcb->kind = ESS_DESC_CONFIGURATION;
694 dcb->field.io =
cb->
getObject(meta->configurationObjid);
695 if (dcb->field.io ==
nullptr)
698 essFreeUuid(&uuid->u);
703 dcb->field.data = dcb->field.io->ddata_alloc(1);
704 if (dcb->field.data ==
nullptr)
707 essFreeUuid(&uuid->u);
712 dsc[idx].uuid = &uuid->u;
713 dsc[idx].att_flags = BLE_ATT_F_READ;
714 dsc[idx].access_cb = descriptorCb;
720# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_MEASUREMENT
721 if (meta->desc & ESS_DESC_MEASUREMENT)
723 SEssDscCb *dcb =
new (std::nothrow) SEssDscCb{};
724 ble_uuid_any_t *uuid = essMakeUuid16(UUID16_ES_MEASUREMENT);
726 meta->measurementFlagsObjid,
727 meta->samplingFunctionObjid,
728 meta->measurementPeriodObjid,
729 meta->updateIntervalObjid,
730 meta->applicationObjid,
731 meta->uncertaintyObjid,
733 if (dcb ==
nullptr || uuid ==
nullptr)
736 essFreeUuid(uuid ? &uuid->u : nullptr);
741 dcb->kind = ESS_DESC_MEASUREMENT;
743 for (
size_t i = 0; i < 6; i++)
751 if (dcb->measurement[i].io ==
nullptr)
753 for (
size_t k = 0; k < 6; k++)
755 delete dcb->measurement[k].data;
758 essFreeUuid(&uuid->u);
763 dcb->measurement[i].data = dcb->measurement[i].io->ddata_alloc(1);
764 if (dcb->measurement[i].data ==
nullptr)
766 for (
size_t k = 0; k < 6; k++)
768 delete dcb->measurement[k].data;
771 essFreeUuid(&uuid->u);
777 dsc[idx].uuid = &uuid->u;
778 dsc[idx].att_flags = BLE_ATT_F_READ;
779 dsc[idx].access_cb = descriptorCb;
785# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_TRIGGER_SETTING
786 if (meta->desc & ESS_DESC_TRIGGER_SETTING)
788 SEssDscCb *dcb =
new (std::nothrow) SEssDscCb{};
789 ble_uuid_any_t *uuid = essMakeUuid16(UUID16_ES_TRIGGER_SETTING);
790 if (dcb ==
nullptr || uuid ==
nullptr)
793 essFreeUuid(uuid ? &uuid->u : nullptr);
798 dcb->kind = ESS_DESC_TRIGGER_SETTING;
799 dcb->field.io =
cb->
getObject(meta->triggerSettingObjid);
800 if (dcb->field.io ==
nullptr)
803 essFreeUuid(&uuid->u);
808 dcb->field.data = dcb->field.io->ddata_alloc(1);
809 if (dcb->field.data ==
nullptr)
812 essFreeUuid(&uuid->u);
817 dsc[idx].uuid = &uuid->u;
818 dsc[idx].att_flags = BLE_ATT_F_READ;
819 dsc[idx].access_cb = descriptorCb;
825 chr->descriptors = dsc;
830void CProtoNimblePrphEss::allocObject(
const SProtoNimblePrphIOBindEssObjid &obj,
833 uint8_t type = cfgIdIOBindEssCfgObjTypeGet(obj.cfg);
834#ifdef CONFIG_DAWN_PROTO_NIMBLE_EXTENDED_METADATA
838 DAWNINFO(
"ESS allocate type=%d object 0x%" PRIx32
"\n", type, obj.objid.v);
842 ioTypeMap.insert_or_assign(obj.objid.v, type);
844#ifdef CONFIG_DAWN_PROTO_NIMBLE_EXTENDED_METADATA
845 for (
size_t i = 0; i < obj.extCount; i++)
847 uint8_t kind = cfgIdIOBindEssExtKindGet(ext[0]);
848 uint8_t size = cfgIdIOBindEssExtSizeGet(ext[0]);
849 const uint32_t *data = &ext[1];
856 size_t bytes =
static_cast<size_t>(size) *
sizeof(uint32_t);
857 bytes = bytes < ESS_USER_DESCRIPTION_MAX ? bytes : ESS_USER_DESCRIPTION_MAX;
859# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_USER_DESCRIPTION
860 meta.desc |= ESS_DESC_USER_DESCRIPTION;
861 std::memcpy(meta.userDescription, data, bytes);
868# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_VALID_RANGE
871 meta.desc |= ESS_DESC_VALID_RANGE;
872 meta.validMin = data[0];
873 meta.validMax = data[1];
881# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_MEASUREMENT
884 meta.desc |= ESS_DESC_MEASUREMENT;
885 meta.measurementFlagsObjid = data[0];
886 meta.samplingFunctionObjid = data[1];
887 meta.measurementPeriodObjid = data[2];
888 meta.updateIntervalObjid = data[3];
889 meta.applicationObjid = data[4];
890 meta.uncertaintyObjid = data[5];
898# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_CONFIGURATION
901 meta.desc |= ESS_DESC_CONFIGURATION;
902 meta.configurationObjid = data[0];
910# ifdef CONFIG_DAWN_PROTO_NIMBLE_ESS_DESC_TRIGGER_SETTING
913 meta.desc |= ESS_DESC_TRIGGER_SETTING;
914 meta.triggerSettingObjid = data[0];
922 DAWNERR(
"unknown ESS extension kind %u\n", kind);
932 ioMetaMap.insert_or_assign(obj.objid.v, meta);
939#ifdef CONFIG_DAWN_PROTO_NIMBLE_EXTENDED_METADATA
940 if (meta.measurementFlagsObjid != 0)
945 if (meta.samplingFunctionObjid != 0)
950 if (meta.measurementPeriodObjid != 0)
955 if (meta.updateIntervalObjid != 0)
960 if (meta.applicationObjid != 0)
965 if (meta.uncertaintyObjid != 0)
970 if (meta.configurationObjid != 0)
975 if (meta.triggerSettingObjid != 0)
981 vio.push_back(obj.objid.v);
992 const SProtoNimblePrphIOBindEss *tmp =
993 reinterpret_cast<const SProtoNimblePrphIOBindEss *
>(&item->
data[k]);
995 uint8_t size = cfgIdIOBindEssCfg0SizeGet(tmp->cfg0);
997 size_t pos = k +
sizeof(SProtoNimblePrphIOBindEss) /
sizeof(uint32_t);
999 for (
size_t i = 0; i < size; i++)
1001 const SProtoNimblePrphIOBindEssObjid *obj =
1002 reinterpret_cast<const SProtoNimblePrphIOBindEssObjid *
>(&item->
data[pos]);
1003 const uint32_t *ext =
1004 &item->
data[pos +
sizeof(SProtoNimblePrphIOBindEssObjid) /
sizeof(uint32_t)];
1006 allocObject(*obj, ext);
1008 pos +=
sizeof(SProtoNimblePrphIOBindEssObjid) /
sizeof(uint32_t);
1009 for (
size_t j = 0; j < obj->extCount; j++)
1011 pos += 1 + cfgIdIOBindEssExtSizeGet(item->
data[pos]);
1030CProtoNimblePrphEss::~CProtoNimblePrphEss()
1041 configureDesc(
desc);
1056 DAWNERR(
"ESS service registration failed\n");
Base class for all I/O objects.
int getData(IODataCmn &data, size_t len, size_t offset=0)
Get data from I/O (public interface with stats tracking).
virtual bool isNotify() const =0
Check if IO supports notifications.
virtual bool isSeekable() const
Check if IO supports partial (seekable) access.
virtual size_t getDataDim() const =0
Get data vector dimension.
virtual size_t getDataSize() const =0
Get data size in bytes.
SObjectId::ObjectId getIdV() const
Get object identifier as raw 32-bit value.
uint8_t getDtype() const
Get data type field.
int deinit()
Deinitialize service.
@ ESS_EXT_TRIGGER_SETTING
Environmental Sensing Trigger Setting descriptor.
@ ESS_EXT_USER_DESCRIPTION
Characteristic User Description descriptor.
@ ESS_EXT_CONFIGURATION
Environmental Sensing Configuration descriptor.
@ ESS_EXT_MEASUREMENT
Environmental Sensing Measurement descriptor.
@ ESS_EXT_VALID_RANGE
Valid Range descriptor.
int start()
Start service.
int init()
Initialize service.
@ PRPH_ESS_TYPE_UVIDX
UV index sensor.
@ PRPH_ESS_TYPE_TEMP
Temperature sensor.
@ PRPH_ESS_TYPE_PRESS
Pressure (barometric) sensor.
@ PRPH_ESS_TYPE_HUM
Humidity sensor.
@ PRPH_ESS_TYPE_GAS
Gas resistance sensor (non-standard UUID).
@ PRPH_ESS_TYPE_LIGHT
Illuminance / light sensor.
Interface for BLE peripheral services with GATT characteristics.
virtual int startService(int id)=0
Start a specific service.
static uint32_t UUID_UVIDX[4]
UV Index Characteristic UUID (0x2A76).
static uint32_t UUID_ESS[4]
Environmental Sensing Service UUID (0x181A).
virtual size_t getObjectsLen()=0
Get count of registered I/O objects.
static float charScaleGet(uint16_t u)
Get scaling factor for a characteristic UUID.
virtual CIOCommon * getObject(SObjectId::ObjectId id)=0
Get protocol object by ID.
static uint32_t UUID_PRESS[4]
Pressure Characteristic UUID (0x2A6D).
static uint32_t UUID_TEMP[4]
Temperature Characteristic UUID (0x2A6E).
static uint32_t UUID_ILLUMINANCE[4]
Illuminance Characteristic UUID (0x2AFB).
static uint32_t UUID_RESISTANCE[4]
Electric Resistance Characteristic UUID (0x272A).
virtual int serviceRegister(struct ble_gatt_svc_def *svc)=0
Register a GATT service with the peripheral.
virtual void regObject(SObjectId::ObjectId id)=0
Register an I/O object for this service.
static uint32_t UUID_HUM[4]
Humidity Characteristic UUID (0x2A6F).
virtual int stopService(int id)=0
Stop a specific service.
Base interface for GATT services exposed by BLE peripheral.
std::vector< SObjectId::ObjectId > vio
Vector of I/O objects exposed by this service.
const SObjectCfg::SObjectCfgItem * desc
Configuration descriptor for this service.
IProtoNimblePrphCb * cb
Callback interface to peripheral.
Out-of-tree user-extension hooks for Dawn.
Single configuration item within object.
ObjectCfgData_t data[]
Configuration data array (flexible, size from cfgid.s.size).
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
@ DTYPE_FLOAT
IEEE 754 single-precision floating point (32-bit).
@ DTYPE_UINT8
Unsigned 8-bit integer (0 to 255).
@ DTYPE_UINT16
Unsigned 16-bit integer (0 to 65535).
@ DTYPE_UINT32
Unsigned 32-bit integer (0 to 4294967295).
uint32_t ObjectId
ObjectID type - single 32-bit value.
Heap-allocated dynamic I/O data buffer.
void * getDataPtr(size_t batch=0)
Get pointer to data only (skips timestamp if present).
T & get(size_t index, size_t batch=0)
Get data element by index and batch (type-safe).
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.