Skip to content

Commit 4a3d5d5

Browse files
committed
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. 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 25f3de7 commit 4a3d5d5

File tree

13 files changed

+852
-95
lines changed

13 files changed

+852
-95
lines changed

doc/releases/release-notes-4.2.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ New APIs and options
8080
* :c:macro:`BT_BAP_ADV_PARAM_BROADCAST_SLOW`
8181
* :c:macro:`BT_BAP_PER_ADV_PARAM_BROADCAST_FAST`
8282
* :c:macro:`BT_BAP_PER_ADV_PARAM_BROADCAST_SLOW`
83+
* :c:func:`bt_cap_unicast_group_create`
84+
* :c:func:`bt_cap_unicast_group_reconfig`
85+
* :c:func:`bt_cap_unicast_group_add_streams`
86+
* :c:func:`bt_cap_unicast_group_delete`
8387

8488
* Host
8589

include/zephyr/bluetooth/audio/cap.h

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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,147 @@ 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+
257401
/** Stream specific parameters for the bt_cap_initiator_unicast_audio_start() function */
258402
struct bt_cap_unicast_audio_start_stream_param {
259403
/** 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);

subsys/bluetooth/audio/bap_unicast_client.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2728,30 +2728,32 @@ static bool valid_unicast_group_stream_param(const struct bt_bap_unicast_group *
27282728
{
27292729
const struct bt_bap_qos_cfg *qos;
27302730

2731-
CHECKIF(param->stream == NULL) {
2731+
if (param->stream == NULL) {
27322732
LOG_DBG("param->stream is NULL");
2733-
return -EINVAL;
2733+
return false;
27342734
}
27352735

27362736
CHECKIF(param->qos == NULL) {
27372737
LOG_DBG("param->qos is NULL");
2738-
return -EINVAL;
2738+
return false;
27392739
}
27402740

2741-
if (param->stream != NULL && param->stream->group != NULL) {
2742-
if (unicast_group != NULL && param->stream->group != unicast_group) {
2741+
/* If unicast_group is non-NULL then we are doing a reconfigure */
2742+
if (unicast_group != NULL) {
2743+
if (param->stream->group != unicast_group) {
27432744
LOG_DBG("stream %p not part of group %p (%p)", param->stream, unicast_group,
27442745
param->stream->group);
2745-
} else {
2746-
LOG_DBG("stream %p already part of group %p", param->stream,
2747-
param->stream->group);
2746+
return false;
27482747
}
2749-
return -EALREADY;
2748+
} else if (param->stream->group != NULL) {
2749+
LOG_DBG("stream %p already part of group %p", param->stream, param->stream->group);
2750+
2751+
return false;
27502752
}
27512753

27522754
CHECKIF(bt_audio_verify_qos(param->qos) != BT_BAP_ASCS_REASON_NONE) {
27532755
LOG_DBG("Invalid QoS");
2754-
return -EINVAL;
2756+
return false;
27552757
}
27562758

27572759
qos = param->qos;

0 commit comments

Comments
 (0)