tests: Bluetooth: Audio: Add BSIM test of the CAP samples
Adds babblesim tests of the CAP Acceptor and the CAP Initiator samples for unicast. This simply checks if at least one stream is connected and is sending (empty) data. This modifies the samples to send data as well as counting the receive ISO data packets. Ideally the TX would be superflous to verify that ISO is working, but a missing feature in the Zephyr LL makes it a requirement. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
daf7d8066a
commit
c07a87abbb
21 changed files with 495 additions and 2 deletions
|
@ -0,0 +1,6 @@
|
|||
CONFIG_BT_BUF_EVT_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_TX_SIZE=251
|
||||
CONFIG_BT_BUF_CMD_TX_SIZE=255
|
||||
|
||||
CONFIG_BT_TINYCRYPT_ECC=y
|
|
@ -0,0 +1,6 @@
|
|||
CONFIG_BT_BUF_EVT_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_TX_SIZE=251
|
||||
CONFIG_BT_BUF_CMD_TX_SIZE=255
|
||||
|
||||
CONFIG_BT_TINYCRYPT_ECC=y
|
|
@ -24,6 +24,8 @@ struct peer_config {
|
|||
struct k_sem sink_stream_sem;
|
||||
/** ACL connection object for the peer device */
|
||||
struct bt_conn *conn;
|
||||
/** Current sequence number for TX */
|
||||
uint16_t tx_seq_num;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <autoconf.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -22,10 +23,12 @@
|
|||
#include <zephyr/bluetooth/hci_types.h>
|
||||
#include <zephyr/bluetooth/iso.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/kernel/thread_stack.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/logging/log_core.h>
|
||||
#include <zephyr/net/buf.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/sys/util_macro.h>
|
||||
|
||||
#include "cap_acceptor.h"
|
||||
|
||||
|
@ -40,6 +43,7 @@ LOG_MODULE_REGISTER(cap_acceptor_unicast, LOG_LEVEL_INF);
|
|||
|
||||
static const struct bt_audio_codec_qos_pref qos_pref = BT_AUDIO_CODEC_QOS_PREF(
|
||||
UNFRAMED_SUPPORTED, PREF_PHY, RTN, LATENCY, MIN_PD, MAX_PD, MIN_PD, MAX_PD);
|
||||
uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */
|
||||
|
||||
static bool log_codec_cfg_cb(struct bt_data *data, void *user_data)
|
||||
{
|
||||
|
@ -290,6 +294,7 @@ static void unicast_stream_enabled_cb(struct bt_bap_stream *bap_stream)
|
|||
static void unicast_stream_started_cb(struct bt_bap_stream *bap_stream)
|
||||
{
|
||||
LOG_INF("Started bap_stream %p", bap_stream);
|
||||
total_rx_iso_packet_count = 0U;
|
||||
}
|
||||
|
||||
static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream)
|
||||
|
@ -320,7 +325,63 @@ static void unicast_stream_released_cb(struct bt_bap_stream *bap_stream)
|
|||
static void unicast_stream_recv_cb(struct bt_bap_stream *bap_stream,
|
||||
const struct bt_iso_recv_info *info, struct net_buf *buf)
|
||||
{
|
||||
/* TODO: Add test code */
|
||||
/* Triggered every time we receive an HCI data packet from the controller.
|
||||
* A call to this does not indicate valid data
|
||||
* (see the `info->flags` for which flags to check),
|
||||
*/
|
||||
|
||||
if ((total_rx_iso_packet_count % 100U) == 0U) {
|
||||
LOG_INF("Received %llu HCI ISO data packets", total_rx_iso_packet_count);
|
||||
}
|
||||
|
||||
total_rx_iso_packet_count++;
|
||||
}
|
||||
|
||||
static void tx_thread_func(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
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 uint8_t data[CONFIG_BT_ISO_TX_MTU];
|
||||
struct peer_config *peer = arg1;
|
||||
struct bt_cap_stream *cap_stream = &peer->source_stream;
|
||||
struct bt_bap_stream *bap_stream = &cap_stream->bap_stream;
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(data); i++) {
|
||||
data[i] = (uint8_t)i;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
/* No-op if stream is not configured */
|
||||
if (bap_stream->ep != NULL) {
|
||||
struct bt_bap_ep_info ep_info;
|
||||
int err;
|
||||
|
||||
err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
|
||||
if (err == 0) {
|
||||
if (ep_info.state == BT_BAP_EP_STATE_STREAMING) {
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = net_buf_alloc(&tx_pool, K_FOREVER);
|
||||
net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
|
||||
|
||||
net_buf_add_mem(buf, data, bap_stream->qos->sdu);
|
||||
|
||||
err = bt_cap_stream_send(cap_stream, buf, peer->tx_seq_num);
|
||||
if (err == 0) {
|
||||
peer->tx_seq_num++;
|
||||
continue; /* Attempt to send again ASAP */
|
||||
} else {
|
||||
LOG_ERR("Unable to send: %d", err);
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* In case of any errors, retry with a delay */
|
||||
k_sleep(K_MSEC(100));
|
||||
}
|
||||
}
|
||||
|
||||
int init_cap_acceptor_unicast(struct peer_config *peer)
|
||||
|
@ -347,10 +408,28 @@ int init_cap_acceptor_unicast(struct peer_config *peer)
|
|||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
cbs_registered = true;
|
||||
}
|
||||
|
||||
bt_cap_stream_ops_register(&peer->source_stream, &unicast_stream_ops);
|
||||
bt_cap_stream_ops_register(&peer->sink_stream, &unicast_stream_ops);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SRC)) {
|
||||
static bool thread_started;
|
||||
|
||||
if (!thread_started) {
|
||||
static K_KERNEL_STACK_DEFINE(tx_thread_stack, 1024);
|
||||
const int tx_thread_prio = K_PRIO_PREEMPT(5);
|
||||
static struct k_thread tx_thread;
|
||||
|
||||
k_thread_create(&tx_thread, tx_thread_stack,
|
||||
K_KERNEL_STACK_SIZEOF(tx_thread_stack), tx_thread_func,
|
||||
peer, NULL, NULL, tx_thread_prio, 0, K_NO_WAIT);
|
||||
k_thread_name_set(&tx_thread, "TX thread");
|
||||
thread_started = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
CONFIG_BT_BUF_EVT_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_TX_SIZE=251
|
||||
CONFIG_BT_BUF_CMD_TX_SIZE=255
|
||||
|
||||
CONFIG_BT_TINYCRYPT_ECC=y
|
|
@ -0,0 +1,6 @@
|
|||
CONFIG_BT_BUF_EVT_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_TX_SIZE=251
|
||||
CONFIG_BT_BUF_CMD_TX_SIZE=255
|
||||
|
||||
CONFIG_BT_TINYCRYPT_ECC=y
|
|
@ -24,10 +24,12 @@
|
|||
#include <zephyr/bluetooth/iso.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/kernel/thread_stack.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/logging/log_core.h>
|
||||
#include <zephyr/net/buf.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/sys/util_macro.h>
|
||||
|
||||
#include "cap_initiator.h"
|
||||
|
@ -42,6 +44,7 @@ LOG_MODULE_REGISTER(cap_initiator_unicast, LOG_LEVEL_INF);
|
|||
static struct bt_bap_lc3_preset unicast_preset_16_2_1 = BT_BAP_LC3_UNICAST_PRESET_16_2_1(
|
||||
BT_AUDIO_LOCATION_MONO_AUDIO, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
|
||||
static struct bt_bap_unicast_group *unicast_group;
|
||||
uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */
|
||||
|
||||
/** Struct to contain information for a specific peer (CAP) device */
|
||||
struct peer_config {
|
||||
|
@ -59,6 +62,8 @@ struct peer_config {
|
|||
struct bt_bap_ep *sink_ep;
|
||||
/** ACL connection object for the peer device */
|
||||
struct bt_conn *conn;
|
||||
/** Current sequence number for TX */
|
||||
uint16_t tx_seq_num;
|
||||
};
|
||||
|
||||
/* TODO: Expand to multiple ACL connections */
|
||||
|
@ -97,6 +102,7 @@ static void unicast_stream_enabled_cb(struct bt_bap_stream *stream)
|
|||
static void unicast_stream_started_cb(struct bt_bap_stream *stream)
|
||||
{
|
||||
LOG_INF("Started stream %p", stream);
|
||||
total_rx_iso_packet_count = 0U;
|
||||
}
|
||||
|
||||
static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *stream)
|
||||
|
@ -128,7 +134,16 @@ static void unicast_stream_released_cb(struct bt_bap_stream *stream)
|
|||
static void unicast_stream_recv_cb(struct bt_bap_stream *stream,
|
||||
const struct bt_iso_recv_info *info, struct net_buf *buf)
|
||||
{
|
||||
/* TODO: Add test code */
|
||||
/* Triggered every time we receive an HCI data packet from the controller.
|
||||
* A call to this does not indicate valid data
|
||||
* (see the `info->flags` for which flags to check),
|
||||
*/
|
||||
|
||||
if ((total_rx_iso_packet_count % 100U) == 0U) {
|
||||
LOG_INF("Received %llu HCI ISO data packets", total_rx_iso_packet_count);
|
||||
}
|
||||
|
||||
total_rx_iso_packet_count++;
|
||||
}
|
||||
|
||||
static struct bt_bap_stream_ops unicast_stream_ops = {
|
||||
|
@ -143,6 +158,52 @@ static struct bt_bap_stream_ops unicast_stream_ops = {
|
|||
.recv = unicast_stream_recv_cb,
|
||||
};
|
||||
|
||||
static void tx_thread_func(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
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 uint8_t data[CONFIG_BT_ISO_TX_MTU];
|
||||
struct bt_cap_stream *cap_stream = &peer.sink_stream;
|
||||
struct bt_bap_stream *bap_stream = &cap_stream->bap_stream;
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(data); i++) {
|
||||
data[i] = (uint8_t)i;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
/* No-op if stream is not configured */
|
||||
if (bap_stream->ep != NULL) {
|
||||
struct bt_bap_ep_info ep_info;
|
||||
int err;
|
||||
|
||||
err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
|
||||
if (err == 0) {
|
||||
if (ep_info.state == BT_BAP_EP_STATE_STREAMING) {
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = net_buf_alloc(&tx_pool, K_FOREVER);
|
||||
net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
|
||||
|
||||
net_buf_add_mem(buf, data, bap_stream->qos->sdu);
|
||||
|
||||
err = bt_cap_stream_send(cap_stream, buf, peer.tx_seq_num);
|
||||
if (err == 0) {
|
||||
peer.tx_seq_num++;
|
||||
continue; /* Attempt to send again ASAP */
|
||||
} else {
|
||||
LOG_ERR("Unable to send: %d", err);
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* In case of any errors, retry with a delay */
|
||||
k_sleep(K_MSEC(100));
|
||||
}
|
||||
}
|
||||
|
||||
static bool log_codec_cb(struct bt_data *data, void *user_data)
|
||||
{
|
||||
const char *str = (const char *)user_data;
|
||||
|
@ -674,6 +735,23 @@ static int init_cap_initiator(void)
|
|||
k_sem_init(&peer.source_stream_sem, 0, 1);
|
||||
k_sem_init(&peer.sink_stream_sem, 0, 1);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK)) {
|
||||
static bool thread_started;
|
||||
|
||||
if (!thread_started) {
|
||||
static K_KERNEL_STACK_DEFINE(tx_thread_stack, 1024);
|
||||
const int tx_thread_prio = K_PRIO_PREEMPT(5);
|
||||
static struct k_thread tx_thread;
|
||||
|
||||
k_thread_create(&tx_thread, tx_thread_stack,
|
||||
K_KERNEL_STACK_SIZEOF(tx_thread_stack), tx_thread_func,
|
||||
net_buf_pull_be16, NULL, NULL, tx_thread_prio, 0,
|
||||
K_NO_WAIT);
|
||||
k_thread_name_set(&tx_thread, "TX thread");
|
||||
thread_started = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(cap_acceptor_self_tets)
|
||||
|
||||
set(cap_acceptor_path ${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
${cap_acceptor_path}/src/main.c
|
||||
${cap_acceptor_path}/src/cap_acceptor_unicast.c
|
||||
)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
src/cap_acceptor_sample_test.c
|
||||
src/test_main.c
|
||||
)
|
||||
|
||||
zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth)
|
||||
|
||||
zephyr_include_directories(
|
||||
${BSIM_COMPONENTS_PATH}/libUtilv1/src/
|
||||
${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
|
||||
)
|
|
@ -0,0 +1,10 @@
|
|||
# Copyright (c) 2023-2024 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
source "${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor/Kconfig.sysbuild"
|
||||
|
||||
config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX
|
||||
int
|
||||
# Let's pass the test arguments to the application MCU test
|
||||
# otherwise by default they would have gone to the net core.
|
||||
default 0 if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP"
|
2
tests/bsim/bluetooth/audio_samples/cap/acceptor/prj.conf
Normal file
2
tests/bsim/bluetooth/audio_samples/cap/acceptor/prj.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Please build using the sample configuration file:
|
||||
# ${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor/prj.conf
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2023-2024 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2017-2019 Oticon A/S
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "bs_types.h"
|
||||
#include "bs_tracing.h"
|
||||
#include "bs_utils.h"
|
||||
#include "time_machine.h"
|
||||
#include "bstests.h"
|
||||
|
||||
#define WAIT_TIME 10 /* Seconds */
|
||||
|
||||
#define PASS_THRESHOLD 100 /* Audio packets */
|
||||
|
||||
extern enum bst_result_t bst_result;
|
||||
|
||||
#define FAIL(...) \
|
||||
do { \
|
||||
bst_result = Failed; \
|
||||
bs_trace_error_time_line(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define PASS(...) \
|
||||
do { \
|
||||
bst_result = Passed; \
|
||||
bs_trace_info_time(1, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
static void test_cap_acceptor_sample_init(void)
|
||||
{
|
||||
/* We set an absolute deadline in 30 seconds */
|
||||
bst_ticker_set_next_tick_absolute(WAIT_TIME * 1e6);
|
||||
bst_result = In_progress;
|
||||
}
|
||||
|
||||
static void test_cap_acceptor_sample_tick(bs_time_t HW_device_time)
|
||||
{
|
||||
/*
|
||||
* If in WAIT_TIME seconds we did not get enough packets through
|
||||
* we consider the test failed
|
||||
*/
|
||||
|
||||
extern uint64_t total_rx_iso_packet_count;
|
||||
|
||||
bs_trace_info_time(2, "%" PRIu64 " packets received, expected >= %i\n",
|
||||
total_rx_iso_packet_count, PASS_THRESHOLD);
|
||||
|
||||
if (total_rx_iso_packet_count >= PASS_THRESHOLD) {
|
||||
PASS("cap_acceptor PASSED\n");
|
||||
} else {
|
||||
FAIL("cap_acceptor FAILED (Did not pass after %i seconds)\n", WAIT_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct bst_test_instance test_sample[] = {
|
||||
{
|
||||
.test_id = "cap_acceptor",
|
||||
.test_descr = "Test based on the unicast client sample. "
|
||||
"It expects to be connected to a compatible unicast server, "
|
||||
"waits for " STR(WAIT_TIME) " seconds, and checks how "
|
||||
"many audio packets have been received correctly",
|
||||
.test_post_init_f = test_cap_acceptor_sample_init,
|
||||
.test_tick_f = test_cap_acceptor_sample_tick,
|
||||
},
|
||||
BSTEST_END_MARKER
|
||||
};
|
||||
|
||||
/* TODO: Add test of reconnection */
|
||||
|
||||
struct bst_test_list *test_cap_acceptor_sample_install(struct bst_test_list *tests)
|
||||
{
|
||||
tests = bst_add_tests(tests, test_sample);
|
||||
return tests;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2023-2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "bstests.h"
|
||||
|
||||
extern struct bst_test_list *test_cap_acceptor_sample_install(struct bst_test_list *tests);
|
||||
|
||||
bst_test_install_t test_installers[] = {
|
||||
test_cap_acceptor_sample_install,
|
||||
NULL
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
# Copyright (c) 2023-2024 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
include(${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor/sysbuild.cmake)
|
||||
|
||||
native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP})
|
|
@ -0,0 +1,25 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(cap_initiator_self_tets)
|
||||
|
||||
set(cap_initiator_path ${ZEPHYR_BASE}/samples/bluetooth/cap_initiator)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
${cap_initiator_path}/src/main.c
|
||||
${cap_initiator_path}/src/cap_initiator_unicast.c
|
||||
)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
src/cap_initiator_sample_test.c
|
||||
src/test_main.c
|
||||
)
|
||||
|
||||
zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth)
|
||||
|
||||
zephyr_include_directories(
|
||||
${BSIM_COMPONENTS_PATH}/libUtilv1/src/
|
||||
${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
|
||||
)
|
|
@ -0,0 +1,10 @@
|
|||
# Copyright (c) 2023-2024 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
source "${ZEPHYR_BASE}/samples/bluetooth/cap_initiator/Kconfig.sysbuild"
|
||||
|
||||
config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX
|
||||
int
|
||||
# Let's pass the test arguments to the application MCU test
|
||||
# otherwise by default they would have gone to the net core.
|
||||
default 0 if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP"
|
|
@ -0,0 +1,2 @@
|
|||
# Please build using the sample configuration file:
|
||||
# ${ZEPHYR_BASE}/samples/bluetooth/cap_initiator/prj.conf
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2023-2024 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2017-2019 Oticon A/S
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "bs_types.h"
|
||||
#include "bs_tracing.h"
|
||||
#include "bs_utils.h"
|
||||
#include "time_machine.h"
|
||||
#include "bstests.h"
|
||||
|
||||
#define WAIT_TIME 10 /* Seconds */
|
||||
|
||||
#define PASS_THRESHOLD 100 /* Audio packets */
|
||||
|
||||
extern enum bst_result_t bst_result;
|
||||
|
||||
#define FAIL(...) \
|
||||
do { \
|
||||
bst_result = Failed; \
|
||||
bs_trace_error_time_line(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define PASS(...) \
|
||||
do { \
|
||||
bst_result = Passed; \
|
||||
bs_trace_info_time(1, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
static void test_cap_initiator_sample_init(void)
|
||||
{
|
||||
bst_ticker_set_next_tick_absolute(WAIT_TIME * 1e6);
|
||||
bst_result = In_progress;
|
||||
}
|
||||
|
||||
static void test_cap_initiator_sample_tick(bs_time_t HW_device_time)
|
||||
{
|
||||
/*
|
||||
* If in WAIT_TIME seconds we did not get enough packets through
|
||||
* we consider the test failed
|
||||
*/
|
||||
|
||||
extern uint64_t total_rx_iso_packet_count;
|
||||
|
||||
bs_trace_info_time(2, "%" PRIu64 " packets received, expected >= %i\n",
|
||||
total_rx_iso_packet_count, PASS_THRESHOLD);
|
||||
|
||||
if (total_rx_iso_packet_count >= PASS_THRESHOLD) {
|
||||
PASS("cap_initiator PASSED\n");
|
||||
} else {
|
||||
FAIL("cap_initiator FAILED (Did not pass after %i seconds)\n", WAIT_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct bst_test_instance test_sample[] = {
|
||||
{
|
||||
.test_id = "cap_initiator",
|
||||
.test_descr = "Test based on the unicast client sample. "
|
||||
"It expects to be connected to a compatible unicast server, "
|
||||
"waits for " STR(WAIT_TIME) " seconds, and checks how "
|
||||
"many audio packets have been received correctly",
|
||||
.test_post_init_f = test_cap_initiator_sample_init,
|
||||
.test_tick_f = test_cap_initiator_sample_tick,
|
||||
},
|
||||
BSTEST_END_MARKER
|
||||
};
|
||||
|
||||
/* TODO: Add test of reconnection */
|
||||
|
||||
struct bst_test_list *test_cap_initiator_sample_install(struct bst_test_list *tests)
|
||||
{
|
||||
tests = bst_add_tests(tests, test_sample);
|
||||
return tests;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright (c) 2023-2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "bstests.h"
|
||||
|
||||
extern struct bst_test_list *test_cap_initiator_sample_install(struct bst_test_list *tests);
|
||||
|
||||
bst_test_install_t test_installers[] = {test_cap_initiator_sample_install, NULL};
|
|
@ -0,0 +1,6 @@
|
|||
# Copyright (c) 2023-2024 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
include(${ZEPHYR_BASE}/samples/bluetooth/cap_initiator/sysbuild.cmake)
|
||||
|
||||
native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP})
|
26
tests/bsim/bluetooth/audio_samples/cap/tests_scripts/cap_unicast.sh
Executable file
26
tests/bsim/bluetooth/audio_samples/cap/tests_scripts/cap_unicast.sh
Executable file
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2023-2024 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Simple selfchecking test for the CAP Acceptor sample.
|
||||
# It relies on the bs_tests hooks to register a test timer callback, which after a deadline
|
||||
# will check how many audio packets the unicast client has received, and if over a threshold
|
||||
# it considers the test passed
|
||||
|
||||
simulation_id="cap_unicast_test"
|
||||
verbosity_level=2
|
||||
|
||||
source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
|
||||
|
||||
cd ${BSIM_OUT_PATH}/bin
|
||||
|
||||
Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_audio_samples_cap_initiator_prj_conf \
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=1 -testid=cap_initiator
|
||||
|
||||
Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_audio_samples_cap_acceptor_prj_conf \
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=1 -testid=cap_acceptor
|
||||
|
||||
Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \
|
||||
-D=2 -sim_length=20e6 $@ -argschannel -at=40
|
||||
|
||||
wait_for_background_jobs #Wait for all programs in background and return != 0 if any fails
|
|
@ -22,6 +22,16 @@ if [ "${BOARD_TS}" == "nrf5340bsim_nrf5340_cpuapp" ]; then
|
|||
app=tests/bsim/bluetooth/audio_samples/bap_broadcast_sink sysbuild=1 \
|
||||
conf_file=${ZEPHYR_BASE}/samples/bluetooth/bap_broadcast_sink/prj.conf \
|
||||
exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile
|
||||
app=tests/bsim/bluetooth/audio_samples/cap/initiator \
|
||||
sample=${ZEPHYR_BASE}/samples/bluetooth/cap_initiator \
|
||||
conf_file=${sample}/prj.conf \
|
||||
conf_overlay=${sample}/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf \
|
||||
exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile
|
||||
app=tests/bsim/bluetooth/audio_samples/cap/acceptor \
|
||||
sample=${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor \
|
||||
conf_file=${sample}/prj.conf \
|
||||
conf_overlay=${sample}/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf \
|
||||
exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile
|
||||
else
|
||||
app=samples/bluetooth/bap_unicast_server conf_overlay=overlay-bt_ll_sw_split.conf \
|
||||
exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile
|
||||
|
@ -36,6 +46,16 @@ else
|
|||
conf_file=${ZEPHYR_BASE}/samples/bluetooth/bap_broadcast_sink/prj.conf \
|
||||
conf_overlay=${ZEPHYR_BASE}/samples/bluetooth/bap_broadcast_sink/overlay-bt_ll_sw_split.conf \
|
||||
exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile
|
||||
app=tests/bsim/bluetooth/audio_samples/cap/initiator \
|
||||
sample=${ZEPHYR_BASE}/samples/bluetooth/cap_initiator \
|
||||
conf_file=${sample}/prj.conf \
|
||||
conf_overlay=${sample}/overlay-bt_ll_sw_split.conf \
|
||||
exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile
|
||||
app=tests/bsim/bluetooth/audio_samples/cap/acceptor \
|
||||
sample=${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor \
|
||||
conf_file=${sample}/prj.conf \
|
||||
conf_overlay=${sample}/overlay-bt_ll_sw_split.conf \
|
||||
exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile
|
||||
fi
|
||||
|
||||
wait_for_background_jobs
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue