Skip to content

Commit 68d1d7d

Browse files
Thalleycarlescufi
authored andcommitted
Bluetooth: Audio: Shell: Add broadcast assistant add broadcast_id
Add command to add a source by the broadcast ID. This will initiate scanning for the broadcast ID, making it unnecessary for the user to keep track of both the broadcast ID, the SID and the address, and just focus on the (properly) known broadcast ID. Signed-off-by: Emil Gydesen <[email protected]>
1 parent d97b0e1 commit 68d1d7d

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed

subsys/bluetooth/audio/shell/bap_broadcast_assistant.c

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,24 @@
1818
#include <zephyr/bluetooth/hci.h>
1919
#include <zephyr/bluetooth/audio/audio.h>
2020
#include <zephyr/bluetooth/audio/bap.h>
21+
#include <zephyr/sys/byteorder.h>
22+
2123
#include "shell/bt.h"
2224
#include "../../host/hci_core.h"
2325
#include "audio.h"
2426

27+
#define INVALID_BROADCAST_ID 0xFFFFFFFFU
28+
2529
static struct bt_bap_base received_base;
2630

31+
static struct bt_auto_scan {
32+
uint32_t broadcast_id;
33+
bool pa_sync;
34+
struct bt_bap_scan_delegator_subgroup subgroup;
35+
} auto_scan = {
36+
.broadcast_id = INVALID_BROADCAST_ID,
37+
};
38+
2739
static bool pa_decode_base(struct bt_data *data, void *user_data)
2840
{
2941
struct bt_bap_base base = { 0 };
@@ -480,6 +492,182 @@ static int cmd_bap_broadcast_assistant_add_src(const struct shell *sh,
480492
return result;
481493
}
482494

495+
static bool broadcast_source_found(struct bt_data *data, void *user_data)
496+
{
497+
struct bt_bap_broadcast_assistant_add_src_param param = { 0 };
498+
const struct bt_le_scan_recv_info *info = user_data;
499+
struct bt_uuid_16 adv_uuid;
500+
uint32_t broadcast_id;
501+
int err;
502+
503+
/* Verify that it is a BAP broadcaster*/
504+
505+
if (data->type != BT_DATA_SVC_DATA16) {
506+
return true;
507+
}
508+
509+
if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) {
510+
return true;
511+
}
512+
513+
if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) {
514+
return true;
515+
}
516+
517+
if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO) != 0) {
518+
return true;
519+
}
520+
521+
broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16);
522+
523+
if (broadcast_id != auto_scan.broadcast_id) {
524+
/* Not the one we want */
525+
return false;
526+
}
527+
528+
shell_print(ctx_shell,
529+
"Found BAP broadcast source with addressand ID 0x%06X\n",
530+
broadcast_id);
531+
532+
bt_addr_le_copy(&param.addr, info->addr);
533+
param.adv_sid = info->sid;
534+
param.pa_interval = info->interval;
535+
param.broadcast_id = broadcast_id;
536+
param.pa_sync = auto_scan.pa_sync;
537+
param.num_subgroups = 1;
538+
param.subgroups = &auto_scan.subgroup;
539+
540+
err = bt_bap_broadcast_assistant_add_src(default_conn, &param);
541+
if (err) {
542+
shell_print(ctx_shell, "Failed to add source: %d", err);
543+
}
544+
545+
memset(&auto_scan, 0, sizeof(auto_scan));
546+
auto_scan.broadcast_id = INVALID_BROADCAST_ID;
547+
548+
return false;
549+
}
550+
551+
static void scan_recv_cb(const struct bt_le_scan_recv_info *info,
552+
struct net_buf_simple *ad)
553+
{
554+
if (auto_scan.broadcast_id == INVALID_BROADCAST_ID) {
555+
/* no op */
556+
return;
557+
}
558+
559+
/* We are only interested in non-connectable periodic advertisers */
560+
if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0 ||
561+
info->interval == 0) {
562+
return;
563+
}
564+
565+
bt_data_parse(ad, broadcast_source_found, (void *)info);
566+
}
567+
568+
static void scan_timeout_cb(void)
569+
{
570+
shell_print(ctx_shell, "Scan timeout");
571+
572+
if (auto_scan.broadcast_id != INVALID_BROADCAST_ID) {
573+
memset(&auto_scan, 0, sizeof(auto_scan));
574+
auto_scan.broadcast_id = INVALID_BROADCAST_ID;
575+
}
576+
}
577+
578+
static struct bt_le_scan_cb scan_callbacks = {
579+
.recv = scan_recv_cb,
580+
.timeout = scan_timeout_cb,
581+
};
582+
583+
static int cmd_bap_broadcast_assistant_add_broadcast_id(const struct shell *sh,
584+
size_t argc,
585+
char **argv)
586+
{
587+
struct bt_bap_scan_delegator_subgroup subgroup = { 0 };
588+
static bool scan_cbs_registered;
589+
unsigned long broadcast_id;
590+
unsigned long pa_sync;
591+
int err = 0;
592+
593+
if (!scan_cbs_registered) {
594+
bt_le_scan_cb_register(&scan_callbacks);
595+
scan_cbs_registered = true;
596+
}
597+
598+
if (auto_scan.broadcast_id != INVALID_BROADCAST_ID) {
599+
shell_info(sh, "Already scanning, wait for sync or timeout");
600+
601+
return -ENOEXEC;
602+
}
603+
604+
broadcast_id = shell_strtoul(argv[0], 0, &err);
605+
if (err != 0) {
606+
shell_error(sh, "failed to parse broadcast_id: %d", err);
607+
608+
return -ENOEXEC;
609+
} else if (broadcast_id > 0xFFFFFF /* 24 bits */) {
610+
shell_error(sh, "Broadcast ID maximum 24 bits (was %x)",
611+
broadcast_id);
612+
613+
return -ENOEXEC;
614+
}
615+
616+
pa_sync = shell_strtoul(argv[1], 0, &err);
617+
if (err != 0) {
618+
shell_error(sh, "failed to parse pa_sync: %d", err);
619+
620+
return -ENOEXEC;
621+
} else if (pa_sync != 0U && pa_sync != 1U) {
622+
shell_error(sh, "pa_sync shall be boolean: %ul", pa_sync);
623+
624+
return -ENOEXEC;
625+
}
626+
627+
/* TODO: Support multiple subgroups */
628+
if (argc > 2) {
629+
const unsigned long bis_sync = shell_strtoul(argv[2], 0, &err);
630+
631+
if (err != 0) {
632+
shell_error(sh, "failed to parse bis_sync: %d", err);
633+
634+
return -ENOEXEC;
635+
} else if (!IN_RANGE(bis_sync, 0, UINT32_MAX)) {
636+
shell_error(sh, "Invalid bis_sync: %lu", bis_sync);
637+
638+
return -ENOEXEC;
639+
}
640+
641+
subgroup.bis_sync = bis_sync;
642+
}
643+
644+
if (argc > 3) {
645+
subgroup.metadata_len = hex2bin(argv[3], strlen(argv[3]),
646+
subgroup.metadata,
647+
sizeof(subgroup.metadata));
648+
649+
if (subgroup.metadata_len == 0U) {
650+
shell_error(sh, "Could not parse metadata");
651+
652+
return -ENOEXEC;
653+
}
654+
}
655+
656+
err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
657+
if (err) {
658+
shell_print(sh, "Fail to start scanning: %d", err);
659+
660+
return -ENOEXEC;
661+
}
662+
663+
/* Store results in the `auto_scan` struct */
664+
auto_scan.broadcast_id = broadcast_id;
665+
auto_scan.pa_sync = pa_sync;
666+
memcpy(&auto_scan.subgroup, &subgroup, sizeof(subgroup));
667+
668+
return 0;
669+
}
670+
483671
static int cmd_bap_broadcast_assistant_mod_src(const struct shell *sh,
484672
size_t argc, char **argv)
485673
{
@@ -819,6 +1007,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bap_broadcast_assistant_cmds,
8191007
"<broadcast_id> [<pa_interval>] [<sync_bis>] "
8201008
"[<metadata>]",
8211009
cmd_bap_broadcast_assistant_add_src, 6, 3),
1010+
SHELL_CMD_ARG(add_broadcast_id, NULL,
1011+
"Add a source by broadcast ID <broadcast_id> <sync_pa> "
1012+
"[<sync_bis>] [<metadata>]",
1013+
cmd_bap_broadcast_assistant_add_broadcast_id, 3, 2),
8221014
SHELL_CMD_ARG(add_pa_sync, NULL,
8231015
"Add a PA sync as a source <sync_pa> <broadcast_id> "
8241016
"[bis_index [bis_index [bix_index [...]]]]>",

0 commit comments

Comments
 (0)