Skip to content

Commit

Permalink
Bluetooth: BAP: Refactor bt_bap_base
Browse files Browse the repository at this point in the history
Signed-off-by: Emil Gydesen <[email protected]>
  • Loading branch information
Thalley committed Oct 25, 2023
1 parent 01aa800 commit a5efa6a
Show file tree
Hide file tree
Showing 16 changed files with 1,348 additions and 581 deletions.
252 changes: 212 additions & 40 deletions include/zephyr/bluetooth/audio/bap.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ extern "C" {
*/
#define BT_BAP_BASE_MIN_SIZE 16

/** The minimum size of a bt_bap_base_bis_data */
#define BT_BAP_BASE_BIS_DATA_MIN_SIZE 2 /* index and length */

/** Periodic advertising state reported by the Scan Delegator */
enum bt_bap_pa_state {
/** The periodic advertising has not been synchronized */
Expand Down Expand Up @@ -276,7 +273,6 @@ struct bt_bap_unicast_group;
/** @brief Abstract Audio Endpoint structure. */
struct bt_bap_ep;

/* TODO: Replace with struct bt_bap_base_subgroup */
/** Struct to hold subgroup specific information for the receive state */
struct bt_bap_scan_delegator_subgroup {
/** BIS synced bitfield */
Expand Down Expand Up @@ -1351,55 +1347,229 @@ int bt_bap_unicast_client_discover(struct bt_conn *conn, enum bt_audio_dir dir);
* @{
*/

struct bt_bap_base_bis_data {
// struct bt_bap_base_bis_data {

Check failure on line 1350 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1350 do not use C99 // comments
// /* Unique index of the BIS */

Check warning on line 1351 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1351 please, no space before tabs

Check failure on line 1351 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1351 do not use C99 // comments
// uint8_t index;

Check warning on line 1352 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1352 please, no space before tabs

Check failure on line 1352 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1352 do not use C99 // comments
// #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0

Check failure on line 1353 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1353 do not use C99 // comments
// /** Codec Specific Data length. */

Check warning on line 1354 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1354 please, no space before tabs

Check failure on line 1354 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1354 do not use C99 // comments
// size_t data_len;

Check warning on line 1355 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1355 please, no space before tabs

Check failure on line 1355 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1355 do not use C99 // comments
// /** Codec Specific Data */

Check warning on line 1356 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1356 please, no space before tabs

Check failure on line 1356 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1356 do not use C99 // comments
// uint8_t data[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE];

Check warning on line 1357 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1357 please, no space before tabs

Check failure on line 1357 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1357 do not use C99 // comments
// #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */

Check failure on line 1358 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1358 do not use C99 // comments
// };

Check failure on line 1359 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/bluetooth/audio/bap.h:1359 do not use C99 // comments

struct bt_bap_base_subgroup;
// {
// /* Number of BIS in the subgroup */

Check warning on line 1363 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1363 please, no space before tabs
// size_t bis_count;

Check warning on line 1364 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1364 please, no space before tabs
// /** Codec information for the subgroup

Check warning on line 1365 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1365 please, no space before tabs
// *

Check warning on line 1366 in include/zephyr/bluetooth/audio/bap.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

include/zephyr/bluetooth/audio/bap.h:1366 please, no space before tabs
// * If the data_len of the codec is 0, then codec specific data may be
// * found for each BIS in the bis_data.
// */
// struct bt_audio_codec_cfg codec_cfg;
// /* Array of BIS specific data for each BIS in the subgroup */
// struct bt_bap_base_bis_data bis_data[BROADCAST_SNK_STREAM_CNT];
// };

struct bt_bap_base;
// {
// /** @brief QoS Presentation Delay in microseconds
// *
// * Value range 0 to @ref BT_AUDIO_PD_MAX.
// */
// uint32_t pd;

// /* Number of subgroups in the BASE */
// size_t subgroup_count;

// /* Array of subgroups in the BASE */
// struct bt_bap_base_subgroup subgroups[BROADCAST_SNK_SUBGROUP_CNT];
// };

/** @brief Decode a Broadcast Audio Source Endpoint (BASE) from advertising data
*
* The BASE is sent via periodic advertising, and can be decoded into a
* bt_bap_base using this function.
*
* @param data The periodic advertising data
* @param base The output struct to put the decode BASE in
*
* @return 0 in case of success or negative errno value in case of error.
*/
// int bt_bap_decode_base(struct bt_data *data, struct bt_bap_base *base);

struct bt_bap_base_codec_id {
/** Codec ID */
uint8_t id;
/** Codec Company ID */
uint16_t cid;
/** Codec Company Vendor ID */
uint16_t vid;
};

struct bt_bap_base_subgroup_bis {
/* Unique index of the BIS */
uint8_t index;
#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
/** Codec Specific Data length. */
size_t data_len;
uint8_t data_len;
/** Codec Specific Data */
uint8_t data[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE];
#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
uint8_t *data;
};

struct bt_bap_base_subgroup {
/* Number of BIS in the subgroup */
size_t bis_count;
/** Codec information for the subgroup
*
* If the data_len of the codec is 0, then codec specific data may be
* found for each BIS in the bis_data.
*/
struct bt_audio_codec_cfg codec_cfg;
/* Array of BIS specific data for each BIS in the subgroup */
struct bt_bap_base_bis_data bis_data[BROADCAST_SNK_STREAM_CNT];
};
/**
* @brief Generate a pointer to a BASE from periodic advertising data
*
* @param ad The periodic advertising data
*
* @retval NULL if the data does not contain a BASE
* @retval Pointer to a bt_bap_base structure
*/
const struct bt_bap_base *bt_bap_base_get_base_from_ad(const struct bt_data *ad);

struct bt_bap_base {
/** @brief QoS Presentation Delay in microseconds
*
* Value range 0 to @ref BT_AUDIO_PD_MAX.
*/
uint32_t pd;
/**
* @brief Get the presentation delay value of a BASE
*
* @param base The BASE pointer
*
* @retval -EINVAL if arguments are invalid
* @retval The 24-bit presentation delay value
*/
int bt_bap_base_get_pres_delay(const struct bt_bap_base *base);

/* Number of subgroups in the BASE */
size_t subgroup_count;
/**
* @brief Get the subgroup count of a BASE
*
* @param base The BASE pointer
*
* @retval -EINVAL if arguments are invalid
* @retval The 8-bit subgroup count value
*/
int bt_bap_base_get_subgroup_count(const struct bt_bap_base *base);

/* Array of subgroups in the BASE */
struct bt_bap_base_subgroup subgroups[BROADCAST_SNK_SUBGROUP_CNT];
};
/**
* @brief Get all BIS indexes of a BASE
*
* @param[in] base The BASE pointer
* @param[out] bis_indexes 32-bit BIS index bitfield that will be populated
*
* @retval -EINVAL if arguments are invalid
* @retval -EBADMSG if the supplied @p base has invalid values
* @retval 0 on success
*/
int bt_bap_base_get_bis_indexes(const struct bt_bap_base *base, uint32_t *bis_indexes);

/** @brief Decode a Broadcast Audio Source Endpoint (BASE) from advertising data
/**
* @brief Iterate on all subgroups in the BASE
*
* The BASE is sent via periodic advertising, and can be decoded into a
* bt_bap_base using this function.
* @param base The BASE pointer
* @param func Callback function. Return true to continue iterating, or false to stop.
* @param user_data Userdata supplied to @p func
*
* @param data The periodic advertising data
* @param base The output struct to put the decode BASE in
* @retval -EINVAL if arguments are invalid
* @retval -EBADMSG if the supplied @p base has invalid values
* @retval -ECANCELED if iterating over the subgroups stopped prematurely by @p func
* @retval 0 if all subgroups were iterated
*/
int bt_bap_base_foreach_subgroup(const struct bt_bap_base *base,
bool (*func)(const struct bt_bap_base_subgroup *subgroup,
void *user_data),
void *user_data);

/**
* @brief Get the codec ID of a subgroup
*
* @return 0 in case of success or negative errno value in case of error.
* @param[in] subgroup The subgroup pointer
* @param[out] codec_id Pointer to the struct where the results are placed
*
* @retval -EINVAL if arguments are invalid
* @retval 0 on success
*/
int bt_bap_base_get_subgroup_codec_id(const struct bt_bap_base_subgroup *subgroup,
struct bt_bap_base_codec_id *codec_id);

/**
* @brief Get the codec configuration data of a subgroup
*
* @param[in] subgroup The subgroup pointer
* @param[out] data Pointer that will point to the resulting codec configuration data
*
* @retval -EINVAL if arguments are invalid
* @retval -EBADMSG if the supplied @p subgroup has invalid values
* @retval 0 on success
*/
int bt_bap_base_get_subgroup_codec_data(const struct bt_bap_base_subgroup *subgroup,
uint8_t **data);

/**
* @brief Get the codec metadata of a subgroup
*
* @param[in] subgroup The subgroup pointer
* @param[out] data Pointer that will point to the resulting codec metadata
*
* @retval -EINVAL if arguments are invalid
* @retval -EBADMSG if the supplied @p subgroup has invalid values
* @retval 0 on success
*/
int bt_bap_base_get_subgroup_codec_meta(const struct bt_bap_base_subgroup *subgroup,
uint8_t **meta);

/**
* @brief Store subgroup codec data in a @ref bt_audio_codec_cfg
*
* @param[in] subgroup The subgroup pointer
* @param[out] codec_cfg Pointer to the struct where the results are placed
*
* @retval -EINVAL if arguments are invalid
* @retval -EBADMSG if the supplied @p subgroup has invalid values
* @retval -ENOMEM if the @p codec_cfg cannot store the @p subgroup codec data
* @retval 0 on success
*/
int bt_bap_base_subgroup_codec_to_codec_cfg(const struct bt_bap_base_subgroup *subgroup,
struct bt_audio_codec_cfg *codec_cfg);

/**
* @brief Get the BIS count of a subgroup
*
* @param subgroup The subgroup pointer
*
* @retval -EINVAL if arguments are invalid
* @retval The 8-bit BIS count value
*/
int bt_bap_base_get_subgroup_bis_count(const struct bt_bap_base_subgroup *subgroup);

/**
* @brief Iterate on all BIS in the subgroup
*
* @param subgroup The subgroup pointer
* @param func Callback function. Return true to continue iterating, or false to stop.
* @param user_data Userdata supplied to @p func
*
* @retval -EINVAL if arguments are invalid
* @retval -EBADMSG if the supplied @p base has invalid values
* @retval -ECANCELED if iterating over the subgroups stopped prematurely by @p func
* @retval 0 if all BIS were iterated
*/
int bt_bap_base_foreach_bis(const struct bt_bap_base_subgroup *subgroup,
bool (*func)(const struct bt_bap_base_subgroup_bis *bis,
void *user_data),
void *user_data);

/**
* @brief Store BIS codec configuration data in a @ref bt_audio_codec_cfg
*
* This only sets the @ref bt_audio_codec_cfg.data and @ref bt_audio_codec_cfg.data_len, but is
* useful to use the BIS codec configuration data with the bt_audio_codec_cfg_* functions.
*
* @param[in] bis The BIS pointer
* @param[out] codec_cfg Pointer to the struct where the results are placed
*
* @retval -EINVAL if arguments are invalid
* @retval -ENOMEM if the @p codec_cfg cannot store the @p subgroup codec data
* @retval 0 on success
*/
int bt_bap_decode_base(struct bt_data *data, struct bt_bap_base *base);
int bt_bap_base_subgroup_bis_codec_to_codec_cfg(const struct bt_bap_base_subgroup_bis *bis,
struct bt_audio_codec_cfg *codec_cfg);

/** @} */ /* End of group bt_bap_broadcast */

Expand Down Expand Up @@ -1649,8 +1819,10 @@ struct bt_bap_broadcast_sink_cb {
*
* @param sink Pointer to the sink structure.
* @param base Broadcast Audio Source Endpoint (BASE).
* @param base_size Size of the @p base
*/
void (*base_recv)(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base);
void (*base_recv)(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base,
size_t base_size);

/** @brief Broadcast sink is syncable
*
Expand Down
44 changes: 30 additions & 14 deletions samples/bluetooth/broadcast_audio_sink/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,28 +136,44 @@ static struct bt_bap_stream_ops stream_ops = {
.recv = stream_recv_cb
};

static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base)
static bool base_subgroup_bis_cb(const struct bt_bap_base_subgroup_bis *bis, void *user_data)
{
uint32_t *base_bis_index_bitfield = user_data;

printk("\tIndex 0x%02x\n", bis->index);

*base_bis_index_bitfield |= BIT(bis->index);

return true;
}

static bool base_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, void *user_data)
{
printk("Subgroup %p has %zu streams\n", subgroup,
bt_bap_base_get_subgroup_bis_count(subgroup));

bt_bap_base_foreach_bis(subgroup, base_subgroup_bis_cb, user_data);

return true;
}

static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base,
size_t base_size)
{
uint32_t base_bis_index_bitfield = 0U;
int err;

if (k_sem_count_get(&sem_base_received) != 0U) {
return;
}

printk("Received BASE with %u subgroups from broadcast sink %p\n",
base->subgroup_count, sink);

for (size_t i = 0U; i < base->subgroup_count; i++) {
const size_t bis_count = base->subgroups[i].bis_count;

printk("Subgroup[%zu] has %zu streams\n", i, bis_count);
for (size_t j = 0U; j < bis_count; j++) {
const uint8_t index = base->subgroups[i].bis_data[j].index;
printk("Received BASE with %d subgroups from broadcast sink %p\n",
bt_bap_base_get_subgroup_count(base), sink);

printk("\tIndex 0x%02x\n", index);

base_bis_index_bitfield |= BIT(index);
}
err = bt_bap_base_get_bis_indexes(base, &base_bis_index_bitfield);
if (err != 0) {
printk("Failed to BIS indexes: %d\n", err);
return;
}

bis_index_bitfield = base_bis_index_bitfield & bis_index_mask;
Expand Down
Loading

0 comments on commit a5efa6a

Please sign in to comment.