Skip to content

Commit 2ab5882

Browse files
Thalleykartben
authored andcommitted
Bluetooth: CAP: Add cap_unicast_group API
Adds a new abstract struct for unicast group that is specific for CAP. The difference between this and the BAP unicast group, is that the parameters are CAP streams and thus ensuring that the streams in the group adhere to the additional requirements that CAP has on top of BAP. This also adds foreach functions for both CAP and BAP to allow users to iterate on the streams in the abstract groups. Various samples, modules and tests have been updated to use the CAP struct and API. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
1 parent 7a663fb commit 2ab5882

File tree

14 files changed

+1105
-102
lines changed

14 files changed

+1105
-102
lines changed

doc/releases/release-notes-4.2.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@ New APIs and options
158158
* :c:macro:`BT_BAP_PER_ADV_PARAM_BROADCAST_SLOW`
159159
* :c:func:`bt_csip_set_member_set_size_and_rank`
160160
* :c:func:`bt_csip_set_member_get_info`
161+
* :c:func:`bt_bap_unicast_group_foreach_stream`
162+
* :c:func:`bt_cap_unicast_group_create`
163+
* :c:func:`bt_cap_unicast_group_reconfig`
164+
* :c:func:`bt_cap_unicast_group_add_streams`
165+
* :c:func:`bt_cap_unicast_group_delete`
166+
* :c:func:`bt_cap_unicast_group_foreach_stream`
161167

162168
* Host
163169

include/zephyr/bluetooth/audio/bap.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* @brief Header for Bluetooth BAP.
44
*
55
* Copyright (c) 2020 Bose Corporation
6-
* Copyright (c) 2021-2024 Nordic Semiconductor ASA
6+
* Copyright (c) 2021-2025 Nordic Semiconductor ASA
77
*
88
* SPDX-License-Identifier: Apache-2.0
99
*/
@@ -1720,6 +1720,32 @@ int bt_bap_unicast_group_add_streams(struct bt_bap_unicast_group *unicast_group,
17201720
*/
17211721
int bt_bap_unicast_group_delete(struct bt_bap_unicast_group *unicast_group);
17221722

1723+
/** Callback function for bt_bap_unicast_group_foreach_stream()
1724+
*
1725+
* @param stream The audio stream
1726+
* @param user_data User data
1727+
*
1728+
* @retval true Stop iterating.
1729+
* @retval false Continue iterating.
1730+
*/
1731+
typedef bool (*bt_bap_unicast_group_foreach_stream_func_t)(struct bt_bap_stream *stream,
1732+
void *user_data);
1733+
1734+
/**
1735+
* @brief Iterate through all streams in a unicast group
1736+
*
1737+
* @param unicast_group The unicast group
1738+
* @param func The callback function
1739+
* @param user_data User specified data that sent to the callback function
1740+
*
1741+
* @retval 0 Success (even if no streams exists in the group).
1742+
* @retval -ECANCELED Iteration was stopped by the callback function before complete.
1743+
* @retval -EINVAL @p unicast_group or @p func were NULL.
1744+
*/
1745+
int bt_bap_unicast_group_foreach_stream(struct bt_bap_unicast_group *unicast_group,
1746+
bt_bap_unicast_group_foreach_stream_func_t func,
1747+
void *user_data);
1748+
17231749
/** Unicast Client callback structure */
17241750
struct bt_bap_unicast_client_cb {
17251751
/**

include/zephyr/bluetooth/audio/cap.h

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
/*
7-
* Copyright (c) 2022-2024 Nordic Semiconductor ASA
7+
* Copyright (c) 2022-2025 Nordic Semiconductor ASA
88
*
99
* SPDX-License-Identifier: Apache-2.0
1010
*/
@@ -50,6 +50,9 @@ extern "C" {
5050
/** @brief Abstract Audio Broadcast Source structure. */
5151
struct bt_cap_broadcast_source;
5252

53+
/** @brief Abstract CAP Unicast Group structure. */
54+
struct bt_cap_unicast_group;
55+
5356
/**
5457
* @brief Register the Common Audio Service.
5558
*
@@ -254,6 +257,173 @@ int bt_cap_stream_send_ts(struct bt_cap_stream *stream, struct net_buf *buf, uin
254257
*/
255258
int bt_cap_stream_get_tx_sync(struct bt_cap_stream *stream, struct bt_iso_tx_info *info);
256259

260+
/** Parameter struct for each stream in the unicast group */
261+
struct bt_cap_unicast_group_stream_param {
262+
/** Pointer to a stream object. */
263+
struct bt_cap_stream *stream;
264+
265+
/** The QoS settings for the stream object. */
266+
struct bt_bap_qos_cfg *qos_cfg;
267+
};
268+
269+
/**
270+
* @brief Parameter struct for the unicast group functions
271+
*
272+
* Parameter struct for the bt_cap_unicast_group_create() and
273+
* bt_cap_unicast_group_add_streams() functions.
274+
*/
275+
struct bt_cap_unicast_group_stream_pair_param {
276+
/** Pointer to a receiving stream parameters. */
277+
struct bt_cap_unicast_group_stream_param *rx_param;
278+
279+
/** Pointer to a transmitting stream parameters. */
280+
struct bt_cap_unicast_group_stream_param *tx_param;
281+
};
282+
283+
/** Parameters for the creating unicast groups with bt_cap_unicast_group_create() */
284+
struct bt_cap_unicast_group_param {
285+
/** The number of parameters in @p params */
286+
size_t params_count;
287+
288+
/** Array of stream parameters */
289+
struct bt_cap_unicast_group_stream_pair_param *params;
290+
291+
/**
292+
* @brief Unicast Group packing mode.
293+
*
294+
* @ref BT_ISO_PACKING_SEQUENTIAL or @ref BT_ISO_PACKING_INTERLEAVED.
295+
*
296+
* @note This is a recommendation to the controller, which the controller may ignore.
297+
*/
298+
uint8_t packing;
299+
300+
#if defined(CONFIG_BT_ISO_TEST_PARAMS) || defined(__DOXYGEN__)
301+
/**
302+
* @brief Central to Peripheral flush timeout
303+
*
304+
* The flush timeout in multiples of ISO_Interval for each payload sent
305+
* from the Central to Peripheral.
306+
*
307+
* Value range from @ref BT_ISO_FT_MIN to @ref BT_ISO_FT_MAX
308+
*/
309+
uint8_t c_to_p_ft;
310+
311+
/**
312+
* @brief Peripheral to Central flush timeout
313+
*
314+
* The flush timeout in multiples of ISO_Interval for each payload sent
315+
* from the Peripheral to Central.
316+
*
317+
* Value range from @ref BT_ISO_FT_MIN to @ref BT_ISO_FT_MAX.
318+
*/
319+
uint8_t p_to_c_ft;
320+
321+
/**
322+
* @brief ISO interval
323+
*
324+
* Time between consecutive CIS anchor points.
325+
*
326+
* Value range from @ref BT_ISO_ISO_INTERVAL_MIN to @ref BT_ISO_ISO_INTERVAL_MAX.
327+
*/
328+
uint16_t iso_interval;
329+
#endif /* CONFIG_BT_ISO_TEST_PARAMS */
330+
};
331+
332+
/**
333+
* @brief Create unicast group.
334+
*
335+
* Create a new audio unicast group with one or more audio streams as a unicast client.
336+
* All streams shall share the same framing.
337+
* All streams in the same direction shall share the same interval and latency (see
338+
* @ref bt_bap_qos_cfg).
339+
*
340+
* @param[in] param The unicast group create parameters.
341+
* @param[out] unicast_group Pointer to the unicast group created.
342+
*
343+
* @return Zero on success or (negative) error code otherwise.
344+
*/
345+
int bt_cap_unicast_group_create(const struct bt_cap_unicast_group_param *param,
346+
struct bt_cap_unicast_group **unicast_group);
347+
348+
/**
349+
* @brief Reconfigure unicast group.
350+
*
351+
* Reconfigure a unicast group with one or more audio streams as a unicast client.
352+
* All streams shall share the same framing.
353+
* All streams in the same direction shall share the same interval and latency (see
354+
* @ref bt_bap_qos_cfg).
355+
* All streams in @p param shall already belong to @p unicast_group.
356+
* Use bt_cap_unicast_group_add_streams() to add additional streams.
357+
*
358+
* @param unicast_group Pointer to the unicast group created.
359+
* @param param The unicast group reconfigure parameters.
360+
*
361+
* @return Zero on success or (negative) error code otherwise.
362+
*/
363+
int bt_cap_unicast_group_reconfig(struct bt_cap_unicast_group *unicast_group,
364+
const struct bt_cap_unicast_group_param *param);
365+
366+
/**
367+
* @brief Add streams to a unicast group as a unicast client
368+
*
369+
* This function can be used to add additional streams to a bt_cap_unicast_group.
370+
*
371+
* This can be called at any time before any of the streams in the group has been started
372+
* (see bt_bap_stream_ops.started()).
373+
* This can also be called after the streams have been stopped (see bt_bap_stream_ops.stopped()).
374+
*
375+
* Once a stream has been added to a unicast group, it cannot be removed. To remove a stream from a
376+
* group, the group must be deleted with bt_cap_unicast_group_delete(), but this will require all
377+
* streams in the group to be released first.
378+
*
379+
* @param unicast_group Pointer to the unicast group
380+
* @param params Array of stream parameters with streams being added to the group.
381+
* @param num_param Number of parameters in @p params.
382+
*
383+
* @return 0 in case of success or negative value in case of error.
384+
*/
385+
int bt_cap_unicast_group_add_streams(struct bt_cap_unicast_group *unicast_group,
386+
const struct bt_cap_unicast_group_stream_pair_param params[],
387+
size_t num_param);
388+
389+
/**
390+
* @brief Delete audio unicast group.
391+
*
392+
* Delete a audio unicast group as a client. All streams in the group shall
393+
* be in the idle or configured state.
394+
*
395+
* @param unicast_group Pointer to the unicast group to delete
396+
*
397+
* @return Zero on success or (negative) error code otherwise.
398+
*/
399+
int bt_cap_unicast_group_delete(struct bt_cap_unicast_group *unicast_group);
400+
401+
/** Callback function for bt_bap_unicast_group_foreach_stream()
402+
*
403+
* @param stream The audio stream
404+
* @param user_data User data
405+
*
406+
* @retval true Stop iterating.
407+
* @retval false Continue iterating.
408+
*/
409+
typedef bool (*bt_cap_unicast_group_foreach_stream_func_t)(struct bt_cap_stream *stream,
410+
void *user_data);
411+
412+
/**
413+
* @brief Iterate through all streams in a unicast group
414+
*
415+
* @param unicast_group The unicast group
416+
* @param func The callback function
417+
* @param user_data User specified data that sent to the callback function
418+
*
419+
* @retval 0 Success (even if no streams exists in the group).
420+
* @retval -ECANCELED Iteration was stopped by the callback function before complete.
421+
* @retval -EINVAL @p unicast_group or @p func were NULL.
422+
*/
423+
int bt_cap_unicast_group_foreach_stream(struct bt_cap_unicast_group *unicast_group,
424+
bt_cap_unicast_group_foreach_stream_func_t func,
425+
void *user_data);
426+
257427
/** Stream specific parameters for the bt_cap_initiator_unicast_audio_start() function */
258428
struct bt_cap_unicast_audio_start_stream_param {
259429
/** Coordinated or ad-hoc set member. */

samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ LOG_MODULE_REGISTER(cap_initiator_unicast, LOG_LEVEL_INF);
4444
*/
4545
static struct bt_bap_lc3_preset unicast_preset_16_2_1 = BT_BAP_LC3_UNICAST_PRESET_16_2_1(
4646
BT_AUDIO_LOCATION_MONO_AUDIO, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
47-
static struct bt_bap_unicast_group *unicast_group;
47+
static struct bt_cap_unicast_group *unicast_group;
4848
uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */
4949
uint64_t total_unicast_tx_iso_packet_count; /* This value is exposed to test code */
5050

@@ -336,16 +336,16 @@ static int discover_sources(void)
336336

337337
static int unicast_group_create(void)
338338
{
339-
struct bt_bap_unicast_group_stream_param source_stream_param = {
340-
.qos = &unicast_preset_16_2_1.qos,
341-
.stream = &peer.source_stream.bap_stream,
339+
struct bt_cap_unicast_group_stream_param source_stream_param = {
340+
.qos_cfg = &unicast_preset_16_2_1.qos,
341+
.stream = &peer.source_stream,
342342
};
343-
struct bt_bap_unicast_group_stream_param sink_stream_param = {
344-
.qos = &unicast_preset_16_2_1.qos,
345-
.stream = &peer.sink_stream.bap_stream,
343+
struct bt_cap_unicast_group_stream_param sink_stream_param = {
344+
.qos_cfg = &unicast_preset_16_2_1.qos,
345+
.stream = &peer.sink_stream,
346346
};
347-
struct bt_bap_unicast_group_stream_pair_param pair_params = {0};
348-
struct bt_bap_unicast_group_param group_param = {0};
347+
struct bt_cap_unicast_group_stream_pair_param pair_params = {0};
348+
struct bt_cap_unicast_group_param group_param = {0};
349349
int err;
350350

351351
if (peer.source_ep != NULL) {
@@ -359,7 +359,7 @@ static int unicast_group_create(void)
359359
group_param.params_count = 1U;
360360
group_param.params = &pair_params;
361361

362-
err = bt_bap_unicast_group_create(&group_param, &unicast_group);
362+
err = bt_cap_unicast_group_create(&group_param, &unicast_group);
363363
if (err != 0) {
364364
LOG_ERR("Failed to create group: %d", err);
365365
return err;
@@ -374,7 +374,7 @@ static int unicast_group_delete(void)
374374
{
375375
int err;
376376

377-
err = bt_bap_unicast_group_delete(unicast_group);
377+
err = bt_cap_unicast_group_delete(unicast_group);
378378
if (err != 0) {
379379
LOG_ERR("Failed to delete group: %d", err);
380380
return err;

samples/bluetooth/tmap_central/src/cap_initiator.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -313,23 +313,23 @@ static struct bt_bap_unicast_client_cb unicast_client_cbs = {
313313
.endpoint = endpoint_cb,
314314
};
315315

316-
static int unicast_group_create(struct bt_bap_unicast_group **out_unicast_group)
316+
static int unicast_group_create(struct bt_cap_unicast_group **out_unicast_group)
317317
{
318318
int err = 0;
319-
struct bt_bap_unicast_group_stream_param group_stream_params;
320-
struct bt_bap_unicast_group_stream_pair_param pair_params;
321-
struct bt_bap_unicast_group_param group_param;
319+
struct bt_cap_unicast_group_stream_param group_stream_params;
320+
struct bt_cap_unicast_group_stream_pair_param pair_params;
321+
struct bt_cap_unicast_group_param group_param;
322322

323-
group_stream_params.qos = &unicast_preset_48_2_1.qos;
324-
group_stream_params.stream = &unicast_streams[0].bap_stream;
323+
group_stream_params.qos_cfg = &unicast_preset_48_2_1.qos;
324+
group_stream_params.stream = &unicast_streams[0];
325325
pair_params.tx_param = &group_stream_params;
326326
pair_params.rx_param = NULL;
327327

328328
group_param.packing = BT_ISO_PACKING_SEQUENTIAL;
329329
group_param.params_count = 1;
330330
group_param.params = &pair_params;
331331

332-
err = bt_bap_unicast_group_create(&group_param, out_unicast_group);
332+
err = bt_cap_unicast_group_create(&group_param, out_unicast_group);
333333
if (err != 0) {
334334
printk("Failed to create group: %d\n", err);
335335
return err;
@@ -444,7 +444,7 @@ int cap_initiator_init(void)
444444
int cap_initiator_setup(struct bt_conn *conn)
445445
{
446446
int err = 0;
447-
struct bt_bap_unicast_group *unicast_group;
447+
struct bt_cap_unicast_group *unicast_group;
448448

449449
k_sem_reset(&sem_cas_discovery);
450450
k_sem_reset(&sem_discover_sink);

0 commit comments

Comments
 (0)