From 5d0009316a1fcd16882358b6b0fcab4ea388622e 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 EATT Credit Based Flow Control Mode --- components/bt/CMakeLists.txt | 1 + components/bt/host/nimble/Kconfig.in | 7 ++ .../host/nimble/port/include/esp_nimble_cfg.h | 71 ++++++++++++++++++- examples/bluetooth/nimble/blecent/main/main.c | 70 +++++++++++++++++- examples/bluetooth/nimble/bleprph/main/main.c | 38 +++++++++- 5 files changed, 184 insertions(+), 3 deletions(-) diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index f101b517f0..e82d002709 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -620,6 +620,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" ) list(APPEND srcs diff --git a/components/bt/host/nimble/Kconfig.in b/components/bt/host/nimble/Kconfig.in index f154ae42e4..3655ded6bd 100644 --- a/components/bt/host/nimble/Kconfig.in +++ b/components/bt/host/nimble/Kconfig.in @@ -937,3 +937,10 @@ menu "BLE Services" help Defines maximum number of report characteristics per service instance 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/port/include/esp_nimble_cfg.h b/components/bt/host/nimble/port/include/esp_nimble_cfg.h index 8bbae57b44..b2b81f5d0d 100644 --- a/components/bt/host/nimble/port/include/esp_nimble_cfg.h +++ b/components/bt/host/nimble/port/include/esp_nimble_cfg.h @@ -507,6 +507,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 @@ -531,6 +535,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 @@ -547,6 +555,49 @@ #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 MYNEWT_VAL_BLE_GATT_CACHING +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_ROBUST_CACHING (1) +#else +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_ROBUST_CACHING (0) +#endif //MYNEWT_VAL_BLE_GATT_CACHING + +#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_ROBUST_CACHING | \ + 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 @@ -587,6 +638,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif @@ -713,16 +768,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 @@ -736,8 +801,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/examples/bluetooth/nimble/blecent/main/main.c b/examples/bluetooth/nimble/blecent/main/main.c index b2dc006940..41b6a6f6f9 100644 --- a/examples/bluetooth/nimble/blecent/main/main.c +++ b/examples/bluetooth/nimble/blecent/main/main.c @@ -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) > 0 +static uint16_t cids[MYNEWT_VAL(BLE_EATT_CHAN_NUM)]; +static uint16_t bearers; +#endif + void ble_store_config_init(void); /** @@ -755,6 +760,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) > 0 + /* 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; @@ -771,14 +784,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; @@ -851,6 +866,51 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) return 0; #endif +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + 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 /* MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 */ + return 0; default: return 0; } @@ -871,6 +931,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(); @@ -962,4 +1023,11 @@ app_main(void) stack_init_deinit(); #endif +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + 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 b1a5800a14..6a1526387a 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) > 0 +static uint16_t cids[MYNEWT_VAL(BLE_EATT_CHAN_NUM)]; +static uint16_t bearers; +#endif + void ble_store_config_init(void); /** @@ -418,13 +423,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) > 0 + 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 } return 0; @@ -567,4 +596,11 @@ app_main(void) if (rc != ESP_OK) { ESP_LOGE(tag, "scli_init() failed"); } + +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + bearers = 0; + for (int i = 0; i < MYNEWT_VAL(BLE_EATT_CHAN_NUM); i++) { + cids[i] = 0; + } +#endif }