Bluetooth: Audio: Scan Delegator: Guard for duplication in add_source

Added a check for duplication of add source operation in the Scan
Delagator. BAP 6.5.4 states that an assistant may not perform add
source operation if it results in a duplication of a source. While
this is not mentioned for the Scan Delegator, the spirit of the spec.
must be that no duplications can exists in the recv_state, which is
what this commit fixes.

Signed-off-by: Fredrik Danebjer <frdn@demant.com>
This commit is contained in:
Fredrik Danebjer 2024-03-04 10:34:29 +01:00 committed by Fabio Baltieri
parent d73b6e50b9
commit 0fe8ddd75e

View File

@ -279,7 +279,7 @@ static void scan_delegator_security_changed(struct bt_conn *conn,
}
/* Notify all receive states after a bonded device reconnects */
for (int i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
for (size_t i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
struct bass_recv_state_internal *internal_state = &scan_delegator.recv_states[i];
int gatt_err;
@ -318,7 +318,7 @@ static struct broadcast_assistant *get_bap_broadcast_assistant(struct bt_conn *c
{
struct broadcast_assistant *new = NULL;
for (int i = 0; i < ARRAY_SIZE(scan_delegator.assistant_configs); i++) {
for (size_t i = 0; i < ARRAY_SIZE(scan_delegator.assistant_configs); i++) {
if (scan_delegator.assistant_configs[i].conn == conn) {
return &scan_delegator.assistant_configs[i];
} else if (new == NULL &&
@ -344,7 +344,7 @@ static uint8_t next_src_id(void)
while (!unique) {
next_src_id = scan_delegator.next_src_id++;
unique = true;
for (int i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
for (size_t i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
if (scan_delegator.recv_states[i].active &&
scan_delegator.recv_states[i].state.src_id == next_src_id) {
unique = false;
@ -358,7 +358,7 @@ static uint8_t next_src_id(void)
static struct bass_recv_state_internal *bass_lookup_src_id(uint8_t src_id)
{
for (int i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
for (size_t i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
if (scan_delegator.recv_states[i].active &&
scan_delegator.recv_states[i].state.src_id == src_id) {
return &scan_delegator.recv_states[i];
@ -370,7 +370,7 @@ static struct bass_recv_state_internal *bass_lookup_src_id(uint8_t src_id)
static struct bass_recv_state_internal *bass_lookup_pa_sync(struct bt_le_per_adv_sync *sync)
{
for (int i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
for (size_t i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
if (scan_delegator.recv_states[i].pa_sync == sync) {
return &scan_delegator.recv_states[i];
}
@ -381,7 +381,7 @@ static struct bass_recv_state_internal *bass_lookup_pa_sync(struct bt_le_per_adv
static struct bass_recv_state_internal *bass_lookup_addr(const bt_addr_le_t *addr)
{
for (int i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
for (size_t i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
if (bt_addr_le_eq(&scan_delegator.recv_states[i].state.addr,
addr)) {
return &scan_delegator.recv_states[i];
@ -493,6 +493,24 @@ static int pa_sync_term_request(struct bt_conn *conn,
return err;
}
static bool bass_source_is_duplicate(uint32_t broadcast_id, uint8_t adv_sid, bt_addr_le_t addr)
{
struct bass_recv_state_internal *state;
for (size_t i = 0; i < ARRAY_SIZE(scan_delegator.recv_states); i++) {
state = &scan_delegator.recv_states[i];
if (state != NULL && state->state.broadcast_id == broadcast_id
&& state->state.adv_sid == adv_sid && state->state.addr.type == addr.type) {
LOG_DBG("recv_state already exists at src_id=0x%02X", state->state.src_id);
return true;
}
}
return false;
}
static int scan_delegator_add_source(struct bt_conn *conn,
struct net_buf_simple *buf)
{
@ -502,6 +520,7 @@ static int scan_delegator_add_source(struct bt_conn *conn,
uint8_t pa_sync;
uint16_t pa_interval;
uint32_t aggregated_bis_syncs = 0;
uint32_t broadcast_id;
bool bis_sync_requested;
/* subtract 1 as the opcode has already been pulled */
@ -535,7 +554,17 @@ static int scan_delegator_add_source(struct bt_conn *conn,
return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
}
state->broadcast_id = net_buf_simple_pull_le24(buf);
broadcast_id = net_buf_simple_pull_le24(buf);
if (bass_source_is_duplicate(broadcast_id, state->adv_sid, state->addr)) {
LOG_DBG("Adding broadcast_id=0x%06X, adv_sid=0x%02X, and addr.type=0x%02X would "
"result in duplication", state->broadcast_id, state->adv_sid,
state->addr.type);
return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED);
}
state->broadcast_id = broadcast_id;
pa_sync = net_buf_simple_pull_u8(buf);
if (pa_sync > BT_BAP_BASS_PA_REQ_SYNC) {