From db2f236ec106d4dff8f282e28acc6f6798e3cfdb Mon Sep 17 00:00:00 2001 From: Astha Verma Date: Mon, 30 Jun 2025 11:45:02 +0530 Subject: [PATCH] fix(nimble): Added missing api in nimble which is present in bluedroid --- nimble/host/include/host/ble_gap.h | 36 ++++++ nimble/host/include/host/ble_gatt.h | 30 +++++ nimble/host/src/ble_gap.c | 20 ++++ nimble/host/src/ble_gap_priv.h | 3 + nimble/host/src/ble_gattc.c | 154 +++++++++++++++++++++++++ nimble/host/src/ble_gattc_cache.c | 111 +++++++++++++++++- nimble/host/src/ble_gattc_cache_conn.c | 142 +++++++++++++++++++++++ nimble/host/src/ble_gattc_cache_priv.h | 13 +++ 8 files changed, 507 insertions(+), 2 deletions(-) diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index 9f633865b..e48ea82bd 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -171,6 +171,7 @@ struct hci_conn_update; #define BLE_GAP_EVENT_PER_SUBEV_DATA_REQ 40 #define BLE_GAP_EVENT_PER_SUBEV_RESP 41 #define BLE_GAP_EVENT_PERIODIC_TRANSFER_V2 42 +#define BLE_GAP_EVENT_CACHE_ASSOC 43 /* ISO events */ #define BLE_GAP_EVENT_CIS_ESTAB 43 @@ -876,6 +877,41 @@ struct ble_gap_event { uint16_t conn_handle; } passkey; +#if MYNEWT_VAL(BLE_GATT_CACHING_ASSOC_ENABLE) + /** + * Represents an attempt to associate the cached attribute data of a peer + * device with the data already stored on the host. This is typically done + * after a connection is established to avoid full service discovery if + * valid cached data is available. + * + * If the association is successful, `cache_state` will be set to + * CACHE_LOADED, indicating that the cached attributes can be used. + * If the association fails, `cache_state` will be set to CACHE_INVALID, + * meaning the cache is unusable and full discovery may be required. + * + * Valid for the following event types: + * o BLE_GAP_EVENT_CACHE_ASSOC + */ + struct { + /** + * Indicates the result of the cache association attempt; + * o 0: association successful; + * o BLE host error code: association failed for the specified reason. + */ + int status; + + /** The handle of the relevant connection. */ + uint16_t conn_handle; + + /** + * Represents the state of the cache: + * o CACHE_LOADED : Cache successfully loaded + * o CACHE_INVALID : Cache invalid or unavailable + */ + uint8_t cache_state; + } cache_assoc; +#endif + /** * Represents a received ATT notification or indication. * diff --git a/nimble/host/include/host/ble_gatt.h b/nimble/host/include/host/ble_gatt.h index c2a378c2f..961f190b4 100644 --- a/nimble/host/include/host/ble_gatt.h +++ b/nimble/host/include/host/ble_gatt.h @@ -949,6 +949,36 @@ int ble_gatts_notify(uint16_t conn_handle, uint16_t chr_val_handle); */ int ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle); +/** + * Unregisters for notifications on a specified characteristic by writing to its + * Client Characteristic Configuration Descriptor (CCCD). + * + * This function initiates discovery of all descriptors associated with the given + * characteristic value handle (`char_val_handle`). If a CCCD is found, it writes + * a value to disable notifications. + * + * @param conn_handle The handle of the connection with the peer device. + * @param char_val_handle The value handle of the characteristic to unregister from notification. + * + * @return 0 on success, non-zero error code on failure. + */ +int ble_gattc_unregister_for_notification(uint16_t conn_handle, uint16_t char_val_handle); + +/** + * Registers for notifications on a specified characteristic by writing to its + * Client Characteristic Configuration Descriptor (CCCD). + * + * This function initiates discovery of all descriptors associated with the given + * characteristic value handle (`char_val_handle`). If a CCCD is found, it writes + * the appropriate value to enable notifications. + * + * @param conn_handle The handle of the connection with the peer device. + * @param char_val_handle The value handle of the characteristic to register for notification. + * + * @return 0 on success, non-zero error code on failure. + */ +int ble_gattc_register_for_notification(uint16_t conn_handle, uint16_t char_val_handle); + /** * Sends a "free-form" characteristic indication. The provided mbuf contains * the indication payload. This function consumes the supplied mbuf regardless diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 07f0aa03b..40eb0a44d 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -8885,6 +8885,26 @@ ble_gap_pairing_complete_event(uint16_t conn_handle, int status) ble_gap_call_conn_event_cb(&event, conn_handle); #endif } +/***************************************************************************** + * $cache * + *****************************************************************************/ +#if MYNEWT_VAL(BLE_GATT_CACHING_ASSOC_ENABLE) +void +ble_gap_assoc_event(uint16_t conn_handle, int status, uint8_t cache_state) +{ +#if NIMBLE_BLE_CONNECT + struct ble_gap_event event; + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_CACHE_ASSOC; + event.cache_assoc.conn_handle = conn_handle; + event.cache_assoc.status = status; + event.cache_assoc.cache_state = cache_state; + + ble_gap_call_conn_event_cb(&event, conn_handle); +#endif +} +#endif /***************************************************************************** * $rssi * diff --git a/nimble/host/src/ble_gap_priv.h b/nimble/host/src/ble_gap_priv.h index f59c8763e..b76430c2e 100644 --- a/nimble/host/src/ble_gap_priv.h +++ b/nimble/host/src/ble_gap_priv.h @@ -159,6 +159,9 @@ void ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored, int bonded); void ble_gap_passkey_event(uint16_t conn_handle, struct ble_gap_passkey_params *passkey_params); +#if MYNEWT_VAL(BLE_GATT_CACHING_ASSOC_ENABLE) +void ble_gap_assoc_event(uint16_t conn_handle, int status, uint8_t cache_state); +#endif void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle, struct os_mbuf *om, int is_indication); void ble_gap_notify_tx_event(int status, uint16_t conn_handle, diff --git a/nimble/host/src/ble_gattc.c b/nimble/host/src/ble_gattc.c index 10b252159..0e6e29b65 100644 --- a/nimble/host/src/ble_gattc.c +++ b/nimble/host/src/ble_gattc.c @@ -269,6 +269,7 @@ static ble_gattc_err_fn ble_gattc_read_mult_var_err; static ble_gattc_err_fn ble_gattc_write_err; static ble_gattc_err_fn ble_gattc_write_long_err; static ble_gattc_err_fn ble_gattc_write_reliable_err; +static bool gatt_proc_active = false; #endif #if MYNEWT_VAL(BLE_GATTS) @@ -5344,6 +5345,159 @@ ble_gattc_notify_custom(uint16_t conn_handle, uint16_t chr_val_handle, { return ble_gatts_notify_custom(conn_handle, chr_val_handle, txom); } + +static int +ble_gattc_cccd_write_complete_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, + void *arg) +{ + BLE_HS_LOG(INFO, + "CCCD write : " + "status=%d conn_handle=%d attr_handle=%d", + error->status, conn_handle, attr->handle); + + return 0; +} + +static int ble_gattc_cccd_register_cb(uint16_t conn_handle, const struct ble_gatt_error *error, + uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, + void *arg) +{ + int rc = error->status; + bool *cccd_reg_flag = (bool *)arg; + + if (error->status == BLE_HS_EDONE) { + /* GATT procedure completed reset active flag */ + gatt_proc_active = false; + if (cccd_reg_flag) { + free(cccd_reg_flag); + } + } else if (error->status == 0) { + if (cccd_reg_flag && *cccd_reg_flag && + (ble_uuid_cmp(&dsc->uuid.u, BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16)) == 0)) { + /* Prevent duplicate CCCD writes */ + *cccd_reg_flag = false; + /* Enable notification */ + uint8_t cccd_val[2] = {0x01, 0x00}; + + /* write to CCCD to enable notifications */ + rc = ble_gattc_write_flat(conn_handle, + dsc->handle, + cccd_val, sizeof(cccd_val), + ble_gattc_cccd_write_complete_cb, NULL); + if (rc != 0) { + BLE_HS_LOG(WARN, "Failed to Register for Notification, status = %d", rc); + } + } + } else { + BLE_HS_LOG(WARN, "GATT descriptor discovery failed with status = %d", error->status); + gatt_proc_active = false; + if (cccd_reg_flag) { + free(cccd_reg_flag); + } + } + + return rc; +} + +int ble_gattc_register_for_notification(uint16_t conn_handle, uint16_t char_val_handle) +{ + /* Check if a GATT procedure is already active */ + if (gatt_proc_active) { + BLE_HS_LOG(WARN, "Gatt procedure active; cannot start new process."); + return BLE_HS_EBUSY; + } + + bool *cccd_reg_flag = (bool *)malloc(sizeof(bool)); + if (!cccd_reg_flag) { + BLE_HS_LOG(ERROR, "Failed to allocate memory for CCCD Reg Flag."); + return BLE_HS_ENOMEM; + } + + *cccd_reg_flag = true; + /* Mark that a GATT procedure is now active */ + gatt_proc_active = true; + + int rc = ble_gattc_disc_all_dscs(conn_handle, char_val_handle, 0xffff, + ble_gattc_cccd_register_cb, cccd_reg_flag); + if (rc != 0) { + gatt_proc_active = false; + free(cccd_reg_flag); + } + + return rc; +} + +static int ble_gattc_cccd_unregister_cb(uint16_t conn_handle, const struct ble_gatt_error *error, + uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, + void *arg) +{ + int rc = error->status; + bool *cccd_unreg_flag = (bool *)arg; + + if (error->status == BLE_HS_EDONE) { + /* GATT procedure completed reset active flag */ + gatt_proc_active = false; + if (cccd_unreg_flag) { + free(cccd_unreg_flag); + } + } else if (error->status == 0) { + if (cccd_unreg_flag && *cccd_unreg_flag && + (ble_uuid_cmp(&dsc->uuid.u, BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16)) == 0)) { + /* Prevent duplicate CCCD writes */ + *cccd_unreg_flag = false; + /* Disable notification or indication */ + uint8_t cccd_val[2] = {0x00, 0x00}; + + /* write to CCCD to disable notifications or indication */ + rc = ble_gattc_write_flat(conn_handle, + dsc->handle, + cccd_val, sizeof(cccd_val), + ble_gattc_cccd_write_complete_cb, NULL); + if (rc != 0) { + BLE_HS_LOG(WARN, "Failed to Unregister for Notification, status = %d", rc); + } + } + } else { + BLE_HS_LOG(WARN, "GATT descriptor discovery failed with status = %d", error->status); + gatt_proc_active = false; + if (cccd_unreg_flag) { + free(cccd_unreg_flag); + } + } + + return rc; +} + + +int ble_gattc_unregister_for_notification(uint16_t conn_handle, uint16_t char_val_handle) +{ + if (gatt_proc_active) { + BLE_HS_LOG(WARN, "Gatt procedure active; cannot start new process"); + return BLE_HS_EBUSY; + } + + int rc; + bool *cccd_unreg_flag = (bool *)malloc(sizeof(bool)); + + if (!cccd_unreg_flag) { + BLE_HS_LOG(ERROR, "Failed to allocate memory for CCCD Reg Flag"); + return BLE_HS_ENOMEM; + } + + *cccd_unreg_flag = true; + gatt_proc_active = true; + + rc = ble_gattc_disc_all_dscs(conn_handle, char_val_handle, 0xFFFF, + ble_gattc_cccd_unregister_cb, cccd_unreg_flag); + if (rc != 0) { + gatt_proc_active = false; + free(cccd_unreg_flag); + } + + return rc; +} #endif int diff --git a/nimble/host/src/ble_gattc_cache.c b/nimble/host/src/ble_gattc_cache.c index 497393c33..45ddca94f 100644 --- a/nimble/host/src/ble_gattc_cache.c +++ b/nimble/host/src/ble_gattc_cache.c @@ -261,6 +261,30 @@ ble_gattc_cache_find_addr(ble_addr_t addr) return INVALID_ADDR_NUM; } +void ble_gattc_cache_get_addr_list(ble_addr_t *addr_list, uint8_t *out_num) +{ + uint8_t num = cache_env->num_addr; + + if (addr_list == NULL || out_num == NULL) { + BLE_HS_LOG(WARN, "Invalid input to ble_gattc_cache_get_addr_list."); + return; + } + + for (uint8_t i = 0; i < num; i++) { + memcpy(&addr_list[i], &cache_env->cache_addr[i].addr, sizeof(ble_addr_t)); + } + + *out_num = num; + + BLE_HS_LOG(DEBUG, "Total %d addresses in cache (each %u bytes):", num, (unsigned int)sizeof(ble_addr_t)); + for (uint8_t i = 0; i < num; i++) { + ble_addr_t *addr = &addr_list[i]; + BLE_HS_LOG(DEBUG, "[%d] Addr: %02x:%02x:%02x:%02x:%02x:%02x, type: %d\n", i, + addr->val[5], addr->val[4], addr->val[3], + addr->val[2], addr->val[1], addr->val[0], addr->type); + } +} + static uint8_t ble_gattc_cache_find_hash(uint8_t * hash_key) { @@ -330,7 +354,7 @@ static void ble_gattc_fill_nv_attr(struct ble_gattc_cache_conn *peer, size_t num_attr, struct ble_gatt_nv_attr *nv_attr) { struct ble_gattc_cache_conn_svc *svc; -#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) struct ble_gattc_cache_conn_incl_svc *included_svc; #endif struct ble_gattc_cache_conn_chr *chr; @@ -626,6 +650,89 @@ ble_gattc_add_dsc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_at nimble_platform_mem_free(gatt_dsc); return rc; } +#if MYNEWT_VAL(BLE_GATT_CACHING_ASSOC_ENABLE) +int +ble_gattc_cache_assoc_load(ble_addr_t src_addr, uint8_t src_index, ble_addr_t assoc_addr) +{ + int rc = 0; + int num_attr = 50; + struct ble_gatt_nv_attr *nv_attr; + + if (!cacheOpen(src_addr, true, &src_index)) { + BLE_HS_LOG(INFO, "gattc cache open fail for src addr"); + return BLE_HS_EINVAL; + } + + /* Load the GATT attributes stored at src_index */ + nv_attr = ble_gattc_cache_load_nv_attr(src_index, &num_attr); + if (nv_attr == NULL) { + BLE_HS_LOG(ERROR, "Failed to load nv_attr from source index %d", src_index); + return BLE_HS_EINVAL; + } + + /* Load each attribute from the source into the associated address */ + for (int i = 0; i < num_attr; i++) { + switch (nv_attr[i].attr_type) { + case BLE_GATT_ATTR_TYPE_SRVC: + rc = ble_gattc_add_svc_from_cache(assoc_addr, nv_attr[i]); + break; + + case BLE_GATT_ATTR_TYPE_CHAR: + rc = ble_gattc_add_chr_from_cache(assoc_addr, nv_attr[i]); + break; + + case BLE_GATT_ATTR_TYPE_CHAR_DESCR: + rc = ble_gattc_add_dsc_from_cache(assoc_addr, nv_attr[i]); + break; + +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + case BLE_GATT_ATTR_TYPE_INCL_SRVC: + rc = ble_gattc_add_inc_from_cache(assoc_addr, nv_attr[i]); + break; +#endif + + default: + break; + } + } + + nimble_platform_mem_free(nv_attr); + + /* Copy the database hash from src_addr entry and associate it with assoc_addr */ + ble_gattc_cache_conn_load_hash(assoc_addr, + cache_env->cache_addr[src_index].hash_key); + + BLE_HS_LOG(DEBUG, "Successfully associated cache from src_addr to assoc_addr."); + return 0; +} + +int +ble_gattc_cache_find_source(struct ble_gattc_cache_conn *cache_conn, uint8_t *database_hash) +{ + uint8_t addr_index = 0; + uint8_t num = cache_env->num_addr; + cache_addr_info_t *addr_info = &cache_env->cache_addr[0]; + int rc = ESP_FAIL; + + /* Iterate through all cached addresses to find a matching database hash */ + for (addr_index = 0; addr_index < num; addr_index++, addr_info++) { + /* Compare stored hash with the provided database_hash */ + if (!memcmp(&addr_info->hash_key, database_hash, sizeof(uint8_t) * 16)) { + rc = ble_gattc_cache_assoc_load(addr_info->addr, addr_index, cache_conn->ble_gattc_cache_conn_addr); + if (rc == 0) { + cache_conn->cache_state = CACHE_LOADED; + cache_conn->assoc_success = 1; + BLE_HS_LOG(INFO, "Cache successfully loaded from src"); + break; + } + } + } + + ble_gap_assoc_event(cache_conn->conn_handle, rc, cache_conn->cache_state); + return rc; +} +#endif + int ble_gattc_cache_load(ble_addr_t peer_addr) @@ -660,7 +767,7 @@ ble_gattc_cache_load(ble_addr_t peer_addr) rc = ble_gattc_add_dsc_from_cache(peer_addr, nv_attr[i]); break; -#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) case BLE_GATT_ATTR_TYPE_INCL_SRVC: rc = ble_gattc_add_inc_from_cache(peer_addr, nv_attr[i]); break; diff --git a/nimble/host/src/ble_gattc_cache_conn.c b/nimble/host/src/ble_gattc_cache_conn.c index 542daac9f..1892673a0 100644 --- a/nimble/host/src/ble_gattc_cache_conn.c +++ b/nimble/host/src/ble_gattc_cache_conn.c @@ -1723,6 +1723,9 @@ ble_gattc_cache_conn_create(uint16_t conn_handle, ble_addr_t ble_gattc_cache_con /* set the conn as dirty initially as the cache is not built */ cache_conn->cache_state = CACHE_INVALID; cache_conn->conn_handle = conn_handle; +#if MYNEWT_VAL(BLE_GATT_CACHING_ASSOC_ENABLE) + cache_conn->assoc_success = 0; +#endif memcpy(&cache_conn->ble_gattc_cache_conn_addr, &ble_gattc_cache_conn_addr, sizeof(ble_addr_t)); SLIST_INSERT_HEAD(&ble_gattc_cache_conns, cache_conn, next); @@ -1731,6 +1734,7 @@ ble_gattc_cache_conn_create(uint16_t conn_handle, ble_addr_t ble_gattc_cache_con if (rc == 0) { cache_conn->cache_state = CACHE_LOADED; } + return 0; } @@ -1962,6 +1966,136 @@ ble_gattc_cache_conn_update(uint16_t conn_handle, uint16_t start_handle, uint16_ } #endif +int ble_gattc_cache_refresh(ble_addr_t peer_addr) +{ + struct ble_hs_conn *hs_conn; + struct ble_gattc_cache_conn *conn; + int rc; + + hs_conn = ble_hs_conn_find_by_addr(&peer_addr); + + if (hs_conn == NULL) { + BLE_HS_LOG(ERROR, "GATT cache refresh: connection not found for peer: %02x:%02x:%02x:%02x:%02x:%02x\n", + peer_addr.val[0], peer_addr.val[1], peer_addr.val[2], + peer_addr.val[3], peer_addr.val[4], peer_addr.val[5]); + + return BLE_HS_ENOTCONN; + } + + + /* Lookup cache connection entry */ + conn = ble_gattc_cache_conn_find_by_addr(peer_addr); + if (conn == NULL) { + BLE_HS_LOG(WARN, "GATT cache refresh: no cache entry found for peer."); + return BLE_HS_EUNKNOWN; + } + + ble_gattc_cacheReset(&peer_addr); + /* Invalidate and restart discovery*/ + rc = ble_gattc_cache_conn_disc(conn); + + return rc; +} + +#if MYNEWT_VAL(BLE_GATT_CACHING_ASSOC_ENABLE) +static int +ble_gattc_cache_conn_assoc_on_read(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, + void *arg) +{ + uint16_t res; + uint8_t database_hash[16]; + int rc; + + if (error->status == BLE_HS_EDONE) { + /* Ignore Read by UUID follow-up callback */ + return 0; + } + if (error->status != 0) { + res = error->status; + return res; + } + rc = os_mbuf_copydata(attr->om, 0, sizeof(database_hash), database_hash); + if (rc != 0) { + BLE_HS_LOG(WARN, "Failed to copy database hash from attr->om (rc=%d)", rc); + return rc; + } + rc = ble_gattc_cache_find_source((struct ble_gattc_cache_conn *)arg, database_hash); + + return rc; +} + +int ble_gattc_cache_assoc(ble_addr_t peer_addr) +{ + int rc; + struct ble_gattc_cache_conn *cache_conn; + + cache_conn = ble_gattc_cache_conn_find_by_addr(peer_addr); + if (cache_conn == NULL) { + BLE_HS_LOG(WARN, "No cache entry found for peer."); + return BLE_HS_EUNKNOWN; + } + + if (cache_conn->cache_state == CACHE_LOADED) { + + BLE_HS_LOG(INFO, "Cache already loaded for conn_handle=%d; " + "cache state=%d. Skipping association.", + cache_conn->conn_handle, cache_conn->cache_state); + ble_gap_assoc_event(cache_conn->conn_handle, 0, cache_conn->cache_state); + } + + if (cache_conn->cache_state == CACHE_INVALID) { + rc = ble_gattc_read_by_uuid(cache_conn->conn_handle, 0x0001, 0xFFFF, + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16), + ble_gattc_cache_conn_assoc_on_read, cache_conn); + + if (rc != 0) { + cache_conn->cache_state = CACHE_INVALID; + return rc; + } + } + return 0; + +} +#endif + +int ble_gattc_cache_clean(ble_addr_t peer_addr) +{ + struct ble_hs_conn *hs_conn; + struct ble_gattc_cache_conn *conn; + + // Check if the device is connected + hs_conn = ble_hs_conn_find_by_addr(&peer_addr); + if (hs_conn == NULL) { + BLE_HS_LOG(WARN, "GATT cache clean: No active connection found for peer:" + " %02x:%02x:%02x:%02x:%02x:%02x, Attempting cache clean anyway.", + peer_addr.val[0], peer_addr.val[1], peer_addr.val[2], + peer_addr.val[3], peer_addr.val[4], peer_addr.val[5]); + + ble_gattc_cacheReset(&peer_addr); + return 0; + } + + // Find cached GATT services for this peer + conn = ble_gattc_cache_conn_find_by_addr(peer_addr); + if (conn == NULL) { + BLE_HS_LOG(WARN, "GATT cache clean: no cache entry found for peer."); + return BLE_HS_EUNKNOWN; + } + + // Reset any existing discovery flags/cache markers + ble_gattc_cacheReset(&peer_addr); + + conn->cache_state = CACHE_INVALID; + + BLE_HS_LOG(INFO, "GATT cache cleaned for peer: %02x:%02x:%02x:%02x:%02x:%02x", + peer_addr.val[0], peer_addr.val[1], peer_addr.val[2], + peer_addr.val[3], peer_addr.val[4], peer_addr.val[5]); + + return 0; +} + uint16_t ble_gattc_cache_conn_get_svc_changed_handle(uint16_t conn_handle) { @@ -2143,6 +2277,14 @@ static int ble_gattc_cache_conn_verify(struct ble_gattc_cache_conn *conn) { struct ble_hs_conn *gap_conn; int rc; +#if MYNEWT_VAL(BLE_GATT_CACHING_ASSOC_ENABLE) + if (conn->assoc_success && conn->cache_state == CACHE_LOADED) { + conn->cache_state = CACHE_VERIFIED; + BLE_HS_LOG(INFO, "Associate complete, skipping Discovery"); + ble_gattc_cache_conn_disc_complete(conn, 0); + return 0; + } +#endif if (conn->cache_state == CACHE_VERIFIED) { return 0; diff --git a/nimble/host/src/ble_gattc_cache_priv.h b/nimble/host/src/ble_gattc_cache_priv.h index a9d3ef14f..7dde2192d 100644 --- a/nimble/host/src/ble_gattc_cache_priv.h +++ b/nimble/host/src/ble_gattc_cache_priv.h @@ -134,6 +134,11 @@ struct ble_gattc_cache_conn { /* event to be posted to inform the application about the discovery results */ struct ble_npl_event disc_ev; + +#if MYNEWT_VAL(BLE_GATT_CACHING_ASSOC_ENABLE) + /** Indicates whether association was successful (0 = fail, 1 = success) */ + uint8_t assoc_success; +#endif }; /** Enumerates types of GATT database attributes */ @@ -287,6 +292,14 @@ void ble_gattc_cache_conn_broken(uint16_t conn_handle); void ble_gattc_cache_conn_bonding_established(uint16_t conn_handle); void ble_gattc_cache_conn_bonding_restored(uint16_t conn_handle); +void ble_gattc_cache_get_addr_list(ble_addr_t *addr_list, uint8_t *out_num); +int ble_gattc_cache_refresh(ble_addr_t peer_addr); +int ble_gattc_cache_clean(ble_addr_t peer_addr); +#if MYNEWT_VAL(BLE_GATT_CACHING_ASSOC_ENABLE) +int ble_gattc_cache_assoc(ble_addr_t peer_addr); +int ble_gattc_cache_find_source(struct ble_gattc_cache_conn *cache_conn, uint8_t *database_hash); +int ble_gattc_cache_assoc_load(ble_addr_t src_addr, uint8_t src_index, ble_addr_t assoc_addr); +#endif /* cache search */ int ble_gattc_cache_conn_search_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb, void *cb_arg);