Bluetooth: Audio: Add packing to unicast group create

Add the ISO packing field when creating a unicast group.

This refactors the structure of the unicast group create,
as it now takes both the packing as a group parameter, as well
as an array of stream-specific parameters.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2022-12-20 15:54:37 +01:00 committed by Carles Cufí
commit 4e3205d238
5 changed files with 79 additions and 43 deletions

View file

@ -1940,14 +1940,14 @@ int bt_audio_stream_send(struct bt_audio_stream *stream, struct net_buf *buf,
* Parameter struct for the bt_audio_unicast_group_create() and * Parameter struct for the bt_audio_unicast_group_create() and
* bt_audio_unicast_group_add_streams() functions. * bt_audio_unicast_group_add_streams() functions.
*/ */
struct bt_audio_unicast_group_param { struct bt_audio_unicast_group_stream_param {
/** Pointer to a stream object. */ /** Pointer to a stream object. */
struct bt_audio_stream *stream; struct bt_audio_stream *stream;
/** The QoS settings for the @ref bt_audio_unicast_group_param.stream. */ /** The QoS settings for the @ref bt_audio_unicast_group_stream_param.stream. */
struct bt_codec_qos *qos; struct bt_codec_qos *qos;
/** @brief The direction of the @ref bt_audio_unicast_group_param.stream /** @brief The direction of the @ref bt_audio_unicast_group_stream_param.stream
* *
* If two streams are being used for the same ACL connection but in * If two streams are being used for the same ACL connection but in
* different directions, they may use the same CIS. * different directions, they may use the same CIS.
@ -1955,21 +1955,35 @@ struct bt_audio_unicast_group_param {
enum bt_audio_dir dir; enum bt_audio_dir dir;
}; };
struct bt_audio_unicast_group_param {
/** The number of parameters in @p params */
size_t params_count;
/** Array of stream parameters */
struct bt_audio_unicast_group_stream_param *params;
/** @brief Unicast Group packing mode.
*
* @ref BT_ISO_PACKING_SEQUENTIAL or @ref BT_ISO_PACKING_INTERLEAVED.
*
* @note This is a recommendation to the controller, which the
* controller may ignore.
*/
uint8_t packing;
};
/** @brief Create audio unicast group. /** @brief Create audio unicast group.
* *
* Create a new audio unicast group with one or more audio streams as a * Create a new audio unicast group with one or more audio streams as a
* unicast client. Streams in a unicast group shall share the same interval, * unicast client. Streams in a unicast group shall share the same interval,
* framing and latency (see @ref bt_codec_qos). * framing and latency (see @ref bt_codec_qos).
* *
* @param[in] params Array of stream parameters being used for * @param[in] param The unicast group create parameters.
* the group. * @param[out] unicast_group Pointer to the unicast group created.
* @param[in] num_param Number of parameters in @p params.
* @param[out] unicast_group Pointer to the unicast group created
* *
* @return Zero on success or (negative) error code otherwise. * @return Zero on success or (negative) error code otherwise.
*/ */
int bt_audio_unicast_group_create(struct bt_audio_unicast_group_param params[], int bt_audio_unicast_group_create(struct bt_audio_unicast_group_param *param,
size_t num_param,
struct bt_audio_unicast_group **unicast_group); struct bt_audio_unicast_group **unicast_group);
/** @brief Add streams to a unicast group as a unicast client /** @brief Add streams to a unicast group as a unicast client
@ -1995,7 +2009,7 @@ int bt_audio_unicast_group_create(struct bt_audio_unicast_group_param params[],
* @return 0 in case of success or negative value in case of error. * @return 0 in case of success or negative value in case of error.
*/ */
int bt_audio_unicast_group_add_streams(struct bt_audio_unicast_group *unicast_group, int bt_audio_unicast_group_add_streams(struct bt_audio_unicast_group *unicast_group,
struct bt_audio_unicast_group_param params[], struct bt_audio_unicast_group_stream_param params[],
size_t num_param); size_t num_param);
/** @brief Delete audio unicast group. /** @brief Delete audio unicast group.

View file

@ -908,17 +908,21 @@ static int configure_streams(void)
static int create_group(void) static int create_group(void)
{ {
struct bt_audio_unicast_group_param params[ARRAY_SIZE(streams)]; struct bt_audio_unicast_group_stream_param stream_params[ARRAY_SIZE(streams)];
struct bt_audio_unicast_group_param param;
int err; int err;
for (size_t i = 0U; i < configured_stream_count; i++) { for (size_t i = 0U; i < configured_stream_count; i++) {
params[i].stream = &streams[i]; stream_params[i].stream = &streams[i];
params[i].qos = &codec_configuration.qos; stream_params[i].qos = &codec_configuration.qos;
params[i].dir = stream_dir(params[i].stream); stream_params[i].dir = stream_dir(stream_params[i].stream);
} }
err = bt_audio_unicast_group_create(params, configured_stream_count, param.params = stream_params;
&unicast_group); param.params_count = configured_stream_count;
param.packing = BT_ISO_PACKING_SEQUENTIAL;
err = bt_audio_unicast_group_create(&param, &unicast_group);
if (err != 0) { if (err != 0) {
printk("Could not create unicast group (err %d)\n", err); printk("Could not create unicast group (err %d)\n", err);
return err; return err;

View file

@ -948,8 +948,7 @@ static void unicast_group_free(struct bt_audio_unicast_group *group)
group->allocated = false; group->allocated = false;
} }
int bt_audio_unicast_group_create(struct bt_audio_unicast_group_param params[], int bt_audio_unicast_group_create(struct bt_audio_unicast_group_param *param,
size_t num_param,
struct bt_audio_unicast_group **out_unicast_group) struct bt_audio_unicast_group **out_unicast_group)
{ {
struct bt_audio_unicast_group *unicast_group; struct bt_audio_unicast_group *unicast_group;
@ -963,39 +962,44 @@ int bt_audio_unicast_group_create(struct bt_audio_unicast_group_param params[],
/* Set out_unicast_group to NULL until the source has actually been created */ /* Set out_unicast_group to NULL until the source has actually been created */
*out_unicast_group = NULL; *out_unicast_group = NULL;
CHECKIF(params == NULL) { CHECKIF(param == NULL) {
LOG_DBG("streams is NULL"); LOG_DBG("streams is NULL");
return -EINVAL; return -EINVAL;
} }
CHECKIF(num_param > UNICAST_GROUP_STREAM_CNT) { CHECKIF(param->params_count > UNICAST_GROUP_STREAM_CNT) {
LOG_DBG("Too many streams provided: %u/%u", num_param, UNICAST_GROUP_STREAM_CNT); LOG_DBG("Too many streams provided: %u/%u",
param->params_count, UNICAST_GROUP_STREAM_CNT);
return -EINVAL; return -EINVAL;
} }
for (size_t i = 0U; i < num_param; i++) { for (size_t i = 0U; i < param->params_count; i++) {
CHECKIF(params[i].stream == NULL || struct bt_audio_unicast_group_stream_param *stream_param = &param->params[i];
params[i].qos == NULL ||
(params[i].dir != BT_AUDIO_DIR_SINK && CHECKIF(stream_param->stream == NULL ||
params[i].dir != BT_AUDIO_DIR_SOURCE)) { stream_param->qos == NULL ||
(stream_param->dir != BT_AUDIO_DIR_SINK &&
stream_param->dir != BT_AUDIO_DIR_SOURCE)) {
LOG_DBG("Invalid params[%zu] values", i); LOG_DBG("Invalid params[%zu] values", i);
return -EINVAL; return -EINVAL;
} }
if (params[i].stream->group != NULL) { if (stream_param->stream->group != NULL) {
LOG_DBG("params[%zu] stream (%p) already part of group %p", i, LOG_DBG("params[%zu] stream (%p) already part of group %p",
params[i].stream, params[i].stream->group); i, stream_param->stream,
stream_param->stream->group);
return -EALREADY; return -EALREADY;
} }
if (group_qos == NULL) { if (group_qos == NULL) {
group_qos = params[i].qos; group_qos = stream_param->qos;
} else if (!unicast_group_valid_qos(group_qos, params[i].qos)) { } else if (!unicast_group_valid_qos(group_qos,
stream_param->qos)) {
LOG_DBG("Stream[%zu] QoS incompatible with group QoS", i); LOG_DBG("Stream[%zu] QoS incompatible with group QoS", i);
return -EINVAL; return -EINVAL;
} }
CHECKIF(!bt_audio_valid_qos(params[i].qos)) { CHECKIF(!bt_audio_valid_qos(stream_param->qos)) {
LOG_DBG("Invalid QoS"); LOG_DBG("Invalid QoS");
return -EINVAL; return -EINVAL;
} }
@ -1007,9 +1011,13 @@ int bt_audio_unicast_group_create(struct bt_audio_unicast_group_param params[],
return -ENOMEM; return -ENOMEM;
} }
for (size_t i = 0U; i < num_param; i++) { for (size_t i = 0U; i < param->params_count; i++) {
err = unicast_group_add_stream(unicast_group, params[i].stream, struct bt_audio_unicast_group_stream_param *stream_param = &param->params[i];
params[i].qos, params[i].dir);
err = unicast_group_add_stream(unicast_group,
stream_param->stream,
stream_param->qos,
stream_param->dir);
if (err < 0) { if (err < 0) {
LOG_DBG("unicast_group_add_stream failed: %d", err); LOG_DBG("unicast_group_add_stream failed: %d", err);
unicast_group_free(unicast_group); unicast_group_free(unicast_group);
@ -1032,7 +1040,7 @@ int bt_audio_unicast_group_create(struct bt_audio_unicast_group_param params[],
} }
int bt_audio_unicast_group_add_streams(struct bt_audio_unicast_group *unicast_group, int bt_audio_unicast_group_add_streams(struct bt_audio_unicast_group *unicast_group,
struct bt_audio_unicast_group_param params[], struct bt_audio_unicast_group_stream_param params[],
size_t num_param) size_t num_param)
{ {
const struct bt_codec_qos *group_qos = unicast_group->qos; const struct bt_codec_qos *group_qos = unicast_group->qos;

View file

@ -1033,13 +1033,18 @@ static int cmd_qos(const struct shell *sh, size_t argc, char *argv[])
} }
if (default_unicast_group == NULL) { if (default_unicast_group == NULL) {
struct bt_audio_unicast_group_param params = { struct bt_audio_unicast_group_stream_param stream_param = {
.stream = default_stream, .stream = default_stream,
.qos = &default_preset->preset.qos, .qos = &default_preset->preset.qos,
.dir = stream_dir(default_stream) .dir = stream_dir(default_stream)
}; };
struct bt_audio_unicast_group_param param = {
.packing = BT_ISO_PACKING_SEQUENTIAL,
.params = &stream_param,
.params_count = 1,
};
err = bt_audio_unicast_group_create(&params, 1, &default_unicast_group); err = bt_audio_unicast_group_create(&param, &default_unicast_group);
if (err != 0) { if (err != 0) {
shell_error(sh, "Unable to create default unicast group: %d", err); shell_error(sh, "Unable to create default unicast group: %d", err);
return -ENOEXEC; return -ENOEXEC;

View file

@ -339,20 +339,25 @@ static size_t release_streams(size_t stream_cnt)
static void create_unicast_group(struct bt_audio_unicast_group **unicast_group, static void create_unicast_group(struct bt_audio_unicast_group **unicast_group,
size_t stream_cnt) size_t stream_cnt)
{ {
struct bt_audio_unicast_group_param params[ARRAY_SIZE(g_streams)]; struct bt_audio_unicast_group_stream_param stream_params[ARRAY_SIZE(g_streams)];
struct bt_audio_unicast_group_param param;
for (size_t i = 0U; i < stream_cnt; i++) { for (size_t i = 0U; i < stream_cnt; i++) {
params[i].stream = &g_streams[i]; stream_params[i].stream = &g_streams[i];
params[i].qos = &preset_16_2_1.qos; stream_params[i].qos = &preset_16_2_1.qos;
params[i].dir = BT_AUDIO_DIR_SINK; /* we only configure sinks */ stream_params[i].dir = BT_AUDIO_DIR_SINK; /* we only configure sinks */
} }
param.params = stream_params;
param.params_count = stream_cnt;
param.packing = BT_ISO_PACKING_SEQUENTIAL;
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) #if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
int err; int err;
/* Require controller support for CIGs */ /* Require controller support for CIGs */
printk("Creating unicast group\n"); printk("Creating unicast group\n");
err = bt_audio_unicast_group_create(&params, 1, unicast_group); err = bt_audio_unicast_group_create(&param, unicast_group);
if (err != 0) { if (err != 0) {
FAIL("Unable to create unicast group: %d", err); FAIL("Unable to create unicast group: %d", err);
return; return;