@@ -43,6 +43,8 @@ static const ble_uuid_t *uuid_chr =
4343 BLE_UUID16_DECLARE (BLE_ATT_UUID_CHARACTERISTIC );
4444static const ble_uuid_t * uuid_ccc =
4545 BLE_UUID16_DECLARE (BLE_GATT_DSC_CLT_CFG_UUID16 );
46+ static const ble_uuid_t * uuid_cep =
47+ BLE_UUID16_DECLARE (BLE_GATT_DSC_EXT_PROP_UUID16 );
4648
4749static const struct ble_gatt_svc_def * * ble_gatts_svc_defs ;
4850static int ble_gatts_num_svc_defs ;
@@ -170,6 +172,22 @@ ble_gatts_chr_clt_cfg_allowed(const struct ble_gatt_chr_def *chr)
170172 return flags ;
171173}
172174
175+ static uint16_t
176+ ble_gatts_chr_ext_prop_allowed (const struct ble_gatt_chr_def * chr )
177+ {
178+ uint16_t flags ;
179+
180+ flags = 0 ;
181+ if (chr -> flags & BLE_GATT_CHR_F_RELIABLE_WRITE ) {
182+ flags |= BLE_GATTS_CEP_F_RELIABLE_WRITE ;
183+ }
184+ if (chr -> flags & BLE_GATT_CHR_F_AUX_WRITE ) {
185+ flags |= BLE_GATTS_CEP_F_AUX_WRITE ;
186+ }
187+
188+ return flags ;
189+ }
190+
173191static uint8_t
174192ble_gatts_att_flags_from_chr_flags (ble_gatt_chr_flags chr_flags )
175193{
@@ -820,6 +838,66 @@ ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle)
820838 return 0 ;
821839}
822840
841+ static int
842+ ble_gatts_cep_access_cb (uint16_t conn_handle , uint16_t attr_handle ,
843+ struct ble_gatt_access_ctxt * ctxt , void * arg )
844+ {
845+ uint16_t prop = POINTER_TO_UINT (arg );
846+
847+ if (ctxt -> op != BLE_GATT_ACCESS_OP_READ_DSC ) {
848+ return BLE_ATT_ERR_WRITE_NOT_PERMITTED ;
849+ }
850+
851+ os_mbuf_append (ctxt -> om , & prop , sizeof (prop ));
852+
853+ return 0 ;
854+ }
855+
856+ static int
857+ ble_gatts_cep_access (uint16_t conn_handle , uint16_t attr_handle ,
858+ uint8_t att_op , uint16_t offset , struct os_mbuf * * om ,
859+ void * arg )
860+ {
861+ struct ble_gatt_access_ctxt gatt_ctxt ;
862+ int rc ;
863+
864+ gatt_ctxt .op = ble_gatts_dsc_op (att_op );
865+
866+ ble_gatts_dsc_inc_stat (gatt_ctxt .op );
867+ rc = ble_gatts_val_access (conn_handle , attr_handle , offset , & gatt_ctxt ,
868+ om , ble_gatts_cep_access_cb , arg );
869+
870+ return rc ;
871+ }
872+
873+ static int
874+ ble_gatts_register_cep_dsc (uint16_t * att_handle , ble_gatt_chr_flags flags )
875+ {
876+ struct ble_gatt_cep_dsc cep ;
877+ int rc ;
878+
879+ cep .properties = 0x0000 ;
880+ if (flags & BLE_GATT_CHR_F_RELIABLE_WRITE ) {
881+ cep .properties |= BLE_GATTS_CEP_F_RELIABLE_WRITE ;
882+ }
883+ if (flags & BLE_GATT_CHR_F_AUX_WRITE ) {
884+ /* TODO: Implement Characteristic User Description
885+ * (Core specification 6.0, vol 3, part G, section 3.3.3.2)*/
886+ cep .properties |= BLE_GATTS_CEP_F_AUX_WRITE ;
887+ }
888+
889+ rc = ble_att_svr_register (uuid_cep , BLE_ATT_F_READ , 0 ,
890+ att_handle , ble_gatts_cep_access ,
891+ UINT_TO_POINTER (cep .properties ));
892+ if (rc != 0 ) {
893+ return rc ;
894+ }
895+
896+ STATS_INC (ble_gatts_stats , dscs );
897+
898+ return 0 ;
899+ }
900+
823901static int
824902ble_gatts_register_chr (const struct ble_gatt_svc_def * svc ,
825903 const struct ble_gatt_chr_def * chr ,
@@ -830,6 +908,7 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
830908 uint16_t def_handle ;
831909 uint16_t val_handle ;
832910 uint16_t dsc_handle ;
911+ uint16_t cep_handle ;
833912 uint8_t att_flags ;
834913 int rc ;
835914
@@ -886,6 +965,14 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
886965 BLE_HS_DBG_ASSERT (dsc_handle == def_handle + 2 );
887966 }
888967
968+ if (ble_gatts_chr_ext_prop_allowed (chr ) != 0 ) {
969+ rc = ble_gatts_register_cep_dsc (& cep_handle , chr -> flags );
970+ if (rc != 0 ) {
971+ return rc ;
972+ }
973+ BLE_HS_DBG_ASSERT (cep_handle == def_handle + 3 );
974+ }
975+
889976 /* Register each descriptor. */
890977 if (chr -> descriptors != NULL ) {
891978 for (dsc = chr -> descriptors ; dsc -> uuid != NULL ; dsc ++ ) {
@@ -2222,6 +2309,21 @@ ble_gatts_count_resources(const struct ble_gatt_svc_def *svcs,
22222309 res -> attrs ++ ;
22232310 }
22242311
2312+ /* If the characteristic permits reliable writes or auxiliary
2313+ * writes, it has an Extended Properties descriptor.
2314+ */
2315+ if (chr -> flags & BLE_GATT_CHR_F_AUX_WRITE ||
2316+ chr -> flags & BLE_GATT_CHR_F_RELIABLE_WRITE ) {
2317+
2318+ /* Each CEP requires:
2319+ * o 1 descriptor
2320+ * o 1 attribute
2321+ */
2322+ res -> dscs ++ ;
2323+ res -> ceps ++ ;
2324+ res -> attrs ++ ;
2325+ }
2326+
22252327 if (chr -> descriptors != NULL ) {
22262328 for (d = 0 ; chr -> descriptors [d ].uuid != NULL ; d ++ ) {
22272329 if (!ble_gatts_dsc_is_sane (chr -> descriptors + d )) {
0 commit comments