diff --git a/subsys/bluetooth/audio/cap_initiator.c b/subsys/bluetooth/audio/cap_initiator.c index c0402853a5dae9..72a32d181b748e 100644 --- a/subsys/bluetooth/audio/cap_initiator.c +++ b/subsys/bluetooth/audio/cap_initiator.c @@ -978,7 +978,8 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) if (free_conn != NULL) { *free_conn = stream_conn; } else { - __ASSERT_PRINT("No free conns"); + __ASSERT(false, "[%zu]: No free conns", i); + return; } } diff --git a/tests/bluetooth/audio/cap_initiator/CMakeLists.txt b/tests/bluetooth/audio/cap_initiator/CMakeLists.txt index f1683d6035fabb..2c7096e8c3249a 100644 --- a/tests/bluetooth/audio/cap_initiator/CMakeLists.txt +++ b/tests/bluetooth/audio/cap_initiator/CMakeLists.txt @@ -14,7 +14,7 @@ target_include_directories(testbinary PRIVATE include) target_sources(testbinary PRIVATE - ${ZEPHYR_BASE}/subsys/bluetooth/host/uuid.c src/main.c src/test_common.c + src/test_unicast_start.c ) diff --git a/tests/bluetooth/audio/cap_initiator/prj.conf b/tests/bluetooth/audio/cap_initiator/prj.conf index 18c79aa8c8e17b..18afc819e241fe 100644 --- a/tests/bluetooth/audio/cap_initiator/prj.conf +++ b/tests/bluetooth/audio/cap_initiator/prj.conf @@ -3,7 +3,6 @@ CONFIG_LOG=y CONFIG_BT=y CONFIG_BT_CENTRAL=y -CONFIG_BT_MAX_CONN=2 CONFIG_BT_AUDIO=y # Dependencies for CAP initiator unicast @@ -13,6 +12,13 @@ CONFIG_BT_CSIP_SET_COORDINATOR=y CONFIG_BT_CAP_INITIATOR=y CONFIG_BT_CAP_INITIATOR_LOG_LEVEL_DBG=y +# Support setting up a sink and source stream on 2 acceptors +CONFIG_BT_MAX_CONN=2 +CONFIG_BT_ISO_MAX_CHAN=4 +CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT=4 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT=2 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT=2 + CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 CONFIG_ASSERT_VERBOSE=y diff --git a/tests/bluetooth/audio/cap_initiator/src/test_common.c b/tests/bluetooth/audio/cap_initiator/src/test_common.c index fa47e617452374..94e9de0cda6174 100644 --- a/tests/bluetooth/audio/cap_initiator/src/test_common.c +++ b/tests/bluetooth/audio/cap_initiator/src/test_common.c @@ -6,6 +6,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + #include "cap_initiator.h" #include "conn.h" #include "test_common.h" @@ -24,7 +27,7 @@ void test_conn_init(struct bt_conn *conn) { conn->index = 0; conn->info.type = BT_CONN_TYPE_LE; - conn->info.role = BT_CONN_ROLE_PERIPHERAL; + conn->info.role = BT_CONN_ROLE_CENTRAL; conn->info.state = BT_CONN_STATE_CONNECTED; conn->info.security.level = BT_SECURITY_L2; conn->info.security.enc_key_size = BT_ENC_KEY_SIZE_MAX; diff --git a/tests/bluetooth/audio/cap_initiator/src/test_unicast_start.c b/tests/bluetooth/audio/cap_initiator/src/test_unicast_start.c new file mode 100644 index 00000000000000..8a83454419a178 --- /dev/null +++ b/tests/bluetooth/audio/cap_initiator/src/test_unicast_start.c @@ -0,0 +1,386 @@ +/* test_unicast_start.c - unit test for unicast start procedure */ + +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bap_endpoint.h" +#include "cap_initiator.h" +#include "conn.h" +#include "expects_util.h" +#include "test_common.h" +#include "ztest_assert.h" +#include "ztest_test.h" + +#define FFF_GLOBALS + +struct cap_initiator_test_unicast_start_fixture { + struct bt_cap_stream cap_streams[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT]; + struct bt_bap_ep eps[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT]; + struct bt_bap_unicast_group unicast_group; + struct bt_conn conns[CONFIG_BT_MAX_CONN]; + struct bt_bap_lc3_preset preset; +}; + +static void cap_initiator_test_unicast_start_fixture_init( + struct cap_initiator_test_unicast_start_fixture *fixture) +{ + fixture->preset = (struct bt_bap_lc3_preset)BT_BAP_LC3_UNICAST_PRESET_16_2_1( + BT_AUDIO_LOCATION_MONO_AUDIO, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + + for (size_t i = 0U; i < ARRAY_SIZE(fixture->conns); i++) { + test_conn_init(&fixture->conns[i]); + } + + for (size_t i = 0U; i < ARRAY_SIZE(fixture->cap_streams); i++) { + struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream; + + sys_slist_append(&fixture->unicast_group.streams, &bap_stream->_node); + bap_stream->group = &fixture->unicast_group; + } + + for (size_t i = 0U; i < ARRAY_SIZE(fixture->eps); i++) { + fixture->eps[i].dir = (i & 1) + 1; /* Makes it either 1 or 2 (sink or source)*/ + } +} + +static void *cap_initiator_test_unicast_start_setup(void) +{ + struct cap_initiator_test_unicast_start_fixture *fixture; + + fixture = malloc(sizeof(*fixture)); + zassert_not_null(fixture); + + return fixture; +} + +static void cap_initiator_test_unicast_start_before(void *f) +{ + int err; + + memset(f, 0, sizeof(struct cap_initiator_test_unicast_start_fixture)); + cap_initiator_test_unicast_start_fixture_init(f); + + err = bt_cap_initiator_register_cb(&mock_cap_initiator_cb); + zassert_equal(0, err, "Unexpected return value %d", err); +} + +static void cap_initiator_test_unicast_start_after(void *f) +{ + struct cap_initiator_test_unicast_start_fixture *fixture = f; + + bt_cap_initiator_unregister_cb(&mock_cap_initiator_cb); + + for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) { + mock_bt_conn_disconnected(&fixture->conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN); + } +} + +static void cap_initiator_test_unicast_start_teardown(void *f) +{ + free(f); +} + +ZTEST_SUITE(cap_initiator_test_unicast_start, NULL, cap_initiator_test_unicast_start_setup, + cap_initiator_test_unicast_start_before, cap_initiator_test_unicast_start_after, + cap_initiator_test_unicast_start_teardown); + +static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start) +{ + struct bt_cap_unicast_audio_start_stream_param + stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = ARRAY_SIZE(stream_params), + .stream_params = stream_params, + }; + int err; + + for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) { + stream_params[i].stream = &fixture->cap_streams[i]; + stream_params[i].codec_cfg = &fixture->preset.codec_cfg; + stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)]; + stream_params[i].ep = &fixture->eps[i]; + } + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, 0, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); + + for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) { + const enum bt_bap_ep_state state = + fixture->cap_streams[i].bap_stream.ep->status.state; + + zassert_equal(state, BT_BAP_EP_STATE_STREAMING, "[%zu] Unexpected state: %d", i, + state); + } +} + +static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_inval_param_null) +{ + int err; + + err = bt_cap_initiator_unicast_audio_start(NULL); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, + test_initiator_unicast_start_inval_param_null_param) +{ + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT, + .stream_params = NULL, + }; + int err; + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, + test_initiator_unicast_start_inval_param_null_member) +{ + struct bt_cap_unicast_audio_start_stream_param + stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = ARRAY_SIZE(stream_params), + .stream_params = stream_params, + }; + int err; + + for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) { + stream_params[i].stream = &fixture->cap_streams[i]; + stream_params[i].codec_cfg = &fixture->preset.codec_cfg; + stream_params[i].ep = &fixture->eps[i]; + } + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_inval_missing_cas) +{ + struct bt_cap_unicast_audio_start_stream_param + stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_CSIP, /* CSIP requires CAS */ + .count = ARRAY_SIZE(stream_params), + .stream_params = stream_params, + }; + int err; + + for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) { + stream_params[i].stream = &fixture->cap_streams[i]; + stream_params[i].codec_cfg = &fixture->preset.codec_cfg; + stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)]; + stream_params[i].ep = &fixture->eps[i]; + } + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, + test_initiator_unicast_start_inval_param_zero_count) +{ + struct bt_cap_unicast_audio_start_stream_param + stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = 0U, + .stream_params = stream_params, + }; + int err; + + for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) { + stream_params[i].stream = &fixture->cap_streams[i]; + stream_params[i].codec_cfg = &fixture->preset.codec_cfg; + stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)]; + stream_params[i].ep = &fixture->eps[i]; + } + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, + test_initiator_unicast_start_inval_param_inval_count) +{ + struct bt_cap_unicast_audio_start_stream_param + stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT + 1U, + .stream_params = stream_params, + }; + int err; + + for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) { + stream_params[i].stream = &fixture->cap_streams[i]; + stream_params[i].codec_cfg = &fixture->preset.codec_cfg; + stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)]; + stream_params[i].ep = &fixture->eps[i]; + } + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, + test_initiator_unicast_start_inval_param_inval_stream_param_null_stream) +{ + struct bt_cap_unicast_audio_start_stream_param stream_param = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = 1, + .stream_params = &stream_param, + }; + int err; + + stream_param.stream = NULL; + stream_param.codec_cfg = &fixture->preset.codec_cfg; + stream_param.member.member = &fixture->conns[0]; + stream_param.ep = &fixture->eps[0]; + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, + test_initiator_unicast_start_inval_param_inval_stream_param_null_codec_cfg) +{ + struct bt_cap_unicast_audio_start_stream_param stream_param = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = 1, + .stream_params = &stream_param, + }; + int err; + + stream_param.stream = &fixture->cap_streams[0]; + stream_param.codec_cfg = NULL; + stream_param.member.member = &fixture->conns[0]; + stream_param.ep = &fixture->eps[0]; + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, + test_initiator_unicast_start_inval_param_inval_stream_param_null_member) +{ + struct bt_cap_unicast_audio_start_stream_param stream_param = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = 1, + .stream_params = &stream_param, + }; + int err; + + stream_param.stream = &fixture->cap_streams[0]; + stream_param.codec_cfg = &fixture->preset.codec_cfg; + stream_param.member.member = NULL; + stream_param.ep = &fixture->eps[0]; + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, + test_initiator_unicast_start_inval_param_inval_stream_param_null_ep) +{ + struct bt_cap_unicast_audio_start_stream_param stream_param = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = 1, + .stream_params = &stream_param, + }; + int err; + + stream_param.stream = &fixture->cap_streams[0]; + stream_param.codec_cfg = &fixture->preset.codec_cfg; + stream_param.member.member = &fixture->conns[0]; + stream_param.ep = NULL; + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} + +static ZTEST_F(cap_initiator_test_unicast_start, + test_initiator_unicast_start_inval_param_inval_stream_param_invalid_meta) +{ + struct bt_cap_unicast_audio_start_stream_param stream_param = {0}; + const struct bt_cap_unicast_audio_start_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .count = 1, + .stream_params = &stream_param, + }; + int err; + + stream_param.stream = &fixture->cap_streams[0]; + stream_param.codec_cfg = &fixture->preset.codec_cfg; + stream_param.member.member = &fixture->conns[0]; + stream_param.ep = &fixture->eps[0]; + + /* CAP requires stream context - Let's remove it */ + memset(stream_param.codec_cfg->meta, 0, sizeof(stream_param.codec_cfg->meta)); + stream_param.codec_cfg->meta_len = 0U; + + err = bt_cap_initiator_unicast_audio_start(¶m); + zassert_equal(err, -EINVAL, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0, + mock_cap_initiator_unicast_start_complete_cb_fake.call_count); +} diff --git a/tests/bluetooth/audio/cap_initiator/uut/CMakeLists.txt b/tests/bluetooth/audio/cap_initiator/uut/CMakeLists.txt index 41249c6b89aae6..dd1bf20368726a 100644 --- a/tests/bluetooth/audio/cap_initiator/uut/CMakeLists.txt +++ b/tests/bluetooth/audio/cap_initiator/uut/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2023 Nordic Semiconductor ASA +# Copyright (c) 2023-2024 Nordic Semiconductor ASA # # SPDX-License-Identifier: Apache-2.0 # @@ -14,6 +14,7 @@ add_library(uut STATIC ${ZEPHYR_BASE}/subsys/bluetooth/audio/cap_common.c ${ZEPHYR_BASE}/subsys/bluetooth/audio/cap_stream.c ${ZEPHYR_BASE}/subsys/bluetooth/common/bt_str.c + ${ZEPHYR_BASE}/subsys/bluetooth/host/uuid.c ${ZEPHYR_BASE}/subsys/logging/log_minimal.c ${ZEPHYR_BASE}/subsys/net/buf_simple.c bap_unicast_client.c diff --git a/tests/bluetooth/audio/cap_initiator/uut/bap_unicast_client.c b/tests/bluetooth/audio/cap_initiator/uut/bap_unicast_client.c index ef9ac1328b80e2..87a0db5dadd431 100644 --- a/tests/bluetooth/audio/cap_initiator/uut/bap_unicast_client.c +++ b/tests/bluetooth/audio/cap_initiator/uut/bap_unicast_client.c @@ -1,10 +1,21 @@ /* * Copyright (c) 2023 Codecoup + * Copyright (c) 2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include + +#include #include +#include + +#include "bap_endpoint.h" +#include "ztest_assert.h" bool bt_bap_ep_is_unicast_client(const struct bt_bap_ep *ep) { @@ -14,43 +25,111 @@ bool bt_bap_ep_is_unicast_client(const struct bt_bap_ep *ep) int bt_bap_unicast_client_config(struct bt_bap_stream *stream, const struct bt_audio_codec_cfg *codec_cfg) { - zassert_unreachable("Unexpected call to '%s()' occurred", __func__); + if (stream == NULL || stream->ep == NULL || codec_cfg == NULL) { + return -EINVAL; + } + + stream->ep->status.state = BT_BAP_EP_STATE_CODEC_CONFIGURED; + + if (stream->ops != NULL && stream->ops->configured != NULL) { + const struct bt_audio_codec_qos_pref pref = {0}; + + stream->ops->configured(stream, &pref); + } + return 0; } int bt_bap_unicast_client_qos(struct bt_conn *conn, struct bt_bap_unicast_group *group) { - zassert_unreachable("Unexpected call to '%s()' occurred", __func__); + struct bt_bap_stream *stream; + + if (conn == NULL || group == NULL) { + return -EINVAL; + } + + SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) { + if (stream->conn == conn) { + stream->ep->status.state = BT_BAP_EP_STATE_QOS_CONFIGURED; + + if (stream->ops != NULL && stream->ops->qos_set != NULL) { + stream->ops->qos_set(stream); + } + } + } + return 0; } -int bt_bap_unicast_client_enable(struct bt_bap_stream *stream, uint8_t meta[], +int bt_bap_unicast_client_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len) { - zassert_unreachable("Unexpected call to '%s()' occurred", __func__); + if (stream == NULL) { + return -EINVAL; + } + + stream->ep->status.state = BT_BAP_EP_STATE_ENABLING; + + if (stream->ops != NULL && stream->ops->enabled != NULL) { + stream->ops->enabled(stream); + } + return 0; } -int bt_bap_unicast_client_metadata(struct bt_bap_stream *stream, uint8_t meta[], +int bt_bap_unicast_client_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len) { - zassert_unreachable("Unexpected call to '%s()' occurred", __func__); + if (stream == NULL) { + return -EINVAL; + } + + if (stream->ops != NULL && stream->ops->metadata_updated != NULL) { + stream->ops->metadata_updated(stream); + } + return 0; } -int bt_bap_unicast_client_disable(struct bt_bap_stream *stream) +int bt_bap_unicast_client_connect(struct bt_bap_stream *stream) { - zassert_unreachable("Unexpected call to '%s()' occurred", __func__); + if (stream == NULL) { + return -EINVAL; + } + + if (stream->ops != NULL && stream->ops->connected != NULL) { + stream->ops->connected(stream); + } + + if (stream->ep != NULL && stream->ep->dir == BT_AUDIO_DIR_SINK) { + /* Mocking that the unicast server automatically starts the stream */ + stream->ep->status.state = BT_BAP_EP_STATE_STREAMING; + + if (stream->ops != NULL && stream->ops->started != NULL) { + stream->ops->started(stream); + } + } + return 0; } -int bt_bap_unicast_client_connect(struct bt_bap_stream *stream) +int bt_bap_unicast_client_start(struct bt_bap_stream *stream) { - zassert_unreachable("Unexpected call to '%s()' occurred", __func__); + /* As per the ASCS spec, only source streams can be started by the client */ + if (stream == NULL || stream->ep == NULL || stream->ep->dir == BT_AUDIO_DIR_SINK) { + return -EINVAL; + } + + stream->ep->status.state = BT_BAP_EP_STATE_STREAMING; + + if (stream->ops != NULL && stream->ops->started != NULL) { + stream->ops->started(stream); + } + return 0; } -int bt_bap_unicast_client_start(struct bt_bap_stream *stream) +int bt_bap_unicast_client_disable(struct bt_bap_stream *stream) { zassert_unreachable("Unexpected call to '%s()' occurred", __func__); return 0; diff --git a/tests/bluetooth/audio/cap_initiator/uut/csip.c b/tests/bluetooth/audio/cap_initiator/uut/csip.c index 4079e1450a06f0..45e1940b8812b8 100644 --- a/tests/bluetooth/audio/cap_initiator/uut/csip.c +++ b/tests/bluetooth/audio/cap_initiator/uut/csip.c @@ -9,6 +9,10 @@ #include #include +#include +#include +#include + #include #include diff --git a/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c b/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c index 7dfbc379e699e1..40fd5c37bffaf6 100644 --- a/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c @@ -510,12 +510,6 @@ static void discover_cas_inval(struct bt_conn *conn) { int err; - err = bt_cap_initiator_unicast_discover(NULL); - if (err == 0) { - FAIL("bt_cap_initiator_unicast_discover with NULL conn did not fail\n"); - return; - } - /* Test if it handles concurrent request for same connection */ UNSET_FLAG(flag_discovered); @@ -576,111 +570,6 @@ static void unicast_group_create(struct bt_bap_unicast_group **out_unicast_group } } -static void unicast_audio_start_inval(struct bt_bap_unicast_group *unicast_group) -{ - struct bt_audio_codec_cfg invalid_codec = BT_AUDIO_CODEC_LC3_CONFIG( - BT_AUDIO_CODEC_CFG_FREQ_16KHZ, BT_AUDIO_CODEC_CFG_DURATION_10, - BT_AUDIO_LOCATION_FRONT_LEFT, 40U, 1, BT_AUDIO_CONTEXT_TYPE_MEDIA); - struct bt_cap_unicast_audio_start_stream_param invalid_stream_param; - struct bt_cap_unicast_audio_start_stream_param valid_stream_param; - struct bt_cap_unicast_audio_start_param invalid_start_param; - struct bt_cap_unicast_audio_start_param valid_start_param; - int err; - - valid_start_param.type = BT_CAP_SET_TYPE_AD_HOC; - valid_start_param.count = 1u; - valid_start_param.stream_params = &valid_stream_param; - - valid_stream_param.member.member = default_conn; - valid_stream_param.stream = &unicast_client_sink_streams[0]; - valid_stream_param.ep = unicast_sink_eps[bt_conn_index(default_conn)][0]; - valid_stream_param.codec_cfg = &unicast_preset_16_2_1.codec_cfg; - - /* Test NULL parameters */ - err = bt_cap_initiator_unicast_audio_start(NULL); - if (err == 0) { - FAIL("bt_cap_initiator_unicast_audio_start with NULL param did not fail\n"); - return; - } - - /* Test invalid parameters */ - memcpy(&invalid_stream_param, &valid_stream_param, sizeof(valid_stream_param)); - memcpy(&invalid_start_param, &valid_start_param, sizeof(valid_start_param)); - invalid_start_param.stream_params = &invalid_stream_param; - - /* Test invalid stream_start parameters */ - invalid_start_param.count = 0U; - err = bt_cap_initiator_unicast_audio_start(&invalid_start_param); - if (err == 0) { - FAIL("bt_cap_initiator_unicast_audio_start with 0 count did not fail\n"); - return; - } - - memcpy(&invalid_start_param, &valid_start_param, sizeof(valid_start_param)); - invalid_start_param.stream_params = &invalid_stream_param; - - invalid_start_param.stream_params = NULL; - err = bt_cap_initiator_unicast_audio_start(&invalid_start_param); - if (err == 0) { - FAIL("bt_cap_initiator_unicast_audio_start with NULL stream params did not fail\n"); - return; - } - - memcpy(&invalid_start_param, &valid_start_param, sizeof(valid_start_param)); - invalid_start_param.stream_params = &invalid_stream_param; - - /* Test invalid stream_param parameters */ - invalid_stream_param.member.member = NULL; - err = bt_cap_initiator_unicast_audio_start(&invalid_start_param); - if (err == 0) { - FAIL("bt_cap_initiator_unicast_audio_start with NULL stream params member did not " - "fail\n"); - return; - } - - memcpy(&invalid_stream_param, &valid_stream_param, sizeof(valid_stream_param)); - - invalid_stream_param.stream = NULL; - err = bt_cap_initiator_unicast_audio_start(&invalid_start_param); - if (err == 0) { - FAIL("bt_cap_initiator_unicast_audio_start with NULL stream params stream did not " - "fail\n"); - return; - } - - memcpy(&invalid_stream_param, &valid_stream_param, sizeof(valid_stream_param)); - - invalid_stream_param.ep = NULL; - err = bt_cap_initiator_unicast_audio_start(&invalid_start_param); - if (err == 0) { - FAIL("bt_cap_initiator_unicast_audio_start with NULL stream params ep did not " - "fail\n"); - return; - } - - memcpy(&invalid_stream_param, &valid_stream_param, sizeof(valid_stream_param)); - - invalid_stream_param.codec_cfg = NULL; - err = bt_cap_initiator_unicast_audio_start(&invalid_start_param); - if (err == 0) { - FAIL("bt_cap_initiator_unicast_audio_start with NULL stream params codec did not " - "fail\n"); - return; - } - - /* Clear metadata so that it does not contain the mandatory stream context */ - memcpy(&invalid_stream_param, &valid_stream_param, sizeof(valid_stream_param)); - memset(&invalid_codec.meta, 0, sizeof(invalid_codec.meta)); - - invalid_stream_param.codec_cfg = &invalid_codec; - err = bt_cap_initiator_unicast_audio_start(&invalid_start_param); - if (err == 0) { - FAIL("bt_cap_initiator_unicast_audio_start with invalid Codec metadata did not " - "fail\n"); - return; - } -} - static void unicast_audio_start(struct bt_bap_unicast_group *unicast_group, bool wait) { struct bt_cap_unicast_audio_start_stream_param stream_param[2]; @@ -926,7 +815,6 @@ static void test_main_cap_initiator_unicast_inval(void) unicast_group_create(&unicast_group); - unicast_audio_start_inval(unicast_group); unicast_audio_start(unicast_group, true); unicast_audio_update_inval();