Skip to content

Commit 75366c1

Browse files
committed
tests: Bluetooth: Classic: Add test suites gap_discovery
Add test cases gap_central.test_01_gap_central_general_discovery and gap_central.test_02_gap_central_limited_discovery. Add test cases gap_peripheral.test_01_gap_peripheral_general_discovery and gap_peripheral.test_02_gap_peripheral_limited_discovery. Signed-off-by: Lyle Zhu <[email protected]>
1 parent d14a547 commit 75366c1

File tree

8 files changed

+1349
-0
lines changed

8 files changed

+1349
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
set(NO_QEMU_SERIAL_BT_SERVER 1)
5+
6+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
7+
project(bluetooth)
8+
9+
if(CONFIG_TEST_GAP_PERIPHERAL)
10+
FILE(GLOB app_sources src/test_peripheral.c)
11+
endif ()
12+
13+
if(CONFIG_TEST_GAP_CENTRAL)
14+
FILE(GLOB app_sources src/test_central.c)
15+
endif()
16+
17+
target_sources(app PRIVATE ${app_sources})
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2025 NXP
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
source "Kconfig.zephyr"
6+
7+
choice TEST_GAP_ROLE
8+
prompt "GAP Role"
9+
default TEST_GAP_PERIPHERAL
10+
help
11+
Select the GAP role for testing
12+
13+
config TEST_GAP_PERIPHERAL
14+
bool "GAP Role Peripheral"
15+
help
16+
Test GAP role as peripheral device
17+
18+
config TEST_GAP_CENTRAL
19+
bool "GAP Role Central"
20+
help
21+
Test GAP role as central device
22+
23+
endchoice
24+
25+
config TEST_GAP_CENTRAL_ADDRESS
26+
string "Central Device Address"
27+
default "00:11:22:33:44:55"
28+
help
29+
GAP central device Bluetooth address in format XX:XX:XX:XX:XX:XX
30+
31+
config TEST_GAP_PERIPHERAL_ADDRESS
32+
string "Peripheral Device Address"
33+
default "AA:BB:CC:DD:EE:FF"
34+
help
35+
GAP peripheral device Bluetooth address in format XX:XX:XX:XX:XX:XX
36+
37+
module = TEST_GAP_DISCOVERY
38+
module-str = test_gap_discovery
39+
source "subsys/logging/Kconfig.template.log_config"
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
.. _bluetooth_classic_gap_discovery_test:
2+
3+
Bluetooth Classic GAP Discovery Test
4+
#####################################
5+
6+
Overview
7+
********
8+
9+
This test verifies the Bluetooth Classic GAP (Generic Access Profile) discovery
10+
functionality. It tests the device's ability to discover nearby Bluetooth Classic
11+
devices through inquiry procedures.
12+
13+
Requirements
14+
************
15+
16+
* A board with Bluetooth Classic support
17+
* Bluetooth Classic controller enabled in the configuration
18+
19+
Building and Running
20+
********************
21+
22+
This test can be built and executed on boards with Bluetooth Classic support.
23+
24+
.. code-block:: console
25+
26+
./tests/bluetooth/classic/gap_discovery/tests_scripts/gap_discovery_run.sh
27+
28+
If the error "Permission denied" occurs, the following command should be used to add permission for
29+
the script.
30+
31+
.. code-block:: console
32+
33+
chmod +x ./tests/bluetooth/classic/gap_discovery/tests_scripts/gap_discovery_run.sh
34+
35+
If the error "west: command not found" occurs, the following command should be used to activate the
36+
virtual environment. Refer to :ref:`getting_started` for details.
37+
38+
.. code-block:: console
39+
40+
source ~/zephyrproject/.venv/bin/activate
41+
42+
Sample Output
43+
*************
44+
45+
.. code-block:: console
46+
47+
------ TESTSUITE SUMMARY START ------
48+
49+
SUITE PASS - 100.00% [gap_central]: pass = 2, fail = 0, skip = 0, total = 2 duration = 46.640 seconds
50+
- PASS - [gap_central.test_01_gap_central_general_discovery] duration = 5.180 seconds
51+
- PASS - [gap_central.test_02_gap_central_limited_discovery] duration = 41.460 seconds
52+
53+
------ TESTSUITE SUMMARY END ------
54+
55+
------ TESTSUITE SUMMARY START ------
56+
57+
SUITE PASS - 100.00% [gap_peripheral]: pass = 2, fail = 0, skip = 0, total = 2 duration = 48.620 seconds
58+
- PASS - [gap_peripheral.test_01_gap_peripheral_general_discovery] duration = 7.180 seconds
59+
- PASS - [gap_peripheral.test_02_gap_peripheral_limited_discovery] duration = 41.440 seconds
60+
61+
------ TESTSUITE SUMMARY END ------
62+
63+
Test Coverage
64+
*************
65+
66+
This test covers:
67+
68+
* Bluetooth Classic initialization
69+
* GAP inquiry start/stop procedures
70+
* Device discovery callbacks
71+
* Inquiry result handling
72+
73+
Configuration Options
74+
*********************
75+
76+
See :file:`prj.conf` for the default configuration.
77+
78+
Additional configuration options can be found in :file:`Kconfig`.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CONFIG_BT=y
2+
CONFIG_BT_CLASSIC=y
3+
CONFIG_LOG=y
4+
CONFIG_ZTEST=y
5+
6+
CONFIG_BT_DEVICE_NAME="gap_discovery"
7+
8+
CONFIG_BT_CREATE_CONN_TIMEOUT=30
9+
CONFIG_BT_PAGE_TIMEOUT=0xFFFF
10+
CONFIG_BT_LIMITED_DISCOVERABLE_DURATION=31
11+
12+
CONFIG_TEST_GAP_DISCOVERY_LOG_LEVEL_DBG=y
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/sys/byteorder.h>
9+
#include <zephyr/bluetooth/bluetooth.h>
10+
#include <zephyr/bluetooth/hci.h>
11+
#include <zephyr/logging/log.h>
12+
#include <zephyr/ztest.h>
13+
14+
#define LOG_MODULE_NAME test_gap_discovery_central
15+
LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_TEST_GAP_DISCOVERY_LOG_LEVEL);
16+
17+
static struct bt_br_discovery_param br_discover_param;
18+
#define BR_DISCOVER_RESULT_COUNT 10
19+
static struct bt_br_discovery_result br_discover_result[BR_DISCOVER_RESULT_COUNT];
20+
21+
static K_SEM_DEFINE(br_discover_sem, 0, 1);
22+
23+
static bt_addr_t peer_addr;
24+
static ATOMIC_DEFINE(test_flags, 32);
25+
26+
#define TEST_FLAG_DEVICE_FOUND 0
27+
#define TEST_FLAG_CONN_CONNECTED 1
28+
#define TEST_FLAG_CONN_DISCONNECTED 2
29+
30+
static void br_discover_timeout(const struct bt_br_discovery_result *results, size_t count)
31+
{
32+
LOG_DBG("BR discovery done, found %zu devices", count);
33+
34+
k_sem_give(&br_discover_sem);
35+
}
36+
37+
static void br_discover_recv(const struct bt_br_discovery_result *result)
38+
{
39+
char br_addr[BT_ADDR_STR_LEN];
40+
41+
bt_addr_to_str(&result->addr, br_addr, sizeof(br_addr));
42+
43+
LOG_DBG("[DEVICE]: %s, RSSI %i", br_addr, result->rssi);
44+
45+
if (bt_addr_eq(&peer_addr, &result->addr)) {
46+
atomic_set_bit(test_flags, TEST_FLAG_DEVICE_FOUND);
47+
LOG_DBG(" Target %s is found", br_addr);
48+
k_sem_give(&br_discover_sem);
49+
}
50+
}
51+
52+
static struct bt_br_discovery_cb br_discover = {
53+
.recv = br_discover_recv,
54+
.timeout = br_discover_timeout,
55+
};
56+
57+
static void br_connected(struct bt_conn *conn, uint8_t conn_err)
58+
{
59+
LOG_DBG("connected: conn %p err 0x%02x", (void *)conn, conn_err);
60+
if (conn_err == 0) {
61+
k_sem_give(&br_discover_sem);
62+
atomic_set_bit(test_flags, TEST_FLAG_CONN_CONNECTED);
63+
} else {
64+
LOG_ERR("Connection failed");
65+
}
66+
}
67+
68+
static void br_disconnected(struct bt_conn *conn, uint8_t reason)
69+
{
70+
LOG_DBG("disconnected: conn %p reason 0x%02x", (void *)conn, reason);
71+
k_sem_give(&br_discover_sem);
72+
atomic_set_bit(test_flags, TEST_FLAG_CONN_DISCONNECTED);
73+
}
74+
75+
BT_CONN_CB_DEFINE(conn_callbacks) = {
76+
.connected = br_connected,
77+
.disconnected = br_disconnected,
78+
};
79+
80+
#define GAP_DISCOVERY_TIMEOUT(count) ((double)count * (double)1.25 + (double)5)
81+
82+
static bool peer_device_discovery(bool limited)
83+
{
84+
int err;
85+
double timeout;
86+
87+
atomic_clear_bit(test_flags, TEST_FLAG_DEVICE_FOUND);
88+
89+
LOG_DBG("Starting Bluetooth inquiry");
90+
91+
br_discover_param.length = BR_DISCOVER_RESULT_COUNT;
92+
br_discover_param.limited = limited;
93+
94+
err = bt_br_discovery_start(&br_discover_param, br_discover_result,
95+
ARRAY_SIZE(br_discover_result));
96+
zassert_equal(err, 0, "Bluetooth inquiry failed (err %d)", err);
97+
98+
/* Wait for all discovery results to be processed */
99+
timeout = GAP_DISCOVERY_TIMEOUT(ARRAY_SIZE(br_discover_result));
100+
LOG_DBG("Will wait for GAP discovery done (timeout %us)", (uint32_t)timeout);
101+
err = k_sem_take(&br_discover_sem, K_SECONDS(timeout));
102+
zassert_equal(err, 0, "Failed to wait for discovery done (err %d)", err);
103+
104+
err = bt_br_discovery_stop();
105+
if (err != 0) {
106+
LOG_ERR("Failed to stop GAP discovery procedure (err %d)", err);
107+
}
108+
109+
LOG_DBG("Bluetooth inquiry completed");
110+
111+
return atomic_test_bit(test_flags, TEST_FLAG_DEVICE_FOUND);
112+
}
113+
114+
static void peer_device_connect(void)
115+
{
116+
int err;
117+
struct bt_conn *conn;
118+
119+
conn = bt_conn_create_br(&peer_addr, BT_BR_CONN_PARAM_DEFAULT);
120+
zassert_true(conn != NULL, "BR connection creating failed");
121+
122+
err = k_sem_take(&br_discover_sem, K_SECONDS(30));
123+
zassert_equal(err, 0, "Connection timeout (err %d)", err);
124+
zassert_true(atomic_test_bit(test_flags, TEST_FLAG_CONN_CONNECTED), "Connection failed");
125+
126+
k_sem_reset(&br_discover_sem);
127+
128+
k_sleep(K_SECONDS(5));
129+
130+
err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
131+
zassert_equal(err, 0, "Disconnection ACL failed (err %d)", err);
132+
133+
err = k_sem_take(&br_discover_sem, K_SECONDS(30));
134+
zassert_equal(err, 0, "Disconnection timeout (err %d)", err);
135+
zassert_true(atomic_test_bit(test_flags, TEST_FLAG_CONN_DISCONNECTED),
136+
"Disconnection failed");
137+
138+
bt_conn_unref(conn);
139+
}
140+
141+
ZTEST(gap_central, test_01_gap_central_general_discovery)
142+
{
143+
bool found;
144+
145+
found = peer_device_discovery(false);
146+
147+
zassert_true(found, "Peer device not found");
148+
149+
peer_device_connect();
150+
}
151+
152+
#define BT_COD_MAJOR_SVC_CLASS_LIMITED_DISCOVER BIT(13)
153+
154+
ZTEST(gap_central, test_02_gap_central_limited_discovery)
155+
{
156+
bool found;
157+
uint32_t cod;
158+
159+
found = peer_device_discovery(true);
160+
161+
zassert_true(found, "Peer device not found");
162+
163+
found = peer_device_discovery(true);
164+
165+
zassert_true(found, "Peer device not found");
166+
167+
cod = sys_get_le24(br_discover_result[0].cod);
168+
zassert_true((cod & BT_COD_MAJOR_SVC_CLASS_LIMITED_DISCOVER) != 0,
169+
"Invalid COD (limited bit not set)");
170+
171+
k_sleep(K_SECONDS(CONFIG_BT_LIMITED_DISCOVERABLE_DURATION + 5));
172+
173+
found = peer_device_discovery(true);
174+
if (found) {
175+
cod = sys_get_le24(br_discover_result[0].cod);
176+
zassert_true((cod & BT_COD_MAJOR_SVC_CLASS_LIMITED_DISCOVER) == 0,
177+
"Invalid COD (limited bit is set)");
178+
}
179+
180+
peer_device_connect();
181+
}
182+
183+
static void *setup(void)
184+
{
185+
int err;
186+
187+
LOG_DBG("Initializing Bluetooth");
188+
189+
/* Initialize the Bluetooth Subsystem */
190+
err = bt_enable(NULL);
191+
zassert_equal(err, 0, "Bluetooth init failed (err %d)", err);
192+
193+
LOG_DBG("Bluetooth initialized");
194+
195+
err = bt_addr_from_str(CONFIG_TEST_GAP_PERIPHERAL_ADDRESS, &peer_addr);
196+
zassert_equal(err, 0, "Invalid peer address (err %d)", err);
197+
198+
LOG_DBG("Register discovery callback");
199+
200+
bt_br_discovery_cb_register(&br_discover);
201+
202+
return NULL;
203+
}
204+
205+
static void teardown(void *f)
206+
{
207+
int err;
208+
209+
LOG_DBG("Disabling Bluetooth");
210+
211+
/* De-initialize the Bluetooth Subsystem */
212+
err = bt_disable();
213+
zassert_equal(err, 0, "Bluetooth de-init failed (err %d)", err);
214+
215+
LOG_DBG("Bluetooth de-initialized");
216+
}
217+
218+
static void before(void *f)
219+
{
220+
atomic_clear_bit(test_flags, TEST_FLAG_DEVICE_FOUND);
221+
atomic_clear_bit(test_flags, TEST_FLAG_CONN_CONNECTED);
222+
atomic_clear_bit(test_flags, TEST_FLAG_CONN_DISCONNECTED);
223+
224+
k_sem_reset(&br_discover_sem);
225+
}
226+
227+
static void after(void *f)
228+
{
229+
}
230+
231+
ZTEST_SUITE(gap_central, NULL, setup, before, after, teardown);

0 commit comments

Comments
 (0)