Bluetooth: CAP: Shell: Initiator fix chan_alloc
When using the CAP initiator shell AC commands, the channel allocation were not done correctly, leading to cases where we attempted to set e.g. 2 LEFT streams for the same device. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
c2f35a4168
commit
7d4c13f55f
1 changed files with 102 additions and 65 deletions
|
@ -623,23 +623,6 @@ static int cap_ac_unicast_start(const struct bap_unicast_ac_param *param,
|
|||
|
||||
snk_stream_cnt++;
|
||||
stream_cnt++;
|
||||
|
||||
/* If we have more than 1 connection or stream in one direction, we set the
|
||||
* location bit accordingly
|
||||
*/
|
||||
if (param->conn_cnt > 1U || param->snk_cnt[i] > 1U) {
|
||||
const int err = bt_audio_codec_cfg_set_chan_allocation(
|
||||
stream_param->codec_cfg, (enum bt_audio_location)BIT(i));
|
||||
|
||||
if (err < 0) {
|
||||
shell_error(ctx_shell,
|
||||
"Failed to set channel allocation for "
|
||||
"snk[%zu][%zu]: %d",
|
||||
i, j, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t j = 0U; j < param->src_cnt[i]; j++) {
|
||||
|
@ -653,23 +636,6 @@ static int cap_ac_unicast_start(const struct bap_unicast_ac_param *param,
|
|||
|
||||
src_stream_cnt++;
|
||||
stream_cnt++;
|
||||
|
||||
/* If we have more than 1 connection or stream in one direction, we set the
|
||||
* location bit accordingly
|
||||
*/
|
||||
if (param->conn_cnt > 1U || param->src_cnt[i] > 1U) {
|
||||
const int err = bt_audio_codec_cfg_set_chan_allocation(
|
||||
stream_param->codec_cfg, (enum bt_audio_location)BIT(i));
|
||||
|
||||
if (err < 0) {
|
||||
shell_error(ctx_shell,
|
||||
"Failed to set channel allocation for "
|
||||
"src[%zu][%zu]: %d",
|
||||
i, j, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -680,6 +646,82 @@ static int cap_ac_unicast_start(const struct bap_unicast_ac_param *param,
|
|||
return bt_cap_initiator_unicast_audio_start(&start_param);
|
||||
}
|
||||
|
||||
static int set_codec_config(const struct shell *sh, struct shell_stream *sh_stream,
|
||||
struct named_lc3_preset *preset, size_t conn_cnt, size_t ep_cnt,
|
||||
size_t chan_cnt, size_t conn_index, size_t ep_index)
|
||||
{
|
||||
enum bt_audio_location new_chan_alloc;
|
||||
enum bt_audio_location chan_alloc;
|
||||
int err;
|
||||
|
||||
copy_unicast_stream_preset(sh_stream, preset);
|
||||
|
||||
if (chan_cnt == 1U) {
|
||||
/* - When we have a single channel on a single connection then we make it mono
|
||||
* - When we have a single channel on a multiple connections then we make it left on
|
||||
* the first connection and right on the second connection
|
||||
* - When we have multiple channels streams for a connection, we make them either
|
||||
* left or right, regardless of the connection count
|
||||
*/
|
||||
if (ep_cnt == 1) {
|
||||
if (conn_cnt == 1) {
|
||||
new_chan_alloc = BT_AUDIO_LOCATION_MONO_AUDIO;
|
||||
} else if (conn_cnt == 2) {
|
||||
if (conn_index == 0) {
|
||||
new_chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT;
|
||||
} else if (conn_index == 1) {
|
||||
new_chan_alloc = BT_AUDIO_LOCATION_FRONT_RIGHT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (ep_cnt == 2) {
|
||||
if (ep_index == 0) {
|
||||
new_chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT;
|
||||
} else if (ep_index == 1) {
|
||||
new_chan_alloc = BT_AUDIO_LOCATION_FRONT_RIGHT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (chan_cnt == 2U) {
|
||||
/* Some audio configuration requires multiple sink channels,
|
||||
* so multiply the SDU based on the channel count
|
||||
*/
|
||||
sh_stream->qos.sdu *= chan_cnt;
|
||||
|
||||
/* If a stream has 2 channels, we make it stereo */
|
||||
new_chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT;
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = bt_audio_codec_cfg_get_chan_allocation(&sh_stream->codec_cfg, &chan_alloc);
|
||||
if (err != 0) {
|
||||
if (err == -ENODATA) {
|
||||
chan_alloc = BT_AUDIO_LOCATION_MONO_AUDIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (chan_alloc != new_chan_alloc) {
|
||||
shell_info(sh,
|
||||
"[%zu][%zu]: Overwriting existing channel allocation 0x%08X with 0x%08X",
|
||||
conn_index, ep_index, chan_alloc, new_chan_alloc);
|
||||
|
||||
err = bt_audio_codec_cfg_set_chan_allocation(&sh_stream->codec_cfg, new_chan_alloc);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cap_ac_unicast(const struct shell *sh, const struct bap_unicast_ac_param *param)
|
||||
{
|
||||
/* Allocate params large enough for any params, but only use what is required */
|
||||
|
@ -735,10 +777,36 @@ int cap_ac_unicast(const struct shell *sh, const struct bap_unicast_ac_param *pa
|
|||
*/
|
||||
for (size_t i = 0U; i < param->conn_cnt; i++) {
|
||||
for (size_t j = 0U; j < param->snk_cnt[i]; j++) {
|
||||
struct shell_stream *snk_uni_stream;
|
||||
|
||||
snk_uni_stream = snk_uni_streams[snk_cnt] = &unicast_streams[snk_cnt];
|
||||
|
||||
err = set_codec_config(sh, snk_uni_stream, &default_sink_preset,
|
||||
param->conn_cnt, param->snk_cnt[i],
|
||||
param->snk_chan_cnt, i, j);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to set codec configuration: %d", err);
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
snk_cnt++;
|
||||
}
|
||||
|
||||
for (size_t j = 0U; j < param->src_cnt[i]; j++) {
|
||||
struct shell_stream *src_uni_stream;
|
||||
|
||||
src_uni_stream = snk_uni_streams[src_cnt] = &unicast_streams[src_cnt];
|
||||
|
||||
err = set_codec_config(sh, src_uni_stream, &default_source_preset,
|
||||
param->conn_cnt, param->src_cnt[i],
|
||||
param->src_chan_cnt, i, j);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to set codec configuration: %d", err);
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
src_cnt++;
|
||||
}
|
||||
}
|
||||
|
@ -747,37 +815,6 @@ int cap_ac_unicast(const struct shell *sh, const struct bap_unicast_ac_param *pa
|
|||
ctx_shell = sh;
|
||||
}
|
||||
|
||||
/* Setup arrays of parameters based on the preset for easier access. This also copies the
|
||||
* preset so that we can modify them (e.g. update the metadata)
|
||||
*/
|
||||
for (size_t i = 0U; i < snk_cnt; i++) {
|
||||
struct shell_stream *snk_uni_stream = snk_uni_streams[i] = &unicast_streams[i];
|
||||
|
||||
if (snk_uni_stream->stream.bap_stream.conn != NULL) {
|
||||
shell_error(sh, "unicast_streams[%zu] already in use", i);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
copy_unicast_stream_preset(snk_uni_stream, &default_sink_preset);
|
||||
|
||||
/* Some audio configuration requires multiple sink channels,
|
||||
* so multiply the SDU based on the channel count
|
||||
*/
|
||||
snk_uni_stream->qos.sdu *= param->snk_chan_cnt;
|
||||
}
|
||||
|
||||
for (size_t i = 0U; i < src_cnt; i++) {
|
||||
struct shell_stream *src_uni_stream = src_uni_streams[i] =
|
||||
&unicast_streams[i + snk_cnt];
|
||||
|
||||
if (src_uni_stream->stream.bap_stream.conn != NULL) {
|
||||
shell_error(sh, "unicast_streams[%zu] already in use", i + snk_cnt);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
copy_unicast_stream_preset(src_uni_stream, &default_source_preset);
|
||||
}
|
||||
|
||||
err = bap_ac_create_unicast_group(param, snk_uni_streams, snk_cnt, src_uni_streams,
|
||||
src_cnt);
|
||||
if (err != 0) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue