mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-09 03:27:57 +00:00
fix(nimble): Added missing api in nimble which is present in bluedroid
This commit is contained in:
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user