Bluetooth: ISO: Add BIG callbacks

Add callbacks that is called for the entire BIG.
The BIG state is from an HCI perspective a single state change
that we previously only propagated as a state change for each
channel.

However it may be simpler for applications and higher layers
to use BIG changes to trigger their behavior.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2024-07-05 10:20:17 +02:00 committed by Benjamin Cabé
commit e8bcb29f3f
2 changed files with 88 additions and 0 deletions

View file

@ -34,6 +34,7 @@
#include <zephyr/sys/atomic.h> #include <zephyr/sys/atomic.h>
#include <zephyr/sys/slist.h> #include <zephyr/sys/slist.h>
#include <zephyr/sys/util_macro.h> #include <zephyr/sys/util_macro.h>
#include <zephyr/sys/slist.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -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); 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 * @brief Creates a BIG as a broadcaster
* *

View file

@ -2525,6 +2525,8 @@ int bt_iso_chan_connect(const struct bt_iso_connect_param *param, size_t count)
#endif /* CONFIG_BT_ISO_UNICAST */ #endif /* CONFIG_BT_ISO_UNICAST */
#if defined(CONFIG_BT_ISO_BROADCAST) #if defined(CONFIG_BT_ISO_BROADCAST)
static sys_slist_t iso_big_cbs = SYS_SLIST_STATIC_INIT(&iso_big_cbs);
static struct bt_iso_big *lookup_big_by_handle(uint8_t big_handle) static struct bt_iso_big *lookup_big_by_handle(uint8_t big_handle)
{ {
return &bigs[big_handle]; return &bigs[big_handle];
@ -2587,6 +2589,16 @@ static void big_disconnect(struct bt_iso_big *big, uint8_t reason)
bt_iso_chan_disconnected(bis, reason); bt_iso_chan_disconnected(bis, reason);
} }
if (!sys_slist_is_empty(&iso_big_cbs)) {
struct bt_iso_big_cb *listener;
SYS_SLIST_FOR_EACH_CONTAINER(&iso_big_cbs, listener, _node) {
if (listener->stopped != NULL) {
listener->stopped(big, reason);
}
}
}
} }
static int big_init_bis(struct bt_iso_big *big, struct bt_iso_chan **bis_channels, uint8_t num_bis, static int big_init_bis(struct bt_iso_big *big, struct bt_iso_chan **bis_channels, uint8_t num_bis,
@ -2617,6 +2629,25 @@ static int big_init_bis(struct bt_iso_big *big, struct bt_iso_chan **bis_channel
return 0; return 0;
} }
int bt_iso_big_register_cb(struct bt_iso_big_cb *cb)
{
CHECKIF(cb == NULL) {
LOG_DBG("cb is NULL");
return -EINVAL;
}
if (sys_slist_find(&iso_big_cbs, &cb->_node, NULL)) {
LOG_DBG("cb %p is already registered", cb);
return -EEXIST;
}
sys_slist_append(&iso_big_cbs, &cb->_node);
return 0;
}
#if defined(CONFIG_BT_ISO_BROADCASTER) #if defined(CONFIG_BT_ISO_BROADCASTER)
static int hci_le_create_big(struct bt_le_ext_adv *padv, struct bt_iso_big *big, static int hci_le_create_big(struct bt_le_ext_adv *padv, struct bt_iso_big *big,
struct bt_iso_big_create_param *param) struct bt_iso_big_create_param *param)
@ -3006,6 +3037,16 @@ void hci_le_big_complete(struct net_buf *buf)
store_bis_broadcaster_info(evt, &iso_conn->iso.info); store_bis_broadcaster_info(evt, &iso_conn->iso.info);
bt_conn_set_state(iso_conn, BT_CONN_CONNECTED); bt_conn_set_state(iso_conn, BT_CONN_CONNECTED);
} }
if (!sys_slist_is_empty(&iso_big_cbs)) {
struct bt_iso_big_cb *listener;
SYS_SLIST_FOR_EACH_CONTAINER(&iso_big_cbs, listener, _node) {
if (listener->started != NULL) {
listener->started(big);
}
}
}
} }
void hci_le_big_terminate(struct net_buf *buf) void hci_le_big_terminate(struct net_buf *buf)
@ -3186,6 +3227,16 @@ void hci_le_big_sync_established(struct net_buf *buf)
store_bis_sync_receiver_info(evt, &iso_conn->iso.info); store_bis_sync_receiver_info(evt, &iso_conn->iso.info);
bt_conn_set_state(iso_conn, BT_CONN_CONNECTED); bt_conn_set_state(iso_conn, BT_CONN_CONNECTED);
} }
if (!sys_slist_is_empty(&iso_big_cbs)) {
struct bt_iso_big_cb *listener;
SYS_SLIST_FOR_EACH_CONTAINER(&iso_big_cbs, listener, _node) {
if (listener->started != NULL) {
listener->started(big);
}
}
}
} }
void hci_le_big_sync_lost(struct net_buf *buf) void hci_le_big_sync_lost(struct net_buf *buf)