This is an automated email from the ASF dual-hosted git repository. kopyscinski pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit d64581c0b1c6ec26f5df34855fe20f695199b574 Author: Krzysztof Kopyściński <[email protected]> AuthorDate: Thu Aug 3 13:50:01 2023 +0200 host/gatts: save reported Client Supported Features per connection GATT Client by writing to Client Supported Features characteristic reports to server what features it supports. These features should be saved for future use so appropriate subprocedures can be selected. --- nimble/host/include/host/ble_gatt.h | 20 +++++++++++ nimble/host/services/gatt/src/ble_svc_gatt.c | 18 +++++----- nimble/host/src/ble_gatt_priv.h | 13 +++++-- nimble/host/src/ble_gatts.c | 54 ++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 10 deletions(-) diff --git a/nimble/host/include/host/ble_gatt.h b/nimble/host/include/host/ble_gatt.h index b38dd32b..cd17cc26 100644 --- a/nimble/host/include/host/ble_gatt.h +++ b/nimble/host/include/host/ble_gatt.h @@ -1076,6 +1076,26 @@ int ble_gatts_reset(void); */ int ble_gatts_start(void); +/** + * Saves Client Supported Features for specified connection. + * + * @param conn_handle Connection handle identifying connection for + * which Client Supported Features should be saved + * @param om The mbuf chain to set value from. + * + * @return 0 on success; + * BLE_HS_ENOTCONN if no matching connection + * was found + * BLE_HS_EINVAL if supplied buffer is empty or + * if any Client Supported Feature was + * attempted to be disabled. + * A BLE host core return code on unexpected + * error. + * + */ +int ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, + struct os_mbuf *om); + #ifdef __cplusplus } #endif diff --git a/nimble/host/services/gatt/src/ble_svc_gatt.c b/nimble/host/services/gatt/src/ble_svc_gatt.c index 501164d5..54162afa 100644 --- a/nimble/host/services/gatt/src/ble_svc_gatt.c +++ b/nimble/host/services/gatt/src/ble_svc_gatt.c @@ -35,8 +35,8 @@ static uint16_t ble_svc_gatt_end_handle; #define BLE_SVC_GATT_CLI_SUP_FEAT_EATT_BIT (0x01) #define BLE_SVC_GATT_CLI_SUP_FEAT_MULT_NTF_BIT (0x02) -static uint8_t ble_svc_gatt_srv_sup_feat = 0; -static uint8_t ble_svc_gatt_cl_sup_feat = 0; +static uint8_t ble_svc_gatt_local_srv_sup_feat = 0; +static uint8_t ble_svc_gatt_local_cl_sup_feat = 0; static int ble_svc_gatt_access(uint16_t conn_handle, uint16_t attr_handle, @@ -91,7 +91,7 @@ ble_svc_gatt_srv_sup_feat_access(uint16_t conn_handle, uint16_t attr_handle, return BLE_ATT_ERR_WRITE_NOT_PERMITTED; } - os_mbuf_append(ctxt->om, &ble_svc_gatt_srv_sup_feat, sizeof(ble_svc_gatt_srv_sup_feat)); + os_mbuf_append(ctxt->om, &ble_svc_gatt_local_srv_sup_feat, sizeof(ble_svc_gatt_local_srv_sup_feat)); return 0; } @@ -106,7 +106,9 @@ ble_svc_gatt_cl_sup_feat_access(uint16_t conn_handle, uint16_t attr_handle, os_mbuf_append(ctxt->om, &eatt_supported, sizeof(eatt_supported)); return 0; } - /* TODO For write just return OK */ + if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { + return ble_gatts_peer_cl_sup_feat_update(conn_handle, ctxt->om); + } return 0; } @@ -140,7 +142,7 @@ ble_svc_gatt_access(uint16_t conn_handle, uint16_t attr_handle, uint8_t ble_svc_gatt_get_local_cl_supported_feat(void) { - return ble_svc_gatt_cl_sup_feat; + return ble_svc_gatt_local_cl_sup_feat; } /** @@ -173,14 +175,14 @@ ble_svc_gatt_init(void) SYSINIT_PANIC_ASSERT(rc == 0); if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0) { - ble_svc_gatt_srv_sup_feat |= (1 << BLE_SVC_GATT_SRV_SUP_FEAT_EATT_BIT); + ble_svc_gatt_local_srv_sup_feat |= (1 << BLE_SVC_GATT_SRV_SUP_FEAT_EATT_BIT); } if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0) { - ble_svc_gatt_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_EATT_BIT); + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_EATT_BIT); } if (MYNEWT_VAL(BLE_ATT_SVR_NOTIFY_MULTI) > 0) { - ble_svc_gatt_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_MULT_NTF_BIT); + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_MULT_NTF_BIT); } } diff --git a/nimble/host/src/ble_gatt_priv.h b/nimble/host/src/ble_gatt_priv.h index f77c78ad..ba0b8067 100644 --- a/nimble/host/src/ble_gatt_priv.h +++ b/nimble/host/src/ble_gatt_priv.h @@ -86,8 +86,9 @@ STATS_SECT_START(ble_gatts_stats) STATS_SECT_END extern STATS_SECT_DECL(ble_gatts_stats) ble_gatts_stats; -#define BLE_GATT_CHR_DECL_SZ_16 5 -#define BLE_GATT_CHR_DECL_SZ_128 19 +#define BLE_GATT_CHR_DECL_SZ_16 5 +#define BLE_GATT_CHR_DECL_SZ_128 19 +#define BLE_GATT_CHR_CLI_SUP_FEAT_SZ 1 typedef uint8_t ble_gatts_conn_flags; @@ -96,6 +97,14 @@ struct ble_gatts_conn { int num_clt_cfgs; uint16_t indicate_val_handle; + + /** + * For now only 3 bits in one octet are defined, but specification expects + * this service to be variable length with no upper bound. Let's make this + * future proof if more octets might be used. + * (Vol. 3, Part G, 7.2) + */ + uint8_t peer_cl_sup_feat[BLE_GATT_CHR_CLI_SUP_FEAT_SZ]; }; /*** @client. */ diff --git a/nimble/host/src/ble_gatts.c b/nimble/host/src/ble_gatts.c index 6732bc16..ce5f1709 100644 --- a/nimble/host/src/ble_gatts.c +++ b/nimble/host/src/ble_gatts.c @@ -1580,6 +1580,60 @@ ble_gatts_chr_updated(uint16_t chr_val_handle) } } +int +ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) +{ + struct ble_hs_conn *conn; + int rc = 0; + int feat_idx = 0; + int i; + + BLE_HS_LOG(DEBUG, ""); + + if (!om) { + return BLE_HS_EINVAL; + } + + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + if (conn == NULL) { + rc = BLE_HS_ENOTCONN; + goto done; + } + if (om->om_len == 0) { + /* Nothing to do */ + goto done; + } else if (os_mbuf_len(om) > BLE_ATT_ATTR_MAX_LEN) { + rc = BLE_HS_ENOMEM; + goto done; + } + + while(om) { + for (i = 0; i < om->om_len; i++) { + /** + * Disabling already enabled features is not permitted + * (Vol. 3, Part F, 3.3.3) + * If value of saved octet, as uint8_t, is greatet than requested + * it means more bits are set. + */ + if (conn->bhc_gatt_svr.peer_cl_sup_feat[feat_idx] > + om->om_data[i]) { + rc = BLE_HS_EINVAL; + goto done; + } + + conn->bhc_gatt_svr.peer_cl_sup_feat[feat_idx] |= om->om_data[i]; + + feat_idx++; + } + om = SLIST_NEXT(om, om_next); + } + +done: + ble_hs_unlock(); + return rc; +} + /** * Sends notifications or indications for the specified characteristic to all * connected devices. The bluetooth spec does not allow more than one
