Bluetooth: Audio: CAP inittiator broadcast stop procedure

Implemented support for stopping and deleting a
CAP broadcast source.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2022-07-05 15:14:47 +02:00 committed by Carles Cufí
parent 9d0ec99315
commit 928e5bbcf0
4 changed files with 96 additions and 4 deletions

View file

@ -360,13 +360,31 @@ int bt_cap_initiator_broadcast_audio_update(struct bt_cap_broadcast_source *broa
* to be enabled.
*
* @param broadcast_source The broadcast source to stop. The audio streams
* in this will be stopped and reset, and the
* @p broadcast_source will be invalidated.
* in this will be stopped and reset.
*
* @return 0 on success or negative error value on failure.
*/
int bt_cap_initiator_broadcast_audio_stop(struct bt_cap_broadcast_source *broadcast_source);
/*
* @brief Delete Common Audio Profile broadcast source
*
* This can only be done after the broadcast source has been stopped by calling
* bt_cap_initiator_broadcast_audio_stop() and after the
* bt_audio_stream_ops.stopped() callback has been called for all streams in the
* broadcast source.
*
* @note @kconfig{CONFIG_BT_CAP_INITIATOR} and
* @kconfig{CONFIG_BT_AUDIO_BROADCAST_SOURCE} must be enabled for this function
* to be enabled.
*
* @param broadcast_source The broadcast source to delete.
* The @p broadcast_source will be invalidated.
*
* @return 0 on success or negative error value on failure.
*/
int bt_cap_initiator_broadcast_audio_delete(struct bt_cap_broadcast_source *broadcast_source);
/**
* @brief Get the broadcast ID of a Common Audio Profile broadcast source
*
@ -402,6 +420,7 @@ int bt_cap_initiator_broadcast_get_id(const struct bt_cap_broadcast_source *sour
int bt_cap_initiator_broadcast_get_base(struct bt_cap_broadcast_source *source,
struct net_buf_simple *base_buf);
struct bt_cap_unicast_to_broadcast_param {
/** The source unicast group with the streams. */
struct bt_audio_unicast_group *unicast_group;

View file

@ -168,7 +168,13 @@ int bt_cap_initiator_broadcast_audio_update(struct bt_cap_broadcast_source *broa
int bt_cap_initiator_broadcast_audio_stop(struct bt_cap_broadcast_source *broadcast_source)
{
return -ENOSYS;
return bt_audio_broadcast_source_stop((struct bt_audio_broadcast_source *)broadcast_source);
}
int bt_cap_initiator_broadcast_audio_delete(struct bt_cap_broadcast_source *broadcast_source)
{
return bt_audio_broadcast_source_delete(
(struct bt_audio_broadcast_source *)broadcast_source);
}
int bt_cap_initiator_broadcast_get_id(const struct bt_cap_broadcast_source *source,

View file

@ -19,6 +19,7 @@ CREATE_FLAG(flag_base_received);
CREATE_FLAG(flag_pa_synced);
CREATE_FLAG(flag_syncable);
CREATE_FLAG(flag_received);
CREATE_FLAG(flag_pa_sync_lost);
static struct bt_audio_broadcast_sink *g_broadcast_sink;
static struct bt_cap_stream broadcast_sink_streams[CONFIG_BT_AUDIO_BROADCAST_SNK_STREAM_COUNT];
@ -148,7 +149,9 @@ static void pa_sync_lost_cb(struct bt_audio_broadcast_sink *sink)
return;
}
FAIL("Sink %p disconnected\n", sink);
printk("Sink %p disconnected\n", sink);
SET_FLAG(flag_pa_sync_lost);
g_broadcast_sink = NULL;
}
@ -338,6 +341,18 @@ static void test_cap_acceptor_broadcast(void)
printk("Waiting for data\n");
WAIT_FOR_FLAG(flag_received);
/* The order of PA sync lost and BIG Sync lost is irrelevant
* and depend on timeout parameters. We just wait for PA first, but
* either way will work.
*/
printk("Waiting for PA disconnected\n");
WAIT_FOR_FLAG(flag_pa_sync_lost);
printk("Waiting for streams to be stopped\n");
for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sink_streams); i++) {
k_sem_take(&sem_broadcast_stopped, K_FOREVER);
}
PASS("CAP acceptor broadcast passed\n");
}

View file

@ -329,6 +329,32 @@ static int start_extended_adv(struct bt_le_ext_adv *adv)
return 0;
}
static int stop_and_delete_extended_adv(struct bt_le_ext_adv *adv)
{
int err;
/* Stop extended advertising */
err = bt_le_per_adv_stop(adv);
if (err) {
printk("Failed to stop periodic advertising: %d\n", err);
return err;
}
err = bt_le_ext_adv_stop(adv);
if (err) {
printk("Failed to stop extended advertising: %d\n", err);
return err;
}
err = bt_le_ext_adv_delete(adv);
if (err) {
printk("Failed to delete extended advertising: %d\n", err);
return err;
}
return 0;
}
static void test_cap_initiator_broadcast(void)
{
struct bt_codec_data bis_codec_data = BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_FREQ,
@ -426,6 +452,32 @@ static void test_cap_initiator_broadcast(void)
/* Keeping running for a little while */
k_sleep(K_SECONDS(5));
err = bt_cap_initiator_broadcast_audio_stop(broadcast_source);
if (err != 0) {
FAIL("Failed to stop broadcast source: %d\n", err);
return;
}
/* Wait for all to be stopped */
printk("Waiting for broadcast_streams to be stopped\n");
for (size_t i = 0U; i < ARRAY_SIZE(broadcast_streams); i++) {
k_sem_take(&sem_broadcast_stopped, K_FOREVER);
}
err = bt_cap_initiator_broadcast_audio_delete(broadcast_source);
if (err != 0) {
FAIL("Failed to stop broadcast source: %d\n", err);
return;
}
broadcast_source = NULL;
err = stop_and_delete_extended_adv(adv);
if (err != 0) {
FAIL("Failed to stop and delete extended advertising: %d\n", err);
return;
}
adv = NULL;
PASS("CAP initiator broadcast passed\n");
}