Skip to content

Commit d9be0f7

Browse files
committed
Bluetooth: Host: Conn: Add GAP service verification
Implement the verification if there is exactly one GAP service in GATT database. The verification is performed as soon as the GATT database is available and forbids to enable the Bluetooth if the configuration is not compatible with the Bluetooth Specification. The verification may be disabled by the user for better performance or deliberate implementation that is not compliant with the specification. Signed-off-by: Radosław Koppel <[email protected]>
1 parent 2140f30 commit d9be0f7

File tree

6 files changed

+118
-0
lines changed

6 files changed

+118
-0
lines changed

subsys/bluetooth/host/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ if(CONFIG_BT_HCI_HOST)
4949
gatt.c
5050
)
5151

52+
zephyr_library_sources_ifdef(
53+
CONFIG_GATT_GAP_SVC_VALIDATE
54+
gatt_gap_svc_validate.c
55+
)
56+
5257
if(CONFIG_BT_SMP)
5358
zephyr_library_sources(
5459
smp.c

subsys/bluetooth/host/Kconfig.gatt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,5 @@ config BT_GATT_AUTHORIZATION_CUSTOM
267267
with the bt_gatt_authorization_cb_register API. See the API
268268
documentation for more details.
269269

270+
rsource 'Kconfig.gatt_gap_svc_validate'
270271
endmenu
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Bluetooth GATT GAP service validation
2+
3+
# Copyright (c) 2025 Koppel Electronic
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
menuconfig GATT_GAP_SVC_VALIDATE
7+
bool "GATT GAP Service validation"
8+
depends on BT_CONN
9+
default y
10+
help
11+
Validate if in the GATT database exactly one GAP service is present.
12+
This helps to debug any issues related to GAP service that may make
13+
the Bluetooth implementation not compatible with the standard.
14+
15+
if GATT_GAP_SVC_VALIDATE
16+
17+
module = GATT_GAP_SVC_VALIDATE
18+
module-str = gatt-gap-validate
19+
source "subsys/logging/Kconfig.template.log_config"
20+
21+
endif # GATT_GAP_SVC_VALIDATE

subsys/bluetooth/host/conn.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "common/bt_str.h"
5353
#include "conn_internal.h"
5454
#include "direction_internal.h"
55+
#include "gatt_gap_svc_validate.h"
5556
#include "hci_core.h"
5657
#include "id.h"
5758
#include "iso_internal.h"
@@ -4285,6 +4286,14 @@ int bt_conn_init(void)
42854286

42864287
bt_att_init();
42874288

4289+
if (IS_ENABLED(CONFIG_GATT_GAP_SVC_VALIDATE)) {
4290+
err = gatt_gap_svc_validate();
4291+
if (err) {
4292+
LOG_ERR("GATT GAP service validation failed (err %d)", err);
4293+
return err;
4294+
}
4295+
}
4296+
42884297
err = bt_smp_init();
42894298
if (err) {
42904299
return err;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* gatt_gap_validate.c - GAP service inside GATT validation functions */
2+
3+
/*
4+
* Copyright (c) 2025 Koppel Electronic
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#include <zephyr/bluetooth/gatt.h>
10+
#include <zephyr/bluetooth/uuid.h>
11+
#include <zephyr/logging/log.h>
12+
13+
14+
#define MODULE gatt_gap_validate
15+
16+
LOG_MODULE_REGISTER(MODULE, CONFIG_GATT_GAP_SVC_VALIDATE_LOG_LEVEL);
17+
18+
19+
static uint8_t gap_service_check_cb(const struct bt_gatt_attr *attr,
20+
uint16_t handle,
21+
void *user_data)
22+
{
23+
size_t *cnt = user_data;
24+
const struct bt_uuid *svc_uuid = attr->user_data;
25+
26+
if (svc_uuid && bt_uuid_cmp(svc_uuid, BT_UUID_GAP) == 0) {
27+
(*cnt)++;
28+
LOG_DBG("GAP service found at handle: %u", handle);
29+
if (*cnt > 1) {
30+
LOG_ERR("Multiple (%zu) GAP services found at handle: %u",
31+
*cnt, handle);
32+
}
33+
}
34+
35+
return BT_GATT_ITER_CONTINUE;
36+
}
37+
38+
int gatt_gap_svc_validate(void)
39+
{
40+
size_t gap_svc_count = 0;
41+
42+
bt_gatt_foreach_attr_type(
43+
BT_ATT_FIRST_ATTRIBUTE_HANDLE,
44+
BT_ATT_LAST_ATTRIBUTE_HANDLE,
45+
BT_UUID_GATT_PRIMARY,
46+
NULL, 0,
47+
gap_service_check_cb,
48+
&gap_svc_count);
49+
50+
if (gap_svc_count != 1) {
51+
LOG_ERR("GAP service count invalid: %zu", gap_svc_count);
52+
return -EINVAL;
53+
}
54+
return 0;
55+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/** @file
2+
* @brief Internal API GATT GAP service validation.
3+
*/
4+
5+
/*
6+
* Copyright (c) 2025 Koppel Electronic
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*/
10+
11+
#ifndef __BT_GATT_GAP_SVC_VALIDATE_H
12+
#define __BT_GATT_GAP_SVC_VALIDATE_H
13+
14+
15+
/** @brief Validate GATT database contains exactly one GAP service.
16+
*
17+
* This function iterates through the GATT attribute database and verifies
18+
* that exactly one Generic Access Profile (GAP) service is present. The
19+
* Bluetooth specification requires that a GATT server expose exactly one
20+
* GAP service.
21+
*
22+
* @return 0 on success (exactly one GAP service found).
23+
* @return -EINVAL if zero or multiple GAP services are found.
24+
*/
25+
int gatt_gap_svc_validate(void);
26+
27+
#endif /* __BT_GATT_GAP_SVC_VALIDATE_H */

0 commit comments

Comments
 (0)