@@ -42,6 +42,8 @@ static const ble_uuid_t *uuid_chr =
4242 BLE_UUID16_DECLARE (BLE_ATT_UUID_CHARACTERISTIC );
4343static const ble_uuid_t * uuid_ccc =
4444 BLE_UUID16_DECLARE (BLE_GATT_DSC_CLT_CFG_UUID16 );
45+ static const ble_uuid_t * uuid_cep =
46+ BLE_UUID16_DECLARE (BLE_GATT_DSC_EXT_PROP_UUID16 );
4547
4648static const struct ble_gatt_svc_def * * ble_gatts_svc_defs ;
4749static int ble_gatts_num_svc_defs ;
@@ -161,6 +163,22 @@ ble_gatts_chr_clt_cfg_allowed(const struct ble_gatt_chr_def *chr)
161163 return flags ;
162164}
163165
166+ static uint16_t
167+ ble_gatts_chr_ext_prop_allowed (const struct ble_gatt_chr_def * chr )
168+ {
169+ uint16_t flags ;
170+
171+ flags = 0 ;
172+ if (chr -> flags & BLE_GATT_CHR_F_RELIABLE_WRITE ) {
173+ flags |= BLE_GATTS_CEP_F_RELIABLE_WRITE ;
174+ }
175+ if (chr -> flags & BLE_GATT_CHR_F_AUX_WRITE ) {
176+ flags |= BLE_GATTS_CEP_F_AUX_WRITE ;
177+ }
178+
179+ return flags ;
180+ }
181+
164182static uint8_t
165183ble_gatts_att_flags_from_chr_flags (ble_gatt_chr_flags chr_flags )
166184{
@@ -811,6 +829,66 @@ ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle)
811829 return 0 ;
812830}
813831
832+ static int
833+ ble_gatts_cep_access_cb (uint16_t conn_handle , uint16_t attr_handle ,
834+ struct ble_gatt_access_ctxt * ctxt , void * arg )
835+ {
836+ uint16_t prop = POINTER_TO_UINT (arg );
837+
838+ if (ctxt -> op != BLE_GATT_ACCESS_OP_READ_DSC ) {
839+ return BLE_ATT_ERR_WRITE_NOT_PERMITTED ;
840+ }
841+
842+ os_mbuf_append (ctxt -> om , & prop , sizeof (prop ));
843+
844+ return 0 ;
845+ }
846+
847+ static int
848+ ble_gatts_cep_access (uint16_t conn_handle , uint16_t attr_handle ,
849+ uint8_t att_op , uint16_t offset , struct os_mbuf * * om ,
850+ void * arg )
851+ {
852+ struct ble_gatt_access_ctxt gatt_ctxt ;
853+ int rc ;
854+
855+ gatt_ctxt .op = ble_gatts_dsc_op (att_op );
856+
857+ ble_gatts_dsc_inc_stat (gatt_ctxt .op );
858+ rc = ble_gatts_val_access (conn_handle , attr_handle , offset , & gatt_ctxt ,
859+ om , ble_gatts_cep_access_cb , arg );
860+
861+ return rc ;
862+ }
863+
864+ static int
865+ ble_gatts_register_cep_dsc (uint16_t * att_handle , ble_gatt_chr_flags flags )
866+ {
867+ struct ble_gatt_cep_dsc cep ;
868+ int rc ;
869+
870+ cep .properties = 0x0000 ;
871+ if (flags & BLE_GATT_CHR_F_RELIABLE_WRITE ) {
872+ cep .properties |= BLE_GATTS_CEP_F_RELIABLE_WRITE ;
873+ }
874+ if (flags & BLE_GATT_CHR_F_AUX_WRITE ) {
875+ /* TODO: Implement Characteristic User Description
876+ * (Core specification 6.0, vol 3, part G, section 3.3.3.2)*/
877+ cep .properties |= BLE_GATTS_CEP_F_AUX_WRITE ;
878+ }
879+
880+ rc = ble_att_svr_register (uuid_cep , BLE_ATT_F_READ , 0 ,
881+ att_handle , ble_gatts_cep_access ,
882+ UINT_TO_POINTER (cep .properties ));
883+ if (rc != 0 ) {
884+ return rc ;
885+ }
886+
887+ STATS_INC (ble_gatts_stats , dscs );
888+
889+ return 0 ;
890+ }
891+
814892static int
815893ble_gatts_register_chr (const struct ble_gatt_svc_def * svc ,
816894 const struct ble_gatt_chr_def * chr ,
@@ -821,6 +899,7 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
821899 uint16_t def_handle ;
822900 uint16_t val_handle ;
823901 uint16_t dsc_handle ;
902+ uint16_t cep_handle ;
824903 uint8_t att_flags ;
825904 int rc ;
826905
@@ -877,6 +956,14 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
877956 BLE_HS_DBG_ASSERT (dsc_handle == def_handle + 2 );
878957 }
879958
959+ if (ble_gatts_chr_ext_prop_allowed (chr ) != 0 ) {
960+ rc = ble_gatts_register_cep_dsc (& cep_handle , chr -> flags );
961+ if (rc != 0 ) {
962+ return rc ;
963+ }
964+ BLE_HS_DBG_ASSERT (cep_handle == def_handle + 3 );
965+ }
966+
880967 /* Register each descriptor. */
881968 if (chr -> descriptors != NULL ) {
882969 for (dsc = chr -> descriptors ; dsc -> uuid != NULL ; dsc ++ ) {
@@ -2188,6 +2275,21 @@ ble_gatts_count_resources(const struct ble_gatt_svc_def *svcs,
21882275 res -> attrs ++ ;
21892276 }
21902277
2278+ /* If the characteristic permits reliable writes or auxiliary
2279+ * writes, it has an Extended Properties descriptor.
2280+ */
2281+ if (chr -> flags & BLE_GATT_CHR_F_AUX_WRITE ||
2282+ chr -> flags & BLE_GATT_CHR_F_RELIABLE_WRITE ) {
2283+
2284+ /* Each CEP requires:
2285+ * o 1 descriptor
2286+ * o 1 attribute
2287+ */
2288+ res -> dscs ++ ;
2289+ res -> ceps ++ ;
2290+ res -> attrs ++ ;
2291+ }
2292+
21912293 if (chr -> descriptors != NULL ) {
21922294 for (d = 0 ; chr -> descriptors [d ].uuid != NULL ; d ++ ) {
21932295 if (!ble_gatts_dsc_is_sane (chr -> descriptors + d )) {
0 commit comments