tests: Bluetooth: BAP: Add broadcast sink with assistant test

Add a test for the broadcast sink that uses the BAP
Scan Delegator functionality with a Broadcast Assistant
device adding the broadcast source.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2023-10-16 13:30:18 +02:00 committed by Carles Cufí
parent f58bea6b7b
commit 0e67c990cd
2 changed files with 195 additions and 9 deletions

View file

@ -17,12 +17,14 @@
extern enum bst_result_t bst_result;
CREATE_FLAG(broadcaster_found);
CREATE_FLAG(base_received);
CREATE_FLAG(flag_base_received);
CREATE_FLAG(flag_base_metadata_updated);
CREATE_FLAG(pa_synced);
CREATE_FLAG(flag_syncable);
CREATE_FLAG(pa_sync_lost);
CREATE_FLAG(flag_received);
CREATE_FLAG(flag_pa_request);
CREATE_FLAG(flag_bis_sync_requested);
static struct bt_bap_broadcast_sink *g_sink;
static struct bt_le_scan_recv_info broadcaster_info;
@ -31,6 +33,9 @@ static struct bt_le_per_adv_sync *pa_sync;
static uint32_t broadcaster_broadcast_id;
static struct bap_test_stream broadcast_sink_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
static struct bt_bap_stream *streams[ARRAY_SIZE(broadcast_sink_streams)];
static uint32_t requested_bis_sync;
static struct bt_le_ext_adv *ext_adv;
static const struct bt_bap_scan_delegator_recv_state *req_recv_state;
static const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_ANY,
@ -53,7 +58,7 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap
{
uint32_t base_bis_index_bitfield = 0U;
if (TEST_FLAG(base_received)) {
if (TEST_FLAG(flag_base_received)) {
if (base->subgroup_count > 0 &&
memcmp(metadata, base->subgroups[0].codec_cfg.meta,
@ -82,7 +87,7 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap
bis_index_bitfield = base_bis_index_bitfield & bis_index_mask;
SET_FLAG(base_received);
SET_FLAG(flag_base_received);
}
static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted)
@ -185,6 +190,61 @@ static struct bt_pacs_cap cap = {
.codec_cap = &codec_cap,
};
static int pa_sync_req_cb(struct bt_conn *conn,
const struct bt_bap_scan_delegator_recv_state *recv_state,
bool past_avail, uint16_t pa_interval)
{
if (recv_state->pa_sync_state == BT_BAP_PA_STATE_SYNCED ||
recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) {
/* Already syncing */
/* TODO: Terminate existing sync and then sync to new?*/
return -EALREADY;
}
req_recv_state = recv_state;
SET_FLAG(flag_pa_request);
return 0;
}
static int pa_sync_term_req_cb(struct bt_conn *conn,
const struct bt_bap_scan_delegator_recv_state *recv_state)
{
if (pa_sync == NULL || recv_state->pa_sync_state == BT_BAP_PA_STATE_NOT_SYNCED) {
return -EALREADY;
}
req_recv_state = recv_state;
UNSET_FLAG(flag_pa_request);
return 0;
}
static int bis_sync_req_cb(struct bt_conn *conn,
const struct bt_bap_scan_delegator_recv_state *recv_state,
const uint32_t bis_sync_req[BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS])
{
printk("BIS sync request received for %p: 0x%08x\n", recv_state, bis_sync_req[0]);
/* We only care about a single subgroup in this test */
requested_bis_sync = bis_sync_req[0];
broadcaster_broadcast_id = recv_state->broadcast_id;
if (bis_sync_req[0] != 0) {
SET_FLAG(flag_bis_sync_requested);
} else {
UNSET_FLAG(flag_bis_sync_requested);
}
return 0;
}
static struct bt_bap_scan_delegator_cb scan_delegator_cbs = {
.pa_sync_req = pa_sync_req_cb,
.pa_sync_term_req = pa_sync_term_req_cb,
.bis_sync_req = bis_sync_req_cb,
};
static void started_cb(struct bt_bap_stream *stream)
{
printk("Stream %p started\n", stream);
@ -274,11 +334,12 @@ static int init(void)
return err;
}
bt_bap_scan_delegator_register_cb(&scan_delegator_cbs);
bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb);
bt_le_scan_cb_register(&bap_scan_cb);
UNSET_FLAG(broadcaster_found);
UNSET_FLAG(base_received);
UNSET_FLAG(flag_base_received);
UNSET_FLAG(pa_synced);
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
@ -323,6 +384,18 @@ static int pa_sync_create(void)
return bt_le_per_adv_sync_create(&create_params, &pa_sync);
}
static void test_pa_sync_delete(void)
{
int err;
err = bt_le_per_adv_sync_delete(pa_sync);
if (err != 0) {
FAIL("Unable to stop sink: %d", err);
return;
}
pa_sync = NULL;
}
static void test_scan_and_pa_sync(void)
{
@ -507,6 +580,7 @@ static void test_broadcast_delete(void)
}
/* No "sync lost" event is generated when we initialized the disconnect */
g_sink = NULL;
}
static void test_broadcast_delete_inval(void)
@ -520,6 +594,39 @@ static void test_broadcast_delete_inval(void)
}
}
static void test_start_adv(void)
{
const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_BASS_VAL),
BT_UUID_16_ENCODE(BT_UUID_PACS_VAL)),
BT_DATA_BYTES(BT_DATA_SVC_DATA16, BT_UUID_16_ENCODE(BT_UUID_BASS_VAL)),
};
int err;
/* Create a non-connectable non-scannable advertising set */
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN_NAME, NULL, &ext_adv);
if (err != 0) {
FAIL("Failed to create advertising set (err %d)\n", err);
return;
}
err = bt_le_ext_adv_set_data(ext_adv, ad, ARRAY_SIZE(ad), NULL, 0);
if (err != 0) {
FAIL("Failed to set advertising data (err %d)\n", err);
return;
}
err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT);
if (err != 0) {
FAIL("Failed to start advertising set (err %d)\n", err);
return;
}
}
static void test_common(void)
{
int err;
@ -536,7 +643,7 @@ static void test_common(void)
test_broadcast_sink_create();
printk("Broadcast source PA synced, waiting for BASE\n");
WAIT_FOR_FLAG(base_received);
WAIT_FOR_FLAG(flag_base_received);
printk("BASE received\n");
printk("Waiting for BIG syncable\n");
@ -585,25 +692,75 @@ static void test_sink_disconnect(void)
test_broadcast_delete_inval();
test_broadcast_delete();
g_sink = NULL;
PASS("Broadcast sink disconnect passed\n");
}
static void broadcast_sink_with_assistant(void)
{
int err;
err = init();
if (err) {
FAIL("Init failed (err %d)\n", err);
return;
}
test_start_adv();
WAIT_FOR_FLAG(flag_connected);
printk("Waiting for PA sync request\n");
WAIT_FOR_FLAG(flag_pa_request);
test_scan_and_pa_sync();
test_broadcast_sink_create();
printk("Broadcast source PA synced, waiting for BASE\n");
WAIT_FOR_FLAG(flag_base_received);
printk("BASE received\n");
printk("Waiting for BIG syncable\n");
WAIT_FOR_FLAG(flag_syncable);
printk("Waiting for BIG sync request\n");
WAIT_FOR_FLAG(flag_bis_sync_requested);
test_broadcast_sync();
printk("Waiting for data\n");
WAIT_FOR_FLAG(flag_received);
printk("Waiting for BIG sync terminate request\n");
WAIT_FOR_UNSET_FLAG(flag_bis_sync_requested);
test_broadcast_stop();
printk("Waiting for PA sync terminate request\n");
WAIT_FOR_UNSET_FLAG(flag_pa_request);
test_pa_sync_delete();
test_broadcast_delete();
PASS("Broadcast sink with assistant passed\n");
}
static const struct bst_test_instance test_broadcast_sink[] = {
{
.test_id = "broadcast_sink",
.test_post_init_f = test_init,
.test_tick_f = test_tick,
.test_main_f = test_main
.test_main_f = test_main,
},
{
.test_id = "broadcast_sink_disconnect",
.test_post_init_f = test_init,
.test_tick_f = test_tick,
.test_main_f = test_sink_disconnect
.test_main_f = test_sink_disconnect,
},
BSTEST_END_MARKER
{
.test_id = "broadcast_sink_with_assistant",
.test_post_init_f = test_init,
.test_tick_f = test_tick,
.test_main_f = broadcast_sink_with_assistant,
},
BSTEST_END_MARKER,
};
struct bst_test_list *test_broadcast_sink_install(struct bst_test_list *tests)

View file

@ -0,0 +1,29 @@
#!/usr/bin/env bash
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
SIMULATION_ID="bap_broadcast_audio_assistant"
VERBOSITY_LEVEL=2
EXECUTE_TIMEOUT=20
source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
cd ${BSIM_OUT_PATH}/bin
printf "\n\n======== Running BAP Broadcast Audio Assistant =========\n\n"
Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \
-v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=broadcast_sink_with_assistant -rs=24
Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \
-v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=bap_broadcast_assistant_client_sync -rs=46
Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \
-v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=broadcast_source -rs=69
# Simulation time should be larger than the WAIT_TIME in common.h
Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -D=3 -sim_length=60e6 $@
wait_for_background_jobs