Bluetooth: GATT: Change get_handle function of find_by_uuid

bt_gatt_find_by_uuid used bt_gatt_attr_value_handle but that
function only works to get the value handle of a characteristic
declaration, i.e. if the UUID is not BT_UUID_GATT_CHRC then it
would always return handle = 0. This meant that
bt_gatt_find_by_uuid would always use handle = 0 as the starting
handle for non-BT_UUID_GATT_CHRC attributes, instead of the handle
of the provided attr.

This was not an issue for any UUIDs that may only exist once on a
GATT server, which is most UUIDs, but for UUIDs like the
BT_UUID_TBS_* UUIDs that may be multiple instances of, it would
always return the first attribute rather than the one starting
from the provided start attr.

This commit also ensures that we do not overflow the `end_handle`
when adding 2 uint16_t values.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2025-01-14 14:23:46 +01:00 committed by Benjamin Cabé
parent 8b7beff153
commit e4c5bb99b0
4 changed files with 22 additions and 17 deletions

View file

@ -717,7 +717,8 @@ uint16_t bt_gatt_attr_get_handle(const struct bt_gatt_attr *attr);
*
* @param attr A Characteristic Attribute.
*
* @note The ``user_data`` of the attribute must of type @ref bt_gatt_chrc.
* @note The ``user_data`` of the attribute must of type @ref bt_gatt_chrc and the ``uuid`` shall be
* BT_UUID_GATT_CHRC
*
* @return the handle of the corresponding Characteristic Value. The value will
* be zero (the invalid handle) if @p attr was not a characteristic

View file

@ -7,6 +7,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/bluetooth/att.h>
#include <zephyr/kernel.h>
#include <string.h>
#include <errno.h>
@ -2852,12 +2855,20 @@ struct bt_gatt_attr *bt_gatt_find_by_uuid(const struct bt_gatt_attr *attr,
const struct bt_uuid *uuid)
{
struct bt_gatt_attr *found = NULL;
uint16_t start_handle = bt_gatt_attr_value_handle(attr);
uint16_t end_handle = start_handle && attr_count ?
start_handle + attr_count : 0xffff;
uint16_t start_handle = bt_gatt_attr_get_handle(attr);
uint16_t end_handle = start_handle && attr_count
? MIN(start_handle + attr_count, BT_ATT_LAST_ATTRIBUTE_HANDLE)
: BT_ATT_LAST_ATTRIBUTE_HANDLE;
bt_gatt_foreach_attr_type(start_handle, end_handle, uuid, NULL, 1,
find_next, &found);
if (attr != NULL && start_handle == 0U) {
/* If start_handle is 0 then `attr` is not in our database, and should not be used
* as a starting point for the search
*/
LOG_DBG("Could not find handle of attr %p", attr);
return NULL;
}
bt_gatt_foreach_attr_type(start_handle, end_handle, uuid, NULL, 1, find_next, &found);
return found;
}

View file

@ -230,11 +230,8 @@ static void check_ccc_handle(void)
__ASSERT(actual_val_handle == VAL_HANDLE,
"Please update the VAL_HANDLE define (actual_val_handle=%d)", actual_val_handle);
struct bt_gatt_attr attr = {
.uuid = BT_UUID_GATT_CHRC,
.user_data = &(struct bt_gatt_chrc){ .value_handle = actual_val_handle }};
struct bt_gatt_attr *ccc_attr = bt_gatt_find_by_uuid(&attr, 0, BT_UUID_GATT_CCC);
struct bt_gatt_attr *ccc_attr =
bt_gatt_find_by_uuid(service_notify_attr, 0, BT_UUID_GATT_CCC);
uint16_t actual_ccc_handle = bt_gatt_attr_get_handle(ccc_attr);
__ASSERT(actual_ccc_handle == CCC_HANDLE,

View file

@ -272,12 +272,8 @@ static void check_ccc_handle(void)
struct bt_gatt_attr *service_notify_attr =
bt_gatt_find_by_uuid(NULL, 0, &notify_characteristic_uuid.uuid);
struct bt_gatt_attr attr = {
.uuid = BT_UUID_GATT_CHRC,
.user_data = &(struct bt_gatt_chrc){
.value_handle = bt_gatt_attr_get_handle(service_notify_attr)}};
struct bt_gatt_attr *ccc_attr = bt_gatt_find_by_uuid(&attr, 0, BT_UUID_GATT_CCC);
struct bt_gatt_attr *ccc_attr =
bt_gatt_find_by_uuid(service_notify_attr, 0, BT_UUID_GATT_CCC);
uint16_t actual_ccc_handle = bt_gatt_attr_get_handle(ccc_attr);
__ASSERT(actual_ccc_handle == CCC_HANDLE,