mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-26 20:00:02 +00:00
fix(nimble): Added api's for fetching gatt cache data and for discovering included services
This commit is contained in:
@@ -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
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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 *
|
||||
*****************************************************************************/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user