Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 66 additions & 2 deletions include/zephyr/bluetooth/audio/bap.h
Original file line number Diff line number Diff line change
Expand Up @@ -2001,6 +2001,53 @@ int bt_bap_base_subgroup_bis_codec_to_codec_cfg(const struct bt_bap_base_subgrou
* @{
*/

/**
* @brief Struct to hold the Broadcast Source callbacks
*
* These can be registered for usage with bt_bap_broadcast_source_register_cb().
*/
struct bt_bap_broadcast_source_cb {
/**
* @brief The Broadcast Source has started and all of the streams are ready for audio data
*
* @param source The started Broadcast Source
*/
void (*started)(struct bt_bap_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 Broadcast Source stopped (see the BT_HCI_ERR_* values)
*/
void (*stopped)(struct bt_bap_broadcast_source *source, uint8_t reason);

/** @internal Internally used field for list handling */
sys_snode_t _node;
};

/**
* @brief Registers callbacks for Broadcast Sources
*
* @param cb Pointer to the callback structure.
*
* @retval 0 on success
* @retval -EINVAL if @p cb is NULL
* @retval -EEXIST if @p cb is already registered
*/
int bt_bap_broadcast_source_register_cb(struct bt_bap_broadcast_source_cb *cb);

/**
* @brief Unregisters callbacks for Broadcast Sources
*
* @param cb Pointer to the callback structure.
*
* @retval 0 on success
* @retval -EINVAL if @p cb is NULL
* @retval -ENOENT if @p cb is not registered
*/
int bt_bap_broadcast_source_unregister_cb(struct bt_bap_broadcast_source_cb *cb);

/** Broadcast Source stream parameters */
struct bt_bap_broadcast_source_stream_param {
/** Audio stream */
Expand Down Expand Up @@ -2245,6 +2292,22 @@ struct bt_bap_broadcast_sink_cb {
*/
void (*syncable)(struct bt_bap_broadcast_sink *sink, const struct bt_iso_biginfo *biginfo);

/**
* @brief The Broadcast Sink has started and audio data may be received from all of the
* streams
*
* @param sink The started Broadcast Sink
*/
void (*started)(struct bt_bap_broadcast_sink *sink);

/**
* @brief The Broadcast Sink has stopped and none of the streams will receive audio data
*
* @param sink The stopped Broadcast Sink
* @param reason The reason why the Broadcast Sink stopped (see the BT_HCI_ERR_* values)
*/
void (*stopped)(struct bt_bap_broadcast_sink *sink, uint8_t reason);

/** @internal Internally used list node */
sys_snode_t _node;
};
Expand All @@ -2255,11 +2318,12 @@ struct bt_bap_broadcast_sink_cb {
* It is possible to register multiple struct of callbacks, but a single struct can only be
* registered once.
* Registering the same callback multiple times is undefined behavior and may break the stack.
*

* @param cb Broadcast sink callback structure.
*
* @retval 0 in case of success
* @retval 0 on success
* @retval -EINVAL if @p cb is NULL
* @retval -EALREADY if @p cb was already registered
*/
int bt_bap_broadcast_sink_register_cb(struct bt_bap_broadcast_sink_cb *cb);

Expand Down
16 changes: 16 additions & 0 deletions include/zephyr/bluetooth/audio/cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,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 Broadcast Source 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
37 changes: 37 additions & 0 deletions include/zephyr/bluetooth/iso.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <zephyr/sys/atomic.h>
#include <zephyr/sys/slist.h>
#include <zephyr/sys/util_macro.h>
#include <zephyr/sys/slist.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -1102,6 +1103,42 @@ int bt_iso_chan_get_info(const struct bt_iso_chan *chan, struct bt_iso_info *inf
*/
int bt_iso_chan_get_tx_sync(const struct bt_iso_chan *chan, struct bt_iso_tx_info *info);

/**
* @brief Struct to hold the Broadcast Isochronous Group callbacks
*
* These can be registered for usage with bt_iso_big_register_cb().
*/
struct bt_iso_big_cb {
/**
* @brief The BIG has started and all of the streams are ready for data
*
* @param big The started BIG
*/
void (*started)(struct bt_iso_big *big);

/**
* @brief The BIG has stopped and none of the streams are ready for data
*
* @param big The stopped BIG
* @param reason The reason why the BIG stopped (see the BT_HCI_ERR_* values)
*/
void (*stopped)(struct bt_iso_big *big, uint8_t reason);

/** @internal Internally used field for list handling */
sys_snode_t _node;
};

/**
* @brief Registers callbacks for Broadcast Sources
*
* @param cb Pointer to the callback structure.
*
* @retval 0 on success
* @retval -EINVAL if @p cb is NULL
* @retval -EEXIST if @p cb is already registered
*/
int bt_iso_big_register_cb(struct bt_iso_big_cb *cb);

/**
* @brief Creates a BIG as a broadcaster
*
Expand Down
34 changes: 19 additions & 15 deletions samples/bluetooth/bap_broadcast_sink/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,11 +536,6 @@ static void stream_started_cb(struct bt_bap_stream *stream)
#endif /* CONFIG_LIBLC3 */

k_sem_give(&sem_stream_started);
if (k_sem_count_get(&sem_stream_started) == stream_count) {
big_synced = true;
printk("BIG synced\n");
k_sem_give(&sem_big_synced);
}
}

static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
Expand All @@ -553,11 +548,6 @@ static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
if (err != 0) {
printk("Failed to take sem_stream_started: %d\n", err);
}

if (k_sem_count_get(&sem_stream_started) != stream_count) {
printk("BIG sync terminated\n");
big_synced = false;
}
}

static void stream_recv_cb(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info,
Expand Down Expand Up @@ -818,9 +808,27 @@ static void syncable_cb(struct bt_bap_broadcast_sink *sink, const struct bt_iso_
}
}

static void broadcast_sink_started_cb(struct bt_bap_broadcast_sink *sink)
{
printk("Broadcast sink %p started\n", sink);

big_synced = true;
k_sem_give(&sem_big_synced);
}

static void broadcast_sink_stopped_cb(struct bt_bap_broadcast_sink *sink, uint8_t reason)
{
printk("Broadcast sink %p stopped with reason 0x%02X\n", sink, reason);

big_synced = false;
k_sem_give(&sem_broadcast_sink_stopped);
}

static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = {
.base_recv = base_recv_cb,
.syncable = syncable_cb,
.started = broadcast_sink_started_cb,
.stopped = broadcast_sink_stopped_cb,
};

static void pa_timer_handler(struct k_work *work)
Expand Down Expand Up @@ -1027,8 +1035,6 @@ static int bis_sync_req_cb(struct bt_conn *conn,

return err;
}

k_sem_give(&sem_broadcast_sink_stopped);
}

broadcaster_broadcast_id = recv_state->broadcast_id;
Expand Down Expand Up @@ -1242,7 +1248,7 @@ static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync,
if (info->reason != BT_HCI_ERR_LOCALHOST_TERM_CONN && req_recv_state != NULL) {
int err;

if (k_sem_count_get(&sem_stream_connected) > 0) {
if (big_synced) {
err = bt_bap_broadcast_sink_stop(broadcast_sink);
if (err != 0) {
printk("Failed to stop Broadcast Sink: %d\n", err);
Expand All @@ -1257,8 +1263,6 @@ static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync,

return;
}

k_sem_give(&sem_broadcast_sink_stopped);
}
}
}
Expand Down
48 changes: 31 additions & 17 deletions samples/bluetooth/bap_broadcast_source/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ static int16_t send_pcm_data[MAX_NUM_SAMPLES];
static uint16_t seq_num;
static bool stopping;

static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(streams));
static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams));
static K_SEM_DEFINE(sem_started, 0U, 1U);
static K_SEM_DEFINE(sem_stopped, 0U, 1U);

#define BROADCAST_SOURCE_LIFETIME 120U /* seconds */

Expand Down Expand Up @@ -365,12 +365,6 @@ static void stream_started_cb(struct bt_bap_stream *stream)

source_stream->seq_num = 0U;
source_stream->sent_cnt = 0U;
k_sem_give(&sem_started);
}

static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
{
k_sem_give(&sem_stopped);
}

static void stream_sent_cb(struct bt_bap_stream *stream)
Expand All @@ -387,7 +381,9 @@ static void stream_sent_cb(struct bt_bap_stream *stream)
}

static struct bt_bap_stream_ops stream_ops = {
.started = stream_started_cb, .stopped = stream_stopped_cb, .sent = stream_sent_cb};
.started = stream_started_cb,
.sent = stream_sent_cb,
};

static int setup_broadcast_source(struct bt_bap_broadcast_source **source)
{
Expand Down Expand Up @@ -439,8 +435,24 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source)
return 0;
}

static void source_started_cb(struct bt_bap_broadcast_source *source)
{
printk("Broadcast source %p started\n", source);
k_sem_give(&sem_started);
}

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

int main(void)
{
static struct bt_bap_broadcast_source_cb broadcast_source_cb = {
.started = source_started_cb,
.stopped = source_stopped_cb,
};
struct bt_le_ext_adv *adv;
int err;

Expand All @@ -451,6 +463,12 @@ int main(void)
}
printk("Bluetooth initialized\n");

err = bt_bap_broadcast_source_register_cb(&broadcast_source_cb);
if (err != 0) {
printk("Failed to register broadcast source callbacks (err %d)\n", err);
return 0;
}

for (size_t i = 0U; i < ARRAY_SIZE(send_pcm_data); i++) {
/* Initialize mock data */
send_pcm_data[i] = i;
Expand Down Expand Up @@ -581,10 +599,8 @@ int main(void)
return 0;
}

/* Wait for all to be started */
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
k_sem_take(&sem_started, K_FOREVER);
}
/* Wait for broadcast source to be started */
k_sem_take(&sem_started, K_FOREVER);
printk("Broadcast source started\n");

/* Initialize sending */
Expand All @@ -608,10 +624,8 @@ int main(void)
return 0;
}

/* Wait for all to be stopped */
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
k_sem_take(&sem_stopped, K_FOREVER);
}
/* Wait for broadcast source to be stopped */
k_sem_take(&sem_stopped, K_FOREVER);
printk("Broadcast source stopped\n");

printk("Deleting broadcast source\n");
Expand Down
Loading
Loading