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:
parent
0d59c1a780
commit
38d09af445
6 changed files with 215 additions and 38 deletions
|
@ -24,7 +24,19 @@ does not actually support syncing with periodic advertisements yet.
|
|||
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>
|
||||
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
|
||||
==============
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,20 +1338,23 @@ 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);
|
||||
pa_sync = bt_le_per_adv_sync_lookup_addr(¶m->addr, param->sid);
|
||||
|
||||
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();
|
||||
if (internal_state == NULL) {
|
||||
|
@ -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, ¶m->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
|
||||
|
|
|
@ -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,
|
||||
static int cmd_bap_scan_delegator_add_src(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
struct bt_bap_scan_delegator_add_src_param param = {0};
|
||||
struct bt_bap_bass_subgroup *subgroup_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], ¶m.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 = ¶m.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(¶m);
|
||||
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)
|
||||
{
|
||||
/* 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_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_bap_scan_delegator_add_src_param 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(¶m.addr, &sync_info.addr);
|
||||
param.sid = sync_info.sid;
|
||||
|
||||
broadcast_id = shell_strtoul(argv[1], 16, &err);
|
||||
if (err != 0) {
|
||||
|
@ -627,8 +750,8 @@ 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,
|
||||
subgroup_param->metadata_len =
|
||||
hex2bin(argv[4], strlen(argv[4]), subgroup_param->metadata,
|
||||
sizeof(subgroup_param->metadata));
|
||||
|
||||
if (subgroup_param->metadata_len == 0U) {
|
||||
|
@ -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,
|
||||
|
|
|
@ -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(¶m.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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue