@@ -39,6 +39,8 @@ static const ble_uuid_t *uuid_chr =
3939 BLE_UUID16_DECLARE (BLE_ATT_UUID_CHARACTERISTIC );
4040static const ble_uuid_t * uuid_ccc =
4141 BLE_UUID16_DECLARE (BLE_GATT_DSC_CLT_CFG_UUID16 );
42+ static const ble_uuid_t * uuid_cep =
43+ BLE_UUID16_DECLARE (BLE_GATT_DSC_EXT_PROP_UUID16 );
4244
4345static const struct ble_gatt_svc_def * * ble_gatts_svc_defs ;
4446static int ble_gatts_num_svc_defs ;
@@ -154,6 +156,22 @@ ble_gatts_chr_clt_cfg_allowed(const struct ble_gatt_chr_def *chr)
154156 return flags ;
155157}
156158
159+ static uint16_t
160+ ble_gatts_chr_ext_prop_allowed (const struct ble_gatt_chr_def * chr )
161+ {
162+ uint16_t flags ;
163+
164+ flags = 0 ;
165+ if (chr -> flags & BLE_GATT_CHR_F_RELIABLE_WRITE ) {
166+ flags |= BLE_GATTS_CEP_F_RELIABLE_WRITE ;
167+ }
168+ if (chr -> flags & BLE_GATT_CHR_F_AUX_WRITE ) {
169+ flags |= BLE_GATTS_CEP_F_AUX_WRITE ;
170+ }
171+
172+ return flags ;
173+ }
174+
157175static uint8_t
158176ble_gatts_att_flags_from_chr_flags (ble_gatt_chr_flags chr_flags )
159177{
@@ -804,6 +822,66 @@ ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle)
804822 return 0 ;
805823}
806824
825+ static int
826+ ble_gatts_cep_access_cb (uint16_t conn_handle , uint16_t attr_handle ,
827+ struct ble_gatt_access_ctxt * ctxt , void * arg )
828+ {
829+ uint16_t prop = POINTER_TO_UINT (arg );
830+
831+ if (ctxt -> op != BLE_GATT_ACCESS_OP_READ_DSC ) {
832+ return BLE_ATT_ERR_WRITE_NOT_PERMITTED ;
833+ }
834+
835+ os_mbuf_append (ctxt -> om , & prop , sizeof (prop ));
836+
837+ return 0 ;
838+ }
839+
840+ static int
841+ ble_gatts_cep_access (uint16_t conn_handle , uint16_t attr_handle ,
842+ uint8_t att_op , uint16_t offset , struct os_mbuf * * om ,
843+ void * arg )
844+ {
845+ struct ble_gatt_access_ctxt gatt_ctxt ;
846+ int rc ;
847+
848+ gatt_ctxt .op = ble_gatts_dsc_op (att_op );
849+
850+ ble_gatts_dsc_inc_stat (gatt_ctxt .op );
851+ rc = ble_gatts_val_access (conn_handle , attr_handle , offset , & gatt_ctxt ,
852+ om , ble_gatts_cep_access_cb , arg );
853+
854+ return rc ;
855+ }
856+
857+ static int
858+ ble_gatts_register_cep_dsc (uint16_t * att_handle , ble_gatt_chr_flags flags )
859+ {
860+ struct ble_gatt_cep_dsc cep ;
861+ int rc ;
862+
863+ cep .properties = 0x0000 ;
864+ if (flags & BLE_GATT_CHR_F_RELIABLE_WRITE ) {
865+ cep .properties |= BLE_GATTS_CEP_F_RELIABLE_WRITE ;
866+ }
867+ if (flags & BLE_GATT_CHR_F_AUX_WRITE ) {
868+ /* TODO: Implement Characteristic User Description
869+ * (Core specification 6.0, vol 3, part G, section 3.3.3.2)*/
870+ cep .properties |= BLE_GATTS_CEP_F_AUX_WRITE ;
871+ }
872+
873+ rc = ble_att_svr_register (uuid_cep , BLE_ATT_F_READ , 0 ,
874+ att_handle , ble_gatts_cep_access ,
875+ UINT_TO_POINTER (cep .properties ));
876+ if (rc != 0 ) {
877+ return rc ;
878+ }
879+
880+ STATS_INC (ble_gatts_stats , dscs );
881+
882+ return 0 ;
883+ }
884+
807885static int
808886ble_gatts_register_chr (const struct ble_gatt_svc_def * svc ,
809887 const struct ble_gatt_chr_def * chr ,
@@ -814,6 +892,7 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
814892 uint16_t def_handle ;
815893 uint16_t val_handle ;
816894 uint16_t dsc_handle ;
895+ uint16_t cep_handle ;
817896 uint8_t att_flags ;
818897 int rc ;
819898
@@ -870,6 +949,14 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
870949 BLE_HS_DBG_ASSERT (dsc_handle == def_handle + 2 );
871950 }
872951
952+ if (ble_gatts_chr_ext_prop_allowed (chr ) != 0 ) {
953+ rc = ble_gatts_register_cep_dsc (& cep_handle , chr -> flags );
954+ if (rc != 0 ) {
955+ return rc ;
956+ }
957+ BLE_HS_DBG_ASSERT (cep_handle == def_handle + 3 );
958+ }
959+
873960 /* Register each descriptor. */
874961 if (chr -> descriptors != NULL ) {
875962 for (dsc = chr -> descriptors ; dsc -> uuid != NULL ; dsc ++ ) {
@@ -2172,6 +2259,21 @@ ble_gatts_count_resources(const struct ble_gatt_svc_def *svcs,
21722259 res -> attrs ++ ;
21732260 }
21742261
2262+ /* If the characteristic permits reliable writes or auxiliary
2263+ * writes, it has an Extended Properties descriptor.
2264+ */
2265+ if (chr -> flags & BLE_GATT_CHR_F_AUX_WRITE ||
2266+ chr -> flags & BLE_GATT_CHR_F_RELIABLE_WRITE ) {
2267+
2268+ /* Each CEP requires:
2269+ * o 1 descriptor
2270+ * o 1 attribute
2271+ */
2272+ res -> dscs ++ ;
2273+ res -> ceps ++ ;
2274+ res -> attrs ++ ;
2275+ }
2276+
21752277 if (chr -> descriptors != NULL ) {
21762278 for (d = 0 ; chr -> descriptors [d ].uuid != NULL ; d ++ ) {
21772279 if (!ble_gatts_dsc_is_sane (chr -> descriptors + d )) {
0 commit comments