From f265e50ca0fc4557ca6acf6c848a77bb95b0ef41 Mon Sep 17 00:00:00 2001 From: Sumeet Singh Date: Fri, 29 Mar 2024 12:41:18 +0530 Subject: [PATCH] feat(nimble): Added support for Enhanced ATT or ATT over Enhanced L2CAP Credit Based Flow Control Mode --- components/bt/CMakeLists.txt | 1 + components/bt/host/nimble/Kconfig.in | 7 ++ components/bt/host/nimble/nimble | 2 +- .../host/nimble/port/include/esp_nimble_cfg.h | 62 ++++++++++++++- .../nimble/include/nimble/nimble_opt_auto.h | 4 + examples/bluetooth/nimble/blecent/main/main.c | 79 +++++++++++++++++-- examples/bluetooth/nimble/bleprph/main/main.c | 38 ++++++++- 7 files changed, 185 insertions(+), 8 deletions(-) diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index d32a6d372c..69a0d13ec0 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -712,6 +712,7 @@ if(CONFIG_BT_ENABLED) "host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c" "host/nimble/nimble/nimble/host/src/ble_gattc_cache.c" "host/nimble/nimble/nimble/host/src/ble_gattc_cache_conn.c" + "host/nimble/nimble/nimble/host/src/ble_eatt.c" ) if(CONFIG_BT_CONTROLLER_DISABLED AND CONFIG_BT_NIMBLE_TRANSPORT_UART) diff --git a/components/bt/host/nimble/Kconfig.in b/components/bt/host/nimble/Kconfig.in index d02293a87a..598b67aa1c 100644 --- a/components/bt/host/nimble/Kconfig.in +++ b/components/bt/host/nimble/Kconfig.in @@ -1048,3 +1048,10 @@ menu "Host-controller Transport" help UART HCI CTS pin endmenu + +config BT_NIMBLE_EATT_CHAN_NUM + int "Maximum number of EATT channels" + default 0 + depends on BT_NIMBLE_ENABLED + help + Defines the number of channels EATT bearers can use diff --git a/components/bt/host/nimble/nimble b/components/bt/host/nimble/nimble index 5a1245bcaa..1be1f55eaa 160000 --- a/components/bt/host/nimble/nimble +++ b/components/bt/host/nimble/nimble @@ -1 +1 @@ -Subproject commit 5a1245bcaad3899a74a5a54ac98a7456f7bec9c8 +Subproject commit 1be1f55eaaf32e6499e707ea284d65eb3164e98c diff --git a/components/bt/host/nimble/port/include/esp_nimble_cfg.h b/components/bt/host/nimble/port/include/esp_nimble_cfg.h index d2fa333886..c37c5a91a9 100644 --- a/components/bt/host/nimble/port/include/esp_nimble_cfg.h +++ b/components/bt/host/nimble/port/include/esp_nimble_cfg.h @@ -543,6 +543,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (1) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -567,6 +571,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_MULT_VAR +#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT_VAR (1) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE #define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1) #endif @@ -583,6 +591,40 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (CONFIG_BT_NIMBLE_EATT_CHAN_NUM) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + +#ifndef MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES +#if CONFIG_BT_NIMBLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_EATT (2) +#else +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_EATT (0) +#endif //CONFIG_BT_NIMBLE_EATT_CHAN_NUM + +#if MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_NOTIFY_MULTI (4) +#else +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_NOTIFY_MULTI (0) +#endif //MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES ( \ + MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_EATT | \ + MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_NOTIFY_MULTI \ + ) +#endif //MYNEWT_VAL_CLIENT_SUPPORTED_FEATURES + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -623,6 +665,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_MULTI_NOTIFY +#define MYNEWT_VAL_BLE_GATT_MULTI_NOTIFY (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif @@ -749,16 +795,26 @@ #define MYNEWT_VAL_BLE_HS_SYSINIT_STAGE (200) #endif +#if CONFIG_BT_NIMBLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (CONFIG_BT_NIMBLE_EATT_CHAN_NUM) +#else #ifndef CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM #define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (2) #else #define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM -#endif +#endif //CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#endif //CONFIG_BT_NIMBLE_EATT_CHAN_NUM #ifndef MYNEWT_VAL_BLE_L2CAP_COC_MPS #define MYNEWT_VAL_BLE_L2CAP_COC_MPS (MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8) #endif +#if CONFIG_BT_NIMBLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC (1) +#else +#define MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC (0) +#endif + #ifndef MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS #define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1) #endif @@ -772,8 +828,12 @@ #endif #ifndef MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS +#ifdef CONFIG_BT_NIMBLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (CONFIG_BT_NIMBLE_EATT_CHAN_NUM) +#else #define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1) #endif +#endif #ifndef MYNEWT_VAL_BLE_MESH #ifdef CONFIG_BT_NIMBLE_MESH diff --git a/components/bt/porting/nimble/include/nimble/nimble_opt_auto.h b/components/bt/porting/nimble/include/nimble/nimble_opt_auto.h index c4baec843b..7974fb231b 100644 --- a/components/bt/porting/nimble/include/nimble/nimble_opt_auto.h +++ b/components/bt/porting/nimble/include/nimble/nimble_opt_auto.h @@ -120,6 +120,10 @@ extern "C" { #define NIMBLE_BLE_ATT_CLT_INDICATE \ (MYNEWT_VAL(BLE_GATT_INDICATE)) +#undef NIMBLE_BLE_ATT_CLT_MULTI_NOTIFY +#define NIMBLE_BLE_ATT_CLT_MULTI_NOTIFY \ + (MYNEWT_VAL(BLE_GATT_MULTI_NOTIFY)) + /** Security manager settings. */ #undef NIMBLE_BLE_SM diff --git a/examples/bluetooth/nimble/blecent/main/main.c b/examples/bluetooth/nimble/blecent/main/main.c index ef62105893..adfde26b01 100644 --- a/examples/bluetooth/nimble/blecent/main/main.c +++ b/examples/bluetooth/nimble/blecent/main/main.c @@ -48,7 +48,7 @@ #endif #endif -/*** The UUID of the service containing the subscribable characterstic ***/ +/*** The UUID of the service containing the subscribable characteristic ***/ static const ble_uuid_t * remote_svc_uuid = BLE_UUID128_DECLARE(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12, 0x99, 0x99, 0x43, 0x95, 0x12, 0x2f, 0x46, 0x59); @@ -62,6 +62,11 @@ static const char *tag = "NimBLE_BLE_CENT"; static int blecent_gap_event(struct ble_gap_event *event, void *arg); static uint8_t peer_addr[6]; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) +static uint16_t cids[MYNEWT_VAL(BLE_EATT_CHAN_NUM)]; +static uint16_t bearers; +#endif + void ble_store_config_init(void); /** @@ -203,7 +208,7 @@ blecent_custom_gatt_operations(const struct peer* peer) remote_chr_uuid, BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16)); if (dsc == NULL) { - MODLOG_DFLT(ERROR, "Error: Peer lacks a CCCD for the subscribable characterstic\n"); + MODLOG_DFLT(ERROR, "Error: Peer lacks a CCCD for the subscribable characteristic\n"); goto err; } @@ -687,7 +692,7 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) return 0; } - /* An advertisment report was received during GAP discovery. */ + /* An advertisement report was received during GAP discovery. */ print_adv_fields(&fields); /* Try to connect to the advertiser if it looks interesting. */ @@ -773,6 +778,14 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) /* Forget about peer. */ peer_delete(event->disconnect.conn.conn_handle); +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) + /* Reset EATT config */ + bearers = 0; + for (int i = 0; i < MYNEWT_VAL(BLE_EATT_CHAN_NUM); i++) { + cids[i] = 0; + } +#endif + /* Resume scanning. */ blecent_scan(); return 0; @@ -789,14 +802,16 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc); assert(rc == 0); print_conn_desc(&desc); +#if !MYNEWT_VAL(BLE_EATT_CHAN_NUM) #if CONFIG_EXAMPLE_ENCRYPTION /*** Go for service discovery after encryption has been successfully enabled ***/ - rc = peer_disc_all(event->connect.conn_handle, + rc = peer_disc_all(event->enc_change.conn_handle, blecent_on_disc_complete, NULL); if (rc != 0) { MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); return 0; } +#endif #endif return 0; @@ -840,7 +855,7 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) #if CONFIG_EXAMPLE_EXTENDED_ADV case BLE_GAP_EVENT_EXT_DISC: - /* An advertisment report was received during GAP discovery. */ + /* An advertisement report was received during GAP discovery. */ ext_print_adv_report(&event->disc); blecent_connect_if_interesting(&event->disc); @@ -868,6 +883,52 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) event->pathloss_threshold.zone_entered); return 0; #endif + +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) + case BLE_GAP_EVENT_EATT: + int i; + MODLOG_DFLT(INFO, "EATT %s : conn_handle=%d cid=%d", + event->eatt.status ? "disconnected" : "connected", + event->eatt.conn_handle, + event->eatt.cid); + if (event->eatt.status) { + /* Remove CID from the list of saved CIDs */ + for (i = 0; i < bearers; i++) { + if (cids[i] == event->eatt.cid) { + break; + } + } + while (i < (bearers - 1)) { + cids[i] = cids[i + 1]; + i += 1; + } + cids[i] = 0; + + /* Now Abort */ + return 0; + } + cids[bearers] = event->eatt.cid; + bearers += 1; + if (bearers != MYNEWT_VAL(BLE_EATT_CHAN_NUM)) { + /* Wait until all EATT bearers are connected before proceeding */ + return 0; + } + /* Set the default bearer to use for further procedures */ + rc = ble_att_set_default_bearer_using_cid(event->eatt.conn_handle, cids[0]); + if (rc != 0) { + MODLOG_DFLT(INFO, "Cannot set default EATT bearer, rc = %d\n", rc); + return rc; + } + + /* Perform service discovery */ + rc = peer_disc_all(event->eatt.conn_handle, + blecent_on_disc_complete, NULL); + if(rc != 0) { + MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); + return 0; + } +#endif + return 0; default: return 0; } @@ -888,6 +949,7 @@ blecent_on_sync(void) rc = ble_hs_util_ensure_addr(0); assert(rc == 0); + #if !CONFIG_EXAMPLE_INIT_DEINIT_LOOP /* Begin scanning for a peripheral to connect to. */ blecent_scan(); @@ -979,4 +1041,11 @@ app_main(void) stack_init_deinit(); #endif +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) + bearers = 0; + for (int i = 0; i < MYNEWT_VAL(BLE_EATT_CHAN_NUM); i++) { + cids[i] = 0; + } +#endif + } diff --git a/examples/bluetooth/nimble/bleprph/main/main.c b/examples/bluetooth/nimble/bleprph/main/main.c index d86364c41c..838581c320 100644 --- a/examples/bluetooth/nimble/bleprph/main/main.c +++ b/examples/bluetooth/nimble/bleprph/main/main.c @@ -45,6 +45,11 @@ static uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM; static uint8_t own_addr_type; #endif +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) +static uint16_t cids[MYNEWT_VAL(BLE_EATT_CHAN_NUM)]; +static uint16_t bearers; +#endif + void ble_store_config_init(void); /** @@ -416,13 +421,37 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg) event->transmit_power.delta); return 0; - case BLE_GAP_EVENT_PATHLOSS_THRESHOLD: + case BLE_GAP_EVENT_PATHLOSS_THRESHOLD: MODLOG_DFLT(INFO, "Pathloss threshold event : conn_handle=%d current path loss=%d " "zone_entered =%d", event->pathloss_threshold.conn_handle, event->pathloss_threshold.current_path_loss, event->pathloss_threshold.zone_entered); return 0; +#endif +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) + case BLE_GAP_EVENT_EATT: + MODLOG_DFLT(INFO, "EATT %s : conn_handle=%d cid=%d", + event->eatt.status ? "disconnected" : "connected", + event->eatt.conn_handle, + event->eatt.cid); + if (event->eatt.status) { + /* Abort if disconnected */ + return 0; + } + cids[bearers] = event->eatt.cid; + bearers += 1; + if (bearers != MYNEWT_VAL(BLE_EATT_CHAN_NUM)) { + /* Wait until all EATT bearers are connected before proceeding */ + return 0; + } + /* Set the default bearer to use for further procedures */ + rc = ble_att_set_default_bearer_using_cid(event->eatt.conn_handle, cids[0]); + if (rc != 0) { + MODLOG_DFLT(INFO, "Cannot set default EATT bearer, rc = %d\n", rc); + return rc; + } + return 0; #endif } @@ -566,4 +595,11 @@ app_main(void) if (rc != ESP_OK) { ESP_LOGE(tag, "scli_init() failed"); } + +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) + bearers = 0; + for (int i = 0; i < MYNEWT_VAL(BLE_EATT_CHAN_NUM); i++) { + cids[i] = 0; + } +#endif }