Skip to content

Commit

Permalink
Bluetooth: CAP: Add broadcast source callback structs
Browse files Browse the repository at this point in the history
These callbacks are trigger for changes that affect the entire
broadcast source, such as the BIG started and terminated events.

Signed-off-by: Emil Gydesen <[email protected]>
  • Loading branch information
Thalley committed Jul 5, 2024
1 parent 1cbd1ad commit 1f4d967
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 15 deletions.
16 changes: 16 additions & 0 deletions include/zephyr/bluetooth/audio/cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,22 @@ struct bt_cap_initiator_cb {
*/
void (*unicast_stop_complete)(int err, struct bt_conn *conn);
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
#if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
/**
* @brief The Broadcast Source has started and all of the streams are ready for audio data
*
* @param source The started Broadcast Source
*/
void (*broadcast_started)(struct bt_cap_broadcast_source *source);

/**
* @brief The Broadcast Source has stopped and none of the streams are ready for audio data
*
* @param source The stopped Broadcast Source
* @param reason The reason why the BIG stopped (see the BT_HCI_ERR_* values)
*/
void (*broadcast_stopped)(struct bt_cap_broadcast_source *source, uint8_t reason);
#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
};

/**
Expand Down
57 changes: 57 additions & 0 deletions subsys/bluetooth/audio/cap_initiator.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,52 @@ int bt_cap_initiator_broadcast_audio_create(
&(*broadcast_source)->bap_broadcast);
}

static struct bt_cap_broadcast_source *get_cap_broadcast_source_by_bap_broadcast_source(
const struct bt_bap_broadcast_source *bap_broadcast_source)
{
for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sources); i++) {
if (broadcast_sources[i].bap_broadcast == bap_broadcast_source) {
return &broadcast_sources[i];
}
}

return NULL;
}

static void broadcast_source_started_cb(struct bt_bap_broadcast_source *bap_broadcast_source)
{
if (cap_cb && cap_cb->broadcast_started) {
struct bt_cap_broadcast_source *source =
get_cap_broadcast_source_by_bap_broadcast_source(bap_broadcast_source);

if (source == NULL) {
/* Not one of ours */
return;
}
cap_cb->broadcast_started(source);
}
}

static void broadcast_source_stopped_cb(struct bt_bap_broadcast_source *bap_broadcast_source,
uint8_t reason)
{
if (cap_cb && cap_cb->broadcast_stopped) {
struct bt_cap_broadcast_source *source =
get_cap_broadcast_source_by_bap_broadcast_source(bap_broadcast_source);

if (source == NULL) {
/* Not one of ours */
return;
}
cap_cb->broadcast_stopped(source, reason);
}
}

int bt_cap_initiator_broadcast_audio_start(struct bt_cap_broadcast_source *broadcast_source,
struct bt_le_ext_adv *adv)
{
static bool broadcast_source_cbs_registered;

CHECKIF(adv == NULL) {
LOG_DBG("adv is NULL");
return -EINVAL;
Expand All @@ -268,6 +311,20 @@ int bt_cap_initiator_broadcast_audio_start(struct bt_cap_broadcast_source *broad
return -EINVAL;
}

if (!broadcast_source_cbs_registered) {
static struct bt_bap_broadcast_source_cb broadcast_source_cb = {
.started = broadcast_source_started_cb,
.stopped = broadcast_source_stopped_cb,
};
const int err = bt_bap_broadcast_source_register_cb(&broadcast_source_cb);

if (err != 0) {
__ASSERT(false, "Failed to register BAP broadcast source callbacks");
}

broadcast_source_cbs_registered = true;
}

return bt_bap_broadcast_source_start(broadcast_source->bap_broadcast, adv);
}

Expand Down
3 changes: 3 additions & 0 deletions tests/bluetooth/audio/mocks/include/cap_initiator.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@ DECLARE_FAKE_VOID_FUNC(mock_cap_initiator_unicast_discovery_complete_cb, struct
DECLARE_FAKE_VOID_FUNC(mock_cap_initiator_unicast_start_complete_cb, int, struct bt_conn *);
DECLARE_FAKE_VOID_FUNC(mock_cap_initiator_unicast_update_complete_cb, int, struct bt_conn *);
DECLARE_FAKE_VOID_FUNC(mock_cap_initiator_unicast_stop_complete_cb, int, struct bt_conn *);
DECLARE_FAKE_VOID_FUNC(mock_cap_initiator_broadcast_started_cb, struct bt_cap_broadcast_source *);
DECLARE_FAKE_VOID_FUNC(mock_cap_initiator_broadcast_stopped_cb, struct bt_cap_broadcast_source *,
uint8_t);

#endif /* MOCKS_CAP_INITIATOR_H_ */
7 changes: 7 additions & 0 deletions tests/bluetooth/audio/mocks/src/cap_initiator.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ DEFINE_FAKE_VOID_FUNC(mock_cap_initiator_unicast_discovery_complete_cb, struct b
DEFINE_FAKE_VOID_FUNC(mock_cap_initiator_unicast_start_complete_cb, int, struct bt_conn *);
DEFINE_FAKE_VOID_FUNC(mock_cap_initiator_unicast_update_complete_cb, int, struct bt_conn *);
DEFINE_FAKE_VOID_FUNC(mock_cap_initiator_unicast_stop_complete_cb, int, struct bt_conn *);
DEFINE_FAKE_VOID_FUNC(mock_cap_initiator_broadcast_started_cb, struct bt_cap_broadcast_source *);
DEFINE_FAKE_VOID_FUNC(mock_cap_initiator_broadcast_stopped_cb, struct bt_cap_broadcast_source *,
uint8_t);

const struct bt_cap_initiator_cb mock_cap_initiator_cb = {
#if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
Expand All @@ -33,6 +36,10 @@ const struct bt_cap_initiator_cb mock_cap_initiator_cb = {
.unicast_update_complete = mock_cap_initiator_unicast_update_complete_cb,
.unicast_stop_complete = mock_cap_initiator_unicast_stop_complete_cb,
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
#if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
.broadcast_started = mock_cap_initiator_broadcast_started_cb,
.broadcast_stopped = mock_cap_initiator_broadcast_stopped_cb,
#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
};

void mock_cap_initiator_init(void)
Expand Down
58 changes: 43 additions & 15 deletions tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,10 @@ static struct bt_bap_lc3_preset broadcast_preset_16_2_1 =
BT_BAP_LC3_BROADCAST_PRESET_16_2_1(LOCATION, CONTEXT);
static size_t stream_count;

static K_SEM_DEFINE(sem_broadcast_started, 0U, ARRAY_SIZE(broadcast_streams));
static K_SEM_DEFINE(sem_broadcast_stopped, 0U, ARRAY_SIZE(broadcast_streams));
static K_SEM_DEFINE(sem_broadcast_stream_started, 0U, ARRAY_SIZE(broadcast_streams));
static K_SEM_DEFINE(sem_broadcast_stream_stopped, 0U, ARRAY_SIZE(broadcast_streams));
static K_SEM_DEFINE(sem_broadcast_started, 0U, 1U);
static K_SEM_DEFINE(sem_broadcast_stopped, 0U, 1U);

static const struct named_lc3_preset lc3_broadcast_presets[] = {
{"8_1_1", BT_BAP_LC3_BROADCAST_PRESET_8_1_1(LOCATION, CONTEXT)},
Expand Down Expand Up @@ -113,19 +115,19 @@ static const struct named_lc3_preset lc3_broadcast_presets[] = {
{"48_6_2", BT_BAP_LC3_BROADCAST_PRESET_48_6_2(LOCATION, CONTEXT)},
};

static void broadcast_started_cb(struct bt_bap_stream *stream)
static void broadcast_stream_started_cb(struct bt_bap_stream *stream)
{
printk("Stream %p started\n", stream);
k_sem_give(&sem_broadcast_started);
k_sem_give(&sem_broadcast_stream_started);
}

static void broadcast_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
static void broadcast_stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
{
printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
k_sem_give(&sem_broadcast_stopped);
k_sem_give(&sem_broadcast_stream_stopped);
}

static void broadcast_sent_cb(struct bt_bap_stream *bap_stream)
static void broadcast_stream_sent_cb(struct bt_bap_stream *bap_stream)
{
struct audio_test_stream *test_stream = audio_test_stream_from_bap_stream(bap_stream);
struct bt_cap_stream *cap_stream = cap_stream_from_audio_test_stream(test_stream);
Expand Down Expand Up @@ -172,13 +174,30 @@ static void broadcast_sent_cb(struct bt_bap_stream *bap_stream)
}

static struct bt_bap_stream_ops broadcast_stream_ops = {
.started = broadcast_started_cb,
.stopped = broadcast_stopped_cb,
.sent = broadcast_sent_cb,
.started = broadcast_stream_started_cb,
.stopped = broadcast_stream_stopped_cb,
.sent = broadcast_stream_sent_cb,
};

static void broadcast_source_started_cb(struct bt_cap_broadcast_source *broadcast_source)
{
printk("Broadcast source %p started\n", broadcast_source);
k_sem_give(&sem_broadcast_started);
}

static void broadcast_source_stopped_cb(struct bt_cap_broadcast_source *broadcast_source,
uint8_t reason)
{
printk("Broadcast source %p stopped with reason 0x%02X\n", broadcast_source, reason);
k_sem_give(&sem_broadcast_stopped);
}

static void init(void)
{
static struct bt_cap_initiator_cb broadcast_cbs = {
.broadcast_started = broadcast_source_started_cb,
.broadcast_stopped = broadcast_source_stopped_cb,
};
int err;

err = bt_enable(NULL);
Expand All @@ -194,6 +213,12 @@ static void init(void)
cap_stream_from_audio_test_stream(&broadcast_source_streams[i]);
bt_cap_stream_ops_register(broadcast_streams[i], &broadcast_stream_ops);
}

err = bt_cap_initiator_register_cb(&broadcast_cbs);
if (err != 0) {
FAIL("Failed to register broadcast callbacks: %d\n", err);
return;
}
}

static void setup_extended_adv(struct bt_le_ext_adv **adv)
Expand Down Expand Up @@ -577,8 +602,9 @@ static void test_broadcast_audio_stop(struct bt_cap_broadcast_source *broadcast_
/* Wait for all to be stopped */
printk("Waiting for broadcast_streams to be stopped\n");
for (size_t i = 0U; i < stream_count; i++) {
k_sem_take(&sem_broadcast_stopped, K_FOREVER);
k_sem_take(&sem_broadcast_stream_stopped, K_FOREVER);
}
k_sem_take(&sem_broadcast_stopped, K_FOREVER);

printk("Broadcast source stopped\n");

Expand Down Expand Up @@ -651,8 +677,9 @@ static void test_main_cap_initiator_broadcast(void)
/* Wait for all to be started */
printk("Waiting for broadcast_streams to be started\n");
for (size_t i = 0U; i < stream_count; i++) {
k_sem_take(&sem_broadcast_started, K_FOREVER);
k_sem_take(&sem_broadcast_stream_started, K_FOREVER);
}
k_sem_take(&sem_broadcast_started, K_FOREVER);

/* Initialize sending */
for (size_t i = 0U; i < stream_count; i++) {
Expand All @@ -661,7 +688,7 @@ static void test_main_cap_initiator_broadcast(void)
test_stream->tx_active = true;

for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) {
broadcast_sent_cb(bap_stream_from_audio_test_stream(test_stream));
broadcast_stream_sent_cb(bap_stream_from_audio_test_stream(test_stream));
}
}

Expand Down Expand Up @@ -757,8 +784,9 @@ static int test_cap_initiator_ac(const struct cap_initiator_ac_param *param)
/* Wait for all to be started */
printk("Waiting for broadcast_streams to be started\n");
for (size_t i = 0U; i < stream_count; i++) {
k_sem_take(&sem_broadcast_started, K_FOREVER);
k_sem_take(&sem_broadcast_stream_started, K_FOREVER);
}
k_sem_take(&sem_broadcast_started, K_FOREVER);

/* Initialize sending */
for (size_t i = 0U; i < stream_count; i++) {
Expand All @@ -767,7 +795,7 @@ static int test_cap_initiator_ac(const struct cap_initiator_ac_param *param)
test_stream->tx_active = true;

for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) {
broadcast_sent_cb(bap_stream_from_audio_test_stream(test_stream));
broadcast_stream_sent_cb(bap_stream_from_audio_test_stream(test_stream));
}
}

Expand Down

0 comments on commit 1f4d967

Please sign in to comment.