Bluetooth: CAP: Add check for streaming state when starting unicast

When calling bt_cap_initiator_unicast_audio_start on a set of streams
that are all in the streaming state we return early with -EALREADY.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2024-06-12 13:20:05 +02:00 committed by Carles Cufí
commit 0e4e7628fd
3 changed files with 58 additions and 1 deletions

View file

@ -346,7 +346,10 @@ int bt_cap_initiator_unregister_cb(const struct bt_cap_initiator_cb *cb);
*
* @param param Parameters to start the audio streams.
*
* @return 0 on success or negative error value on failure.
* @retval 0 on success
* @retval -EBUSY if a CAP procedure is already in progress
* @retval -EINVAL if any parameter is invalid
* @retval -EALREADY All streams are already in the streaming state
*/
int bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start_param *param);

View file

@ -26,6 +26,7 @@
#include <zephyr/sys/check.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys/util_macro.h>
#include <sys/errno.h>
#include "bap_endpoint.h"
#include "cap_internal.h"
@ -860,6 +861,8 @@ static int cap_initiator_unicast_audio_configure(
int bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start_param *param)
{
bool all_streaming = true;
if (bt_cap_common_proc_is_active()) {
LOG_DBG("A CAP procedure is already in progress");
@ -870,6 +873,20 @@ int bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start
return -EINVAL;
}
for (size_t i = 0U; i < param->count; i++) {
const struct bt_bap_stream *bap_stream =
&param->stream_params[i].stream->bap_stream;
if (!stream_is_in_state(bap_stream, BT_BAP_EP_STATE_STREAMING)) {
all_streaming = false;
}
}
if (all_streaming) {
LOG_DBG("All streams are already in the streaming state");
return -EALREADY;
}
return cap_initiator_unicast_audio_configure(param);
}

View file

@ -500,3 +500,40 @@ static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_st
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
}
}
static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_state_streaming)
{
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];
test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
stream_params[i].ep, &fixture->preset,
BT_BAP_EP_STATE_STREAMING);
}
err = bt_cap_initiator_unicast_audio_start(&param);
zassert_equal(err, -EALREADY, "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);
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
const enum bt_bap_ep_state state = bap_stream->ep->status.state;
zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
}
}