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>
This commit is contained in:
parent
4a97746312
commit
c476456c59
11 changed files with 782 additions and 0 deletions
|
@ -18,6 +18,7 @@ ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/compile.sh
|
|||
${ZEPHYR_BASE}/tests/bsim/bluetooth/host/security/compile.sh
|
||||
|
||||
app=tests/bsim/bluetooth/host/iso/cis compile
|
||||
app=tests/bsim/bluetooth/host/iso/bis compile
|
||||
|
||||
app=tests/bsim/bluetooth/host/misc/disable compile
|
||||
app=tests/bsim/bluetooth/host/misc/disconnect/dut compile
|
||||
|
|
22
tests/bsim/bluetooth/host/iso/bis/CMakeLists.txt
Normal file
22
tests/bsim/bluetooth/host/iso/bis/CMakeLists.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
|
||||
project(bsim_test_iso_bis)
|
||||
|
||||
add_subdirectory(${ZEPHYR_BASE}/tests/bsim/babblekit babblekit)
|
||||
target_link_libraries(app PRIVATE babblekit)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
src/common.c
|
||||
src/bis_broadcaster.c
|
||||
src/bis_receiver.c
|
||||
src/main.c
|
||||
)
|
||||
|
||||
zephyr_include_directories(
|
||||
${BSIM_COMPONENTS_PATH}/libUtilv1/src/
|
||||
${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
|
||||
)
|
27
tests/bsim/bluetooth/host/iso/bis/prj.conf
Normal file
27
tests/bsim/bluetooth/host/iso/bis/prj.conf
Normal file
|
@ -0,0 +1,27 @@
|
|||
CONFIG_BT=y
|
||||
CONFIG_LOG=y
|
||||
CONFIG_ASSERT=y
|
||||
CONFIG_BT_EXT_ADV=y
|
||||
CONFIG_BT_PER_ADV=y
|
||||
CONFIG_BT_PER_ADV_SYNC=y
|
||||
|
||||
CONFIG_BT_DEVICE_NAME="BIS test"
|
||||
|
||||
CONFIG_BT_ISO_BROADCASTER=y
|
||||
CONFIG_BT_ISO_SYNC_RECEIVER=y
|
||||
CONFIG_BT_ISO_TX_BUF_COUNT=4
|
||||
CONFIG_BT_ISO_MAX_CHAN=4
|
||||
CONFIG_BT_ISO_TX_MTU=200
|
||||
CONFIG_BT_ISO_RX_MTU=200
|
||||
|
||||
CONFIG_BT_ISO_LOG_LEVEL_DBG=y
|
||||
|
||||
# Controller ISO configs
|
||||
CONFIG_BT_CTLR_ADV_ISO=y
|
||||
CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=4
|
||||
CONFIG_BT_CTLR_SYNC_ISO=y
|
||||
CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=4
|
||||
CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=208
|
||||
CONFIG_BT_CTLR_ISO_TX_BUFFERS=4
|
||||
CONFIG_BT_CTLR_ISOAL_SOURCES=4
|
||||
CONFIG_BT_CTLR_ISOAL_SINKS=4
|
328
tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c
Normal file
328
tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c
Normal file
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/iso.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "babblekit/flags.h"
|
||||
#include "babblekit/sync.h"
|
||||
#include "babblekit/testcase.h"
|
||||
|
||||
LOG_MODULE_REGISTER(bis_broadcaster, LOG_LEVEL_INF);
|
||||
|
||||
#define LATENCY_MS 10U /* 10ms */
|
||||
#define SDU_INTERVAL_US 10U * USEC_PER_MSEC /* 10 ms */
|
||||
|
||||
extern enum bst_result_t bst_result;
|
||||
static struct bt_iso_chan iso_chans[CONFIG_BT_ISO_MAX_CHAN];
|
||||
static struct bt_iso_chan *default_chan = &iso_chans[0];
|
||||
static uint16_t seq_num;
|
||||
NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT,
|
||||
BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
|
||||
CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
|
||||
|
||||
static DEFINE_FLAG(flag_iso_connected);
|
||||
|
||||
static void send_data_cb(struct k_work *work);
|
||||
K_WORK_DELAYABLE_DEFINE(iso_send_work, send_data_cb);
|
||||
|
||||
static void send_data(struct bt_iso_chan *chan)
|
||||
{
|
||||
static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU];
|
||||
static size_t len_to_send = 1U;
|
||||
static bool data_initialized;
|
||||
struct net_buf *buf;
|
||||
int ret;
|
||||
|
||||
if (!IS_FLAG_SET(flag_iso_connected)) {
|
||||
/* TX has been aborted */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data_initialized) {
|
||||
for (int i = 0; i < ARRAY_SIZE(buf_data); i++) {
|
||||
buf_data[i] = (uint8_t)i;
|
||||
}
|
||||
|
||||
data_initialized = true;
|
||||
}
|
||||
|
||||
buf = net_buf_alloc(&tx_pool, K_NO_WAIT);
|
||||
TEST_ASSERT(buf != NULL, "Failed to allocate buffer");
|
||||
|
||||
net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
|
||||
|
||||
net_buf_add_mem(buf, buf_data, len_to_send);
|
||||
|
||||
ret = bt_iso_chan_send(default_chan, buf, seq_num++);
|
||||
if (ret < 0) {
|
||||
LOG_DBG("Failed to send ISO data: %d", ret);
|
||||
net_buf_unref(buf);
|
||||
|
||||
/* Reschedule for next interval */
|
||||
k_work_reschedule(&iso_send_work, K_USEC(SDU_INTERVAL_US));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
len_to_send++;
|
||||
if (len_to_send > ARRAY_SIZE(buf_data)) {
|
||||
len_to_send = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void send_data_cb(struct k_work *work)
|
||||
{
|
||||
const uint16_t tx_pool_cnt = tx_pool.uninit_count;
|
||||
|
||||
/* Send/enqueue as many as we can */
|
||||
for (uint16_t i = 0U; i < tx_pool_cnt; i++) {
|
||||
send_data(default_chan);
|
||||
}
|
||||
}
|
||||
|
||||
static void iso_connected_cb(struct bt_iso_chan *chan)
|
||||
{
|
||||
LOG_INF("ISO Channel %p connected", chan);
|
||||
|
||||
if (chan == default_chan) {
|
||||
seq_num = 0U;
|
||||
|
||||
SET_FLAG(flag_iso_connected);
|
||||
}
|
||||
}
|
||||
|
||||
static void iso_disconnected_cb(struct bt_iso_chan *chan, uint8_t reason)
|
||||
{
|
||||
LOG_INF("ISO Channel %p disconnected (reason 0x%02x)", chan, reason);
|
||||
|
||||
if (chan == default_chan) {
|
||||
k_work_cancel_delayable(&iso_send_work);
|
||||
|
||||
UNSET_FLAG(flag_iso_connected);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdu_sent_cb(struct bt_iso_chan *chan)
|
||||
{
|
||||
if (!IS_FLAG_SET(flag_iso_connected)) {
|
||||
/* TX has been aborted */
|
||||
return;
|
||||
}
|
||||
|
||||
send_data(chan);
|
||||
}
|
||||
|
||||
static void init(void)
|
||||
{
|
||||
static struct bt_iso_chan_ops iso_ops = {
|
||||
.disconnected = iso_disconnected_cb,
|
||||
.connected = iso_connected_cb,
|
||||
.sent = sdu_sent_cb,
|
||||
};
|
||||
static struct bt_iso_chan_io_qos iso_tx = {
|
||||
.sdu = CONFIG_BT_ISO_TX_MTU,
|
||||
.phy = BT_GAP_LE_PHY_2M,
|
||||
.rtn = 1,
|
||||
.path = NULL,
|
||||
};
|
||||
static struct bt_iso_chan_qos iso_qos = {
|
||||
.tx = &iso_tx,
|
||||
.rx = NULL,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = bt_enable(NULL);
|
||||
TEST_ASSERT(err == 0, "Bluetooth enable failed: %d", err);
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(iso_chans); i++) {
|
||||
iso_chans[i].ops = &iso_ops;
|
||||
iso_chans[i].qos = &iso_qos;
|
||||
}
|
||||
|
||||
bk_sync_init();
|
||||
}
|
||||
|
||||
static void create_ext_adv(struct bt_le_ext_adv **adv)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_INF("Creating extended advertising set with periodic advertising");
|
||||
|
||||
/* Create a non-connectable non-scannable advertising set */
|
||||
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv);
|
||||
TEST_ASSERT(err == 0, "Unable to create extended advertising set: %d", err);
|
||||
|
||||
/* Set periodic advertising parameters */
|
||||
err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_PARAM(BT_GAP_PER_ADV_FAST_INT_MIN_2,
|
||||
BT_GAP_PER_ADV_FAST_INT_MAX_2,
|
||||
BT_LE_PER_ADV_OPT_NONE));
|
||||
TEST_ASSERT(err == 0, "Failed to set periodic advertising parameters: %d", err);
|
||||
}
|
||||
|
||||
static void start_ext_adv(struct bt_le_ext_adv *adv)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_INF("Starting extended and periodic advertising");
|
||||
|
||||
/* Start extended advertising */
|
||||
err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
|
||||
TEST_ASSERT(err == 0, "Failed to start extended advertising: %d", err);
|
||||
|
||||
/* FIXME: Temporary workaround to get around an assert in the controller
|
||||
* Open issue: https://github.com/zephyrproject-rtos/zephyr/issues/72852
|
||||
*/
|
||||
k_sleep(K_MSEC(100));
|
||||
|
||||
/* Enable Periodic Advertising */
|
||||
err = bt_le_per_adv_start(adv);
|
||||
TEST_ASSERT(err == 0, "Failed to enable periodic advertising: %d", err);
|
||||
}
|
||||
|
||||
static void create_big(struct bt_le_ext_adv *adv, size_t cnt, struct bt_iso_big **out_big)
|
||||
{
|
||||
struct bt_iso_chan *channels[ARRAY_SIZE(iso_chans)];
|
||||
struct bt_iso_big_create_param param = {
|
||||
.packing = BT_ISO_PACKING_SEQUENTIAL,
|
||||
.framing = BT_ISO_FRAMING_UNFRAMED,
|
||||
.interval = SDU_INTERVAL_US,
|
||||
.bis_channels = channels,
|
||||
.latency = LATENCY_MS,
|
||||
.encryption = false,
|
||||
.num_bis = cnt,
|
||||
};
|
||||
int err;
|
||||
|
||||
for (size_t i = 0U; i < cnt; i++) {
|
||||
channels[i] = &iso_chans[i];
|
||||
}
|
||||
|
||||
LOG_INF("Creating BIG");
|
||||
|
||||
err = bt_iso_big_create(adv, ¶m, out_big);
|
||||
TEST_ASSERT(err == 0, "Failed to create BIG: %d", err);
|
||||
|
||||
WAIT_FOR_FLAG(flag_iso_connected);
|
||||
}
|
||||
|
||||
static void start_tx(void)
|
||||
{
|
||||
const uint16_t tx_pool_cnt = tx_pool.uninit_count;
|
||||
|
||||
LOG_INF("Starting TX");
|
||||
|
||||
/* Send/enqueue as many as we can */
|
||||
for (uint16_t i = 0U; i < tx_pool_cnt; i++) {
|
||||
send_data(default_chan);
|
||||
}
|
||||
}
|
||||
|
||||
static void terminate_big(struct bt_iso_big *big)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_INF("Terminating BIG");
|
||||
|
||||
err = bt_iso_big_terminate(big);
|
||||
TEST_ASSERT(err == 0, "Failed to terminate BIG: %d", err);
|
||||
|
||||
big = NULL;
|
||||
}
|
||||
|
||||
static void reset_bluetooth(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_INF("Resetting Bluetooth");
|
||||
|
||||
err = bt_disable();
|
||||
TEST_ASSERT(err == 0, "Failed to disable: %d", err);
|
||||
|
||||
err = bt_enable(NULL);
|
||||
TEST_ASSERT(err == 0, "Failed to re-enable: %d", err);
|
||||
}
|
||||
|
||||
static void test_main(void)
|
||||
{
|
||||
struct bt_le_ext_adv *adv;
|
||||
struct bt_iso_big *big;
|
||||
|
||||
init();
|
||||
|
||||
/* Create advertising set and BIG and start it and starting TXing */
|
||||
create_ext_adv(&adv);
|
||||
create_big(adv, 1U, &big);
|
||||
start_ext_adv(adv);
|
||||
start_tx();
|
||||
|
||||
/* Wait for receiver to tell us to terminate */
|
||||
bk_sync_wait();
|
||||
|
||||
terminate_big(big);
|
||||
big = NULL;
|
||||
|
||||
TEST_PASS("Test passed");
|
||||
}
|
||||
|
||||
static void test_main_disable(void)
|
||||
{
|
||||
struct bt_le_ext_adv *adv;
|
||||
struct bt_iso_big *big;
|
||||
|
||||
init();
|
||||
|
||||
/* Create advertising set and BIG */
|
||||
create_ext_adv(&adv);
|
||||
create_big(adv, ARRAY_SIZE(iso_chans), &big);
|
||||
|
||||
/* Reset BT to see if we can set it up again */
|
||||
reset_bluetooth();
|
||||
|
||||
/* After a disable, all advertising sets and BIGs are removed */
|
||||
big = NULL;
|
||||
adv = NULL;
|
||||
|
||||
/* Set everything up again to see if everything still works as expected */
|
||||
create_ext_adv(&adv);
|
||||
create_big(adv, ARRAY_SIZE(iso_chans), &big);
|
||||
start_ext_adv(adv);
|
||||
start_tx();
|
||||
|
||||
/* Wait for receiver to tell us to terminate */
|
||||
bk_sync_wait();
|
||||
|
||||
terminate_big(big);
|
||||
big = NULL;
|
||||
|
||||
TEST_PASS("Disable test passed");
|
||||
}
|
||||
|
||||
static const struct bst_test_instance test_def[] = {
|
||||
{
|
||||
.test_id = "broadcaster",
|
||||
.test_descr = "Minimal BIS broadcaster that broadcast ISO data",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main,
|
||||
},
|
||||
{
|
||||
.test_id = "broadcaster_disable",
|
||||
.test_descr = "BIS broadcaster that tests bt_disable for ISO",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main_disable,
|
||||
},
|
||||
BSTEST_END_MARKER,
|
||||
};
|
||||
|
||||
struct bst_test_list *test_main_bis_broadcaster_install(struct bst_test_list *tests)
|
||||
{
|
||||
return bst_add_tests(tests, test_def);
|
||||
}
|
280
tests/bsim/bluetooth/host/iso/bis/src/bis_receiver.c
Normal file
280
tests/bsim/bluetooth/host/iso/bis/src/bis_receiver.c
Normal file
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/iso.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "babblekit/flags.h"
|
||||
#include "babblekit/sync.h"
|
||||
#include "babblekit/testcase.h"
|
||||
|
||||
LOG_MODULE_REGISTER(bis_receiver, LOG_LEVEL_INF);
|
||||
|
||||
#define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 5U /* Set the timeout relative to interval */
|
||||
|
||||
extern enum bst_result_t bst_result;
|
||||
|
||||
static DEFINE_FLAG(flag_broadcaster_found);
|
||||
static DEFINE_FLAG(flag_iso_connected);
|
||||
static DEFINE_FLAG(flag_data_received);
|
||||
static DEFINE_FLAG(flag_pa_synced);
|
||||
static DEFINE_FLAG(flag_biginfo);
|
||||
|
||||
static struct bt_iso_chan iso_chans[CONFIG_BT_ISO_MAX_CHAN];
|
||||
static struct bt_le_scan_recv_info broadcaster_info;
|
||||
static bt_addr_le_t broadcaster_addr;
|
||||
static uint8_t broadcaster_num_bis;
|
||||
|
||||
/** Log data as d_0 d_1 d_2 ... d_(n-2) d_(n-1) d_(n) to show the 3 first and 3 last octets
|
||||
*
|
||||
* Examples:
|
||||
* 01
|
||||
* 0102
|
||||
* 010203
|
||||
* 01020304
|
||||
* 0102030405
|
||||
* 010203040506
|
||||
* 010203...050607
|
||||
* 010203...060708
|
||||
* etc.
|
||||
*/
|
||||
static void iso_log_data(uint8_t *data, size_t data_len)
|
||||
{
|
||||
/* Maximum number of octets from each end of the data */
|
||||
const uint8_t max_octets = 3;
|
||||
char data_str[35];
|
||||
size_t str_len;
|
||||
|
||||
str_len = bin2hex(data, MIN(max_octets, data_len), data_str, sizeof(data_str));
|
||||
if (data_len > max_octets) {
|
||||
if (data_len > (max_octets * 2)) {
|
||||
static const char dots[] = "...";
|
||||
|
||||
strcat(&data_str[str_len], dots);
|
||||
str_len += strlen(dots);
|
||||
}
|
||||
|
||||
str_len += bin2hex(data + (data_len - MIN(max_octets, data_len - max_octets)),
|
||||
MIN(max_octets, data_len - max_octets), data_str + str_len,
|
||||
sizeof(data_str) - str_len);
|
||||
}
|
||||
|
||||
LOG_DBG("\t %s", data_str);
|
||||
}
|
||||
|
||||
static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
if (info->flags & BT_ISO_FLAGS_VALID) {
|
||||
LOG_DBG("Incoming data channel %p len %u", chan, buf->len);
|
||||
iso_log_data(buf->data, buf->len);
|
||||
SET_FLAG(flag_data_received);
|
||||
}
|
||||
}
|
||||
|
||||
static void iso_connected(struct bt_iso_chan *chan)
|
||||
{
|
||||
LOG_INF("ISO Channel %p connected", chan);
|
||||
|
||||
SET_FLAG(flag_iso_connected);
|
||||
}
|
||||
|
||||
static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
|
||||
{
|
||||
LOG_INF("ISO Channel %p disconnected (reason 0x%02x)", chan, reason);
|
||||
|
||||
UNSET_FLAG(flag_iso_connected);
|
||||
}
|
||||
|
||||
static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad)
|
||||
{
|
||||
if (IS_FLAG_SET(flag_broadcaster_found)) {
|
||||
/* no-op*/
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INF("Broadcaster found");
|
||||
|
||||
if (info->interval != 0U) {
|
||||
memcpy(&broadcaster_info, info, sizeof(broadcaster_info));
|
||||
bt_addr_le_copy(&broadcaster_addr, info->addr);
|
||||
SET_FLAG(flag_broadcaster_found);
|
||||
}
|
||||
}
|
||||
|
||||
static void pa_synced_cb(struct bt_le_per_adv_sync *sync,
|
||||
struct bt_le_per_adv_sync_synced_info *info)
|
||||
{
|
||||
LOG_INF("PA synced");
|
||||
|
||||
SET_FLAG(flag_pa_synced);
|
||||
}
|
||||
|
||||
static void pa_term_cb(struct bt_le_per_adv_sync *sync,
|
||||
const struct bt_le_per_adv_sync_term_info *info)
|
||||
{
|
||||
LOG_INF("PA terminated");
|
||||
|
||||
UNSET_FLAG(flag_pa_synced);
|
||||
}
|
||||
|
||||
static void pa_biginfo_cb(struct bt_le_per_adv_sync *sync, const struct bt_iso_biginfo *biginfo)
|
||||
{
|
||||
if (IS_FLAG_SET(flag_biginfo)) {
|
||||
/* no-op*/
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INF("BIGInfo received");
|
||||
|
||||
broadcaster_num_bis = biginfo->num_bis;
|
||||
SET_FLAG(flag_biginfo);
|
||||
}
|
||||
|
||||
static void init(void)
|
||||
{
|
||||
static struct bt_le_per_adv_sync_cb pa_sync_cbs = {
|
||||
.biginfo = pa_biginfo_cb,
|
||||
.synced = pa_synced_cb,
|
||||
.term = pa_term_cb,
|
||||
};
|
||||
static struct bt_le_scan_cb bap_scan_cb = {
|
||||
.recv = broadcast_scan_recv,
|
||||
};
|
||||
static struct bt_iso_chan_io_qos iso_rx = {
|
||||
.sdu = CONFIG_BT_ISO_TX_MTU,
|
||||
};
|
||||
static struct bt_iso_chan_ops iso_ops = {
|
||||
.recv = iso_recv,
|
||||
.connected = iso_connected,
|
||||
.disconnected = iso_disconnected,
|
||||
};
|
||||
static struct bt_iso_chan_qos iso_qos = {
|
||||
.rx = &iso_rx,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = bt_enable(NULL);
|
||||
TEST_ASSERT(err == 0, "Bluetooth enable failed (err %d)", err);
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(iso_chans); i++) {
|
||||
iso_chans[i].ops = &iso_ops;
|
||||
iso_chans[i].qos = &iso_qos;
|
||||
}
|
||||
|
||||
bt_le_per_adv_sync_cb_register(&pa_sync_cbs);
|
||||
bt_le_scan_cb_register(&bap_scan_cb);
|
||||
|
||||
bk_sync_init();
|
||||
}
|
||||
|
||||
static uint16_t interval_to_sync_timeout(uint16_t pa_interval)
|
||||
{
|
||||
uint32_t interval_ms;
|
||||
uint16_t pa_timeout;
|
||||
uint32_t timeout;
|
||||
|
||||
/* Add retries and convert to unit in 10's of ms */
|
||||
interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(pa_interval);
|
||||
timeout = (interval_ms * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO) / 10U;
|
||||
|
||||
/* Enforce restraints */
|
||||
pa_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT);
|
||||
|
||||
return pa_timeout;
|
||||
}
|
||||
|
||||
static void scan_and_sync_pa(struct bt_le_per_adv_sync **out_sync)
|
||||
{
|
||||
struct bt_le_per_adv_sync_param create_params = {0};
|
||||
int err;
|
||||
|
||||
LOG_INF("Starting scan");
|
||||
err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL);
|
||||
TEST_ASSERT(err == 0, "Failed to start scan: %d", err);
|
||||
|
||||
WAIT_FOR_FLAG(flag_broadcaster_found);
|
||||
|
||||
bt_addr_le_copy(&create_params.addr, &broadcaster_addr);
|
||||
create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE;
|
||||
create_params.sid = broadcaster_info.sid;
|
||||
create_params.skip = 0U;
|
||||
create_params.timeout = interval_to_sync_timeout(broadcaster_info.interval);
|
||||
|
||||
LOG_INF("Creating PA sync");
|
||||
err = bt_le_per_adv_sync_create(&create_params, out_sync);
|
||||
TEST_ASSERT(err == 0, "Failed to sync to PA: %d", err);
|
||||
|
||||
WAIT_FOR_FLAG(flag_pa_synced);
|
||||
|
||||
LOG_INF("Stopping scan");
|
||||
err = bt_le_scan_stop();
|
||||
TEST_ASSERT(err == 0, "Failed to stop scan: %d", err);
|
||||
}
|
||||
|
||||
static void sync_big(struct bt_le_per_adv_sync *sync, uint8_t cnt, struct bt_iso_big **out_big)
|
||||
{
|
||||
struct bt_iso_chan *bis_channels[CONFIG_BT_ISO_MAX_CHAN];
|
||||
struct bt_iso_big_sync_param param = {
|
||||
.sync_timeout = interval_to_sync_timeout(broadcaster_info.interval),
|
||||
.bis_bitfield = BIT_MASK(cnt) << 1U, /* BIS indexes start from 1, thus shift by 1 */
|
||||
.bis_channels = bis_channels,
|
||||
.mse = BT_ISO_SYNC_MSE_MIN,
|
||||
.encryption = false,
|
||||
.num_bis = cnt,
|
||||
};
|
||||
int err;
|
||||
|
||||
TEST_ASSERT(cnt <= ARRAY_SIZE(bis_channels));
|
||||
for (size_t i = 0U; i < cnt; i++) {
|
||||
bis_channels[i] = &iso_chans[i];
|
||||
}
|
||||
|
||||
LOG_INF("Creating BIG sync");
|
||||
err = bt_iso_big_sync(sync, ¶m, out_big);
|
||||
TEST_ASSERT(err == 0, "Failed to create BIG sync: %d");
|
||||
|
||||
WAIT_FOR_FLAG(flag_iso_connected);
|
||||
}
|
||||
|
||||
static void test_main(void)
|
||||
{
|
||||
struct bt_le_per_adv_sync *sync;
|
||||
struct bt_iso_big *big;
|
||||
|
||||
init();
|
||||
scan_and_sync_pa(&sync);
|
||||
WAIT_FOR_FLAG(flag_biginfo);
|
||||
sync_big(sync, MIN(broadcaster_num_bis, CONFIG_BT_ISO_MAX_CHAN), &big);
|
||||
|
||||
LOG_INF("Waiting for data");
|
||||
WAIT_FOR_FLAG(flag_data_received);
|
||||
bk_sync_send();
|
||||
|
||||
LOG_INF("Waiting for sync lost");
|
||||
WAIT_FOR_FLAG_UNSET(flag_iso_connected);
|
||||
|
||||
TEST_PASS("Test passed");
|
||||
}
|
||||
|
||||
static const struct bst_test_instance test_def[] = {
|
||||
{
|
||||
.test_id = "receiver",
|
||||
.test_descr = "receiver",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main,
|
||||
},
|
||||
BSTEST_END_MARKER,
|
||||
};
|
||||
|
||||
struct bst_test_list *test_main_bis_receiver_install(struct bst_test_list *tests)
|
||||
{
|
||||
return bst_add_tests(tests, test_def);
|
||||
}
|
31
tests/bsim/bluetooth/host/iso/bis/src/common.c
Normal file
31
tests/bsim/bluetooth/host/iso/bis/src/common.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/addr.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include "babblekit/flags.h"
|
||||
#include "babblekit/testcase.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern enum bst_result_t bst_result;
|
||||
|
||||
void test_init(void)
|
||||
{
|
||||
bst_result = In_progress;
|
||||
bst_ticker_set_next_tick_absolute(WAIT_TIME);
|
||||
}
|
||||
|
||||
void test_tick(bs_time_t HW_device_time)
|
||||
{
|
||||
if (bst_result != Passed) {
|
||||
TEST_FAIL("Test failed (not passed after %" PRIu64 " us)", WAIT_TIME);
|
||||
}
|
||||
}
|
16
tests/bsim/bluetooth/host/iso/bis/src/common.h
Normal file
16
tests/bsim/bluetooth/host/iso/bis/src/common.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Common functions and helpers for ISO broadcast tests
|
||||
*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "bs_types.h"
|
||||
#include "bs_tracing.h"
|
||||
#include "bstests.h"
|
||||
|
||||
#define WAIT_TIME (30e6) /* 30 seconds*/
|
||||
|
||||
void test_init(void);
|
||||
void test_tick(bs_time_t HW_device_time);
|
22
tests/bsim/bluetooth/host/iso/bis/src/main.c
Normal file
22
tests/bsim/bluetooth/host/iso/bis/src/main.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "bstests.h"
|
||||
|
||||
extern struct bst_test_list *test_main_bis_broadcaster_install(struct bst_test_list *tests);
|
||||
extern struct bst_test_list *test_main_bis_receiver_install(struct bst_test_list *tests);
|
||||
|
||||
bst_test_install_t test_installers[] = {
|
||||
test_main_bis_broadcaster_install,
|
||||
test_main_bis_receiver_install,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
bst_main();
|
||||
return 0;
|
||||
}
|
13
tests/bsim/bluetooth/host/iso/bis/tests_scripts/_compile.sh
Executable file
13
tests/bsim/bluetooth/host/iso/bis/tests_scripts/_compile.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2023 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
set -eu
|
||||
: "${ZEPHYR_BASE:?ZEPHYR_BASE must be defined}"
|
||||
|
||||
INCR_BUILD=1
|
||||
|
||||
source ${ZEPHYR_BASE}/tests/bsim/compile.source
|
||||
|
||||
app="$(guess_test_relpath)" compile
|
||||
|
||||
wait_for_background_jobs
|
21
tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis.sh
Executable file
21
tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis.sh
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright (c) 2023 Nordic Semiconductor
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
|
||||
|
||||
simulation_id="iso_bis"
|
||||
verbosity_level=2
|
||||
|
||||
cd ${BSIM_OUT_PATH}/bin
|
||||
|
||||
Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_bis_prj_conf \
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=0 -testid=broadcaster
|
||||
|
||||
Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_bis_prj_conf \
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=1 -testid=receiver
|
||||
|
||||
Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \
|
||||
-D=2 -sim_length=30e6 $@
|
||||
|
||||
wait_for_background_jobs
|
21
tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis_disable.sh
Executable file
21
tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis_disable.sh
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright (c) 2023 Nordic Semiconductor
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
|
||||
|
||||
simulation_id="iso_bis_disable"
|
||||
verbosity_level=2
|
||||
|
||||
cd ${BSIM_OUT_PATH}/bin
|
||||
|
||||
Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_bis_prj_conf \
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=0 -testid=broadcaster_disable
|
||||
|
||||
Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_bis_prj_conf \
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=1 -testid=receiver
|
||||
|
||||
Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \
|
||||
-D=2 -sim_length=30e6 $@
|
||||
|
||||
wait_for_background_jobs
|
Loading…
Add table
Add a link
Reference in a new issue