Bluetooth: BAP: Broadcast source reconfig with subgroups
Modify the bt_bap_broadcast_source_reconfig to use the same parameter struct as bt_bap_broadcast_source_create so that the two are more similar, since they both set the same values. This allow for full control of which subgroups and stream are updated. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
7fca0aa8a6
commit
d327b1625c
6 changed files with 125 additions and 35 deletions
|
@ -1400,7 +1400,7 @@ struct bt_bap_broadcast_source_subgroup_param {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Broadcast Source create parameters */
|
/** Broadcast Source create parameters */
|
||||||
struct bt_bap_broadcast_source_create_param {
|
struct bt_bap_broadcast_source_param {
|
||||||
/** The number of parameters in @p subgroup_params */
|
/** The number of parameters in @p subgroup_params */
|
||||||
size_t params_count;
|
size_t params_count;
|
||||||
|
|
||||||
|
@ -1451,7 +1451,7 @@ struct bt_bap_broadcast_source_create_param {
|
||||||
*
|
*
|
||||||
* @return Zero on success or (negative) error code otherwise.
|
* @return Zero on success or (negative) error code otherwise.
|
||||||
*/
|
*/
|
||||||
int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param *param,
|
int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_param *param,
|
||||||
struct bt_bap_broadcast_source **source);
|
struct bt_bap_broadcast_source **source);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1460,15 +1460,21 @@ int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param *
|
||||||
* Reconfigure an audio broadcast source with a new codec and codec quality of
|
* Reconfigure an audio broadcast source with a new codec and codec quality of
|
||||||
* service parameters. This can only be done when the source is stopped.
|
* service parameters. This can only be done when the source is stopped.
|
||||||
*
|
*
|
||||||
|
* Since this may modify the Broadcast Audio Source Endpoint (BASE),
|
||||||
|
* bt_bap_broadcast_source_get_base() should be called after this to get the new BASE information.
|
||||||
|
*
|
||||||
|
* If the @p param.params_count is smaller than the number of subgroups that have been created in
|
||||||
|
* the Broadcast Source, only the first @p param.params_count subgroups are updated. If a stream
|
||||||
|
* exist in a subgroup not part of @p param, then that stream is left as is (i.e. it is not removed;
|
||||||
|
* the only way to remove a stream from a Broadcast Source is to recreate the Broadcast Source).
|
||||||
|
*
|
||||||
* @param source Pointer to the broadcast source
|
* @param source Pointer to the broadcast source
|
||||||
* @param codec_cfg Codec configuration.
|
* @param param Pointer to parameters used to reconfigure the broadcast source.
|
||||||
* @param qos Quality of Service configuration
|
|
||||||
*
|
*
|
||||||
* @return Zero on success or (negative) error code otherwise.
|
* @return Zero on success or (negative) error code otherwise.
|
||||||
*/
|
*/
|
||||||
int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source,
|
int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source,
|
||||||
struct bt_audio_codec_cfg *codec_cfg,
|
struct bt_bap_broadcast_source_param *param);
|
||||||
struct bt_audio_codec_qos *qos);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Modify the metadata of an audio broadcast source.
|
* @brief Modify the metadata of an audio broadcast source.
|
||||||
|
|
|
@ -93,7 +93,7 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source)
|
||||||
stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
|
stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
|
||||||
struct bt_bap_broadcast_source_subgroup_param
|
struct bt_bap_broadcast_source_subgroup_param
|
||||||
subgroup_param[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
|
subgroup_param[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
|
||||||
struct bt_bap_broadcast_source_create_param create_param;
|
struct bt_bap_broadcast_source_param create_param;
|
||||||
const size_t streams_per_subgroup = ARRAY_SIZE(stream_params) / ARRAY_SIZE(subgroup_param);
|
const size_t streams_per_subgroup = ARRAY_SIZE(stream_params) / ARRAY_SIZE(subgroup_param);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|
|
@ -476,7 +476,8 @@ static void broadcast_source_cleanup(struct bt_bap_broadcast_source *source)
|
||||||
(void)memset(source, 0, sizeof(*source));
|
(void)memset(source, 0, sizeof(*source));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool valid_create_param(const struct bt_bap_broadcast_source_create_param *param)
|
static bool valid_broadcast_source_param(const struct bt_bap_broadcast_source_param *param,
|
||||||
|
const struct bt_bap_broadcast_source *source)
|
||||||
{
|
{
|
||||||
const struct bt_audio_codec_qos *qos;
|
const struct bt_audio_codec_qos *qos;
|
||||||
|
|
||||||
|
@ -555,7 +556,8 @@ static bool valid_create_param(const struct bt_bap_broadcast_source_create_param
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECKIF(stream_param->stream->group != NULL) {
|
CHECKIF(stream_param->stream->group != NULL &&
|
||||||
|
stream_param->stream->group != source) {
|
||||||
LOG_DBG("subgroup_params[%zu].stream_params[%zu]->stream is "
|
LOG_DBG("subgroup_params[%zu].stream_params[%zu]->stream is "
|
||||||
"already part of group %p",
|
"already part of group %p",
|
||||||
i, j, stream_param->stream->group);
|
i, j, stream_param->stream->group);
|
||||||
|
@ -618,7 +620,7 @@ static enum bt_bap_ep_state broadcast_source_get_state(struct bt_bap_broadcast_s
|
||||||
return stream->ep->status.state;
|
return stream->ep->status.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param *param,
|
int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_param *param,
|
||||||
struct bt_bap_broadcast_source **out_source)
|
struct bt_bap_broadcast_source **out_source)
|
||||||
{
|
{
|
||||||
struct bt_bap_broadcast_source *source;
|
struct bt_bap_broadcast_source *source;
|
||||||
|
@ -635,7 +637,7 @@ int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param *
|
||||||
/* Set out_source to NULL until the source has actually been created */
|
/* Set out_source to NULL until the source has actually been created */
|
||||||
*out_source = NULL;
|
*out_source = NULL;
|
||||||
|
|
||||||
if (!valid_create_param(param)) {
|
if (!valid_broadcast_source_param(param, NULL)) {
|
||||||
LOG_DBG("Invalid parameters");
|
LOG_DBG("Invalid parameters");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -738,35 +740,20 @@ int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param *
|
||||||
}
|
}
|
||||||
|
|
||||||
int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source,
|
int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source,
|
||||||
struct bt_audio_codec_cfg *codec_cfg,
|
struct bt_bap_broadcast_source_param *param)
|
||||||
struct bt_audio_codec_qos *qos)
|
|
||||||
{
|
{
|
||||||
struct bt_bap_broadcast_subgroup *subgroup;
|
struct bt_bap_broadcast_subgroup *subgroup;
|
||||||
enum bt_bap_ep_state broadcast_state;
|
enum bt_bap_ep_state broadcast_state;
|
||||||
struct bt_bap_stream *stream;
|
struct bt_audio_codec_qos *qos;
|
||||||
|
size_t subgroup_cnt;
|
||||||
|
|
||||||
CHECKIF(source == NULL) {
|
CHECKIF(source == NULL) {
|
||||||
LOG_DBG("source is NULL");
|
LOG_DBG("source is NULL");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECKIF(!bt_audio_valid_codec_cfg(codec_cfg)) {
|
if (!valid_broadcast_source_param(param, source)) {
|
||||||
LOG_DBG("codec_cfg is invalid");
|
LOG_DBG("Invalid parameters");
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECKIF(qos == NULL) {
|
|
||||||
LOG_DBG("qos is NULL");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECKIF(bt_audio_verify_qos(qos) != BT_BAP_ASCS_REASON_NONE) {
|
|
||||||
LOG_DBG("qos is invalid");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECKIF(qos->rtn > BT_ISO_BROADCAST_RTN_MAX) {
|
|
||||||
LOG_DBG("qos->rtn %u invalid", qos->rtn);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,9 +763,97 @@ int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source,
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify that the parameter counts do not exceed existing number of subgroups and streams*/
|
||||||
|
subgroup_cnt = 0U;
|
||||||
SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
|
SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
|
||||||
|
const struct bt_bap_broadcast_source_subgroup_param *subgroup_param =
|
||||||
|
¶m->params[subgroup_cnt];
|
||||||
|
const size_t subgroup_stream_param_cnt = subgroup_param->params_count;
|
||||||
|
struct bt_bap_stream *stream;
|
||||||
|
size_t stream_cnt = 0U;
|
||||||
|
|
||||||
SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
|
SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
|
||||||
|
stream_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify that the param stream is in the subgroup */
|
||||||
|
for (size_t i = 0U; i < subgroup_param->params_count; i++) {
|
||||||
|
struct bt_bap_stream *subgroup_stream;
|
||||||
|
struct bt_bap_stream *param_stream;
|
||||||
|
bool stream_in_subgroup;
|
||||||
|
|
||||||
|
param_stream = subgroup_param->params[i].stream;
|
||||||
|
|
||||||
|
SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, subgroup_stream, _node) {
|
||||||
|
if (subgroup_stream == param_stream) {
|
||||||
|
stream_in_subgroup = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stream_in_subgroup) {
|
||||||
|
LOG_DBG("Invalid param->params[%zu]->param[%zu].stream "
|
||||||
|
"not in subgroup",
|
||||||
|
subgroup_cnt, i);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subgroup_stream_param_cnt < stream_cnt) {
|
||||||
|
LOG_DBG("Invalid param->params[%zu]->params_count: %zu "
|
||||||
|
"(only %zu streams in subgroup)",
|
||||||
|
subgroup_cnt, subgroup_stream_param_cnt, stream_cnt);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
subgroup_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subgroup_cnt < param->params_count) {
|
||||||
|
LOG_DBG("Invalid param->params_count: %zu (only %zu subgroups in source)",
|
||||||
|
param->params_count, subgroup_cnt);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qos = param->qos;
|
||||||
|
|
||||||
|
/* We update up to the first param->params_count subgroups */
|
||||||
|
for (size_t i = 0U; i < param->params_count; i++) {
|
||||||
|
const struct bt_bap_broadcast_source_subgroup_param *subgroup_param;
|
||||||
|
struct bt_audio_codec_cfg *codec_cfg;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
subgroup =
|
||||||
|
SYS_SLIST_PEEK_HEAD_CONTAINER(&source->subgroups, subgroup, _node);
|
||||||
|
} else {
|
||||||
|
subgroup = SYS_SLIST_PEEK_NEXT_CONTAINER(subgroup, _node);
|
||||||
|
}
|
||||||
|
|
||||||
|
subgroup_param = ¶m->params[i];
|
||||||
|
codec_cfg = subgroup_param->codec_cfg;
|
||||||
|
subgroup->codec_cfg = codec_cfg;
|
||||||
|
|
||||||
|
for (size_t j = 0U; j < subgroup_param->params_count; j++) {
|
||||||
|
const struct bt_bap_broadcast_source_stream_param *stream_param;
|
||||||
|
struct bt_audio_broadcast_stream_data *stream_data;
|
||||||
|
struct bt_bap_stream *subgroup_stream;
|
||||||
struct bt_iso_chan_io_qos *iso_qos;
|
struct bt_iso_chan_io_qos *iso_qos;
|
||||||
|
struct bt_bap_stream *stream;
|
||||||
|
bool stream_in_subgroup;
|
||||||
|
size_t stream_idx;
|
||||||
|
|
||||||
|
stream_param = &subgroup_param->params[j];
|
||||||
|
stream = stream_param->stream;
|
||||||
|
|
||||||
|
stream_idx = 0U;
|
||||||
|
SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, subgroup_stream, _node) {
|
||||||
|
if (subgroup_stream == stream) {
|
||||||
|
stream_in_subgroup = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_idx++;
|
||||||
|
}
|
||||||
|
|
||||||
iso_qos = stream->ep->iso->chan.qos->tx;
|
iso_qos = stream->ep->iso->chan.qos->tx;
|
||||||
|
|
||||||
|
@ -787,6 +862,15 @@ int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source,
|
||||||
bt_audio_codec_qos_to_iso_qos(iso_qos, qos);
|
bt_audio_codec_qos_to_iso_qos(iso_qos, qos);
|
||||||
bt_audio_codec_cfg_to_iso_path(iso_qos->path, codec_cfg);
|
bt_audio_codec_cfg_to_iso_path(iso_qos->path, codec_cfg);
|
||||||
stream->qos = qos;
|
stream->qos = qos;
|
||||||
|
|
||||||
|
/* Store the BIS specific codec configuration data in the broadcast source.
|
||||||
|
* It is stored in the broadcast* source, instead of the stream object,
|
||||||
|
* as this is only relevant for the broadcast source, and not used
|
||||||
|
* for unicast or broadcast sink.
|
||||||
|
*/
|
||||||
|
stream_data = &source->stream_data[stream_idx];
|
||||||
|
(void)memcpy(stream_data->data, stream_param->data, stream_param->data_len);
|
||||||
|
stream_data->data_len = stream_param->data_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ static bool cap_initiator_broadcast_audio_start_valid_param(
|
||||||
|
|
||||||
static void cap_initiator_broadcast_to_bap_broadcast_param(
|
static void cap_initiator_broadcast_to_bap_broadcast_param(
|
||||||
const struct bt_cap_initiator_broadcast_create_param *cap_param,
|
const struct bt_cap_initiator_broadcast_create_param *cap_param,
|
||||||
struct bt_bap_broadcast_source_create_param *bap_param,
|
struct bt_bap_broadcast_source_param *bap_param,
|
||||||
struct bt_bap_broadcast_source_subgroup_param
|
struct bt_bap_broadcast_source_subgroup_param
|
||||||
bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT],
|
bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT],
|
||||||
struct bt_bap_broadcast_source_stream_param
|
struct bt_bap_broadcast_source_stream_param
|
||||||
|
@ -170,7 +170,7 @@ int bt_cap_initiator_broadcast_audio_create(
|
||||||
bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
|
bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
|
||||||
struct bt_bap_broadcast_source_stream_param
|
struct bt_bap_broadcast_source_stream_param
|
||||||
bap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
|
bap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
|
||||||
struct bt_bap_broadcast_source_create_param bap_create_param;
|
struct bt_bap_broadcast_source_param bap_create_param;
|
||||||
|
|
||||||
CHECKIF(param == NULL) {
|
CHECKIF(param == NULL) {
|
||||||
LOG_DBG("param is NULL");
|
LOG_DBG("param is NULL");
|
||||||
|
|
|
@ -2052,7 +2052,7 @@ static int cmd_create_broadcast(const struct shell *sh, size_t argc,
|
||||||
struct bt_bap_broadcast_source_stream_param
|
struct bt_bap_broadcast_source_stream_param
|
||||||
stream_params[ARRAY_SIZE(broadcast_source_streams)];
|
stream_params[ARRAY_SIZE(broadcast_source_streams)];
|
||||||
struct bt_bap_broadcast_source_subgroup_param subgroup_param;
|
struct bt_bap_broadcast_source_subgroup_param subgroup_param;
|
||||||
struct bt_bap_broadcast_source_create_param create_param = {0};
|
struct bt_bap_broadcast_source_param create_param = {0};
|
||||||
const struct named_lc3_preset *named_preset;
|
const struct named_lc3_preset *named_preset;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|
|
@ -1043,7 +1043,7 @@ static int cap_ac_broadcast(const struct shell *sh, size_t argc, char **argv,
|
||||||
uint8_t left_data[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC,
|
uint8_t left_data[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC,
|
||||||
BT_AUDIO_LOCATION_FRONT_LEFT)};
|
BT_AUDIO_LOCATION_FRONT_LEFT)};
|
||||||
struct bt_bap_broadcast_source_subgroup_param subgroup_param = {0};
|
struct bt_bap_broadcast_source_subgroup_param subgroup_param = {0};
|
||||||
struct bt_bap_broadcast_source_create_param create_param = {0};
|
struct bt_bap_broadcast_source_param create_param = {0};
|
||||||
const struct named_lc3_preset *named_preset;
|
const struct named_lc3_preset *named_preset;
|
||||||
struct bt_le_ext_adv *adv;
|
struct bt_le_ext_adv *adv;
|
||||||
int err;
|
int err;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue