Skip to content

Commit c476456

Browse files
Thalleyjhedberg
authored andcommitted
Tests: Bluetooth: Add BSIM test of ISO BIS
Adds 2 tests for ISO broadcast. First test is just a minimal test that sets up a BIG, transmits data and verifies that it is being received on the ISO sync receiver. The second test creates a BIG, disables BT, enables BT, and the verifies the above. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
1 parent 4a97746 commit c476456

File tree

11 files changed

+782
-0
lines changed

11 files changed

+782
-0
lines changed

tests/bsim/bluetooth/host/compile.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/compile.sh
1818
${ZEPHYR_BASE}/tests/bsim/bluetooth/host/security/compile.sh
1919

2020
app=tests/bsim/bluetooth/host/iso/cis compile
21+
app=tests/bsim/bluetooth/host/iso/bis compile
2122

2223
app=tests/bsim/bluetooth/host/misc/disable compile
2324
app=tests/bsim/bluetooth/host/misc/disconnect/dut compile
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
7+
project(bsim_test_iso_bis)
8+
9+
add_subdirectory(${ZEPHYR_BASE}/tests/bsim/babblekit babblekit)
10+
target_link_libraries(app PRIVATE babblekit)
11+
12+
target_sources(app PRIVATE
13+
src/common.c
14+
src/bis_broadcaster.c
15+
src/bis_receiver.c
16+
src/main.c
17+
)
18+
19+
zephyr_include_directories(
20+
${BSIM_COMPONENTS_PATH}/libUtilv1/src/
21+
${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
22+
)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
CONFIG_BT=y
2+
CONFIG_LOG=y
3+
CONFIG_ASSERT=y
4+
CONFIG_BT_EXT_ADV=y
5+
CONFIG_BT_PER_ADV=y
6+
CONFIG_BT_PER_ADV_SYNC=y
7+
8+
CONFIG_BT_DEVICE_NAME="BIS test"
9+
10+
CONFIG_BT_ISO_BROADCASTER=y
11+
CONFIG_BT_ISO_SYNC_RECEIVER=y
12+
CONFIG_BT_ISO_TX_BUF_COUNT=4
13+
CONFIG_BT_ISO_MAX_CHAN=4
14+
CONFIG_BT_ISO_TX_MTU=200
15+
CONFIG_BT_ISO_RX_MTU=200
16+
17+
CONFIG_BT_ISO_LOG_LEVEL_DBG=y
18+
19+
# Controller ISO configs
20+
CONFIG_BT_CTLR_ADV_ISO=y
21+
CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=4
22+
CONFIG_BT_CTLR_SYNC_ISO=y
23+
CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=4
24+
CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=208
25+
CONFIG_BT_CTLR_ISO_TX_BUFFERS=4
26+
CONFIG_BT_CTLR_ISOAL_SOURCES=4
27+
CONFIG_BT_CTLR_ISOAL_SINKS=4
Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "common.h"
8+
9+
#include <zephyr/bluetooth/bluetooth.h>
10+
#include <zephyr/bluetooth/iso.h>
11+
#include <zephyr/logging/log.h>
12+
13+
#include "babblekit/flags.h"
14+
#include "babblekit/sync.h"
15+
#include "babblekit/testcase.h"
16+
17+
LOG_MODULE_REGISTER(bis_broadcaster, LOG_LEVEL_INF);
18+
19+
#define LATENCY_MS 10U /* 10ms */
20+
#define SDU_INTERVAL_US 10U * USEC_PER_MSEC /* 10 ms */
21+
22+
extern enum bst_result_t bst_result;
23+
static struct bt_iso_chan iso_chans[CONFIG_BT_ISO_MAX_CHAN];
24+
static struct bt_iso_chan *default_chan = &iso_chans[0];
25+
static uint16_t seq_num;
26+
NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT,
27+
BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
28+
CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
29+
30+
static DEFINE_FLAG(flag_iso_connected);
31+
32+
static void send_data_cb(struct k_work *work);
33+
K_WORK_DELAYABLE_DEFINE(iso_send_work, send_data_cb);
34+
35+
static void send_data(struct bt_iso_chan *chan)
36+
{
37+
static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU];
38+
static size_t len_to_send = 1U;
39+
static bool data_initialized;
40+
struct net_buf *buf;
41+
int ret;
42+
43+
if (!IS_FLAG_SET(flag_iso_connected)) {
44+
/* TX has been aborted */
45+
return;
46+
}
47+
48+
if (!data_initialized) {
49+
for (int i = 0; i < ARRAY_SIZE(buf_data); i++) {
50+
buf_data[i] = (uint8_t)i;
51+
}
52+
53+
data_initialized = true;
54+
}
55+
56+
buf = net_buf_alloc(&tx_pool, K_NO_WAIT);
57+
TEST_ASSERT(buf != NULL, "Failed to allocate buffer");
58+
59+
net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
60+
61+
net_buf_add_mem(buf, buf_data, len_to_send);
62+
63+
ret = bt_iso_chan_send(default_chan, buf, seq_num++);
64+
if (ret < 0) {
65+
LOG_DBG("Failed to send ISO data: %d", ret);
66+
net_buf_unref(buf);
67+
68+
/* Reschedule for next interval */
69+
k_work_reschedule(&iso_send_work, K_USEC(SDU_INTERVAL_US));
70+
71+
return;
72+
}
73+
74+
len_to_send++;
75+
if (len_to_send > ARRAY_SIZE(buf_data)) {
76+
len_to_send = 1;
77+
}
78+
}
79+
80+
static void send_data_cb(struct k_work *work)
81+
{
82+
const uint16_t tx_pool_cnt = tx_pool.uninit_count;
83+
84+
/* Send/enqueue as many as we can */
85+
for (uint16_t i = 0U; i < tx_pool_cnt; i++) {
86+
send_data(default_chan);
87+
}
88+
}
89+
90+
static void iso_connected_cb(struct bt_iso_chan *chan)
91+
{
92+
LOG_INF("ISO Channel %p connected", chan);
93+
94+
if (chan == default_chan) {
95+
seq_num = 0U;
96+
97+
SET_FLAG(flag_iso_connected);
98+
}
99+
}
100+
101+
static void iso_disconnected_cb(struct bt_iso_chan *chan, uint8_t reason)
102+
{
103+
LOG_INF("ISO Channel %p disconnected (reason 0x%02x)", chan, reason);
104+
105+
if (chan == default_chan) {
106+
k_work_cancel_delayable(&iso_send_work);
107+
108+
UNSET_FLAG(flag_iso_connected);
109+
}
110+
}
111+
112+
static void sdu_sent_cb(struct bt_iso_chan *chan)
113+
{
114+
if (!IS_FLAG_SET(flag_iso_connected)) {
115+
/* TX has been aborted */
116+
return;
117+
}
118+
119+
send_data(chan);
120+
}
121+
122+
static void init(void)
123+
{
124+
static struct bt_iso_chan_ops iso_ops = {
125+
.disconnected = iso_disconnected_cb,
126+
.connected = iso_connected_cb,
127+
.sent = sdu_sent_cb,
128+
};
129+
static struct bt_iso_chan_io_qos iso_tx = {
130+
.sdu = CONFIG_BT_ISO_TX_MTU,
131+
.phy = BT_GAP_LE_PHY_2M,
132+
.rtn = 1,
133+
.path = NULL,
134+
};
135+
static struct bt_iso_chan_qos iso_qos = {
136+
.tx = &iso_tx,
137+
.rx = NULL,
138+
};
139+
int err;
140+
141+
err = bt_enable(NULL);
142+
TEST_ASSERT(err == 0, "Bluetooth enable failed: %d", err);
143+
144+
for (size_t i = 0U; i < ARRAY_SIZE(iso_chans); i++) {
145+
iso_chans[i].ops = &iso_ops;
146+
iso_chans[i].qos = &iso_qos;
147+
}
148+
149+
bk_sync_init();
150+
}
151+
152+
static void create_ext_adv(struct bt_le_ext_adv **adv)
153+
{
154+
int err;
155+
156+
LOG_INF("Creating extended advertising set with periodic advertising");
157+
158+
/* Create a non-connectable non-scannable advertising set */
159+
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv);
160+
TEST_ASSERT(err == 0, "Unable to create extended advertising set: %d", err);
161+
162+
/* Set periodic advertising parameters */
163+
err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_PARAM(BT_GAP_PER_ADV_FAST_INT_MIN_2,
164+
BT_GAP_PER_ADV_FAST_INT_MAX_2,
165+
BT_LE_PER_ADV_OPT_NONE));
166+
TEST_ASSERT(err == 0, "Failed to set periodic advertising parameters: %d", err);
167+
}
168+
169+
static void start_ext_adv(struct bt_le_ext_adv *adv)
170+
{
171+
int err;
172+
173+
LOG_INF("Starting extended and periodic advertising");
174+
175+
/* Start extended advertising */
176+
err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
177+
TEST_ASSERT(err == 0, "Failed to start extended advertising: %d", err);
178+
179+
/* FIXME: Temporary workaround to get around an assert in the controller
180+
* Open issue: https://github.com/zephyrproject-rtos/zephyr/issues/72852
181+
*/
182+
k_sleep(K_MSEC(100));
183+
184+
/* Enable Periodic Advertising */
185+
err = bt_le_per_adv_start(adv);
186+
TEST_ASSERT(err == 0, "Failed to enable periodic advertising: %d", err);
187+
}
188+
189+
static void create_big(struct bt_le_ext_adv *adv, size_t cnt, struct bt_iso_big **out_big)
190+
{
191+
struct bt_iso_chan *channels[ARRAY_SIZE(iso_chans)];
192+
struct bt_iso_big_create_param param = {
193+
.packing = BT_ISO_PACKING_SEQUENTIAL,
194+
.framing = BT_ISO_FRAMING_UNFRAMED,
195+
.interval = SDU_INTERVAL_US,
196+
.bis_channels = channels,
197+
.latency = LATENCY_MS,
198+
.encryption = false,
199+
.num_bis = cnt,
200+
};
201+
int err;
202+
203+
for (size_t i = 0U; i < cnt; i++) {
204+
channels[i] = &iso_chans[i];
205+
}
206+
207+
LOG_INF("Creating BIG");
208+
209+
err = bt_iso_big_create(adv, &param, out_big);
210+
TEST_ASSERT(err == 0, "Failed to create BIG: %d", err);
211+
212+
WAIT_FOR_FLAG(flag_iso_connected);
213+
}
214+
215+
static void start_tx(void)
216+
{
217+
const uint16_t tx_pool_cnt = tx_pool.uninit_count;
218+
219+
LOG_INF("Starting TX");
220+
221+
/* Send/enqueue as many as we can */
222+
for (uint16_t i = 0U; i < tx_pool_cnt; i++) {
223+
send_data(default_chan);
224+
}
225+
}
226+
227+
static void terminate_big(struct bt_iso_big *big)
228+
{
229+
int err;
230+
231+
LOG_INF("Terminating BIG");
232+
233+
err = bt_iso_big_terminate(big);
234+
TEST_ASSERT(err == 0, "Failed to terminate BIG: %d", err);
235+
236+
big = NULL;
237+
}
238+
239+
static void reset_bluetooth(void)
240+
{
241+
int err;
242+
243+
LOG_INF("Resetting Bluetooth");
244+
245+
err = bt_disable();
246+
TEST_ASSERT(err == 0, "Failed to disable: %d", err);
247+
248+
err = bt_enable(NULL);
249+
TEST_ASSERT(err == 0, "Failed to re-enable: %d", err);
250+
}
251+
252+
static void test_main(void)
253+
{
254+
struct bt_le_ext_adv *adv;
255+
struct bt_iso_big *big;
256+
257+
init();
258+
259+
/* Create advertising set and BIG and start it and starting TXing */
260+
create_ext_adv(&adv);
261+
create_big(adv, 1U, &big);
262+
start_ext_adv(adv);
263+
start_tx();
264+
265+
/* Wait for receiver to tell us to terminate */
266+
bk_sync_wait();
267+
268+
terminate_big(big);
269+
big = NULL;
270+
271+
TEST_PASS("Test passed");
272+
}
273+
274+
static void test_main_disable(void)
275+
{
276+
struct bt_le_ext_adv *adv;
277+
struct bt_iso_big *big;
278+
279+
init();
280+
281+
/* Create advertising set and BIG */
282+
create_ext_adv(&adv);
283+
create_big(adv, ARRAY_SIZE(iso_chans), &big);
284+
285+
/* Reset BT to see if we can set it up again */
286+
reset_bluetooth();
287+
288+
/* After a disable, all advertising sets and BIGs are removed */
289+
big = NULL;
290+
adv = NULL;
291+
292+
/* Set everything up again to see if everything still works as expected */
293+
create_ext_adv(&adv);
294+
create_big(adv, ARRAY_SIZE(iso_chans), &big);
295+
start_ext_adv(adv);
296+
start_tx();
297+
298+
/* Wait for receiver to tell us to terminate */
299+
bk_sync_wait();
300+
301+
terminate_big(big);
302+
big = NULL;
303+
304+
TEST_PASS("Disable test passed");
305+
}
306+
307+
static const struct bst_test_instance test_def[] = {
308+
{
309+
.test_id = "broadcaster",
310+
.test_descr = "Minimal BIS broadcaster that broadcast ISO data",
311+
.test_post_init_f = test_init,
312+
.test_tick_f = test_tick,
313+
.test_main_f = test_main,
314+
},
315+
{
316+
.test_id = "broadcaster_disable",
317+
.test_descr = "BIS broadcaster that tests bt_disable for ISO",
318+
.test_post_init_f = test_init,
319+
.test_tick_f = test_tick,
320+
.test_main_f = test_main_disable,
321+
},
322+
BSTEST_END_MARKER,
323+
};
324+
325+
struct bst_test_list *test_main_bis_broadcaster_install(struct bst_test_list *tests)
326+
{
327+
return bst_add_tests(tests, test_def);
328+
}

0 commit comments

Comments
 (0)