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)) {

Reply via email to