diff --git a/samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..96dc0eb4e3b --- /dev/null +++ b/samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -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 diff --git a/samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..96dc0eb4e3b --- /dev/null +++ b/samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -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 diff --git a/samples/bluetooth/cap_acceptor/src/cap_acceptor.h b/samples/bluetooth/cap_acceptor/src/cap_acceptor.h index 20c8da5f1d1..7db7dec6019 100644 --- a/samples/bluetooth/cap_acceptor/src/cap_acceptor.h +++ b/samples/bluetooth/cap_acceptor/src/cap_acceptor.h @@ -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; }; /** diff --git a/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c index 87358f79b3e..968e46c454f 100644 --- a/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c +++ b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c @@ -7,6 +7,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -22,10 +23,12 @@ #include #include #include +#include #include #include #include #include +#include #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; } diff --git a/samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..96dc0eb4e3b --- /dev/null +++ b/samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -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 diff --git a/samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..96dc0eb4e3b --- /dev/null +++ b/samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -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 diff --git a/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c b/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c index 76be7ef0dad..030fe3835c3 100644 --- a/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c +++ b/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c @@ -24,10 +24,12 @@ #include #include #include +#include #include #include #include #include +#include #include #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; } diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/CMakeLists.txt b/tests/bsim/bluetooth/audio_samples/cap/acceptor/CMakeLists.txt new file mode 100644 index 00000000000..e446554ca73 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/CMakeLists.txt @@ -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/ + ) diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/Kconfig.sysbuild b/tests/bsim/bluetooth/audio_samples/cap/acceptor/Kconfig.sysbuild new file mode 100644 index 00000000000..3b2c35e65c5 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/Kconfig.sysbuild @@ -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" diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/prj.conf b/tests/bsim/bluetooth/audio_samples/cap/acceptor/prj.conf new file mode 100644 index 00000000000..e8122ebe95f --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/prj.conf @@ -0,0 +1,2 @@ +# Please build using the sample configuration file: +# ${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor/prj.conf diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/cap_acceptor_sample_test.c b/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/cap_acceptor_sample_test.c new file mode 100644 index 00000000000..2f3260dfd2e --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/cap_acceptor_sample_test.c @@ -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; +} diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/test_main.c b/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/test_main.c new file mode 100644 index 00000000000..fa6a7c977ce --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/test_main.c @@ -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 +}; diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/sysbuild.cmake b/tests/bsim/bluetooth/audio_samples/cap/acceptor/sysbuild.cmake new file mode 100644 index 00000000000..be3e589dd35 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/sysbuild.cmake @@ -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}) diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/CMakeLists.txt b/tests/bsim/bluetooth/audio_samples/cap/initiator/CMakeLists.txt new file mode 100644 index 00000000000..786575379c7 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/CMakeLists.txt @@ -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/ + ) diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/Kconfig.sysbuild b/tests/bsim/bluetooth/audio_samples/cap/initiator/Kconfig.sysbuild new file mode 100644 index 00000000000..c9f3abf294f --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/Kconfig.sysbuild @@ -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" diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/prj.conf b/tests/bsim/bluetooth/audio_samples/cap/initiator/prj.conf new file mode 100644 index 00000000000..ab925ee17c0 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/prj.conf @@ -0,0 +1,2 @@ +# Please build using the sample configuration file: +# ${ZEPHYR_BASE}/samples/bluetooth/cap_initiator/prj.conf diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/src/cap_initiator_sample_test.c b/tests/bsim/bluetooth/audio_samples/cap/initiator/src/cap_initiator_sample_test.c new file mode 100644 index 00000000000..e6defdbad02 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/src/cap_initiator_sample_test.c @@ -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; +} diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/src/test_main.c b/tests/bsim/bluetooth/audio_samples/cap/initiator/src/test_main.c new file mode 100644 index 00000000000..3aa6fac9b02 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/src/test_main.c @@ -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}; diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/sysbuild.cmake b/tests/bsim/bluetooth/audio_samples/cap/initiator/sysbuild.cmake new file mode 100644 index 00000000000..185eb396b01 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/sysbuild.cmake @@ -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}) diff --git a/tests/bsim/bluetooth/audio_samples/cap/tests_scripts/cap_unicast.sh b/tests/bsim/bluetooth/audio_samples/cap/tests_scripts/cap_unicast.sh new file mode 100755 index 00000000000..389ac0182b3 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/tests_scripts/cap_unicast.sh @@ -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 diff --git a/tests/bsim/bluetooth/audio_samples/compile.sh b/tests/bsim/bluetooth/audio_samples/compile.sh index b5b19f325f9..1bec1bb8319 100755 --- a/tests/bsim/bluetooth/audio_samples/compile.sh +++ b/tests/bsim/bluetooth/audio_samples/compile.sh @@ -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