fix(nimble): Added api's for fetching gatt cache data and for discovering included services

This commit is contained in:
Astha Verma
2025-05-12 11:28:09 +05:30
parent 7c18dde8d7
commit 92b8a227f0
7 changed files with 1694 additions and 57 deletions
@@ -0,0 +1,255 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#ifndef H_BLE_ESP_GATTC_GET_CACHE_
#define H_BLE_ESP_GATTC_GET_CACHE_
#ifdef __cplusplus
extern "C" {
#endif
#if MYNEWT_VAL(BLE_GATT_CACHING)
#include "../src/ble_gattc_cache_priv.h"
/** Enumerates types of GATT database attributes */
typedef enum {
ESP_BLE_GATT_DB_PRIMARY_SERVICE, /*!< Primary services in the GATT database */
ESP_BLE_GATT_DB_SECONDARY_SERVICE, /*!< Secondary services in the GATT database */
ESP_BLE_GATT_DB_INCLUDED_SERVICE, /*!< Included services in the GATT database */
ESP_BLE_GATT_DB_CHARACTERISTIC, /*!< Characteristics in the GATT database */
ESP_BLE_GATT_DB_DESCRIPTOR, /*!< Descriptors in the GATT database */
ESP_BLE_GATT_DB_ALL, /*!< All attributes in the GATT database */
} esp_ble_gatt_db_attr_type_t;
/** @brief Represents a GATT service element. */
typedef struct {
bool is_primary; /*!< Indicates if the service is primary. */
uint16_t start_handle; /*!< Service start handle. */
uint16_t end_handle; /*!< Service end handle. */
ble_uuid_any_t uuid; /*!< Service UUID. */
} ble_gattc_service_elem_t;
/** @brief Represents a GATT included service element. */
typedef struct {
uint16_t handle; /*!< handle */
uint16_t incl_svc_s_handle; /*!< Included service start handle. */
uint16_t incl_svc_e_handle; /*!< Included service end handle. */
ble_uuid_any_t uuid; /*!< Included service UUID. */
} ble_gattc_included_svc_elem_t;
/** @brief Represents a GATT characteristic element. */
typedef struct {
uint16_t char_handle; /*!< Characteristic value handle. */
uint8_t properties; /*!< Characteristic properties. */
ble_uuid_any_t uuid; /*!< Characteristic UUID. */
} ble_gattc_char_elem_t;
/** @brief Represents a GATT descriptor element. */
typedef struct {
uint16_t handle; /*!< Descriptor handle. */
ble_uuid_any_t uuid; /*!< Descriptor UUID. */
} ble_gattc_descr_elem_t;
/**
* Retrieve service(s) from the cached GATT database for a given connection.
*
* This function searches the local GATT cache for a service matching the given UUID.
* If `svc_uuid` is not NULL, it returns the matching service(s).
* If `svc_uuid` is NULL, it returns all cached services.
*
* @param conn_handle Connection handle of the peer device.
* @param svc_uuid UUID of the service to search for (can be NULL to fetch all services).
* @param result Output buffer to store the retrieved service(s).
* @param count Number of entries in the cache
* @param offset Index offset for paginated access (used when more services exist).
*
* @return 0 on success, error code otherwise.
*/
int ble_gattc_get_service(uint16_t conn_handle,
ble_uuid_t *svc_uuid,
ble_gattc_service_elem_t *result,
uint16_t *count, uint16_t offset);
/**
* Retrieve all characteristics in a specified handle range from the cached GATT database.
*
* This function fetches all characteristics between the given start and end handles,
* typically the range of a service. Characteristics are returned from the local cache.
*
* @param conn_handle Connection handle of the peer device.
* @param start_handle Start handle of the attribute range (usually the service's start handle).
* @param end_handle End handle of the attribute range (usually the service's end handle).
* @param result Output buffer to store the retrieved characteristics.
* @param count The number of characteristics to retrieve. It will be updated with the actual number of characteristics found.
* @param offset The position offset to retrieve
*
* @return 0 on success, error code otherwise.
*/
int ble_gattc_get_all_char(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_gattc_char_elem_t *result,
uint16_t *count, uint16_t offset);
/**
* Retrieve all descriptors of a given characteristic from the cached GATT database.
*
* This function fetches all descriptors associated with the specified characteristic
* handle from the local GATT cache.
*
* @param conn_handle Connection handle of the peer device.
* @param char_handle Handle of the characteristic whose descriptors are to be fetched.
* @param result Output buffer to store the retrieved descriptors.
* @param count The number of descriptors to retrieve. It will be updated with the actual number of descriptors found.
* @param offset The position offset to retrieve
*
* @return 0 on success, error code otherwise.
*/
int ble_gattc_get_all_descr(uint16_t conn_handle,
uint16_t char_handle,
ble_gattc_descr_elem_t *result,
uint16_t *count, uint16_t offset);
/**
* Retrieve characteristics with a specific UUID from the cached GATT database.
*
* This function fetches all characteristics matching the given UUID within the specified
* handle range (typically a service's start and end handles) from the local GATT cache.
*
* @param conn_handle Connection handle of the peer device.
* @param start_handle Start handle of the attribute range.
* @param end_handle End handle of the attribute range.
* @param char_uuid UUID of the characteristic to search for.
* @param result Output buffer to store the retrieved characteristics.
* @param count The number of characteristics to retrieve. It will be updated with the actual number of characteristics found.
*
* @return 0 on success, error code otherwise.
*/
int ble_gattc_get_char_by_uuid(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_uuid_t *char_uuid,
ble_gattc_char_elem_t *result, uint16_t *count);
/**
* Retrieve descriptors with a specific UUID from the cached GATT database.
*
* This function searches for all descriptors that match the given descriptor UUID
* within the specified handle range and associated with the given characteristic UUID.
*
* @param conn_handle Connection handle of the peer device.
* @param start_handle Start handle of the attribute range.
* @param end_handle End handle of the attribute range.
* @param char_uuid UUID of the characteristic to which the descriptor belongs.
* @param descr_uuid UUID of the descriptor to search for.
* @param result Output buffer to store the retrieved descriptors.
* @param count The number of descriptors to retrieve. It will be updated with the actual number of descriptors found.
*
* @return 0 on success, error code otherwise.
*/
int ble_gattc_get_descr_by_uuid(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_uuid_t *char_uuid,
ble_uuid_t *descr_uuid,
ble_gattc_descr_elem_t *result, uint16_t *count);
/**
* Retrieve descriptors with a specific UUID for a given characteristic handle from the cached GATT database.
*
* This function searches the local GATT cache for descriptors matching the provided UUID
* that are associated with the specified characteristic handle.
*
* @param conn_handle Connection handle of the peer device.
* @param char_handle Handle of the characteristic whose descriptors are to be searched.
* @param descr_uuid UUID of the descriptor to search for.
* @param result Output buffer to store the retrieved descriptors.
* @param count The number of descriptors to retrieve. It will be updated with the actual number of descriptors found.
*
* @return 0 on success, error code otherwise.
*/
int ble_gattc_get_descr_by_char_handle(uint16_t conn_handle,
uint16_t char_handle,
ble_uuid_t *descr_uuid,
ble_gattc_descr_elem_t *result, uint16_t *count);
/**
* Retrieve included services within a specified handle range from the cached GATT database.
*
* This function searches for included (referenced) services within the specified start and end handle range.
* If `incl_uuid` is not NULL, it returns only the included services that match the provided UUID.
* Otherwise, it returns all included services found in the range.
*
* @param conn_handle Connection handle of the peer device.
* @param start_handle Start handle of the attribute range.
* @param end_handle End handle of the attribute range.
* @param incl_uuid UUID of the included service to search for (can be NULL to fetch all).
* @param result Output buffer to store the retrieved included services.
* @param count The number of included services to retrieve. It will be updated with the actual number of included services found.
*
* @return 0 on success, error code otherwise.
*/
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
int ble_gattc_get_include_service(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_uuid_t *incl_uuid,
ble_gattc_included_svc_elem_t *result, uint16_t *count);
#endif
/**
* Get the number of attributes of a given type from the cached GATT database.
*
* This function counts the number of attributes (services, characteristics, or descriptors)
* present in the local GATT cache within a specified handle range or under a specific
* characteristic, depending on the attribute type.
*
* @param conn_handle Connection handle of the peer device.
* @param type Type of attribute to count (e.g., service, characteristic, descriptor).
* @param start_handle Start handle of the range to search.
* @param end_handle End handle of the range to search.
* @param char_handle Characteristic handle (used only if type is `ESP_BLE_GATT_DB_DESCRIPTOR`).
* @param count Output pointer to store the number of attributes found.
*
* @return 0 on success, error code otherwise.
*/
int ble_gattc_get_attr_count(uint16_t conn_handle, esp_ble_gatt_db_attr_type_t type,
uint16_t start_handle, uint16_t end_handle,
uint16_t char_handle, uint16_t *count);
/**
* Retrieve cached GATT attributes within a given handle range.
*
* This function fetches services, characteristics, and descriptors from the local
* GATT database cache between the specified start and end handles.
*
* @param conn_handle Connection handle of the peer device.
* @param start_handle Start handle of the GATT database range.
* @param end_handle End handle of the GATT database range.
* @param result Output buffer to store the retrieved GATT database elements.
* @param count The number of attribute to retrieve. It will be updated with the actual number of attributes found.
*
* @return 0 on success, error code otherwise.
*/
int ble_gattc_get_db(uint16_t conn_handle,
uint16_t start_handle, uint16_t end_handle,
ble_gattc_db_elem_t* result, uint16_t *count);
#ifdef __cplusplus
}
#endif
#endif
#endif
+29 -2
View File
@@ -189,7 +189,7 @@ struct ble_hs_cfg;
#define BLE_GATT_SVC_TYPE_SECONDARY 2
/** @} */
/**
/**
* Client Presentation Format
* GATT Format Types
* Ref: Assigned Numbers Specification
@@ -419,6 +419,22 @@ struct ble_gatt_svc {
ble_uuid_any_t uuid;
};
#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES))
/** Represents a GATT Service. */
struct ble_gatt_incl_svc {
/** The handle of the GATT include service. */
uint16_t handle;
/** The start handle of the GATT include service. */
uint16_t start_handle;
/** The end handle of the GATT include service. */
uint16_t end_handle;
/** The UUID of the GATT service. */
ble_uuid_any_t uuid;
};
#endif
/** Represents a GATT attribute. */
struct ble_gatt_attr {
@@ -469,6 +485,12 @@ typedef int ble_gatt_disc_svc_fn(uint16_t conn_handle,
const struct ble_gatt_svc *service,
void *arg);
#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES))
typedef int ble_gatt_disc_incl_svc_fn(uint16_t conn_handle,
const struct ble_gatt_error *error,
const struct ble_gatt_incl_svc *incl_svc,
void *arg);
#endif
/**
* The host will free the attribute mbuf automatically after the callback is
* executed. The application can take ownership of the mbuf and prevent it
@@ -572,10 +594,15 @@ int ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid,
*
* @return 0 on success; nonzero on failure.
*/
#if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
int ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle,
ble_gatt_disc_incl_svc_fn *cb, void *cb_arg);
#else
int ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle,
ble_gatt_disc_svc_fn *cb, void *cb_arg);
#endif
/**
* Initiates GATT procedure: Discover All Characteristics of a Service.
*
+14 -1
View File
@@ -1959,7 +1959,20 @@ ble_att_svr_service_uuid(struct ble_att_svr_entry *entry,
return rc;
}
rc = ble_uuid_init_from_buf(uuid, val, attr_len);
/**
* - For Primary/Secondary Services: attr_len is typically 2 (16-bit), 4 (32-bit), or 16 (128-bit)
* - For Included Services:
* - When UUID is 16-bit, value length = 2 (start) + 2 (end) + 2 (uuid) = 6
* - So, attr_len == 6 implies 16-bit UUID, and the UUID is at offset 4
*/
if (attr_len == 6) {
// Adjust attr_len to pass only UUID (last 2 bytes) to uuid init
attr_len = 2;
rc = ble_uuid_init_from_buf(uuid, val + 4, attr_len);
} else {
// For normal services (not included), UUID starts at offset 0
rc = ble_uuid_init_from_buf(uuid, val, attr_len);
}
return rc;
}
+446 -4
View File
@@ -61,7 +61,9 @@
#include "host/ble_gap.h"
#include "ble_hs_priv.h"
#include "ble_gattc_cache_priv.h"
#if MYNEWT_VAL(BLE_GATT_CACHING)
#include "host/ble_esp_gattc_cache.h"
#endif
#if NIMBLE_BLE_CONNECT
#ifndef min
@@ -140,7 +142,11 @@ struct ble_gattc_proc {
uint16_t cur_start;
uint16_t cur_end;
#if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
ble_gatt_disc_incl_svc_fn *cb;
#else
ble_gatt_disc_svc_fn *cb;
#endif
void *cb_arg;
} find_inc_svcs;
@@ -1926,15 +1932,22 @@ done:
* @return The return code of the callback (or 0 if there
* is no callback).
*/
#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES))
static int
ble_gattc_find_inc_svcs_cb(struct ble_gattc_proc *proc, int status,
uint16_t att_handle,
struct ble_gatt_svc *service)
struct ble_gatt_incl_svc *incl_svc)
#else
static int
ble_gattc_find_inc_svcs_cb(struct ble_gattc_proc *proc, int status,
uint16_t att_handle,
struct ble_gatt_svc *incl_svc)
#endif
{
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
BLE_HS_DBG_ASSERT(service != NULL || status != 0);
BLE_HS_DBG_ASSERT(incl_svc != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
if (status != 0 && status != BLE_HS_EDONE) {
@@ -1946,7 +1959,7 @@ ble_gattc_find_inc_svcs_cb(struct ble_gattc_proc *proc, int status,
} else {
rc = proc->find_inc_svcs.cb(proc->conn_handle,
ble_gattc_error(status, att_handle),
service, proc->find_inc_svcs.cb_arg);
incl_svc, proc->find_inc_svcs.cb_arg);
}
return rc;
@@ -2036,7 +2049,11 @@ static int
ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_proc *proc, int status,
struct os_mbuf **om)
{
#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES))
struct ble_gatt_incl_svc service;
#else
struct ble_gatt_svc service;
#endif
int rc;
ble_gattc_dbg_assert_proc_not_inserted(proc);
@@ -2065,6 +2082,7 @@ ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_proc *proc, int status,
/* Report discovered service to application. */
service.start_handle = proc->find_inc_svcs.cur_start;
service.end_handle = proc->find_inc_svcs.cur_end;
rc = ble_gattc_find_inc_svcs_cb(proc, 0, 0, &service);
if (rc != 0) {
/* Application has indicated that the procedure should be aborted. */
@@ -2094,7 +2112,11 @@ static int
ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_proc *proc,
struct ble_att_read_type_adata *adata)
{
#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES))
struct ble_gatt_incl_svc service = {0};
#else
struct ble_gatt_svc service = {0};
#endif
int call_cb;
int cbrc;
int rc;
@@ -2128,6 +2150,9 @@ ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_proc *proc,
break;
case BLE_GATTS_INC_SVC_LEN_UUID:
#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES))
service.handle = adata->att_handle;
#endif
service.start_handle = get_le16(adata->value + 0);
service.end_handle = get_le16(adata->value + 2);
rc = ble_uuid_init_from_att_buf(&service.uuid, adata->value + 4, 2);
@@ -2188,10 +2213,17 @@ ble_gattc_find_inc_svcs_rx_complete(struct ble_gattc_proc *proc, int status)
return 0;
}
#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES))
int
ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle,
ble_gatt_disc_incl_svc_fn *cb, void *cb_arg)
#else
int
ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle,
ble_gatt_disc_svc_fn *cb, void *cb_arg)
#endif
{
#if !MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS)
return BLE_HS_ENOTSUP;
@@ -2200,6 +2232,12 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
struct ble_gattc_proc *proc;
int rc;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
rc = ble_gattc_cache_conn_search_inc_svcs(conn_handle, start_handle, end_handle, cb, cb_arg);
if (rc == 0) {
return rc;
}
#endif
STATS_INC(ble_gattc_stats, find_inc_svcs);
proc = ble_gattc_proc_alloc();
@@ -2947,6 +2985,410 @@ done:
return rc;
}
#if MYNEWT_VAL(BLE_GATT_CACHING)
int ble_gattc_check_valid_param(uint16_t num, uint16_t offset)
{
if (num == 0) {
return BLE_ATT_ERR_ATTR_NOT_FOUND;
} else if (offset >= num) {
return BLE_ATT_ERR_INVALID_OFFSET;
}
return 0; // Success
}
static void ble_gattc_fill_gatt_db_conversion(uint16_t *count, uint16_t num, esp_ble_gatt_db_attr_type_t type,
uint16_t offset, void *result, ble_gattc_db_elem_t *db)
{
uint16_t db_size = ((*count + offset) > num) ? (num - offset) : *count;
switch (type) {
case ESP_BLE_GATT_DB_PRIMARY_SERVICE:
case ESP_BLE_GATT_DB_SECONDARY_SERVICE: {
ble_gattc_service_elem_t *svc_result = (ble_gattc_service_elem_t *)result;
for (int i = 0; i < db_size; i++) {
svc_result->is_primary = (db[offset + i].type == (int)BLE_GATT_DB_PRIMARY_SERVICE);
svc_result->start_handle = db[offset + i].start_handle;
svc_result->end_handle = db[offset + i].end_handle;
svc_result->uuid = db[offset + i].uuid;
svc_result++;
}
break;
}
case ESP_BLE_GATT_DB_CHARACTERISTIC: {
ble_gattc_char_elem_t *char_result = (ble_gattc_char_elem_t *)result;
for (int i = 0; i < db_size; i++) {
char_result->char_handle = db[offset + i].handle;
char_result->properties = db[offset + i].properties;
char_result->uuid = db[offset + i].uuid;
char_result++;
}
break;
}
case ESP_BLE_GATT_DB_DESCRIPTOR: {
ble_gattc_descr_elem_t *descr_result = (ble_gattc_descr_elem_t *)result;
for (int i = 0; i < db_size; i++) {
descr_result->handle = db[offset + i].handle;
descr_result->uuid = db[offset + i].uuid;
descr_result++;
}
break;
}
case BLE_GATT_DB_INCLUDED_SERVICE: {
ble_gattc_included_svc_elem_t *incl_result = (ble_gattc_included_svc_elem_t *)result;
for (int i = 0; i < db_size; i++) {
incl_result->handle = db[offset + i].handle;
incl_result->incl_svc_s_handle = db[offset + i].start_handle;
incl_result->incl_svc_e_handle = db[offset + i].end_handle;
incl_result->uuid = db[offset + i].uuid;
incl_result++;
}
break;
}
default:
BLE_HS_LOG(DEBUG,"%s(), Not support type(%d)", __func__, type);
break;
}
}
void ble_gattc_get_cached_service_by_uuid_db(uint16_t conn_id,
ble_uuid_t *svc_uuid,
ble_gattc_db_elem_t **db,
uint16_t *count)
{
ble_gattc_get_service_with_uuid(conn_id, svc_uuid, db, count);
}
void ble_gattc_get_cached_all_char_db(uint16_t conn_id, uint16_t start_handle,
uint16_t end_handle, ble_gattc_db_elem_t **db,
uint16_t *count)
{
ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_ALL_CHAR,
0, NULL, NULL, NULL,
start_handle, end_handle, db, count);
}
void ble_gattc_get_cached_all_descriptor_db(uint16_t conn_id, uint16_t char_handle,
ble_gattc_db_elem_t **db, uint16_t *count)
{
ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_ALL_DESC,
char_handle, NULL, NULL, NULL,
0, 0xFFFF, db, count);
}
void ble_gattc_get_cached_char_by_uuid_db(uint16_t conn_id, uint16_t start_handle,
uint16_t end_handle, ble_uuid_t *char_uuid,
ble_gattc_db_elem_t **db, uint16_t *count)
{
ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_CHAR_BY_UUID,
0, char_uuid, NULL, NULL,
start_handle, end_handle, db, count);
}
void ble_gatt_get_cached_descr_by_uuid_db(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle,
ble_uuid_t *char_uuid, ble_uuid_t *descr_uuid,
ble_gattc_db_elem_t **db, uint16_t *count)
{
ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_DESC_BY_UUID,
0, char_uuid, descr_uuid, NULL,
start_handle, end_handle, db, count);
}
void ble_gattc_get_cached_descr_by_char_handle_db(uint16_t conn_id, uint16_t char_handle,
ble_uuid_t *descr_uuid,
ble_gattc_db_elem_t **db, uint16_t *count)
{
ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_DESC_BY_HANDLE,
char_handle, NULL, descr_uuid, NULL,
0, 0xFFFF, db, count);
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
void ble_gattc_get_cached_include_service_db(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle,
ble_uuid_t *incl_uuid,
ble_gattc_db_elem_t **db, uint16_t *count)
{
ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_INCLUDE_SVC,
0, NULL, NULL, incl_uuid,
start_handle, end_handle, db, count);
}
#endif
void ble_gattc_get_db_size(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle, uint16_t *count)
{
ble_gattc_get_db_size_handle(conn_handle, start_handle, end_handle, count);
}
void ble_gattc_get_db_size_by_type(uint16_t conn_handle, ble_gattc_db_attr_type type,
uint16_t start_handle, uint16_t end_handle,
uint16_t char_handle, uint16_t *count)
{
ble_gattc_get_db_size_with_type_handle(conn_handle, type, start_handle, end_handle, char_handle, count);
}
void ble_gattc_get_cached_gatt_db(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_gattc_db_elem_t **db,
uint16_t *count, uint16_t *db_num)
{
ble_gattc_get_gatt_db(conn_handle, start_handle, end_handle, db,count, db_num);
}
int ble_gattc_get_service(uint16_t conn_handle,
ble_uuid_t *svc_uuid,
ble_gattc_service_elem_t *result,
uint16_t *count, uint16_t offset)
{
int rc;
ble_gattc_db_elem_t *db = NULL;
uint16_t svc_num = 0;
ble_gattc_get_cached_service_by_uuid_db(conn_handle, svc_uuid, &db, &svc_num);
rc = ble_gattc_check_valid_param(svc_num, offset);
if (rc != 0) {
if (db) {
free(db);
}
*count = 0;
return rc;
} else {
ble_gattc_fill_gatt_db_conversion(count, svc_num, ESP_BLE_GATT_DB_PRIMARY_SERVICE, offset, (void *)result, db);
}
*count = svc_num;
//free the db buffer after used.
if (db) {
free(db);
}
return 0;
}
int ble_gattc_get_all_char(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_gattc_char_elem_t *result,
uint16_t *count, uint16_t offset)
{
int rc;
ble_gattc_db_elem_t *db = NULL;
uint16_t char_num = 0;
ble_gattc_get_cached_all_char_db(conn_handle, start_handle, end_handle, &db, &char_num);
rc = ble_gattc_check_valid_param(char_num, offset);
if (rc != 0) {
if (db) {
free(db);
}
*count = 0;
return rc;
} else {
ble_gattc_fill_gatt_db_conversion(count, char_num, ESP_BLE_GATT_DB_CHARACTERISTIC, offset, (void *)result, db);
}
*count = char_num;
//free the db buffer after used.
if (db) {
free(db);
}
return 0;
}
int ble_gattc_get_all_descr(uint16_t conn_handle,
uint16_t char_handle,
ble_gattc_descr_elem_t *result,
uint16_t *count, uint16_t offset)
{
int rc;
ble_gattc_db_elem_t *db = NULL;
uint16_t descr_num = 0;
ble_gattc_get_cached_all_descriptor_db(conn_handle, char_handle, &db, &descr_num);
rc = ble_gattc_check_valid_param(descr_num, offset);
if (rc != 0) {
if (db) {
free(db);
}
*count = 0;
return rc;
} else {
ble_gattc_fill_gatt_db_conversion(count, descr_num, ESP_BLE_GATT_DB_DESCRIPTOR, offset, (void *)result, db);
}
*count = descr_num;
// free the db buffer after used.
if (db) {
free(db);
}
return 0;
}
int ble_gattc_get_char_by_uuid(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_uuid_t *char_uuid,
ble_gattc_char_elem_t *result, uint16_t *count)
{
int rc;
ble_gattc_db_elem_t *db = NULL;
uint16_t char_num = 0;
ble_gattc_get_cached_char_by_uuid_db(conn_handle, start_handle, end_handle, char_uuid, &db, &char_num);
rc = ble_gattc_check_valid_param(char_num, 0);
if (rc != 0) {
if (db) {
free(db);
}
*count = 0;
return rc;
} else {
ble_gattc_fill_gatt_db_conversion(count, char_num, ESP_BLE_GATT_DB_CHARACTERISTIC, 0, (void *)result, db);
}
*count = char_num;
// free the db buffer after used.
if (db) {
free(db);
}
return 0;
}
int ble_gattc_get_descr_by_uuid(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_uuid_t *char_uuid,
ble_uuid_t *descr_uuid,
ble_gattc_descr_elem_t *result, uint16_t *count)
{
int rc;
ble_gattc_db_elem_t *db = NULL;
uint16_t descr_num = 0;
ble_gatt_get_cached_descr_by_uuid_db(conn_handle, start_handle, end_handle, char_uuid, descr_uuid, &db, &descr_num);
rc = ble_gattc_check_valid_param(descr_num, 0);
if (rc != 0) {
if (db) {
free(db);
}
*count = 0;
return rc;
} else {
ble_gattc_fill_gatt_db_conversion(count, descr_num, ESP_BLE_GATT_DB_DESCRIPTOR, 0, (void *)result, db);
}
*count = descr_num;
// free the db buffer after used.
if (db) {
free(db);
}
return 0;
}
int ble_gattc_get_descr_by_char_handle(uint16_t conn_handle,
uint16_t char_handle,
ble_uuid_t *descr_uuid,
ble_gattc_descr_elem_t *result, uint16_t *count)
{
int rc;
ble_gattc_db_elem_t *db = NULL;
uint16_t descr_num = 0;
ble_gattc_get_cached_descr_by_char_handle_db(conn_handle, char_handle, descr_uuid, &db, &descr_num);
rc = ble_gattc_check_valid_param(descr_num, 0);
if (rc != 0) {
if (db) {
free(db);
}
*count = 0;
return rc;
} else {
ble_gattc_fill_gatt_db_conversion(count, descr_num, ESP_BLE_GATT_DB_DESCRIPTOR, 0, (void *)result, db);
}
*count = descr_num;
// free the db buffer after used.
if (db) {
free(db);
}
return 0;
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
int ble_gattc_get_include_service(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_uuid_t *incl_uuid,
ble_gattc_included_svc_elem_t *result, uint16_t *count)
{
int rc;
ble_gattc_db_elem_t *db = NULL;
uint16_t incl_num = 0;
ble_gattc_get_cached_include_service_db(conn_handle, start_handle, end_handle, incl_uuid, &db, &incl_num);
rc = ble_gattc_check_valid_param(incl_num,0);
if (rc != 0) {
if (db) {
free(db);
}
*count = 0;
return rc;
} else {
ble_gattc_fill_gatt_db_conversion(count, incl_num, ESP_BLE_GATT_DB_INCLUDED_SERVICE, 0, (void *)result, db);
}
*count = incl_num;
//free the db buffer after used.
if (db) {
free(db);
}
return 0;
}
#endif
int ble_gattc_get_attr_count(uint16_t conn_handle, esp_ble_gatt_db_attr_type_t type,
uint16_t start_handle, uint16_t end_handle,
uint16_t char_handle, uint16_t *count)
{
if (type == ESP_BLE_GATT_DB_ALL) {
ble_gattc_get_db_size(conn_handle, start_handle, end_handle, count);
} else {
ble_gattc_get_db_size_by_type(conn_handle, type, start_handle, end_handle, char_handle, count);
}
return 0;
}
int ble_gattc_get_db(uint16_t conn_handle,
uint16_t start_handle, uint16_t end_handle,
ble_gattc_db_elem_t *result, uint16_t *count)
{
uint16_t num = 0;
ble_gattc_db_elem_t *db = NULL;
ble_gattc_get_cached_gatt_db(conn_handle, start_handle, end_handle, &db, &num, count);
if (num == 0) {
return BLE_ATT_ERR_ATTR_NOT_FOUND;
}
if (db) {
memcpy(result, db, num * sizeof(ble_gattc_db_elem_t)); // Copy data
free(db); // Free allocated memory
}
return 0;
}
#endif
/*****************************************************************************
* $read *
*****************************************************************************/
+41 -19
View File
@@ -31,7 +31,7 @@
#define GATT_CACHE_PREFIX "gatt_"
#define INVALID_ADDR_NUM 0xff
#define MAX_DEVICE_IN_CACHE 50
#define MAX_ADDR_LIST_CACHE_BUF 2048
#define MAX_ADDR_LIST_CACHE_BUF 4096
#if MYNEWT_VAL(BLE_GATT_CACHING)
static const char *cache_key = "gattc_cache_key";
@@ -305,7 +305,8 @@ static void check_uuid(ble_uuid_any_t *uuid)
static void
ble_gattc_fill_nv_attr_entry(ble_uuid_any_t uuid, uint16_t s_handle, uint16_t e_handle,
ble_gatt_attr_type attr_type, bool is_primary,
struct ble_gatt_nv_attr *nv_attr, int index, uint8_t properties)
struct ble_gatt_nv_attr *nv_attr, int index, uint8_t properties,
uint16_t incl_svc_s_handle, uint16_t incl_svc_e_handle)
{
ble_uuid_copy(&nv_attr[index].uuid, &uuid.u);
check_uuid(&nv_attr[index].uuid);
@@ -314,6 +315,8 @@ ble_gattc_fill_nv_attr_entry(ble_uuid_any_t uuid, uint16_t s_handle, uint16_t e_
nv_attr[index].is_primary = is_primary;
nv_attr[index].attr_type = attr_type;
nv_attr[index].properties = properties;
nv_attr[index].incl_svc_s_handle = incl_svc_s_handle;
nv_attr[index].incl_svc_e_handle = incl_svc_e_handle;
if (s_handle >= svc_end_handle) {
svc_end_handle = s_handle;
@@ -327,6 +330,9 @@ 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)
struct ble_gattc_cache_conn_incl_svc *included_svc;
#endif
struct ble_gattc_cache_conn_chr *chr;
struct ble_gattc_cache_conn_dsc *dsc;
@@ -336,18 +342,29 @@ ble_gattc_fill_nv_attr(struct ble_gattc_cache_conn *peer, size_t num_attr, struc
SLIST_FOREACH(svc, &peer->svcs, next) {
ble_gattc_fill_nv_attr_entry(svc->svc.uuid, svc->svc.start_handle, svc->svc.end_handle,
BLE_GATT_ATTR_TYPE_SRVC, svc->type == BLE_GATT_SVC_TYPE_PRIMARY,
nv_attr, index, 0);
nv_attr, index, 0, 0, 0);
svc_index = index;
index++;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
if (!SLIST_EMPTY(&svc->incl_svc)) {
SLIST_FOREACH(included_svc, &svc->incl_svc, next) {
ble_gattc_fill_nv_attr_entry(included_svc->svc.uuid, included_svc->svc.handle,
0, BLE_GATT_ATTR_TYPE_INCL_SRVC, false,
nv_attr, index, 0, included_svc->svc.start_handle, included_svc->svc.end_handle);
index++;
}
}
#endif
SLIST_FOREACH(chr, &svc->chrs, next) {
ble_gattc_fill_nv_attr_entry(chr->chr.uuid, chr->chr.val_handle,
chr->chr.def_handle, BLE_GATT_ATTR_TYPE_CHAR, false,
nv_attr, index, chr->chr.properties);
nv_attr, index, chr->chr.properties, 0, 0);
index++;
SLIST_FOREACH(dsc, &chr->dscs, next) {
ble_gattc_fill_nv_attr_entry(dsc->dsc.uuid, dsc->dsc.handle, 0,
BLE_GATT_ATTR_TYPE_CHAR_DESCR, false, nv_attr, index,
0);
0, 0, 0);
index++;
}
}
@@ -544,29 +561,33 @@ ble_gattc_add_svc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_at
gatt_svc->end_handle = nv_attr.e_handle;
ble_uuid_copy(&gatt_svc->uuid, &nv_attr.uuid.u);
rc = ble_gattc_cache_conn_svc_add(peer_addr, gatt_svc);
rc = ble_gattc_cache_conn_svc_add(peer_addr, gatt_svc, nv_attr.is_primary);
nimble_platform_mem_free(gatt_svc);
return rc;
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
static int
ble_gattc_add_inc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr)
{
struct ble_gatt_svc *gatt_svc;
int rc;
struct ble_gatt_incl_svc *gatt_incl_svc;
gatt_svc = (struct ble_gatt_svc *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_svc));
if (gatt_svc == NULL) {
gatt_incl_svc = (struct ble_gatt_incl_svc *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_incl_svc));
if (gatt_incl_svc == NULL) {
return BLE_HS_ENOMEM;
}
gatt_svc->start_handle = nv_attr.s_handle;
gatt_svc->end_handle = nv_attr.e_handle;
ble_uuid_copy(&gatt_svc->uuid, &nv_attr.uuid.u);
rc = ble_gattc_cache_conn_inc_add(peer_addr, gatt_svc);
nimble_platform_mem_free(gatt_svc);
gatt_incl_svc->handle = nv_attr.s_handle;
gatt_incl_svc->start_handle = nv_attr.incl_svc_s_handle;
gatt_incl_svc->end_handle = nv_attr.incl_svc_e_handle;
ble_uuid_copy(&gatt_incl_svc->uuid, &nv_attr.uuid.u);
rc = ble_gattc_cache_conn_inc_add(peer_addr, gatt_incl_svc);
nimble_platform_mem_free(gatt_incl_svc);
return rc;
}
#endif
static int
ble_gattc_add_chr_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr)
@@ -628,11 +649,7 @@ ble_gattc_cache_load(ble_addr_t peer_addr)
for (int i = 0; i < num_attr; i++) {
switch (nv_attr[i].attr_type) {
case BLE_GATT_ATTR_TYPE_SRVC:
if (nv_attr[i].is_primary) {
rc = ble_gattc_add_svc_from_cache(peer_addr, nv_attr[i]);
} else {
rc = ble_gattc_add_inc_from_cache(peer_addr, nv_attr[i]);
}
rc = ble_gattc_add_svc_from_cache(peer_addr, nv_attr[i]);
break;
case BLE_GATT_ATTR_TYPE_CHAR:
@@ -643,6 +660,11 @@ 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)
case BLE_GATT_ATTR_TYPE_INCL_SRVC:
rc = ble_gattc_add_inc_from_cache(peer_addr, nv_attr[i]);
break;
#endif
default:
break;
}
+768 -28
View File
@@ -89,6 +89,11 @@
static void *ble_gattc_cache_conn_svc_mem;
static struct os_mempool ble_gattc_cache_conn_svc_pool;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
static void *ble_gattc_cache_conn_incl_svc_mem;
static struct os_mempool ble_gattc_cache_conn_incl_svc_pool;
#endif
static void *ble_gattc_cache_conn_chr_mem;
static struct os_mempool ble_gattc_cache_conn_chr_pool;
@@ -340,6 +345,13 @@ ble_gattc_cache_conn_chr_find(const struct ble_gattc_cache_conn_svc *svc, uint16
return chr;
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
static void
ble_gattc_cache_conn_incl_svc_delete(struct ble_gattc_cache_conn_incl_svc *incl_svc)
{
os_memblock_put(&ble_gattc_cache_conn_incl_svc_pool, incl_svc);
}
#endif
static void
ble_gattc_cache_conn_chr_delete(struct ble_gattc_cache_conn_chr *chr)
{
@@ -549,13 +561,68 @@ ble_gattc_cache_conn_dsc_find_uuid(const struct ble_gattc_cache_conn *ble_gattc_
return NULL;
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
static struct ble_gattc_cache_conn_incl_svc *
ble_gattc_cache_conn_incl_svc_find_prev(const struct ble_gattc_cache_conn_svc *svc, uint16_t incl_svc_handle)
{
struct ble_gattc_cache_conn_incl_svc *prev;
struct ble_gattc_cache_conn_incl_svc *incl_svc;
prev = NULL;
SLIST_FOREACH(incl_svc, &svc->incl_svc, next) {
if (incl_svc->svc.handle >= incl_svc_handle) {
break;
}
prev = incl_svc;
}
return prev;
}
static struct ble_gattc_cache_conn_incl_svc *
ble_gattc_cache_conn_incl_svc_find(const struct ble_gattc_cache_conn_svc *svc, uint16_t incl_svc_handle,
struct ble_gattc_cache_conn_incl_svc **out_prev)
{
struct ble_gattc_cache_conn_incl_svc *prev;
struct ble_gattc_cache_conn_incl_svc *incl_svc;
prev = ble_gattc_cache_conn_incl_svc_find_prev(svc, incl_svc_handle);
if (prev == NULL) {
incl_svc = SLIST_FIRST(&svc->incl_svc);
} else {
incl_svc = SLIST_NEXT(prev, next);
}
if (incl_svc != NULL && incl_svc->svc.handle != incl_svc_handle) {
incl_svc = NULL;
}
if (out_prev != NULL) {
*out_prev = prev;
}
return incl_svc;
}
#endif
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
int
ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_incl_svc *gatt_svc)
#else
int
ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc)
#endif
{
struct ble_gattc_cache_conn_svc *prev;
struct ble_gattc_cache_conn_svc *svc;
struct ble_gattc_cache_conn_svc *prev;
struct ble_gattc_cache_conn *peer;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
struct ble_gattc_cache_conn_incl_svc *incl_svc;
struct ble_gattc_cache_conn_incl_svc *incl_svc_prev;
struct ble_gattc_cache_conn_svc *cur_svc;
#endif
peer = ble_gattc_cache_conn_find_by_addr(peer_addr);
if (peer == NULL) {
BLE_HS_LOG(ERROR, "Peer not found");
@@ -563,36 +630,79 @@ ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *ga
}
svc = ble_gattc_cache_conn_svc_find(peer, gatt_svc->start_handle, &prev);
if (svc != NULL) {
/* Inc already discovered. */
if (!svc) {
/* Secondary Service */
svc = os_memblock_get(&ble_gattc_cache_conn_svc_pool);
if (svc == NULL) {
/* Out of memory. */
return BLE_HS_ENOMEM;
}
memset(svc, 0, sizeof * svc);
svc->type = BLE_GATT_SVC_TYPE_SECONDARY;
svc->svc.start_handle = gatt_svc->start_handle;
svc->svc.end_handle = gatt_svc->end_handle;
memcpy(&svc->svc.uuid, &gatt_svc->uuid, sizeof(ble_uuid_any_t));
SLIST_INIT(&svc->chrs);
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
SLIST_INIT(&svc->incl_svc);
#endif
if (prev == NULL) {
SLIST_INSERT_HEAD(&peer->svcs, svc, next);
} else {
SLIST_INSERT_AFTER(prev, svc, next);
}
BLE_HS_LOG(DEBUG, "Secondary Svc added with start_handle = %d , end_handle = %d",
gatt_svc->start_handle, gatt_svc->end_handle);
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
/* Including the services into including list of current service*/
cur_svc = ble_gattc_cache_conn_svc_find_range(peer, gatt_svc->handle);
if (cur_svc == NULL) {
/* Can't find service for discovered included service; this shouldn't
* happen.
*/
BLE_HS_LOG(WARN, "Current Service is NULL.\n");
assert(0);
return BLE_HS_EUNKNOWN;
}
incl_svc = ble_gattc_cache_conn_incl_svc_find(cur_svc, gatt_svc->handle, &incl_svc_prev);
if (incl_svc != NULL) {
/* Already discovered */
return 0;
}
svc = os_memblock_get(&ble_gattc_cache_conn_svc_pool);
if (svc == NULL) {
/* Out of memory. */
incl_svc = os_memblock_get(&ble_gattc_cache_conn_incl_svc_pool);
if (incl_svc == NULL) {
return BLE_HS_ENOMEM;
}
memset(svc, 0, sizeof * svc);
svc->type = BLE_GATT_SVC_TYPE_SECONDARY;
svc->svc = *gatt_svc;
SLIST_INIT(&svc->chrs);
incl_svc->svc.handle = gatt_svc->handle;
incl_svc->svc.start_handle = gatt_svc->start_handle;
incl_svc->svc.end_handle = gatt_svc->end_handle;
memcpy(&incl_svc->svc.uuid, &gatt_svc->uuid, sizeof(ble_uuid_any_t));
if (prev == NULL) {
SLIST_INSERT_HEAD(&peer->svcs, svc, next);
if (incl_svc_prev == NULL) {
SLIST_INSERT_HEAD(&cur_svc->incl_svc, incl_svc, next);
} else {
SLIST_INSERT_AFTER(prev, svc, next);
SLIST_INSERT_AFTER(incl_svc_prev, incl_svc, next);
}
BLE_HS_LOG(DEBUG, "Inc added with start_handle = %d and end_handle = %d",
gatt_svc->start_handle, gatt_svc->end_handle);
BLE_HS_LOG(DEBUG, "Inc added with handle = %d",
gatt_svc->handle);
#endif
return 0;
}
int
ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc)
ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc, bool is_primary)
{
struct ble_gattc_cache_conn_svc *prev;
struct ble_gattc_cache_conn_svc *svc;
@@ -617,8 +727,16 @@ ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *ga
}
memset(svc, 0, sizeof * svc);
svc->type = BLE_GATT_SVC_TYPE_PRIMARY;
if (is_primary) {
svc->type = BLE_GATT_SVC_TYPE_PRIMARY;
} else {
svc->type = BLE_GATT_SVC_TYPE_SECONDARY;
}
svc->svc = *gatt_svc;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
SLIST_INIT(&svc->incl_svc);
#endif
SLIST_INIT(&svc->chrs);
if (prev == NULL) {
@@ -638,6 +756,14 @@ ble_gattc_cache_conn_svc_delete(struct ble_gattc_cache_conn_svc *svc)
{
struct ble_gattc_cache_conn_chr *chr;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
struct ble_gattc_cache_conn_incl_svc *incl_svc;
// Free included services
while ((incl_svc = SLIST_FIRST(&svc->incl_svc)) != NULL) {
SLIST_REMOVE_HEAD(&svc->incl_svc, next);
ble_gattc_cache_conn_incl_svc_delete(incl_svc);
}
#endif
while ((chr = SLIST_FIRST(&svc->chrs)) != NULL) {
SLIST_REMOVE_HEAD(&svc->chrs, next);
ble_gattc_cache_conn_chr_delete(chr);
@@ -655,11 +781,19 @@ ble_gattc_cache_conn_get_db_size(struct ble_gattc_cache_conn *peer)
size_t db_size = 0;
struct ble_gattc_cache_conn_svc *svc;
#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;
struct ble_gattc_cache_conn_dsc *dsc;
SLIST_FOREACH(svc, &peer->svcs, next) {
db_size++;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
SLIST_FOREACH(included_svc, &svc->incl_svc, next) {
db_size++;
}
#endif
SLIST_FOREACH(chr, &svc->chrs, next) {
db_size++;
SLIST_FOREACH(dsc, &chr->dscs, next) {
@@ -671,6 +805,553 @@ ble_gattc_cache_conn_get_db_size(struct ble_gattc_cache_conn *peer)
return db_size;
}
size_t
ble_gattc_get_db_size_with_handle(struct ble_gattc_cache_conn *peer, uint16_t start_handle, uint16_t end_handle)
{
if (peer == NULL || SLIST_EMPTY(&peer->svcs)) {
return 0;
}
struct ble_gattc_cache_conn_svc *svc;
#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;
struct ble_gattc_cache_conn_dsc *dsc;
size_t db_size = 0;
SLIST_FOREACH(svc, &peer->svcs, next) {
if (svc->svc.end_handle < start_handle) {
continue;
}
if (svc->svc.start_handle > end_handle) {
break;
}
db_size++;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
SLIST_FOREACH(included_svc, &svc->incl_svc, next) {
if (included_svc->svc.handle < start_handle) {
continue;
}
if (included_svc->svc.handle > end_handle) {
return db_size;
}
db_size++;
}
#endif
SLIST_FOREACH(chr, &svc->chrs, next) {
if (chr->chr.val_handle < start_handle) {
continue;
}
if (chr->chr.val_handle > end_handle) {
return db_size;
}
db_size++;
SLIST_FOREACH(dsc, &chr->dscs, next) {
if (dsc->dsc.handle < start_handle) {
continue;
}
if (dsc->dsc.handle > end_handle) {
return db_size;
}
db_size++;
}
}
}
return db_size;
}
size_t
ble_gattc_get_db_size_with_type(struct ble_gattc_cache_conn *peer, uint8_t type,
uint16_t start_handle, uint16_t end_handle, uint16_t char_handle)
{
if (peer == NULL || SLIST_EMPTY(&peer->svcs)) {
return 0;
}
struct ble_gattc_cache_conn_svc *svc;
#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;
struct ble_gattc_cache_conn_dsc *dsc;
size_t db_size = 0;
// Iterate through the services in the cache connection.
SLIST_FOREACH(svc, &peer->svcs, next) {
// Skip services that are out of the requested handle range.
if (svc->svc.end_handle < start_handle || svc->svc.start_handle > end_handle) {
continue;
}
// Handle the different types of GATT database entries.
switch (type) {
case BLE_GATT_DB_PRIMARY_SERVICE:
if (svc->type == BLE_GATT_SVC_TYPE_PRIMARY &&
svc->svc.start_handle >= start_handle &&
svc->svc.end_handle <= end_handle) {
db_size++;
}
break;
case BLE_GATT_DB_SECONDARY_SERVICE:
if (svc->type == BLE_GATT_SVC_TYPE_SECONDARY &&
svc->svc.start_handle >= start_handle &&
svc->svc.end_handle <= end_handle) {
db_size++;
}
break;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
case BLE_GATT_DB_INCLUDED_SERVICE:
// Iterate through included service.
SLIST_FOREACH(included_svc, &svc->incl_svc, next) {
if (included_svc->svc.handle >= start_handle && included_svc->svc.handle <= end_handle) {
db_size++;
}
}
break;
#endif
case BLE_GATT_DB_CHARACTERISTIC:
// Iterate through characteristics.
SLIST_FOREACH(chr, &svc->chrs, next) {
if (chr->chr.val_handle >= start_handle && chr->chr.val_handle <= end_handle) {
db_size++;
}
}
break;
case BLE_GATT_DB_DESCRIPTOR:
// Iterate through characteristics and their descriptors.
SLIST_FOREACH(chr, &svc->chrs, next) {
if (chr->chr.val_handle >= start_handle && chr->chr.val_handle <= end_handle) {
if (chr->chr.val_handle == char_handle) {
SLIST_FOREACH(dsc, &chr->dscs, next) {
if (dsc->dsc.handle >= start_handle &&
dsc->dsc.handle <= end_handle &&
chr->chr.val_handle == char_handle) {
db_size++;
}
}
}
}
}
break;
}
}
return db_size;
}
// fill a element into database
void ble_gattc_fill_gatt_db_el(ble_gattc_db_elem_t *attr,
ble_gattc_db_attr_type type,
uint16_t handle,
uint16_t s_handle,
uint16_t e_handle,
uint8_t prop,
ble_uuid_any_t uuid)
{
attr->type = type;
attr->handle = handle;
attr->start_handle = s_handle;
attr->end_handle = e_handle;
attr->properties = prop;
attr->uuid = uuid;
}
void ble_gattc_get_service_with_uuid(uint16_t conn_handle,
ble_uuid_t *svc_uuid,
ble_gattc_db_elem_t **svc_db,
uint16_t *count)
{
struct ble_gattc_cache_conn *cache_conn;
struct ble_gattc_cache_conn_svc *svc;
// Find the connection in the cache
cache_conn = ble_gattc_cache_conn_find(conn_handle);
if (cache_conn == NULL || SLIST_EMPTY(&cache_conn->svcs)) {
BLE_HS_LOG(WARN, "%s(), no service.", __func__);
*count = 0;
*svc_db = NULL;
return;
}
size_t db_size = 0;
SLIST_FOREACH(svc, &cache_conn->svcs, next) {
if (svc_uuid == NULL || ble_uuid_cmp(&svc->svc.uuid.u, svc_uuid) == 0) {
db_size++;
}
}
if (!db_size) {
BLE_HS_LOG(DEBUG, "the db size is 0.");
*count = 0;
*svc_db = NULL;
return;
}
// Allocate memory for the GATT database
void *buffer = malloc(db_size * sizeof(ble_gattc_db_elem_t));
if (!buffer) {
BLE_HS_LOG(WARN, "%s(), no resource.", __func__);
*count = 0;
*svc_db = NULL;
return;
}
ble_gattc_db_elem_t *curr_db_attr = buffer;
db_size = 0;
// Iterate through services in the cache
SLIST_FOREACH(svc, &cache_conn->svcs, next) {
if (svc_uuid == NULL || ble_uuid_cmp(&svc->svc.uuid.u, svc_uuid) == 0) {
ble_gattc_fill_gatt_db_el(curr_db_attr,
svc->type == BLE_GATT_SVC_TYPE_PRIMARY ? /* attr type */
BLE_GATT_DB_PRIMARY_SERVICE:BLE_GATT_DB_SECONDARY_SERVICE,
0, /* handle */
svc->svc.start_handle, /* s_handle */
svc->svc.end_handle, /* e_handle */
0, /* property */
svc->svc.uuid); /* uuid */
curr_db_attr++;
db_size++;
}
}
*svc_db = buffer;
*count = db_size;
}
void ble_gattc_get_db_with_operation(uint16_t conn_handle,
ble_gatt_get_db_op_t op,
uint16_t char_handle,
ble_uuid_t *char_uuid,
ble_uuid_t *descr_uuid,
ble_uuid_t *incl_uuid,
uint16_t start_handle, uint16_t end_handle,
ble_gattc_db_elem_t **char_db,
uint16_t *count)
{
struct ble_gattc_cache_conn *cache_conn;
struct ble_gattc_cache_conn_svc *svc;
#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;
struct ble_gattc_cache_conn_dsc *dsc;
// Find the connection in the cache
cache_conn = ble_gattc_cache_conn_find(conn_handle);
if (cache_conn == NULL || SLIST_EMPTY(&cache_conn->svcs)) {
BLE_HS_LOG(WARN, "the service cache is empty.");
*count = 0;
*char_db = NULL;
return;
}
size_t db_size = ble_gattc_get_db_size_with_handle(cache_conn, start_handle, end_handle);
if (!db_size) {
BLE_HS_LOG(DEBUG, "the db size is 0.");
*count = 0;
*char_db = NULL;
return;
}
// Allocate memory for the GATT database
void *buffer = malloc(db_size * sizeof(ble_gattc_db_elem_t));
if (!buffer) {
BLE_HS_LOG(WARN, "%s(), no resource.", __func__);
*count = 0;
*char_db = NULL;
return;
}
ble_gattc_db_elem_t *curr_db_attr = buffer;
db_size = 0;
// Iterate through services in the cache
SLIST_FOREACH(svc, &cache_conn->svcs, next) {
if (svc->svc.end_handle < start_handle || svc->svc.start_handle > end_handle) {
continue;
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
// Check for included services
if (op == BLE_GATT_OP_GET_INCLUDE_SVC) {
if (SLIST_EMPTY(&svc->incl_svc)) {
continue;
}
SLIST_FOREACH(included_svc, &svc->incl_svc, next) {
if (included_svc->svc.handle < start_handle || included_svc->svc.handle > end_handle) {
continue;
}
if (incl_uuid == NULL || ble_uuid_cmp(&included_svc->svc.uuid.u, incl_uuid) == 0) {
ble_gattc_fill_gatt_db_el(curr_db_attr,
BLE_GATT_DB_INCLUDED_SERVICE, /* attr type*/
included_svc->svc.handle, /* handle */
included_svc->svc.start_handle, /* s_handle */
included_svc->svc.end_handle, /* e_handle */
0, /* property */
included_svc->svc.uuid); /* uuid */
curr_db_attr++;
db_size++;
}
}
continue;
}
#endif
// Check for characteristics
SLIST_FOREACH(chr, &svc->chrs, next) {
if (chr->chr.val_handle < start_handle || chr->chr.val_handle > end_handle) {
continue;
}
if ((op == BLE_GATT_OP_GET_ALL_CHAR || op == BLE_GATT_OP_GET_CHAR_BY_UUID) &&
(char_uuid == NULL || ble_uuid_cmp(&chr->chr.uuid.u, char_uuid) == 0)) {
ble_gattc_fill_gatt_db_el(curr_db_attr,
BLE_GATT_DB_CHARACTERISTIC, /* attr type*/
chr->chr.val_handle, /* handle */
0, /* s_handle */
0, /* e_handle */
chr->chr.properties, /* property */
chr->chr.uuid); /* uuid */
curr_db_attr++;
db_size++;
continue;
}
if ((op == BLE_GATT_OP_GET_DESC_BY_HANDLE || op == BLE_GATT_OP_GET_ALL_DESC) &&
(chr->chr.val_handle != char_handle)) {
continue;
}
if ((op == BLE_GATT_OP_GET_DESC_BY_UUID && ble_uuid_cmp(&chr->chr.uuid.u, char_uuid) != 0)) {
continue;
}
// Check for descriptors
if (!SLIST_EMPTY(&chr->dscs)) {
SLIST_FOREACH(dsc, &chr->dscs, next) {
if (dsc->dsc.handle < start_handle || dsc->dsc.handle > end_handle) {
continue;
}
if (((op == BLE_GATT_OP_GET_ALL_DESC || op == BLE_GATT_OP_GET_DESC_BY_UUID) &&
(descr_uuid == NULL || ble_uuid_cmp(&dsc->dsc.uuid.u, descr_uuid) == 0)) ||
(op == BLE_GATT_OP_GET_DESC_BY_HANDLE && ble_uuid_cmp(&dsc->dsc.uuid.u, descr_uuid) == 0)) {
ble_gattc_fill_gatt_db_el(curr_db_attr,
BLE_GATT_DB_DESCRIPTOR, /* attr type*/
dsc->dsc.handle, /* handle */
0, /* s_handle */
0, /* e_handle */
0, /* property */
dsc->dsc.uuid); /* uuid */
curr_db_attr++;
db_size++;
}
}
}
}
}
*char_db = buffer;
*count = db_size;
return;
}
void ble_gattc_get_db_size_with_type_handle(uint16_t conn_handle,
ble_gattc_db_attr_type type,
uint16_t start_handle,
uint16_t end_handle,
uint16_t char_handle, uint16_t *count)
{
struct ble_gattc_cache_conn *cache_conn;
cache_conn = ble_gattc_cache_conn_find(conn_handle);
if (cache_conn == NULL) {
*count = 0;
return ;
}
*count = ble_gattc_get_db_size_with_type(cache_conn, type, start_handle, end_handle, char_handle);
}
void ble_gattc_get_db_size_handle(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
uint16_t *count)
{
struct ble_gattc_cache_conn *cache_conn;
cache_conn = ble_gattc_cache_conn_find(conn_handle);
if (cache_conn == NULL) {
*count = 0;
return;
}
*count = ble_gattc_get_db_size_with_handle(cache_conn, start_handle, end_handle);
}
// Copy the server GATT database into db parameter.
static void ble_gattc_get_gatt_db_impl(struct ble_gattc_cache_conn *peer,
uint16_t start_handle,
uint16_t end_handle,
ble_gattc_db_elem_t **db,
uint16_t *count, uint16_t *db_num)
{
if (!peer || SLIST_EMPTY(&peer->svcs)) {
*count = 0;
*db = NULL;
return;
}
size_t db_size = ble_gattc_get_db_size_with_handle(peer, start_handle, end_handle);
if (!db_size) {
BLE_HS_LOG(DEBUG, "the db size is 0.");
*count = 0;
*db = NULL;
return;
}
db_size = (*db_num > db_size) ? db_size : (*db_num);
// Allocate memory for the GATT database
void *buffer = malloc(db_size * sizeof(ble_gattc_db_elem_t));
if (!buffer) {
BLE_HS_LOG(WARN, "%s(), no resource.", __func__);
*count = 0;
*db = NULL;
return;
}
ble_gattc_db_elem_t *curr_db_attr = buffer;
struct ble_gattc_cache_conn_svc *svc;
#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;
struct ble_gattc_cache_conn_dsc *dsc;
SLIST_FOREACH(svc, &peer->svcs, next) {
if (svc->svc.end_handle < start_handle) {
continue;
}
if (svc->svc.start_handle > end_handle) {
break;
}
ble_gattc_fill_gatt_db_el(curr_db_attr,
svc->type == BLE_GATT_SVC_TYPE_PRIMARY ? /* attr type */
BLE_GATT_DB_PRIMARY_SERVICE:
BLE_GATT_DB_SECONDARY_SERVICE,
0, /* attr handle */
svc->svc.start_handle, /* start handle*/
svc->svc.end_handle, /* end handle */
0, /* property */
svc->svc.uuid); /* uuid */
curr_db_attr++;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
// Iterate over included services
SLIST_FOREACH(included_svc, &svc->incl_svc, next) {
if (included_svc->svc.handle < start_handle) {
continue;
}
if (included_svc->svc.handle > end_handle) {
*db = buffer;
*count = db_size;
return;
}
ble_gattc_fill_gatt_db_el(curr_db_attr,
BLE_GATT_DB_INCLUDED_SERVICE, /* attr type */
included_svc->svc.handle, /* attr handle */
included_svc->svc.start_handle, /* s_handle */
included_svc->svc.end_handle, /* e_handle */
0, /* property */
included_svc->svc.uuid); /* uuid */
curr_db_attr++;
}
#endif
// Iterate over characterstic
SLIST_FOREACH(chr, &svc->chrs, next) {
if (chr->chr.val_handle < start_handle) {
continue;
}
if (chr->chr.val_handle > end_handle) {
*db = buffer;
*count = db_size;
return;
}
ble_gattc_fill_gatt_db_el(curr_db_attr,
BLE_GATT_DB_CHARACTERISTIC, /* attr type */
chr->chr.val_handle, /* attr handle */
0, /* s_handle */
0, /* e_handle */
chr->chr.properties, /* property */
chr->chr.uuid); /* uuid */
curr_db_attr++;
// Iterate over descriptors
SLIST_FOREACH(dsc, &chr->dscs, next) {
if (dsc->dsc.handle < start_handle) {
continue;
}
if (dsc->dsc.handle > end_handle) {
*db = buffer;
*count = db_size;
return;
}
ble_gattc_fill_gatt_db_el(curr_db_attr,
BLE_GATT_DB_DESCRIPTOR, /* attr type */
dsc->dsc.handle, /* attr handle */
0, /* s_handle */
0, /* e_handle */
0, /* property */
dsc->dsc.uuid); /* uuid */
curr_db_attr++;
}
}
}
*db = buffer;
*count = db_size;
return;
}
// Copy the server GATT database into db parameter
void ble_gattc_get_gatt_db(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_gattc_db_elem_t **db,
uint16_t *count, uint16_t *db_num)
{
struct ble_gattc_cache_conn *cache_conn;
cache_conn = ble_gattc_cache_conn_find(conn_handle);
if (cache_conn == NULL) {
BLE_HS_LOG(ERROR, "Unknown conn ID: %d", conn_handle);
return;
}
if (cache_conn->cache_state != CACHE_VERIFIED){
BLE_HS_LOG(ERROR, "server cache not available, server state = %d",cache_conn->cache_state);
return;
}
if (SLIST_EMPTY(&cache_conn->svcs)) {
BLE_HS_LOG(ERROR, "the service cache is empty.");
return;
}
ble_gattc_get_gatt_db_impl(cache_conn, start_handle, end_handle, db, count, db_num);
}
static void
ble_gattc_cache_conn_cache_peer(struct ble_gattc_cache_conn *peer)
{
@@ -884,9 +1565,15 @@ ble_gattc_cache_conn_undisc_all(ble_addr_t peer_addr)
}
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
static int
ble_gattc_cache_conn_inc_disced(uint16_t conn_handle, const struct ble_gatt_error *error,
const struct ble_gatt_incl_svc *service, void *arg)
#else
static int
ble_gattc_cache_conn_inc_disced(uint16_t conn_handle, const struct ble_gatt_error *error,
const struct ble_gatt_svc *service, void *arg)
#endif
{
struct ble_gattc_cache_conn *peer;
int rc;
@@ -901,7 +1588,7 @@ ble_gattc_cache_conn_inc_disced(uint16_t conn_handle, const struct ble_gatt_erro
case BLE_HS_EDONE:
/* All services discovered; start discovering incs. */
ble_gattc_cache_conn_disc_chrs(peer);
ble_gattc_cache_conn_disc_incs(peer);
rc = 0;
break;
@@ -929,7 +1616,7 @@ ble_gattc_cache_conn_svc_disced(uint16_t conn_handle, const struct ble_gatt_erro
switch (error->status) {
case 0:
rc = ble_gattc_cache_conn_svc_add(peer->ble_gattc_cache_conn_addr, service);
rc = ble_gattc_cache_conn_svc_add(peer->ble_gattc_cache_conn_addr, service, true);
break;
case BLE_HS_EDONE:
@@ -1211,6 +1898,7 @@ ble_gattc_cache_conn_disc_incs(struct ble_gattc_cache_conn *peer)
if (peer->cur_svc == NULL) {
if (peer->disc_prev_chr_val > 0) {
ble_gattc_cache_conn_disc_chrs(peer);
return;
}
}
}
@@ -1221,7 +1909,7 @@ ble_gattc_cache_conn_disc_incs(struct ble_gattc_cache_conn *peer)
svc->svc.end_handle,
ble_gattc_cache_conn_inc_disced, peer);
if (rc != 0) {
ble_gattc_cache_conn_disc_complete(peer, rc);
ble_gattc_cache_conn_disc_chrs(peer);
}
return;
}
@@ -1285,6 +1973,10 @@ ble_gattc_cache_conn_free_mem(void)
free(ble_gattc_cache_conn_svc_mem);
ble_gattc_cache_conn_svc_mem = NULL;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
free(ble_gattc_cache_conn_incl_svc_mem);
ble_gattc_cache_conn_incl_svc_mem = NULL;
#endif
free(ble_gattc_cache_conn_chr_mem);
ble_gattc_cache_conn_chr_mem = NULL;
@@ -1298,16 +1990,23 @@ ble_gattc_cache_conn_init()
int rc;
int max_ble_gattc_cache_conns;
int max_svcs;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
int max_incl_svcs;
#endif
int max_chrs;
int max_dscs;
void *storage_cb;
max_ble_gattc_cache_conns = MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS);
max_svcs = (MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) *
max_ble_gattc_cache_conns = MYNEWT_VAL(BLE_MAX_CONNECTIONS);
max_svcs = (MYNEWT_VAL(BLE_MAX_CONNECTIONS)) *
(MYNEWT_VAL(BLE_GATT_CACHING_MAX_SVCS));
max_chrs = (MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) *
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
max_incl_svcs = (MYNEWT_VAL(BLE_MAX_CONNECTIONS)) *
(MYNEWT_VAL(BLE_GATT_CACHING_MAX_INCL_SVCS));
#endif
max_chrs = (MYNEWT_VAL(BLE_MAX_CONNECTIONS)) *
(MYNEWT_VAL(BLE_GATT_CACHING_MAX_CHRS));
max_dscs = (MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) *
max_dscs = (MYNEWT_VAL(BLE_MAX_CONNECTIONS)) *
(MYNEWT_VAL(BLE_GATT_CACHING_MAX_DSCS));
/* Free memory first in case this function gets called more than once. */
ble_gattc_cache_conn_free_mem();
@@ -1342,6 +2041,22 @@ ble_gattc_cache_conn_init()
goto err;
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
ble_gattc_cache_conn_incl_svc_mem = malloc(
OS_MEMPOOL_BYTES(max_incl_svcs, sizeof(struct ble_gattc_cache_conn_incl_svc)));
if (ble_gattc_cache_conn_incl_svc_mem == NULL) {
rc = BLE_HS_ENOMEM;
goto err;
}
rc = os_mempool_init(&ble_gattc_cache_conn_incl_svc_pool, max_incl_svcs,
sizeof(struct ble_gattc_cache_conn_incl_svc), ble_gattc_cache_conn_incl_svc_mem,
"ble_gattc_cache_conn_incl_svc_pool");
if (rc != 0) {
rc = BLE_HS_EOS;
goto err;
}
#endif
ble_gattc_cache_conn_chr_mem = malloc(
OS_MEMPOOL_BYTES(max_chrs, sizeof(struct ble_gattc_cache_conn_chr)));
if (ble_gattc_cache_conn_chr_mem == NULL) {
@@ -1585,7 +2300,13 @@ ble_gattc_cache_conn_search_inc_svcs_cb(struct ble_npl_event *ev)
struct ble_gattc_cache_conn_op *op;
int status = 0;
uint16_t conn_handle;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
struct ble_gattc_cache_conn_incl_svc *incl_svc;
ble_gatt_disc_incl_svc_fn *dcb;
#else
ble_gatt_disc_svc_fn *dcb;
#endif
conn_handle = *(uint16_t*)ble_npl_event_get_arg(ev);
conn = ble_gattc_cache_conn_find(conn_handle);
@@ -1597,6 +2318,17 @@ ble_gattc_cache_conn_search_inc_svcs_cb(struct ble_npl_event *ev)
op = &conn->pending_op;
dcb = op->cb;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
svc = ble_gattc_cache_conn_svc_find_range(conn, op->start_handle);
SLIST_FOREACH(incl_svc, &svc->incl_svc, next) {
dcb(conn->conn_handle, ble_gattc_cache_error(status, 0), &incl_svc->svc, op->cb_arg);
}
status = BLE_HS_EDONE;
dcb(conn->conn_handle, ble_gattc_cache_error(status, 0), &incl_svc->svc, op->cb_arg);
#else
SLIST_FOREACH(svc, &conn->svcs, next) {
if (svc->type == BLE_GATT_SVC_TYPE_SECONDARY &&
(svc->svc.start_handle >= op->start_handle && svc->svc.end_handle <= op->end_handle)) {
@@ -1605,13 +2337,21 @@ ble_gattc_cache_conn_search_inc_svcs_cb(struct ble_npl_event *ev)
}
status = BLE_HS_EDONE;
dcb(conn->conn_handle, ble_gattc_cache_error(status, 0), &svc->svc, op->cb_arg);
#endif
return;
}
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
int
ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle,
ble_gatt_disc_incl_svc_fn *cb, void *cb_arg)
#else
int
ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle,
ble_gatt_disc_svc_fn *cb, void *cb_arg)
#endif
{
struct ble_gattc_cache_conn *conn;
struct ble_gattc_cache_conn_op *op;
@@ -1631,8 +2371,8 @@ ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle
return rc;
}
CHECK_CACHE_CONN_STATE(conn->cache_state, cb, cb_arg, BLE_GATT_OP_DISC_ALL_CHRS,
start_handle, end_handle, &uuid);
CHECK_CACHE_CONN_STATE(conn->cache_state, cb, cb_arg, BLE_GATT_OP_FIND_INC_SVCS,
start_handle, end_handle, uuid);
/* put the event in the queue to mimic the gattc behaviour */
ble_npl_event_init(&conn->disc_ev, ble_gattc_cache_conn_search_inc_svcs_cb, &conn->conn_handle);
ble_npl_eventq_put((struct ble_npl_eventq *)ble_hs_evq_get(), &conn->disc_ev);
+141 -3
View File
@@ -47,6 +47,8 @@ typedef struct ble_gatt_nv_attr {
ble_uuid_any_t uuid;
uint8_t properties; /* used for characteristic only */
unsigned int is_primary : 1; /* used for service only */
uint16_t incl_svc_s_handle;
uint16_t incl_svc_e_handle;
} ble_gatt_nv_attr;
/* cache conn */
@@ -65,6 +67,15 @@ struct ble_gattc_cache_conn_chr {
};
SLIST_HEAD(ble_gattc_cache_conn_chr_list, ble_gattc_cache_conn_chr);
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
struct ble_gattc_cache_conn_incl_svc {
SLIST_ENTRY(ble_gattc_cache_conn_incl_svc) next;
struct ble_gatt_incl_svc svc;
};
SLIST_HEAD(ble_gattc_cache_conn_incl_list, ble_gattc_cache_conn_incl_svc);
#endif
struct ble_gattc_cache_conn_svc {
SLIST_ENTRY(ble_gattc_cache_conn_svc) next;
/**
@@ -74,7 +85,9 @@ struct ble_gattc_cache_conn_svc {
*/
uint8_t type;
struct ble_gatt_svc svc;
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
struct ble_gattc_cache_conn_incl_list incl_svc;
#endif
struct ble_gattc_cache_conn_chr_list chrs;
};
SLIST_HEAD(ble_gattc_cache_conn_svc_list, ble_gattc_cache_conn_svc);
@@ -122,6 +135,35 @@ struct ble_gattc_cache_conn {
the application about the discovery results */
struct ble_npl_event disc_ev;
};
/** Enumerates types of GATT database attributes */
typedef enum {
BLE_GATT_DB_PRIMARY_SERVICE, /*!< Primary service attribute. */
BLE_GATT_DB_SECONDARY_SERVICE, /*!< Secondary service attribute. */
BLE_GATT_DB_INCLUDED_SERVICE, /*!< Included service attribute. */
BLE_GATT_DB_CHARACTERISTIC, /*!< Characteristic attribute. */
BLE_GATT_DB_DESCRIPTOR, /*!< Descriptor attribute. */
} ble_gattc_db_attr_type;
typedef enum {
BLE_GATT_OP_GET_SVC_BY_UUID, /*!< Get primary service from cache using service UUID. */
BLE_GATT_OP_GET_ALL_CHAR, /*!< Get all characteristics for a given service from cache. */
BLE_GATT_OP_GET_ALL_DESC, /*!< Get all descriptors for a given characteristic from cache. */
BLE_GATT_OP_GET_CHAR_BY_UUID, /*!< Get characteristic from a service using characteristic UUID. */
BLE_GATT_OP_GET_DESC_BY_UUID, /*!< Get descriptor from a characteristic using descriptor UUID. */
BLE_GATT_OP_GET_DESC_BY_HANDLE, /*!< Get descriptor from cache using descriptor handle. */
BLE_GATT_OP_GET_INCLUDE_SVC, /*!< Get included services from a given service in cache. */
} ble_gatt_get_db_op_t;
typedef struct {
ble_gatt_get_db_op_t type; /*!< Attribute type (e.g., characteristic, descriptor) */
uint16_t handle; /*!< Attribute handle (unique identifier) */
uint16_t start_handle; /*!< Service start handle */
uint16_t end_handle; /*!< Service end handle */
uint8_t properties; /*!< Characteristic properties (read, write, notify, etc.) */
ble_uuid_any_t uuid; /*!< Attribute UUID */
} ble_gattc_db_elem_t;
/* apis from gatt service */
uint16_t ble_svc_gatt_changed_handle();
uint16_t ble_svc_gatt_hash_handle();
@@ -132,12 +174,100 @@ uint8_t ble_svc_gatt_get_csfs();
void ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle);
#endif
int ble_gattc_cache_conn_add(uint16_t conn_handle, ble_addr_t ble_gattc_cache_conn_addr);
int ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc);
int ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc);
int ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc, bool is_primary);
#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)
int ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_incl_svc *gatt_svc);
#else
int ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr,const struct ble_gatt_svc *gatt_svc);
#endif
int ble_gattc_cache_conn_chr_add(ble_addr_t peer_addr, uint16_t svc_start_handle,
const struct ble_gatt_chr *gatt_chr);
int ble_gattc_cache_conn_dsc_add(ble_addr_t peer_addr, uint16_t chr_val_handle,
const struct ble_gatt_dsc *gatt_dsc);
/**
* These APIs fetch previously discovered GATT information (like services,
* characteristics, or descriptors) from the local cache without triggering
* a new discovery procedure.
*/
void ble_gattc_get_cached_service_by_uuid_db(uint16_t conn_handle,
ble_uuid_t *svc_uuid,
ble_gattc_db_elem_t **db,
uint16_t *count);
void ble_gattc_get_cached_all_char_db(uint16_t conn_id, uint16_t start_handle,
uint16_t end_handle, ble_gattc_db_elem_t **db,
uint16_t *count);
void ble_gattc_get_cached_all_descriptor_db(uint16_t conn_id, uint16_t char_handle,
ble_gattc_db_elem_t **db, uint16_t *count);
void ble_gattc_get_cached_char_by_uuid_db(uint16_t conn_id, uint16_t start_handle,
uint16_t end_handle, ble_uuid_t *char_uuid,
ble_gattc_db_elem_t **db, uint16_t *count);
void ble_gatt_get_cached_descr_by_uuid_db(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle,
ble_uuid_t *char_uuid, ble_uuid_t *descr_uuid,
ble_gattc_db_elem_t **db, uint16_t *count);
void ble_gattc_get_cached_descr_by_char_handle_db(uint16_t conn_id, uint16_t char_handle,
ble_uuid_t *descr_uuid,
ble_gattc_db_elem_t **db, uint16_t *count);
void ble_gattc_get_cached_gatt_db(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
ble_gattc_db_elem_t **db,
uint16_t *count, uint16_t *db_num);
void ble_gattc_get_db_size(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle, uint16_t *count);
void ble_gattc_get_db_size_by_type(uint16_t conn_handle, ble_gattc_db_attr_type type,
uint16_t start_handle, uint16_t end_handle,
uint16_t char_handle, uint16_t *count);
void ble_gattc_fill_gatt_db_el(ble_gattc_db_elem_t *attr,
ble_gattc_db_attr_type type,
uint16_t handle,
uint16_t s_handle,
uint16_t e_handle,
uint8_t prop,
ble_uuid_any_t uuid);
void ble_gattc_get_service_with_uuid(uint16_t conn_handle,
ble_uuid_t *svc_uuid,
ble_gattc_db_elem_t **svc_db,
uint16_t *count);
void ble_gattc_get_db_with_operation(uint16_t conn_handle,
ble_gatt_get_db_op_t op,
uint16_t char_handle,
ble_uuid_t *char_uuid,
ble_uuid_t *descr_uuid,
ble_uuid_t *incl_uuid,
uint16_t start_handle, uint16_t end_handle,
ble_gattc_db_elem_t **char_db,
uint16_t *count);
void ble_gattc_get_db_size_with_type_handle(uint16_t conn_handle,
ble_gattc_db_attr_type type,
uint16_t start_handle,
uint16_t end_handle,
uint16_t char_handle,
uint16_t *count);
void ble_gattc_get_db_size_handle(uint16_t conn_handle,
uint16_t start_handle,
uint16_t end_handle,
uint16_t *count);
void ble_gattc_get_gatt_db(uint16_t conn_id,
uint16_t start_handle,
uint16_t end_handle,
ble_gattc_db_elem_t **db,
uint16_t *count, uint16_t *db_num);
/**
* Loads the cache for the connection given by conn_handle
*/
@@ -162,9 +292,15 @@ int ble_gattc_cache_conn_search_all_svcs(uint16_t conn_handle,
ble_gatt_disc_svc_fn *cb, void *cb_arg);
int ble_gattc_cache_conn_search_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid,
ble_gatt_disc_svc_fn *cb, void *cb_arg);
#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES))
int ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle,
ble_gatt_disc_incl_svc_fn *cb, void *cb_arg);
#else
int ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle,
ble_gatt_disc_svc_fn *cb, void *cb_arg);
#endif
int ble_gattc_cache_conn_search_all_chrs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle, ble_gatt_chr_fn *cb,
void *cb_arg);
@@ -176,6 +312,8 @@ ble_gattc_cache_conn_search_all_dscs(uint16_t conn_handle, uint16_t start_handle
uint16_t end_handle,
ble_gatt_dsc_fn *cb, void *cb_arg);
struct ble_gattc_cache_conn *
ble_gattc_cache_conn_find(uint16_t conn_handle);
#ifdef __cplusplus
}
#endif