Bluetooth: CAP: Make unicast update more similar to unicast start

Modify the parameters for bt_cap_initiator_unicast_audio_update
so that they are more similar to
bt_cap_initiator_unicast_audio_start.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2024-01-17 15:59:13 +01:00 committed by David Leach
commit ec549cebd5
5 changed files with 186 additions and 101 deletions

View file

@ -227,8 +227,9 @@ struct bt_cap_unicast_audio_start_param {
struct bt_cap_unicast_audio_start_stream_param *stream_params;
};
struct bt_cap_unicast_audio_update_param {
/** @brief Stream for the @p member */
/** Stream specific parameters for the bt_cap_initiator_unicast_audio_update() function */
struct bt_cap_unicast_audio_update_stream_param {
/** Stream to update */
struct bt_cap_stream *stream;
/** The length of @p meta. */
@ -242,6 +243,18 @@ struct bt_cap_unicast_audio_update_param {
uint8_t *meta;
};
/** Parameters for the bt_cap_initiator_unicast_audio_update() function */
struct bt_cap_unicast_audio_update_param {
/** The type of the set. */
enum bt_cap_set_type type;
/** The number of parameters in @p stream_params */
size_t count;
/** Array of stream parameters */
struct bt_cap_unicast_audio_update_stream_param *stream_params;
};
/**
* @brief Register Common Audio Profile Initiator callbacks
*
@ -277,13 +290,11 @@ int bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start
* @kconfig{CONFIG_BT_BAP_UNICAST_CLIENT} must be enabled for this function
* to be enabled.
*
* @param params Array of update parameters.
* @param count The number of entries in @p params.
* @param param Update parameters.
*
* @return 0 on success or negative error value on failure.
*/
int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_update_param params[],
size_t count);
int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_update_param *param);
/**
* @brief Stop unicast audio streams for a unicast group.

View file

@ -891,8 +891,104 @@ static bool can_update_metadata(const struct bt_bap_stream *bap_stream)
ep_info.state == BT_BAP_EP_STATE_STREAMING;
}
int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_update_param params[],
size_t count)
static bool valid_unicast_audio_update_param(const struct bt_cap_unicast_audio_update_param *param)
{
struct bt_bap_unicast_group *unicast_group = NULL;
CHECKIF(param == NULL) {
LOG_DBG("param is NULL");
return false;
}
CHECKIF(param->count == 0) {
LOG_DBG("Invalid param->count: %u", param->count);
return false;
}
CHECKIF(param->stream_params == NULL) {
LOG_DBG("param->stream_params is NULL");
return false;
}
CHECKIF(param->count > CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT) {
LOG_DBG("param->count (%zu) is larger than "
"CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT (%d)",
param->count, CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT);
return false;
}
for (size_t i = 0U; i < param->count; i++) {
const struct bt_cap_unicast_audio_update_stream_param *stream_param =
&param->stream_params[i];
const struct bt_cap_stream *cap_stream = stream_param->stream;
const struct bt_bap_stream *bap_stream;
struct bt_cap_common_client *client;
struct bt_conn *conn;
CHECKIF(cap_stream == NULL) {
LOG_DBG("param->stream_params[%zu] is NULL", i);
return false;
}
bap_stream = &cap_stream->bap_stream;
conn = bap_stream->conn;
CHECKIF(conn == NULL) {
LOG_DBG("param->stream_params[%zu].stream->bap_stream.conn is NULL", i);
return -EINVAL;
}
client = bt_cap_common_get_client_by_acl(conn);
if (!client->cas_found) {
LOG_DBG("CAS was not found for param->stream_params[%zu].stream", i);
return false;
}
CHECKIF(bap_stream->group == NULL) {
LOG_DBG("param->stream_params[%zu] is not in a unicast group", i);
return false;
}
/* Use the group of the first stream for comparison */
if (unicast_group == NULL) {
unicast_group = bap_stream->group;
} else {
CHECKIF(bap_stream->group != unicast_group) {
LOG_DBG("param->stream_params[%zu] is not in this group %p", i,
unicast_group);
return false;
}
}
if (!can_update_metadata(bap_stream)) {
LOG_DBG("param->stream_params[%zu].stream is not in right state to be "
"updated",
i);
return false;
}
if (!cap_initiator_valid_metadata(stream_param->meta, stream_param->meta_len)) {
LOG_DBG("param->stream_params[%zu] invalid metadata", i);
return false;
}
for (size_t j = 0U; j < i; j++) {
if (param->stream_params[j].stream == cap_stream) {
LOG_DBG("param->stream_params[%zu] (%p) is "
"duplicated by "
"param->stream_params[%zu] (%p)",
j, param->stream_params[j].stream, i, cap_stream);
return false;
}
}
}
return true;
}
int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_update_param *param)
{
struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
struct bt_cap_initiator_proc_param *proc_param;
@ -901,67 +997,28 @@ int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_upda
size_t meta_len;
int err;
CHECKIF(params == NULL) {
LOG_DBG("params is NULL");
return -EINVAL;
}
CHECKIF(count == 0) {
LOG_DBG("count is 0");
return -EINVAL;
}
if (bt_cap_common_proc_is_active()) {
LOG_DBG("A CAP procedure is already in progress");
return -EBUSY;
}
for (size_t i = 0U; i < count; i++) {
struct bt_cap_stream *cap_stream = params[i].stream;
CHECKIF(cap_stream == NULL) {
LOG_DBG("params[%zu].stream is NULL", i);
return -EINVAL;
}
CHECKIF(cap_stream->bap_stream.conn == NULL) {
LOG_DBG("params[%zu].stream->bap_stream.conn is NULL", i);
return -EINVAL;
}
CHECKIF(!cap_initiator_valid_metadata(params[i].meta,
params[i].meta_len)) {
LOG_DBG("params[%zu].meta is invalid", i);
return -EINVAL;
}
for (size_t j = 0U; j < i; j++) {
if (params[j].stream == cap_stream) {
LOG_DBG("param.streams[%zu] is duplicated by param.streams[%zu]",
j, i);
return -EINVAL;
}
}
if (!can_update_metadata(&cap_stream->bap_stream)) {
LOG_DBG("params[%zu].stream is not in right state to be updated", i);
return -EINVAL;
}
active_proc->proc_param.initiator[i].stream = cap_stream;
active_proc->proc_param.initiator[i].meta_update.meta_len = params[i].meta_len;
memcpy(&active_proc->proc_param.initiator[i].meta_update.meta, params[i].meta,
params[i].meta_len);
if (!valid_unicast_audio_update_param(param)) {
return -EINVAL;
}
bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_UPDATE, count);
for (size_t i = 0U; i < param->count; i++) {
const struct bt_cap_unicast_audio_update_stream_param *stream_param =
&param->stream_params[i];
struct bt_cap_stream *cap_stream = stream_param->stream;
active_proc->proc_param.initiator[i].stream = cap_stream;
active_proc->proc_param.initiator[i].meta_update.meta_len = stream_param->meta_len;
memcpy(&active_proc->proc_param.initiator[i].meta_update.meta, stream_param->meta,
stream_param->meta_len);
}
bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_UPDATE, param->count);
bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_META_UPDATE);
proc_param = &active_proc->proc_param.initiator[0];

View file

@ -337,8 +337,9 @@ static int cmd_cap_initiator_unicast_list(const struct shell *sh, size_t argc,
static int cmd_cap_initiator_unicast_update(const struct shell *sh, size_t argc,
char *argv[])
{
struct bt_cap_unicast_audio_update_param params[CAP_UNICAST_CLIENT_STREAM_COUNT];
size_t count;
struct bt_cap_unicast_audio_update_stream_param
stream_params[CAP_UNICAST_CLIENT_STREAM_COUNT] = {0};
struct bt_cap_unicast_audio_update_param param = {0};
int err = 0;
if (default_conn == NULL) {
@ -346,8 +347,6 @@ static int cmd_cap_initiator_unicast_update(const struct shell *sh, size_t argc,
return -ENOEXEC;
}
count = 0;
if (argc == 2 && strcmp(argv[1], "all") == 0) {
for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
struct bt_cap_stream *stream = &unicast_streams[i].stream;
@ -366,8 +365,7 @@ static int cmd_cap_initiator_unicast_update(const struct shell *sh, size_t argc,
return -ENOEXEC;
}
params[count].stream = stream;
stream_params[param.count].stream = stream;
if (ep_info.dir == BT_AUDIO_DIR_SINK) {
copy_unicast_stream_preset(uni_stream, default_sink_preset);
@ -375,10 +373,10 @@ static int cmd_cap_initiator_unicast_update(const struct shell *sh, size_t argc,
copy_unicast_stream_preset(uni_stream, default_source_preset);
}
params[count].meta = uni_stream->codec_cfg.meta;
params[count].meta_len = uni_stream->codec_cfg.meta_len;
stream_params[param.count].meta = uni_stream->codec_cfg.meta;
stream_params[param.count].meta_len = uni_stream->codec_cfg.meta_len;
count++;
param.count++;
}
} else {
@ -409,7 +407,7 @@ static int cmd_cap_initiator_unicast_update(const struct shell *sh, size_t argc,
return -ENOEXEC;
}
params[count].stream = stream;
stream_params[param.count].stream = stream;
if (ep_info.dir == BT_AUDIO_DIR_SINK) {
copy_unicast_stream_preset(uni_stream, default_sink_preset);
@ -417,22 +415,25 @@ static int cmd_cap_initiator_unicast_update(const struct shell *sh, size_t argc,
copy_unicast_stream_preset(uni_stream, default_source_preset);
}
params[count].meta = uni_stream->codec_cfg.meta;
params[count].meta_len = uni_stream->codec_cfg.meta_len;
stream_params[param.count].meta = uni_stream->codec_cfg.meta;
stream_params[param.count].meta_len = uni_stream->codec_cfg.meta_len;
count++;
param.count++;
}
}
if (count == 0) {
if (param.count == 0) {
shell_error(sh, "No streams to update");
return -ENOEXEC;
}
shell_print(sh, "Updating %zu streams", count);
param.stream_params = stream_params;
param.type = BT_CAP_SET_TYPE_AD_HOC;
err = bt_cap_initiator_unicast_audio_update(params, count);
shell_print(sh, "Updating %zu streams", param.count);
err = bt_cap_initiator_unicast_audio_update(&param);
if (err != 0) {
shell_print(sh, "Failed to update unicast audio: %d", err);
}

View file

@ -341,8 +341,9 @@ static uint8_t btp_cap_unicast_audio_update(const void *cmd, uint16_t cmd_len,
int err;
const uint8_t *data_ptr;
const struct btp_cap_unicast_audio_update_cmd *cp = cmd;
struct bt_cap_unicast_audio_update_param stream_params[
ARRAY_SIZE(btp_csip_set_members) * BTP_BAP_UNICAST_MAX_STREAMS_COUNT];
struct bt_cap_unicast_audio_update_stream_param
stream_params[ARRAY_SIZE(btp_csip_set_members) * BTP_BAP_UNICAST_MAX_STREAMS_COUNT];
struct bt_cap_unicast_audio_update_param param = {0};
LOG_DBG("");
@ -357,7 +358,7 @@ static uint8_t btp_cap_unicast_audio_update(const void *cmd, uint16_t cmd_len,
struct bt_conn *conn;
struct btp_cap_unicast_audio_update_data *update_data =
(struct btp_cap_unicast_audio_update_data *)data_ptr;
struct bt_cap_unicast_audio_update_param *param = &stream_params[i];
struct bt_cap_unicast_audio_update_stream_param *stream_param = &stream_params[i];
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &update_data->address);
if (!conn) {
@ -379,15 +380,19 @@ static uint8_t btp_cap_unicast_audio_update(const void *cmd, uint16_t cmd_len,
return BTP_STATUS_FAILED;
}
param->stream = &u_stream->audio_stream.cap_stream;
param->meta_len = update_data->metadata_ltvs_len;
param->meta = update_data->metadata_ltvs;
stream_param->stream = &u_stream->audio_stream.cap_stream;
stream_param->meta_len = update_data->metadata_ltvs_len;
stream_param->meta = update_data->metadata_ltvs;
data_ptr = ((uint8_t *)update_data) + param->meta_len +
data_ptr = ((uint8_t *)update_data) + stream_param->meta_len +
sizeof(struct btp_cap_unicast_audio_update_data);
}
err = bt_cap_initiator_unicast_audio_update(stream_params, cp->stream_count);
param.count = cp->stream_count;
param.stream_params = stream_params;
param.type = BT_CAP_SET_TYPE_AD_HOC;
err = bt_cap_initiator_unicast_audio_update(&param);
if (err != 0) {
LOG_ERR("Failed to start unicast audio: %d", err);

View file

@ -663,30 +663,36 @@ static void unicast_audio_update_inval(void)
{
struct bt_audio_codec_cfg invalid_codec = BT_AUDIO_CODEC_LC3_CONFIG_16_2(
BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_MEDIA);
struct bt_cap_unicast_audio_update_param param;
struct bt_cap_unicast_audio_update_stream_param stream_params[1] = {0};
struct bt_cap_unicast_audio_update_param param = {0};
int err;
param.stream = &unicast_client_sink_streams[0];
param.meta = unicast_preset_16_2_1.codec_cfg.meta;
param.meta_len = unicast_preset_16_2_1.codec_cfg.meta_len;
stream_params[0].stream = &unicast_client_sink_streams[0];
stream_params[0].meta = unicast_preset_16_2_1.codec_cfg.meta;
stream_params[0].meta_len = unicast_preset_16_2_1.codec_cfg.meta_len;
param.count = ARRAY_SIZE(stream_params);
param.stream_params = stream_params;
param.type = BT_CAP_SET_TYPE_AD_HOC;
err = bt_cap_initiator_unicast_audio_update(NULL, 1);
err = bt_cap_initiator_unicast_audio_update(NULL);
if (err == 0) {
FAIL("bt_cap_initiator_unicast_audio_update with NULL params did not fail\n");
return;
}
err = bt_cap_initiator_unicast_audio_update(&param, 0);
param.count = 0U;
err = bt_cap_initiator_unicast_audio_update(&param);
if (err == 0) {
FAIL("bt_cap_initiator_unicast_audio_update with 0 param count did not fail\n");
return;
}
/* Clear metadata so that it does not contain the mandatory stream context */
param.count = ARRAY_SIZE(stream_params);
memset(&invalid_codec.meta, 0, sizeof(invalid_codec.meta));
param.meta = invalid_codec.meta;
stream_params[0].meta = invalid_codec.meta;
err = bt_cap_initiator_unicast_audio_update(&param, 1);
err = bt_cap_initiator_unicast_audio_update(&param);
if (err == 0) {
FAIL("bt_cap_initiator_unicast_audio_update with invalid Codec metadata did not "
"fail\n");
@ -696,7 +702,8 @@ static void unicast_audio_update_inval(void)
static void unicast_audio_update(void)
{
struct bt_cap_unicast_audio_update_param param[2];
struct bt_cap_unicast_audio_update_stream_param stream_params[2] = {0};
struct bt_cap_unicast_audio_update_param param = {0};
uint8_t new_meta[] = {
3,
BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT,
@ -707,17 +714,21 @@ static void unicast_audio_update(void)
};
int err;
param[0].stream = &unicast_client_sink_streams[0];
param[0].meta = new_meta;
param[0].meta_len = ARRAY_SIZE(new_meta);
stream_params[0].stream = &unicast_client_sink_streams[0];
stream_params[0].meta = new_meta;
stream_params[0].meta_len = ARRAY_SIZE(new_meta);
param[1].stream = &unicast_client_source_streams[0];
param[1].meta = new_meta;
param[1].meta_len = ARRAY_SIZE(new_meta);
stream_params[1].stream = &unicast_client_source_streams[0];
stream_params[1].meta = new_meta;
stream_params[1].meta_len = ARRAY_SIZE(new_meta);
param.count = ARRAY_SIZE(stream_params);
param.stream_params = stream_params;
param.type = BT_CAP_SET_TYPE_AD_HOC;
UNSET_FLAG(flag_updated);
err = bt_cap_initiator_unicast_audio_update(param, ARRAY_SIZE(param));
err = bt_cap_initiator_unicast_audio_update(&param);
if (err != 0) {
FAIL("Failed to update unicast audio: %d\n", err);
return;