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
|
@ -23,8 +23,20 @@ does not actually support syncing with periodic advertisements yet.
|
||||||
bap_scan_delegator --help
|
bap_scan_delegator --help
|
||||||
bap_scan_delegator - Bluetooth BAP Scan Delegator shell commands
|
bap_scan_delegator - Bluetooth BAP Scan Delegator shell commands
|
||||||
Subcommands:
|
Subcommands:
|
||||||
init :Initialize the service and register callbacks
|
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
|
Example Usage
|
||||||
|
@ -36,9 +48,31 @@ Setup
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
uart:~$ bt init
|
uart:~$ bt init
|
||||||
|
uart:~$ bap_scan_delegator init
|
||||||
uart:~$ bt advertise on
|
uart:~$ bt advertise on
|
||||||
Advertising started
|
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
|
When connected
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
|
|
@ -2012,8 +2012,11 @@ int bt_bap_scan_delegator_set_bis_sync_state(
|
||||||
|
|
||||||
/** Parameters for bt_bap_scan_delegator_add_src() */
|
/** Parameters for bt_bap_scan_delegator_add_src() */
|
||||||
struct bt_bap_scan_delegator_add_src_param {
|
struct bt_bap_scan_delegator_add_src_param {
|
||||||
/** The periodic adverting sync */
|
/** Periodic Advertiser Address */
|
||||||
struct bt_le_per_adv_sync *pa_sync;
|
bt_addr_le_t addr;
|
||||||
|
|
||||||
|
/** Advertiser SID */
|
||||||
|
uint8_t sid;
|
||||||
|
|
||||||
/** The broadcast isochronous group encryption state */
|
/** The broadcast isochronous group encryption state */
|
||||||
enum bt_bap_big_enc_state encrypt_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)
|
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_bap_scan_delegator_add_src_param add_src_param;
|
||||||
|
struct bt_le_per_adv_sync_info sync_info;
|
||||||
int err;
|
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;
|
add_src_param.broadcast_id = sink->broadcast_id;
|
||||||
/* Will be updated when we receive the BASE */
|
/* Will be updated when we receive the BASE */
|
||||||
add_src_param.encrypt_state = BT_BAP_BIG_ENC_STATE_NO_ENC;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param->pa_sync == NULL) {
|
CHECKIF(param->addr.type > BT_ADDR_LE_RANDOM) {
|
||||||
LOG_DBG("NULL pa_sync");
|
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;
|
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 bass_recv_state_internal *internal_state = NULL;
|
||||||
struct bt_bap_scan_delegator_recv_state *state;
|
struct bt_bap_scan_delegator_recv_state *state;
|
||||||
struct bt_le_per_adv_sync_info sync_info;
|
struct bt_le_per_adv_sync *pa_sync;
|
||||||
int err;
|
|
||||||
|
|
||||||
CHECKIF(!valid_bt_bap_scan_delegator_add_src_param(param)) {
|
CHECKIF(!valid_bt_bap_scan_delegator_add_src_param(param)) {
|
||||||
return -EINVAL;
|
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 (internal_state != NULL) {
|
|
||||||
LOG_DBG("PA Sync already in a receive state with src_id %u",
|
|
||||||
internal_state->state.src_id);
|
|
||||||
|
|
||||||
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();
|
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;
|
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 = &internal_state->state;
|
||||||
|
|
||||||
state->src_id = next_src_id();
|
state->src_id = next_src_id();
|
||||||
bt_addr_le_copy(&state->addr, &sync_info.addr);
|
bt_addr_le_copy(&state->addr, ¶m->addr);
|
||||||
state->adv_sid = sync_info.sid;
|
state->adv_sid = param->sid;
|
||||||
state->broadcast_id = param->broadcast_id;
|
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;
|
state->num_subgroups = param->num_subgroups;
|
||||||
if (state->num_subgroups > 0U) {
|
if (state->num_subgroups > 0U) {
|
||||||
(void)memcpy(state->subgroups, param->subgroups,
|
(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->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
|
/* Set all requested_bis_sync to BT_BAP_BIS_SYNC_NO_PREF, as no
|
||||||
* Broadcast Assistant has set any requests yet
|
* 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;
|
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)
|
||||||
char **argv)
|
|
||||||
{
|
{
|
||||||
/* TODO: Add support to select which PA sync to BIG sync to */
|
struct bt_bap_scan_delegator_add_src_param param = {0};
|
||||||
struct bt_le_per_adv_sync *pa_sync = per_adv_syncs[0];
|
|
||||||
struct bt_bap_bass_subgroup *subgroup_param;
|
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], ¶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)
|
||||||
|
{
|
||||||
|
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;
|
unsigned long broadcast_id;
|
||||||
struct sync_state *state;
|
struct sync_state *state;
|
||||||
unsigned long enc_state;
|
unsigned long enc_state;
|
||||||
int err;
|
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);
|
broadcast_id = shell_strtoul(argv[1], 16, &err);
|
||||||
if (err != 0) {
|
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) {
|
if (argc > 4) {
|
||||||
subgroup_param->metadata_len = hex2bin(argv[4], strlen(argv[4]),
|
subgroup_param->metadata_len =
|
||||||
subgroup_param->metadata,
|
hex2bin(argv[4], strlen(argv[4]), subgroup_param->metadata,
|
||||||
sizeof(subgroup_param->metadata));
|
sizeof(subgroup_param->metadata));
|
||||||
|
|
||||||
if (subgroup_param->metadata_len == 0U) {
|
if (subgroup_param->metadata_len == 0U) {
|
||||||
shell_error(sh, "Could not parse metadata");
|
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;
|
return -ENOEXEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
param.pa_sync = pa_sync;
|
|
||||||
param.encrypt_state = (enum bt_bap_big_enc_state)enc_state;
|
param.encrypt_state = (enum bt_bap_big_enc_state)enc_state;
|
||||||
param.broadcast_id = broadcast_id;
|
param.broadcast_id = broadcast_id;
|
||||||
param.num_subgroups = 1U;
|
param.num_subgroups = 1U;
|
||||||
|
@ -885,8 +1007,12 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bap_scan_delegator_cmds,
|
||||||
"Terminate PA sync <src_id>",
|
"Terminate PA sync <src_id>",
|
||||||
cmd_bap_scan_delegator_term_pa, 2, 0),
|
cmd_bap_scan_delegator_term_pa, 2, 0),
|
||||||
SHELL_CMD_ARG(add_src, NULL,
|
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]]",
|
"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,
|
SHELL_CMD_ARG(mod_src, NULL,
|
||||||
"Modify source <src_id> <broadcast_id> <enc_state> [bis_sync [metadata]]",
|
"Modify source <src_id> <broadcast_id> <enc_state> [bis_sync [metadata]]",
|
||||||
cmd_bap_scan_delegator_mod_src, 4, 2),
|
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,
|
SHELL_CMD_ARG(synced, NULL,
|
||||||
"Set server scan state <src_id> <bis_syncs>",
|
"Set server scan state <src_id> <bis_syncs>",
|
||||||
cmd_bap_scan_delegator_bis_synced, 3, 0),
|
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,
|
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)
|
static int add_source(struct sync_state *state)
|
||||||
{
|
{
|
||||||
struct bt_bap_scan_delegator_add_src_param param;
|
struct bt_bap_scan_delegator_add_src_param param;
|
||||||
|
struct bt_le_per_adv_sync_info sync_info;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
UNSET_FLAG(flag_recv_state_updated);
|
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.encrypt_state = BT_BAP_BIG_ENC_STATE_NO_ENC;
|
||||||
param.broadcast_id = g_broadcast_id;
|
param.broadcast_id = g_broadcast_id;
|
||||||
param.num_subgroups = 1U;
|
param.num_subgroups = 1U;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue