Bluetooth: BAP: Scan delegator add src without PA sync

Modify the bt_bap_scan_delegator_add_src to take an address and
a sid instead of a PA sync object, so that the scan delegator
can add a source without syncing to the PA.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2024-06-21 15:52:10 +02:00 committed by Anas Nashif
commit 38d09af445
6 changed files with 215 additions and 38 deletions

View file

@ -23,8 +23,20 @@ does not actually support syncing with periodic advertisements yet.
bap_scan_delegator --help
bap_scan_delegator - Bluetooth BAP Scan Delegator shell commands
Subcommands:
init :Initialize the service and register callbacks
synced :Set server scan state <src_id> <pa_synced> <bis_syncs> <enc_state>
init : Initialize the service and register callbacks
set_past_pref : Set PAST preference <true || false>
sync_pa : Sync to PA <src_id>
term_pa : Terminate PA sync <src_id>
add_src : Add a PA as source <addr> <sid> <broadcast_id>
<enc_state> [bis_sync [metadata]]
add_src_by_pa_sync : Add a PA as source <broadcast_id> <enc_state> [bis_sync
[metadata]]
mod_src : Modify source <src_id> <broadcast_id> <enc_state>
[bis_sync [metadata]]
rem_src : Remove source <src_id>
synced : Set server scan state <src_id> <bis_syncs>
Example Usage
@ -36,9 +48,31 @@ Setup
.. code-block:: console
uart:~$ bt init
uart:~$ bap_scan_delegator init
uart:~$ bt advertise on
Advertising started
Adding a source
===============
.. code-block:: console
uart:~$ bap_scan_delegator add_src 11:22:33:44:55:66 public 0 1234 0
Receive state with ID 0 updated
Adding a source from a PA sync
==============================
.. code-block:: console
uart:~$ bt scan on
Found broadcaster with ID 0x681A22 and addr 2C:44:05:82:EB:82 (random) and sid 0x00 (looking for 0x1000000)
uart:~$ bt scan off
uart:~$ bt per-adv-sync-create 2C:44:05:82:EB:82 (random) 0
PA 0x2003e9b0 synced
uart:~$ bap_scan_delegator add_src_by_pa_sync 0x681A22 0
Receive state with ID 0 updated
When connected
==============

View file

@ -2012,8 +2012,11 @@ int bt_bap_scan_delegator_set_bis_sync_state(
/** Parameters for bt_bap_scan_delegator_add_src() */
struct bt_bap_scan_delegator_add_src_param {
/** The periodic adverting sync */
struct bt_le_per_adv_sync *pa_sync;
/** Periodic Advertiser Address */
bt_addr_le_t addr;
/** Advertiser SID */
uint8_t sid;
/** The broadcast isochronous group encryption state */
enum bt_bap_big_enc_state encrypt_state;

View file

@ -457,9 +457,14 @@ static struct bt_bap_broadcast_sink *broadcast_sink_get_by_pa(struct bt_le_per_a
static void broadcast_sink_add_src(struct bt_bap_broadcast_sink *sink)
{
struct bt_bap_scan_delegator_add_src_param add_src_param;
struct bt_le_per_adv_sync_info sync_info;
int err;
add_src_param.pa_sync = sink->pa_sync;
err = bt_le_per_adv_sync_get_info(sink->pa_sync, &sync_info);
__ASSERT_NO_MSG(err == 0);
bt_addr_le_copy(&add_src_param.addr, &sync_info.addr);
add_src_param.sid = sync_info.sid;
add_src_param.broadcast_id = sink->broadcast_id;
/* Will be updated when we receive the BASE */
add_src_param.encrypt_state = BT_BAP_BIG_ENC_STATE_NO_ENC;

View file

@ -1295,9 +1295,13 @@ static bool valid_bt_bap_scan_delegator_add_src_param(
return false;
}
if (param->pa_sync == NULL) {
LOG_DBG("NULL pa_sync");
CHECKIF(param->addr.type > BT_ADDR_LE_RANDOM) {
LOG_DBG("param->addr.type %u is invalid", param->addr.type);
return false;
}
CHECKIF(param->sid > BT_GAP_SID_MAX) {
LOG_DBG("param->sid %d is invalid", param->sid);
return false;
}
@ -1334,19 +1338,22 @@ int bt_bap_scan_delegator_add_src(const struct bt_bap_scan_delegator_add_src_par
{
struct bass_recv_state_internal *internal_state = NULL;
struct bt_bap_scan_delegator_recv_state *state;
struct bt_le_per_adv_sync_info sync_info;
int err;
struct bt_le_per_adv_sync *pa_sync;
CHECKIF(!valid_bt_bap_scan_delegator_add_src_param(param)) {
return -EINVAL;
}
internal_state = bass_lookup_pa_sync(param->pa_sync);
if (internal_state != NULL) {
LOG_DBG("PA Sync already in a receive state with src_id %u",
internal_state->state.src_id);
pa_sync = bt_le_per_adv_sync_lookup_addr(&param->addr, param->sid);
return -EALREADY;
if (pa_sync != NULL) {
internal_state = bass_lookup_pa_sync(pa_sync);
if (internal_state != NULL) {
LOG_DBG("PA Sync already in a receive state with src_id %u",
internal_state->state.src_id);
return -EALREADY;
}
}
internal_state = get_free_recv_state();
@ -1356,20 +1363,14 @@ int bt_bap_scan_delegator_add_src(const struct bt_bap_scan_delegator_add_src_par
return -ENOMEM;
}
err = bt_le_per_adv_sync_get_info(param->pa_sync, &sync_info);
if (err != 0) {
LOG_DBG("Failed to get sync info: %d", err);
return err;
}
state = &internal_state->state;
state->src_id = next_src_id();
bt_addr_le_copy(&state->addr, &sync_info.addr);
state->adv_sid = sync_info.sid;
bt_addr_le_copy(&state->addr, &param->addr);
state->adv_sid = param->sid;
state->broadcast_id = param->broadcast_id;
state->pa_sync_state = BT_BAP_PA_STATE_SYNCED;
state->pa_sync_state =
pa_sync == NULL ? BT_BAP_PA_STATE_NOT_SYNCED : BT_BAP_PA_STATE_SYNCED;
state->num_subgroups = param->num_subgroups;
if (state->num_subgroups > 0U) {
(void)memcpy(state->subgroups, param->subgroups,
@ -1379,7 +1380,7 @@ int bt_bap_scan_delegator_add_src(const struct bt_bap_scan_delegator_add_src_par
}
internal_state->active = true;
internal_state->pa_sync = param->pa_sync;
internal_state->pa_sync = pa_sync;
/* Set all requested_bis_sync to BT_BAP_BIS_SYNC_NO_PREF, as no
* Broadcast Assistant has set any requests yet

View file

@ -565,19 +565,142 @@ static int cmd_bap_scan_delegator_term_pa(const struct shell *sh, size_t argc,
return 0;
}
static int cmd_bap_scan_delegator_add_src(const struct shell *sh, size_t argc,
char **argv)
static int cmd_bap_scan_delegator_add_src(const struct shell *sh, size_t argc, char **argv)
{
/* TODO: Add support to select which PA sync to BIG sync to */
struct bt_le_per_adv_sync *pa_sync = per_adv_syncs[0];
struct bt_bap_scan_delegator_add_src_param param = {0};
struct bt_bap_bass_subgroup *subgroup_param;
struct bt_bap_scan_delegator_add_src_param param;
unsigned long broadcast_id;
struct sync_state *state;
unsigned long enc_state;
unsigned long adv_sid;
int err;
err = bt_addr_le_from_str(argv[1], argv[2], &param.addr);
if (err != 0) {
shell_error(sh, "Invalid peer address (err %d)", err);
return -ENOEXEC;
}
adv_sid = shell_strtoul(argv[3], 0, &err);
if (err != 0) {
shell_error(sh, "Could not parse adv_sid: %d", err);
return -ENOEXEC;
}
if (adv_sid > BT_GAP_SID_MAX) {
shell_error(sh, "Invalid adv_sid: %lu", adv_sid);
return -ENOEXEC;
}
param.sid = adv_sid;
broadcast_id = shell_strtoul(argv[4], 16, &err);
if (err != 0) {
shell_error(sh, "Failed to parse broadcast_id from %s", argv[1]);
return -EINVAL;
}
if (broadcast_id > BT_AUDIO_BROADCAST_ID_MAX) {
shell_error(sh, "Invalid broadcast_id %lu", broadcast_id);
return -EINVAL;
}
enc_state = shell_strtoul(argv[5], 16, &err);
if (err != 0) {
shell_error(sh, "Failed to parse enc_state from %s", argv[2]);
return -EINVAL;
}
if (enc_state > BT_BAP_BIG_ENC_STATE_BAD_CODE) {
shell_error(sh, "Invalid enc_state %s", bt_bap_big_enc_state_str(enc_state));
return -EINVAL;
}
/* TODO: Support multiple subgroups */
subgroup_param = &param.subgroups[0];
if (argc > 6) {
unsigned long bis_sync;
bis_sync = shell_strtoul(argv[6], 16, &err);
if (err != 0) {
shell_error(sh, "Failed to parse bis_sync from %s", argv[3]);
return -EINVAL;
}
if (bis_sync > BT_BAP_BIS_SYNC_NO_PREF) {
shell_error(sh, "Invalid bis_sync %lu", bis_sync);
return -EINVAL;
}
} else {
subgroup_param->bis_sync = 0U;
}
if (argc > 7) {
subgroup_param->metadata_len =
hex2bin(argv[4], strlen(argv[7]), subgroup_param->metadata,
sizeof(subgroup_param->metadata));
if (subgroup_param->metadata_len == 0U) {
shell_error(sh, "Could not parse metadata");
return -EINVAL;
}
} else {
subgroup_param->metadata_len = 0U;
}
state = sync_state_new();
if (state == NULL) {
shell_error(ctx_shell, "Could not get new state");
return -ENOEXEC;
}
param.encrypt_state = (enum bt_bap_big_enc_state)enc_state;
param.broadcast_id = broadcast_id;
param.num_subgroups = 1U;
err = bt_bap_scan_delegator_add_src(&param);
if (err < 0) {
shell_error(ctx_shell, "Failed to add source: %d", err);
return -ENOEXEC;
}
state->src_id = (uint8_t)err;
return 0;
}
static int cmd_bap_scan_delegator_add_src_by_pa_sync(const struct shell *sh, size_t argc,
char **argv)
{
struct bt_le_per_adv_sync *pa_sync = per_adv_syncs[selected_per_adv_sync];
struct bt_bap_scan_delegator_add_src_param param = {0};
struct bt_bap_bass_subgroup *subgroup_param;
struct bt_le_per_adv_sync_info sync_info;
unsigned long broadcast_id;
struct sync_state *state;
unsigned long enc_state;
int err;
err = 0;
err = bt_le_per_adv_sync_get_info(pa_sync, &sync_info);
if (err != 0) {
shell_error(sh, "Failed to get sync info: %d", err);
return -ENOEXEC;
}
bt_addr_le_copy(&param.addr, &sync_info.addr);
param.sid = sync_info.sid;
broadcast_id = shell_strtoul(argv[1], 16, &err);
if (err != 0) {
@ -627,9 +750,9 @@ static int cmd_bap_scan_delegator_add_src(const struct shell *sh, size_t argc,
}
if (argc > 4) {
subgroup_param->metadata_len = hex2bin(argv[4], strlen(argv[4]),
subgroup_param->metadata,
sizeof(subgroup_param->metadata));
subgroup_param->metadata_len =
hex2bin(argv[4], strlen(argv[4]), subgroup_param->metadata,
sizeof(subgroup_param->metadata));
if (subgroup_param->metadata_len == 0U) {
shell_error(sh, "Could not parse metadata");
@ -647,7 +770,6 @@ static int cmd_bap_scan_delegator_add_src(const struct shell *sh, size_t argc,
return -ENOEXEC;
}
param.pa_sync = pa_sync;
param.encrypt_state = (enum bt_bap_big_enc_state)enc_state;
param.broadcast_id = broadcast_id;
param.num_subgroups = 1U;
@ -885,8 +1007,12 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bap_scan_delegator_cmds,
"Terminate PA sync <src_id>",
cmd_bap_scan_delegator_term_pa, 2, 0),
SHELL_CMD_ARG(add_src, NULL,
"Add a PA as source <addr> <sid> <broadcast_id> <enc_state> "
"[bis_sync [metadata]]",
cmd_bap_scan_delegator_add_src, 5, 2),
SHELL_CMD_ARG(add_src_by_pa_sync, NULL,
"Add a PA as source <broadcast_id> <enc_state> [bis_sync [metadata]]",
cmd_bap_scan_delegator_add_src, 3, 2),
cmd_bap_scan_delegator_add_src_by_pa_sync, 3, 2),
SHELL_CMD_ARG(mod_src, NULL,
"Modify source <src_id> <broadcast_id> <enc_state> [bis_sync [metadata]]",
cmd_bap_scan_delegator_mod_src, 4, 2),
@ -896,7 +1022,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bap_scan_delegator_cmds,
SHELL_CMD_ARG(synced, NULL,
"Set server scan state <src_id> <bis_syncs>",
cmd_bap_scan_delegator_bis_synced, 3, 0),
SHELL_SUBCMD_SET_END
SHELL_SUBCMD_SET_END,
);
SHELL_CMD_ARG_REGISTER(bap_scan_delegator, &bap_scan_delegator_cmds,

View file

@ -488,11 +488,19 @@ static struct bt_le_scan_cb scan_cb = {
static int add_source(struct sync_state *state)
{
struct bt_bap_scan_delegator_add_src_param param;
struct bt_le_per_adv_sync_info sync_info;
int res;
UNSET_FLAG(flag_recv_state_updated);
param.pa_sync = state->pa_sync;
res = bt_le_per_adv_sync_get_info(state->pa_sync, &sync_info);
if (res != 0) {
FAIL("Failed to get PA sync info: %d)\n", res);
return true;
}
bt_addr_le_copy(&param.addr, &sync_info.addr);
param.sid = sync_info.sid;
param.encrypt_state = BT_BAP_BIG_ENC_STATE_NO_ENC;
param.broadcast_id = g_broadcast_id;
param.num_subgroups = 1U;