Bluetooth: Audio: Broadcast Assistant: Check add_source duplication
Added a check for checking duplication when adding a source in the broadcast assistant, as per requirement in BAP 6.5.4. It is not permitted to add a source such that a combination of broadcast_id, adv_sid and address type would result in same triple of values. Added a recv_state struct to cache these values when read, and moved past_avail and srd_ids into this as well. Signed-off-by: Fredrik Danebjer <frdn@demant.com>
This commit is contained in:
parent
c50843a98c
commit
bbb87ae0ae
|
@ -3,6 +3,7 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Bose Corporation
|
||||
* Copyright (c) 2022-2023 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2024 Demant A/S
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -34,17 +35,21 @@ LOG_MODULE_REGISTER(bt_bap_broadcast_assistant, CONFIG_BT_BAP_BROADCAST_ASSISTAN
|
|||
|
||||
#define MINIMUM_RECV_STATE_LEN 15
|
||||
|
||||
struct bap_broadcast_assistant_recv_state_info {
|
||||
uint8_t src_id;
|
||||
bt_addr_le_t addr;
|
||||
uint8_t adv_sid;
|
||||
uint32_t broadcast_id;
|
||||
|
||||
/** Cached PAST available */
|
||||
bool past_avail;
|
||||
};
|
||||
|
||||
struct bap_broadcast_assistant_instance {
|
||||
struct bt_conn *conn;
|
||||
bool scanning;
|
||||
uint8_t pa_sync;
|
||||
uint8_t recv_state_cnt;
|
||||
/* Source ID cache so that we can notify application about
|
||||
* which source ID was removed
|
||||
*/
|
||||
uint8_t src_ids[CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT];
|
||||
/** Cached PAST available */
|
||||
bool past_avail[CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT];
|
||||
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
|
@ -62,6 +67,9 @@ struct bap_broadcast_assistant_instance {
|
|||
|
||||
struct k_work_delayable bap_read_work;
|
||||
uint16_t long_read_handle;
|
||||
|
||||
struct bap_broadcast_assistant_recv_state_info recv_states
|
||||
[CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT];
|
||||
};
|
||||
|
||||
static sys_slist_t broadcast_assistant_cbs = SYS_SLIST_STATIC_INIT(&broadcast_assistant_cbs);
|
||||
|
@ -273,10 +281,10 @@ static uint8_t parse_and_send_recv_state(struct bt_conn *conn, uint16_t handle,
|
|||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
broadcast_assistant.src_ids[index] = recv_state->src_id;
|
||||
broadcast_assistant.past_avail[index] = past_available(conn,
|
||||
&recv_state->addr,
|
||||
recv_state->adv_sid);
|
||||
broadcast_assistant.recv_states[index].src_id = recv_state->src_id;
|
||||
broadcast_assistant.recv_states[index].past_avail = past_available(conn,
|
||||
&recv_state->addr,
|
||||
recv_state->adv_sid);
|
||||
|
||||
bap_broadcast_assistant_recv_state_changed(conn, 0, recv_state);
|
||||
|
||||
|
@ -434,9 +442,9 @@ static uint8_t notify_handler(struct bt_conn *conn,
|
|||
return parse_and_send_recv_state(conn, handle, data, length, &recv_state);
|
||||
}
|
||||
} else {
|
||||
broadcast_assistant.past_avail[index] = false;
|
||||
broadcast_assistant.recv_states[index].past_avail = false;
|
||||
bap_broadcast_assistant_recv_state_removed(conn, 0,
|
||||
broadcast_assistant.src_ids[index]);
|
||||
broadcast_assistant.recv_states[index].src_id);
|
||||
}
|
||||
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
|
@ -471,8 +479,14 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err,
|
|||
if (cb_err != 0) {
|
||||
LOG_DBG("Invalid receive state");
|
||||
} else {
|
||||
broadcast_assistant.src_ids[index] = recv_state.src_id;
|
||||
broadcast_assistant.past_avail[index] =
|
||||
struct bap_broadcast_assistant_recv_state_info *stored_state =
|
||||
&broadcast_assistant.recv_states[index];
|
||||
|
||||
stored_state->src_id = recv_state.src_id;
|
||||
stored_state->adv_sid = recv_state.adv_sid;
|
||||
stored_state->broadcast_id = recv_state.broadcast_id;
|
||||
bt_addr_le_copy(&stored_state->addr, &recv_state.addr);
|
||||
broadcast_assistant.recv_states[index].past_avail =
|
||||
past_available(conn, &recv_state.addr,
|
||||
recv_state.adv_sid);
|
||||
}
|
||||
|
@ -782,8 +796,9 @@ static int broadcast_assistant_reset(struct bap_broadcast_assistant_instance *in
|
|||
(void)k_work_cancel_delayable(&inst->bap_read_work);
|
||||
|
||||
for (int i = 0U; i < CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT; i++) {
|
||||
inst->src_ids[i] = 0U;
|
||||
inst->past_avail[i] = false;
|
||||
memset(&inst->recv_states[i], 0,
|
||||
sizeof(struct bap_broadcast_assistant_recv_state_info));
|
||||
inst->recv_states[i].past_avail = false;
|
||||
inst->recv_state_handles[i] = 0U;
|
||||
}
|
||||
|
||||
|
@ -998,6 +1013,7 @@ int bt_bap_broadcast_assistant_add_src(struct bt_conn *conn,
|
|||
const struct bt_bap_broadcast_assistant_add_src_param *param)
|
||||
{
|
||||
struct bt_bap_bass_cp_add_src *cp;
|
||||
struct bap_broadcast_assistant_recv_state_info *state;
|
||||
|
||||
if (conn == NULL) {
|
||||
LOG_DBG("conn is NULL");
|
||||
|
@ -1013,6 +1029,21 @@ int bt_bap_broadcast_assistant_add_src(struct bt_conn *conn,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Check if this operation would result in a duplicate before proceeding */
|
||||
for (size_t i = 0; i < ARRAY_SIZE(broadcast_assistant.recv_states); i++) {
|
||||
state = &broadcast_assistant.recv_states[i];
|
||||
|
||||
if (param->addr.type == state->addr.type && param->adv_sid == state->adv_sid &&
|
||||
param->broadcast_id == state->broadcast_id) {
|
||||
LOG_DBG("recv_state using broadcast_id=0x%06X, adv_sid=0x%02X, and "
|
||||
"addr.type=0x%02X already exists with src_id=0x%02X",
|
||||
param->broadcast_id, param->adv_sid, param->addr.type,
|
||||
state->src_id);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset buffer before using */
|
||||
net_buf_simple_reset(&att_buf);
|
||||
cp = net_buf_simple_add(&att_buf, sizeof(*cp));
|
||||
|
@ -1108,10 +1139,10 @@ int bt_bap_broadcast_assistant_mod_src(struct bt_conn *conn,
|
|||
*/
|
||||
known_recv_state = false;
|
||||
past_avail = false;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(broadcast_assistant.src_ids); i++) {
|
||||
if (broadcast_assistant.src_ids[i] == param->src_id) {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(broadcast_assistant.recv_states); i++) {
|
||||
if (broadcast_assistant.recv_states[i].src_id == param->src_id) {
|
||||
known_recv_state = true;
|
||||
past_avail = broadcast_assistant.past_avail[i];
|
||||
past_avail = broadcast_assistant.recv_states[i].past_avail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue