From 0fe8ddd75e151d3d779011df4e3914c97add74c0 Mon Sep 17 00:00:00 2001 From: Fredrik Danebjer Date: Mon, 4 Mar 2024 10:34:29 +0100 Subject: [PATCH] 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 --- subsys/bluetooth/audio/bap_scan_delegator.c | 43 +++++++++++++++++---- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/subsys/bluetooth/audio/bap_scan_delegator.c b/subsys/bluetooth/audio/bap_scan_delegator.c index 1f9f073f89b..0f5be7ce44a 100644 --- a/subsys/bluetooth/audio/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/bap_scan_delegator.c @@ -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) {