This is an automated email from the ASF dual-hosted git repository. janc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit 2ad8f6fd6455b846f0999ae3faa22fd7c6f7fe2a Author: Piotr Narajowski <[email protected]> AuthorDate: Fri Jul 25 13:25:37 2025 +0200 nimble/host: add support for chrc extended properties descriptor Add support for Characteristic Extended Properties descriptor. For each characteristic that has reliable/auxiliary write flags set an instance of Extended Properties descriptor will be registred. --- nimble/host/include/host/ble_gatt.h | 8 ++++ nimble/host/src/ble_gatt_priv.h | 9 ++++ nimble/host/src/ble_gatts.c | 90 +++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/nimble/host/include/host/ble_gatt.h b/nimble/host/include/host/ble_gatt.h index aebfc7ef3..3ce22d664 100644 --- a/nimble/host/include/host/ble_gatt.h +++ b/nimble/host/include/host/ble_gatt.h @@ -65,6 +65,9 @@ struct ble_hs_cfg; /** GATT Client Characteristic Configuration descriptor 16-bit UUID. */ #define BLE_GATT_DSC_CLT_CFG_UUID16 0x2902 +/** GATT Characteristic Extended Porperties descriptor 16-bit UUID. */ +#define BLE_GATT_DSC_EXT_PROP_UUID16 0x2900 + /** @} */ /** @@ -259,6 +262,11 @@ struct ble_gatt_dsc { ble_uuid_any_t uuid; }; +/** Represents a Characteristic Extended Properties descriptor */ +struct ble_gatt_cep_dsc { + /** Characteristic Extended properties **/ + uint16_t properties; +}; /** Represents a handle-value tuple for multiple handle notifications. */ struct ble_gatt_notif { diff --git a/nimble/host/src/ble_gatt_priv.h b/nimble/host/src/ble_gatt_priv.h index 50e0a75b9..111a540b3 100644 --- a/nimble/host/src/ble_gatt_priv.h +++ b/nimble/host/src/ble_gatt_priv.h @@ -159,6 +159,9 @@ int ble_gattc_init(void); #define BLE_GATTS_INC_SVC_LEN_NO_UUID 4 #define BLE_GATTS_INC_SVC_LEN_UUID 6 +#define BLE_GATTS_CEP_F_RELIABLE_WRITE 0x0001 +#define BLE_GATTS_CEP_F_AUX_WRITE 0x0002 + /** * Contains counts of resources required by the GATT server. The contents of * this struct are generally used to populate a configuration struct before @@ -183,6 +186,12 @@ struct ble_gatt_resources { */ uint16_t cccds; + /** + * Number of characteristic extended properties descriptors. Each of + * these also contributes to the total descriptor count. + */ + uint16_t ceps; + /** Total number of ATT attributes. */ uint16_t attrs; }; diff --git a/nimble/host/src/ble_gatts.c b/nimble/host/src/ble_gatts.c index 6c3ae19de..199e8e469 100644 --- a/nimble/host/src/ble_gatts.c +++ b/nimble/host/src/ble_gatts.c @@ -39,6 +39,7 @@ static const ble_uuid_t *uuid_chr = BLE_UUID16_DECLARE(BLE_ATT_UUID_CHARACTERISTIC); static const ble_uuid_t *uuid_ccc = BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16); +static const ble_uuid_t *uuid_cep = BLE_UUID16_DECLARE(BLE_GATT_DSC_EXT_PROP_UUID16); static const struct ble_gatt_svc_def **ble_gatts_svc_defs; static int ble_gatts_num_svc_defs; @@ -154,6 +155,22 @@ ble_gatts_chr_clt_cfg_allowed(const struct ble_gatt_chr_def *chr) return flags; } +static uint16_t +ble_gatts_chr_ext_prop_allowed(const struct ble_gatt_chr_def *chr) +{ + uint16_t flags; + + flags = 0; + if (chr->flags & BLE_GATT_CHR_F_RELIABLE_WRITE) { + flags |= BLE_GATTS_CEP_F_RELIABLE_WRITE; + } + if (chr->flags & BLE_GATT_CHR_F_AUX_WRITE) { + flags |= BLE_GATTS_CEP_F_AUX_WRITE; + } + + return flags; +} + static uint8_t ble_gatts_att_flags_from_chr_flags(ble_gatt_chr_flags chr_flags) { @@ -831,6 +848,55 @@ ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle) return 0; } +static int +ble_gatts_cep_access(uint16_t conn_handle, uint16_t attr_handle, uint8_t att_op, + uint16_t offset, struct os_mbuf **om, void *arg) +{ + uint16_t prop = POINTER_TO_UINT(arg); + uint8_t *buf; + + ble_gatts_dsc_inc_stat(ble_gatts_dsc_op(att_op)); + + if (att_op != BLE_ATT_ACCESS_OP_READ) { + return BLE_ATT_ERR_WRITE_NOT_PERMITTED; + } + + buf = os_mbuf_extend(*om, sizeof(prop)); + if (buf == NULL) { + return BLE_ATT_ERR_INSUFFICIENT_RES; + } + put_le16(buf, prop); + + return 0; +} + +static int +ble_gatts_register_cep_dsc(uint16_t *att_handle, ble_gatt_chr_flags flags) +{ + struct ble_gatt_cep_dsc cep; + int rc; + + cep.properties = 0x0000; + if (flags & BLE_GATT_CHR_F_RELIABLE_WRITE) { + cep.properties |= BLE_GATTS_CEP_F_RELIABLE_WRITE; + } + if (flags & BLE_GATT_CHR_F_AUX_WRITE) { + /* TODO: Implement Characteristic User Description + * (Core specification 6.0, vol 3, part G, section 3.3.3.2)*/ + cep.properties |= BLE_GATTS_CEP_F_AUX_WRITE; + } + + rc = ble_att_svr_register(uuid_cep, BLE_ATT_F_READ, 0, att_handle, + ble_gatts_cep_access, UINT_TO_POINTER(cep.properties)); + if (rc != 0) { + return rc; + } + + STATS_INC(ble_gatts_stats, dscs); + + return 0; +} + static int ble_gatts_register_chr(const struct ble_gatt_svc_def *svc, const struct ble_gatt_chr_def *chr, @@ -841,6 +907,7 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc, uint16_t def_handle; uint16_t val_handle; uint16_t dsc_handle; + uint16_t cep_handle; uint8_t att_flags; int rc; @@ -897,6 +964,14 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc, BLE_HS_DBG_ASSERT(dsc_handle == def_handle + 2); } + if (ble_gatts_chr_ext_prop_allowed(chr) != 0) { + rc = ble_gatts_register_cep_dsc(&cep_handle, chr->flags); + if (rc != 0) { + return rc; + } + BLE_HS_DBG_ASSERT(cep_handle == def_handle + 3); + } + /* Register each descriptor. */ if (chr->descriptors != NULL) { for (dsc = chr->descriptors; dsc->uuid != NULL; dsc++) { @@ -2199,6 +2274,21 @@ ble_gatts_count_resources(const struct ble_gatt_svc_def *svcs, res->attrs++; } + /* If the characteristic permits reliable writes or auxiliary + * writes, it has an Extended Properties descriptor. + */ + if (chr->flags & BLE_GATT_CHR_F_AUX_WRITE || + chr->flags & BLE_GATT_CHR_F_RELIABLE_WRITE) { + + /* Each CEP requires: + * o 1 descriptor + * o 1 attribute + */ + res->dscs++; + res->ceps++; + res->attrs++; + } + if (chr->descriptors != NULL) { for (d = 0; chr->descriptors[d].uuid != NULL; d++) { if (!ble_gatts_dsc_is_sane(chr->descriptors + d)) {
