Bluetooth: BAP: Shell: Remove use of broadcast sink scan API
The broadcast sink scan API is no longer used by the BAP shell, which handles everything related to PA sync and scan itself now. It has also been made easier to sync to a broadcast source by simply using create_broadcast_sink. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
93ce3e14bc
commit
5b888c361d
3 changed files with 296 additions and 150 deletions
|
@ -17,36 +17,36 @@ Commands
|
|||
bap --help
|
||||
Subcommands:
|
||||
init
|
||||
select_broadcast :<stream>
|
||||
create_broadcast :[preset <preset_name>] [enc <broadcast_code>]
|
||||
start_broadcast :
|
||||
stop_broadcast :
|
||||
delete_broadcast :
|
||||
broadcast_scan :<on, off>
|
||||
accept_broadcast :0x<broadcast_id>
|
||||
sync_broadcast :0x<bis_index> [[[0x<bis_index>] 0x<bis_index>] ...]
|
||||
stop_broadcast_sink :Stops broadcast sink
|
||||
term_broadcast_sink :
|
||||
discover :[dir: sink, source]
|
||||
config :<direction: sink, source> <index> [loc <loc_bits>] [preset <preset_name>]
|
||||
stream_qos :interval [framing] [latency] [pd] [sdu] [phy] [rtn]
|
||||
qos :Send QoS configure for Unicast Group
|
||||
enable :[context]
|
||||
select_broadcast :<stream>
|
||||
create_broadcast :[preset <preset_name>] [enc <broadcast_code>]
|
||||
start_broadcast :
|
||||
stop_broadcast :
|
||||
delete_broadcast :
|
||||
broadcast_scan :<on, off>
|
||||
create_broadcast_sink :0x<broadcast_id>
|
||||
sync_broadcast :0x<bis_index> [[[0x<bis_index>] 0x<bis_index>] ...]
|
||||
stop_broadcast_sink :Stops broadcast sink
|
||||
term_broadcast_sink :
|
||||
discover :[dir: sink, source]
|
||||
config :<direction: sink, source> <index> [loc <loc_bits>] [preset <preset_name>]
|
||||
stream_qos :interval [framing] [latency] [pd] [sdu] [phy] [rtn]
|
||||
qos :Send QoS configure for Unicast Group
|
||||
enable :[context]
|
||||
stop
|
||||
print_ase_info :Print ASE info for default connection
|
||||
metadata :[context]
|
||||
print_ase_info :Print ASE info for default connection
|
||||
metadata :[context]
|
||||
start
|
||||
disable
|
||||
release
|
||||
list
|
||||
select_unicast :<stream>
|
||||
preset :<sink, source, broadcast> [preset]
|
||||
send :Send to Audio Stream [data]
|
||||
start_sine :Start sending a LC3 encoded sine wave
|
||||
stop_sine :Stop sending a LC3 encoded sine wave
|
||||
set_location :<direction: sink, source> <location bitmask>
|
||||
set_context :<direction: sink, source><context bitmask> <type:
|
||||
supported, available>
|
||||
select_unicast :<stream>
|
||||
preset :<sink, source, broadcast> [preset]
|
||||
send :Send to Audio Stream [data]
|
||||
start_sine :Start sending a LC3 encoded sine wave
|
||||
stop_sine :Stop sending a LC3 encoded sine wave
|
||||
set_location :<direction: sink, source> <location bitmask>
|
||||
set_context :<direction: sink, source><context bitmask> <type:
|
||||
supported, available>
|
||||
|
||||
|
||||
.. csv-table:: State Machine Transitions
|
||||
|
@ -139,34 +139,57 @@ Stop and release a broadcast source stream:
|
|||
|
||||
|
||||
Example Broadcast Sink
|
||||
************************
|
||||
**********************
|
||||
|
||||
Scan for and establish a broadcast sink stream:
|
||||
Scan for and establish a broadcast sink stream.
|
||||
The command :code:`bap create_broadcast_sink 0xEF6716` will either use existing periodic advertising
|
||||
sync (if exist) or start scanning and sync to the periodic advertising before syncing to the BIG.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
uart:~$ bap init
|
||||
uart:~$ bap broadcast_scan on
|
||||
Found broadcaster with ID 0xB91CD4
|
||||
uart:~$ bap accept_broadcast 0xB91CD4
|
||||
PA syncing to broadcaster
|
||||
Broadcast scan was terminated: 0
|
||||
PA synced to broadcaster with ID 0xB91CD4 as sink 0x2000d09c
|
||||
Sink 0x2000d09c is set as default
|
||||
Sink 0x2000d09c is ready to sync without encryption
|
||||
Received BASE from sink 0x2000d09c:
|
||||
Found broadcaster with ID 0xEF6716 and addr 3D:A5:F9:35:0B:19 (random) and sid 0x00
|
||||
uart:~$ bap create_broadcast_sink 0xEF6716
|
||||
Attempting to PA sync to the broadcaster
|
||||
PA synced to broadcast with broadcast ID 0xEF6716
|
||||
Attempting to sync to the BIG
|
||||
Received BASE from sink 0x20031fac:
|
||||
Presentation delay: 40000
|
||||
Subgroup count: 2
|
||||
Subgroup[0]:
|
||||
codec 0x06 cid 0x0000 vid 0x0000 count 4
|
||||
codec cfg id 0x06 cid 0x0000 vid 0x0000
|
||||
data_count 4
|
||||
data #0: type 0x01 len 1
|
||||
00000000: 03 |. |
|
||||
data #1: type 0x02 len 1
|
||||
00000000: 01 |. |
|
||||
data #2: type 0x03 len 4
|
||||
00000000: 00 00 00 |... |
|
||||
00000000: 01 00 00 00 |.... |
|
||||
data #3: type 0x04 len 2
|
||||
00000000: 28 |( |
|
||||
00000000: 28 00 |(. |
|
||||
meta_count 4
|
||||
meta #0: type 0x02 len 2
|
||||
BIS[0] index 0x01
|
||||
00000000: 01 00 |.. |
|
||||
BIS[0] index 0x01
|
||||
Subgroup[1]:
|
||||
codec cfg id 0x06 cid 0x0000 vid 0x0000
|
||||
data_count 4
|
||||
data #0: type 0x01 len 1
|
||||
00000000: 03 |. |
|
||||
data #1: type 0x02 len 1
|
||||
00000000: 01 |. |
|
||||
data #2: type 0x03 len 4
|
||||
00000000: 01 00 00 00 |.... |
|
||||
data #3: type 0x04 len 2
|
||||
00000000: 28 00 |(. |
|
||||
meta_count 4
|
||||
meta #0: type 0x02 len 2
|
||||
00000000: 01 00 |.. |
|
||||
BIS[1] index 0x01
|
||||
[0]: 0x01
|
||||
Possible indexes: 0x01
|
||||
[1]: 0x01
|
||||
Possible indexes: 0x01 0x01
|
||||
uart:~$ bap sync_broadcast 0x01
|
||||
|
||||
Stop and release a broadcast sink stream:
|
||||
|
|
|
@ -96,6 +96,15 @@ struct broadcast_source {
|
|||
struct bt_audio_codec_qos qos;
|
||||
};
|
||||
|
||||
struct broadcast_sink {
|
||||
struct bt_bap_broadcast_sink *bap_sink;
|
||||
struct bt_le_per_adv_sync *pa_sync;
|
||||
struct bt_bap_base received_base;
|
||||
uint32_t broadcast_id;
|
||||
size_t stream_cnt;
|
||||
bool syncable;
|
||||
};
|
||||
|
||||
extern struct shell_stream unicast_streams[CONFIG_BT_MAX_CONN * (UNICAST_SERVER_STREAM_COUNT +
|
||||
UNICAST_CLIENT_STREAM_COUNT)];
|
||||
|
||||
|
@ -178,9 +187,7 @@ static inline void print_codec_cfg(const struct shell *sh,
|
|||
for (size_t i = 0U; i < codec_cfg->data_count; i++) {
|
||||
shell_print(sh, "data #%u: type 0x%02x len %u", i, codec_cfg->data[i].data.type,
|
||||
codec_cfg->data[i].data.data_len);
|
||||
shell_hexdump(sh, codec_cfg->data[i].data.data,
|
||||
codec_cfg->data[i].data.data_len -
|
||||
sizeof(codec_cfg->data[i].data.type));
|
||||
shell_hexdump(sh, codec_cfg->data[i].data.data, codec_cfg->data[i].data.data_len);
|
||||
}
|
||||
#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT > 0 */
|
||||
|
||||
|
@ -189,9 +196,7 @@ static inline void print_codec_cfg(const struct shell *sh,
|
|||
for (size_t i = 0U; i < codec_cfg->meta_count; i++) {
|
||||
shell_print(sh, "meta #%u: type 0x%02x len %u", i, codec_cfg->meta[i].data.type,
|
||||
codec_cfg->meta[i].data.data_len);
|
||||
shell_hexdump(sh, codec_cfg->meta[i].data.data,
|
||||
codec_cfg->meta[i].data.data_len -
|
||||
sizeof(codec_cfg->meta[i].data.type));
|
||||
shell_hexdump(sh, codec_cfg->meta[i].data.data, codec_cfg->meta[i].data.data_len);
|
||||
}
|
||||
#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_COUNT > 0 */
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ struct broadcast_source default_source;
|
|||
#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
|
||||
#if defined(CONFIG_BT_BAP_BROADCAST_SINK)
|
||||
static struct bt_bap_stream broadcast_sink_streams[BROADCAST_SNK_STREAM_CNT];
|
||||
static struct bt_bap_broadcast_sink *default_sink;
|
||||
static struct broadcast_sink default_broadcast_sink;
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_SINK */
|
||||
static struct bt_bap_stream *default_stream;
|
||||
|
||||
|
@ -1607,46 +1607,104 @@ static int cmd_release(const struct shell *sh, size_t argc, char *argv[])
|
|||
#endif /* CONFIG_BT_BAP_UNICAST */
|
||||
|
||||
#if defined(CONFIG_BT_BAP_BROADCAST_SINK)
|
||||
static uint32_t accepted_broadcast_id;
|
||||
static struct bt_bap_base received_base;
|
||||
static bool sink_syncable;
|
||||
#define INVALID_BROADCAST_ID (BT_AUDIO_BROADCAST_ID_MAX + 1)
|
||||
#define SYNC_RETRY_COUNT 6 /* similar to retries for connections */
|
||||
#define PA_SYNC_SKIP 5
|
||||
|
||||
static bool broadcast_scan_recv(const struct bt_le_scan_recv_info *info,
|
||||
struct net_buf_simple *ad,
|
||||
uint32_t broadcast_id)
|
||||
static struct broadcast_sink_auto_scan {
|
||||
struct broadcast_sink *broadcast_sink;
|
||||
uint32_t broadcast_id;
|
||||
} auto_scan = {
|
||||
.broadcast_id = INVALID_BROADCAST_ID,
|
||||
};
|
||||
|
||||
static void clear_auto_scan(void)
|
||||
{
|
||||
char le_addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
if (!passes_scan_filter(info, ad)) {
|
||||
return false;
|
||||
if (auto_scan.broadcast_id != INVALID_BROADCAST_ID) {
|
||||
memset(&auto_scan, 0, sizeof(auto_scan));
|
||||
auto_scan.broadcast_id = INVALID_BROADCAST_ID;
|
||||
}
|
||||
}
|
||||
|
||||
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
||||
static uint16_t interval_to_sync_timeout(uint16_t interval)
|
||||
{
|
||||
uint32_t interval_ms;
|
||||
uint16_t timeout;
|
||||
|
||||
shell_print(ctx_shell, "Found broadcaster with ID 0x%06X and addr %s",
|
||||
broadcast_id, le_addr);
|
||||
/* Ensure that the following calculation does not overflow silently */
|
||||
__ASSERT(SYNC_RETRY_COUNT < 10, "SYNC_RETRY_COUNT shall be less than 10");
|
||||
|
||||
if (broadcast_id == accepted_broadcast_id) {
|
||||
shell_print(ctx_shell, "PA syncing to broadcaster");
|
||||
accepted_broadcast_id = 0;
|
||||
/* Add retries and convert to unit in 10's of ms */
|
||||
interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(interval);
|
||||
timeout = (interval_ms * SYNC_RETRY_COUNT) / 10;
|
||||
|
||||
/* Enforce restraints */
|
||||
timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data)
|
||||
{
|
||||
const struct bt_le_scan_recv_info *info = user_data;
|
||||
char le_addr[BT_ADDR_LE_STR_LEN];
|
||||
struct bt_uuid_16 adv_uuid;
|
||||
uint32_t broadcast_id;
|
||||
|
||||
if (data->type != BT_DATA_SVC_DATA16) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16);
|
||||
|
||||
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
||||
|
||||
shell_print(ctx_shell, "Found broadcaster with ID 0x%06X and addr %s and sid 0x%02X",
|
||||
broadcast_id, le_addr, info->sid);
|
||||
|
||||
if (auto_scan.broadcast_id == broadcast_id && auto_scan.broadcast_sink != NULL &&
|
||||
auto_scan.broadcast_sink->pa_sync == NULL) {
|
||||
struct bt_le_per_adv_sync_param create_params = {0};
|
||||
int err;
|
||||
|
||||
err = bt_le_scan_stop();
|
||||
if (err != 0) {
|
||||
shell_error(ctx_shell, "Could not stop scan: %d", err);
|
||||
}
|
||||
|
||||
bt_addr_le_copy(&create_params.addr, info->addr);
|
||||
create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE;
|
||||
create_params.sid = info->sid;
|
||||
create_params.skip = PA_SYNC_SKIP;
|
||||
create_params.timeout = interval_to_sync_timeout(info->interval);
|
||||
|
||||
shell_print(ctx_shell, "Attempting to PA sync to the broadcaster");
|
||||
err = bt_le_per_adv_sync_create(&create_params, &auto_scan.broadcast_sink->pa_sync);
|
||||
if (err != 0) {
|
||||
shell_error(ctx_shell, "Could not create Broadcast PA sync: %d", err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop parsing */
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pa_synced(struct bt_bap_broadcast_sink *sink,
|
||||
struct bt_le_per_adv_sync *sync,
|
||||
uint32_t broadcast_id)
|
||||
static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad)
|
||||
{
|
||||
shell_print(ctx_shell,
|
||||
"PA synced to broadcaster with ID 0x%06X as sink %p",
|
||||
broadcast_id, sink);
|
||||
|
||||
if (default_sink == NULL) {
|
||||
default_sink = sink;
|
||||
|
||||
shell_print(ctx_shell, "Sink %p is set as default", sink);
|
||||
if (passes_scan_filter(info, ad)) {
|
||||
bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)info);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1657,13 +1715,15 @@ static void base_recv(struct bt_bap_broadcast_sink *sink, const struct bt_bap_ba
|
|||
char bis_indexes_str[5 * ARRAY_SIZE(bis_indexes) + 1];
|
||||
size_t index_count = 0;
|
||||
|
||||
if (memcmp(base, &received_base, sizeof(received_base)) == 0) {
|
||||
if (memcmp(base, &default_broadcast_sink.received_base,
|
||||
sizeof(default_broadcast_sink.received_base)) == 0) {
|
||||
/* Don't print duplicates */
|
||||
return;
|
||||
}
|
||||
|
||||
shell_print(ctx_shell, "Received BASE from sink %p:", sink);
|
||||
shell_print(ctx_shell, "Presentation delay: %u", base->pd);
|
||||
shell_print(ctx_shell, "Subgroup count: %u", base->subgroup_count);
|
||||
|
||||
for (int i = 0; i < base->subgroup_count; i++) {
|
||||
const struct bt_bap_base_subgroup *subgroup;
|
||||
|
@ -1708,46 +1768,79 @@ static void base_recv(struct bt_bap_broadcast_sink *sink, const struct bt_bap_ba
|
|||
|
||||
shell_print(ctx_shell, "Possible indexes: %s", bis_indexes_str);
|
||||
|
||||
(void)memcpy(&received_base, base, sizeof(received_base));
|
||||
(void)memcpy(&default_broadcast_sink.received_base, base,
|
||||
sizeof(default_broadcast_sink.received_base));
|
||||
}
|
||||
|
||||
static void syncable(struct bt_bap_broadcast_sink *sink, bool encrypted)
|
||||
{
|
||||
if (sink_syncable) {
|
||||
return;
|
||||
}
|
||||
if (default_broadcast_sink.bap_sink == sink) {
|
||||
if (default_broadcast_sink.syncable) {
|
||||
return;
|
||||
}
|
||||
|
||||
shell_print(ctx_shell, "Sink %p is ready to sync %s encryption",
|
||||
sink, encrypted ? "with" : "without");
|
||||
sink_syncable = true;
|
||||
}
|
||||
|
||||
static void scan_term(int err)
|
||||
{
|
||||
shell_print(ctx_shell, "Broadcast scan was terminated: %d", err);
|
||||
|
||||
}
|
||||
|
||||
static void pa_sync_lost(struct bt_bap_broadcast_sink *sink)
|
||||
{
|
||||
shell_warn(ctx_shell, "Sink %p disconnected", sink);
|
||||
|
||||
if (default_sink == sink) {
|
||||
default_sink = NULL;
|
||||
sink_syncable = false;
|
||||
(void)memset(&received_base, 0, sizeof(received_base));
|
||||
shell_print(ctx_shell, "Sink %p is ready to sync %s encryption", sink,
|
||||
encrypted ? "with" : "without");
|
||||
default_broadcast_sink.syncable = true;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_SINK */
|
||||
|
||||
#if defined(CONFIG_BT_BAP_BROADCAST_SINK)
|
||||
static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync,
|
||||
struct bt_le_per_adv_sync_synced_info *info)
|
||||
{
|
||||
if (auto_scan.broadcast_sink != NULL && sync == auto_scan.broadcast_sink->pa_sync) {
|
||||
shell_print(ctx_shell, "PA synced to broadcast with broadcast ID 0x%06x",
|
||||
auto_scan.broadcast_id);
|
||||
|
||||
if (auto_scan.broadcast_sink->bap_sink == NULL) {
|
||||
shell_print(ctx_shell, "Attempting to sync to the BIG");
|
||||
int err;
|
||||
|
||||
err = bt_bap_broadcast_sink_create(sync, auto_scan.broadcast_id,
|
||||
&auto_scan.broadcast_sink->bap_sink);
|
||||
if (err != 0) {
|
||||
shell_error(ctx_shell, "Could not create broadcast sink: %d", err);
|
||||
}
|
||||
} else {
|
||||
shell_print(ctx_shell, "BIG is already synced");
|
||||
}
|
||||
}
|
||||
|
||||
clear_auto_scan();
|
||||
}
|
||||
|
||||
static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync,
|
||||
const struct bt_le_per_adv_sync_term_info *info)
|
||||
{
|
||||
if (default_broadcast_sink.pa_sync == sync) {
|
||||
default_broadcast_sink.syncable = false;
|
||||
(void)memset(&default_broadcast_sink.received_base, 0,
|
||||
sizeof(default_broadcast_sink.received_base));
|
||||
}
|
||||
|
||||
clear_auto_scan();
|
||||
}
|
||||
|
||||
static void broadcast_scan_timeout_cb(void)
|
||||
{
|
||||
shell_print(ctx_shell, "Scan timeout");
|
||||
|
||||
clear_auto_scan();
|
||||
}
|
||||
|
||||
static struct bt_bap_broadcast_sink_cb sink_cbs = {
|
||||
.scan_recv = broadcast_scan_recv,
|
||||
.pa_synced = pa_synced,
|
||||
.base_recv = base_recv,
|
||||
.syncable = syncable,
|
||||
.scan_term = scan_term,
|
||||
.pa_sync_lost = pa_sync_lost,
|
||||
};
|
||||
|
||||
static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = {
|
||||
.synced = bap_pa_sync_synced_cb,
|
||||
.term = bap_pa_sync_terminated_cb,
|
||||
};
|
||||
|
||||
static struct bt_le_scan_cb bap_scan_cb = {
|
||||
.timeout = broadcast_scan_timeout_cb,
|
||||
.recv = broadcast_scan_recv,
|
||||
};
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_SINK */
|
||||
|
||||
|
@ -1858,6 +1951,24 @@ static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
|
|||
#if defined(CONFIG_LIBLC3)
|
||||
clear_lc3_sine_data(stream);
|
||||
#endif /* CONFIG_LIBLC3 */
|
||||
|
||||
#if defined(CONFIG_BT_BAP_BROADCAST_SINK)
|
||||
if (IS_ARRAY_ELEMENT(broadcast_sink_streams, stream)) {
|
||||
if (default_broadcast_sink.stream_cnt != 0) {
|
||||
default_broadcast_sink.stream_cnt--;
|
||||
}
|
||||
|
||||
if (default_broadcast_sink.stream_cnt == 0) {
|
||||
/* All streams in the broadcast sink has been terminated */
|
||||
default_broadcast_sink.syncable = true;
|
||||
default_broadcast_sink.bap_sink = NULL;
|
||||
memset(&default_broadcast_sink.received_base, 0,
|
||||
sizeof(default_broadcast_sink.received_base));
|
||||
default_broadcast_sink.broadcast_id = 0;
|
||||
default_broadcast_sink.syncable = false;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_SINK */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_BAP_UNICAST)
|
||||
|
@ -2107,42 +2218,9 @@ static int cmd_delete_broadcast(const struct shell *sh, size_t argc,
|
|||
#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
|
||||
|
||||
#if defined(CONFIG_BT_BAP_BROADCAST_SINK)
|
||||
static int cmd_broadcast_scan(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
int err;
|
||||
struct bt_le_scan_param param = {
|
||||
.type = BT_LE_SCAN_TYPE_ACTIVE,
|
||||
.options = BT_LE_SCAN_OPT_NONE,
|
||||
.interval = BT_GAP_SCAN_FAST_INTERVAL,
|
||||
.window = BT_GAP_SCAN_FAST_WINDOW,
|
||||
.timeout = 0 };
|
||||
|
||||
if (!initialized) {
|
||||
shell_error(sh, "Not initialized");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "on") == 0) {
|
||||
err = bt_bap_broadcast_sink_scan_start(¶m);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Could not start scan: %d", err);
|
||||
}
|
||||
} else if (strcmp(argv[1], "off") == 0) {
|
||||
err = bt_bap_broadcast_sink_scan_stop();
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Could not stop scan: %d", err);
|
||||
}
|
||||
} else {
|
||||
shell_help(sh);
|
||||
err = -ENOEXEC;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cmd_accept_broadcast(const struct shell *sh, size_t argc,
|
||||
char *argv[])
|
||||
static int cmd_create_broadcast_sink(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
struct bt_le_per_adv_sync *per_adv_sync = per_adv_syncs[selected_per_adv_sync];
|
||||
unsigned long broadcast_id;
|
||||
int err = 0;
|
||||
|
||||
|
@ -2159,7 +2237,39 @@ static int cmd_accept_broadcast(const struct shell *sh, size_t argc,
|
|||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
accepted_broadcast_id = broadcast_id;
|
||||
if (per_adv_sync == NULL) {
|
||||
const struct bt_le_scan_param param = {
|
||||
.type = BT_LE_SCAN_TYPE_ACTIVE,
|
||||
.options = BT_LE_SCAN_OPT_NONE,
|
||||
.interval = BT_GAP_SCAN_FAST_INTERVAL,
|
||||
.window = BT_GAP_SCAN_FAST_WINDOW,
|
||||
.timeout = 1000, /* 10ms units -> 10 second timeout */
|
||||
};
|
||||
|
||||
shell_print(sh, "No PA sync available, starting scanning for broadcast_id");
|
||||
|
||||
err = bt_le_scan_start(¶m, NULL);
|
||||
if (err) {
|
||||
shell_print(sh, "Fail to start scanning: %d", err);
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
auto_scan.broadcast_sink = &default_broadcast_sink;
|
||||
auto_scan.broadcast_id = broadcast_id;
|
||||
} else {
|
||||
shell_print(sh, "Creating broadcast sink with broadcast ID 0x%06X",
|
||||
(uint32_t)broadcast_id);
|
||||
|
||||
err = bt_bap_broadcast_sink_create(per_adv_sync, (uint32_t)broadcast_id,
|
||||
&default_broadcast_sink.bap_sink);
|
||||
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to create broadcast sink: %d", err);
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2168,9 +2278,11 @@ static int cmd_sync_broadcast(const struct shell *sh, size_t argc, char *argv[])
|
|||
{
|
||||
struct bt_bap_stream *streams[ARRAY_SIZE(broadcast_sink_streams)];
|
||||
uint32_t bis_bitfield;
|
||||
size_t stream_cnt;
|
||||
int err;
|
||||
|
||||
bis_bitfield = 0;
|
||||
stream_cnt = 0U;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
unsigned long val;
|
||||
int err = 0;
|
||||
|
@ -2192,9 +2304,10 @@ static int cmd_sync_broadcast(const struct shell *sh, size_t argc, char *argv[])
|
|||
}
|
||||
|
||||
bis_bitfield |= BIT(val);
|
||||
stream_cnt++;
|
||||
}
|
||||
|
||||
if (default_sink == NULL) {
|
||||
if (default_broadcast_sink.bap_sink == NULL) {
|
||||
shell_error(sh, "No sink available");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
@ -2204,12 +2317,15 @@ static int cmd_sync_broadcast(const struct shell *sh, size_t argc, char *argv[])
|
|||
streams[i] = &broadcast_sink_streams[i];
|
||||
}
|
||||
|
||||
err = bt_bap_broadcast_sink_sync(default_sink, bis_bitfield, streams, NULL);
|
||||
err = bt_bap_broadcast_sink_sync(default_broadcast_sink.bap_sink, bis_bitfield, streams,
|
||||
NULL);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to sync to broadcast: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
default_broadcast_sink.stream_cnt = stream_cnt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2218,12 +2334,12 @@ static int cmd_stop_broadcast_sink(const struct shell *sh, size_t argc,
|
|||
{
|
||||
int err;
|
||||
|
||||
if (default_sink == NULL) {
|
||||
if (default_broadcast_sink.bap_sink == NULL) {
|
||||
shell_error(sh, "No sink available");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
err = bt_bap_broadcast_sink_stop(default_sink);
|
||||
err = bt_bap_broadcast_sink_stop(default_broadcast_sink.bap_sink);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to stop sink: %d", err);
|
||||
return err;
|
||||
|
@ -2237,19 +2353,19 @@ static int cmd_term_broadcast_sink(const struct shell *sh, size_t argc,
|
|||
{
|
||||
int err;
|
||||
|
||||
if (default_sink == NULL) {
|
||||
if (default_broadcast_sink.bap_sink == NULL) {
|
||||
shell_error(sh, "No sink available");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
err = bt_bap_broadcast_sink_delete(default_sink);
|
||||
err = bt_bap_broadcast_sink_delete(default_broadcast_sink.bap_sink);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to term sink: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
default_sink = NULL;
|
||||
sink_syncable = false;
|
||||
default_broadcast_sink.bap_sink = NULL;
|
||||
default_broadcast_sink.syncable = false;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -2420,6 +2536,8 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
|
|||
|
||||
#if defined(CONFIG_BT_BAP_BROADCAST_SINK)
|
||||
bt_bap_broadcast_sink_register_cb(&sink_cbs);
|
||||
bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb);
|
||||
bt_le_scan_cb_register(&bap_scan_cb);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(broadcast_sink_streams); i++) {
|
||||
bt_bap_stream_cb_register(&broadcast_sink_streams[i],
|
||||
|
@ -2737,8 +2855,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
|
|||
SHELL_CMD_ARG(delete_broadcast, NULL, "", cmd_delete_broadcast, 1, 0),
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
|
||||
#if defined(CONFIG_BT_BAP_BROADCAST_SINK)
|
||||
SHELL_CMD_ARG(broadcast_scan, NULL, "<on, off>", cmd_broadcast_scan, 2, 0),
|
||||
SHELL_CMD_ARG(accept_broadcast, NULL, "0x<broadcast_id>", cmd_accept_broadcast, 2, 0),
|
||||
SHELL_CMD_ARG(create_broadcast_sink, NULL, "0x<broadcast_id>", cmd_create_broadcast_sink, 2,
|
||||
0),
|
||||
SHELL_CMD_ARG(sync_broadcast, NULL, "0x<bis_index> [[[0x<bis_index>] 0x<bis_index>] ...]",
|
||||
cmd_sync_broadcast, 2, ARRAY_SIZE(broadcast_sink_streams) - 1),
|
||||
SHELL_CMD_ARG(stop_broadcast_sink, NULL, "Stops broadcast sink", cmd_stop_broadcast_sink, 1,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue