Skip to content

Commit 76589a7

Browse files
committed
samples: Bluetooth: CAP: Acceptor: Various fixes
The sample recently started supporting multiple sink ASEs, but only support a single sink stream. Updated the number of sink streams supported. Modified how/when we reset the requested_bis_sync and FLAG_BROADCAST_SYNC_REQUESTED in the broadcast implementation. Removed a call to bt_bap_broadcast_sink_delete that would always fail because it was already deleted. Modified how/when the total_unicast_rx_iso_packet_count and total_unicast_tx_iso_packet_count values were reset, to support a future case of CAP handover. Signed-off-by: Emil Gydesen <[email protected]>
1 parent 82c0e0d commit 76589a7

File tree

6 files changed

+62
-37
lines changed

6 files changed

+62
-37
lines changed

samples/bluetooth/cap_acceptor/Kconfig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# Copyright (c) 2022 Nordic Semiconductor ASA
1+
# Copyright (c) 2022-2025 Nordic Semiconductor ASA
22
# SPDX-License-Identifier: Apache-2.0
33

44
mainmenu "Bluetooth: Common Audio Profile Acceptor sample"
55

66
config SAMPLE_UNICAST
7-
bool "Whether or not to search for CAP acceptors for unicast audio"
7+
bool "Whether or not advertise connectable support for unicast audio"
88
default y
99
select BT_BAP_UNICAST_SERVER
1010
select BT_ISO_PERIPHERAL
@@ -19,7 +19,7 @@ config SAMPLE_UNICAST
1919
Broadcast Assistants.
2020

2121
config SAMPLE_BROADCAST
22-
bool "Whether or not to search for CAP acceptors for unicast audio"
22+
bool "Whether or not advertise connectable support for broadcast audio"
2323
default y if !SAMPLE_UNICAST
2424
select BT_BAP_SCAN_DELEGATOR
2525
select BT_OBSERVER

samples/bluetooth/cap_acceptor/src/cap_acceptor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
struct peer_config {
1919
/** Stream for the source endpoint */
2020
struct bt_cap_stream source_stream;
21-
/** Stream for the sink endpoint */
22-
struct bt_cap_stream sink_stream;
21+
/** Streams for the sink endpoint */
22+
struct bt_cap_stream sink_streams[CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT];
2323
/** Semaphore to help wait for a release operation if the source stream is not idle */
2424
struct k_sem source_stream_sem;
2525
/** Semaphore to help wait for a release operation if the sink stream is not idle */

samples/bluetooth/cap_acceptor/src/cap_acceptor_broadcast.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ static int check_start_scan(void)
100100
static void broadcast_stream_started_cb(struct bt_bap_stream *bap_stream)
101101
{
102102
LOG_INF("Started bap_stream %p", bap_stream);
103-
total_broadcast_rx_iso_packet_count = 0U;
104103

105104
atomic_clear_bit(flags, FLAG_BROADCAST_SYNCING);
106105
atomic_set_bit(flags, FLAG_BROADCAST_SYNCED);
@@ -256,11 +255,20 @@ static void syncable_cb(struct bt_bap_broadcast_sink *sink, const struct bt_iso_
256255
}
257256
}
258257

258+
static void sink_started_cb(struct bt_bap_broadcast_sink *sink)
259+
{
260+
LOG_INF("Broadcast sink started");
261+
262+
/* Clear requested BIS sync */
263+
broadcast_sink.requested_bis_sync = 0;
264+
atomic_clear_bit(flags, FLAG_BROADCAST_SYNC_REQUESTED);
265+
}
266+
259267
static void sink_stopped_cb(struct bt_bap_broadcast_sink *sink, uint8_t reason)
260268
{
261269
int err;
262270

263-
LOG_INF("Broadcast sink stopped with reason %u", reason);
271+
LOG_INF("Broadcast sink stopped with reason 0x%02X", reason);
264272

265273
err = bt_bap_broadcast_sink_delete(sink);
266274
if (err != 0) {
@@ -481,7 +489,10 @@ static int bis_sync_req_cb(struct bt_conn *conn,
481489
return -ENOMEM;
482490
}
483491

484-
if (broadcast_sink.requested_bis_sync == new_bis_sync_req) {
492+
if (atomic_test_bit(flags, FLAG_BROADCAST_SYNC_REQUESTED) &&
493+
broadcast_sink.requested_bis_sync == new_bis_sync_req) {
494+
LOG_INF("New request (0x%08x) is the same as last request; ignoring",
495+
new_bis_sync_req);
485496
return 0; /* no op */
486497
}
487498

@@ -491,6 +502,8 @@ static int bis_sync_req_cb(struct bt_conn *conn,
491502
*/
492503
int err;
493504

505+
LOG_INF("Already synced. Stopping current sync and attempt resyncing");
506+
494507
/* The stream stopped callback will be called as part of this,
495508
* and we do not need to wait for any events from the
496509
* controller. Thus, when this returns, the broadcast sink is stopped
@@ -502,13 +515,7 @@ static int bis_sync_req_cb(struct bt_conn *conn,
502515
return err;
503516
}
504517

505-
err = bt_bap_broadcast_sink_delete(broadcast_sink.bap_broadcast_sink);
506-
if (err != 0) {
507-
LOG_ERR("Failed to delete Broadcast Sink: %d", err);
508-
509-
return err;
510-
}
511-
broadcast_sink.bap_broadcast_sink = NULL;
518+
/* Broadcast sink will be deleted and set to NULL in `sink_stopped_cb` */
512519

513520
atomic_clear_bit(flags, FLAG_BROADCAST_SYNCED);
514521
}
@@ -517,8 +524,6 @@ static int bis_sync_req_cb(struct bt_conn *conn,
517524
if (broadcast_sink.requested_bis_sync != 0U) {
518525
atomic_set_bit(flags, FLAG_BROADCAST_SYNC_REQUESTED);
519526
check_sync_broadcast();
520-
} else {
521-
atomic_clear_bit(flags, FLAG_BROADCAST_SYNC_REQUESTED);
522527
}
523528

524529
return 0;
@@ -568,10 +573,9 @@ static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync,
568573
if (sync == broadcast_sink.pa_sync) {
569574
int err;
570575

571-
LOG_INF("PA sync %p lost with reason %u", (void *)sync, info->reason);
576+
LOG_INF("PA sync %p lost with reason 0x%02X", (void *)sync, info->reason);
572577

573578
/* Without PA we cannot sync to any new BIG - Clear data */
574-
broadcast_sink.requested_bis_sync = 0;
575579
broadcast_sink.pa_sync = NULL;
576580
k_work_cancel_delayable(&pa_timer);
577581
atomic_clear_bit(flags, FLAG_BROADCAST_SYNCABLE);
@@ -736,6 +740,7 @@ int init_cap_acceptor_broadcast(void)
736740
static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = {
737741
.base_recv = base_recv_cb,
738742
.syncable = syncable_cb,
743+
.started = sink_started_cb,
739744
.stopped = sink_stopped_cb,
740745
};
741746
static struct bt_bap_stream_ops broadcast_stream_ops = {

samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @file
22
* @brief Bluetooth Common Audio Profile (CAP) Acceptor unicast.
33
*
4-
* Copyright (c) 2021-2024 Nordic Semiconductor ASA
4+
* Copyright (c) 2021-2025 Nordic Semiconductor ASA
55
* Copyright (c) 2023 NXP
66
*
77
* SPDX-License-Identifier: Apache-2.0
@@ -296,7 +296,6 @@ static void unicast_stream_enabled_cb(struct bt_bap_stream *bap_stream)
296296
static void unicast_stream_started_cb(struct bt_bap_stream *bap_stream)
297297
{
298298
LOG_INF("Started bap_stream %p", bap_stream);
299-
total_unicast_rx_iso_packet_count = 0U;
300299
}
301300

302301
static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream)
@@ -438,7 +437,10 @@ int init_cap_acceptor_unicast(struct peer_config *peer)
438437
}
439438

440439
bt_cap_stream_ops_register(&peer->source_stream, &unicast_stream_ops);
441-
bt_cap_stream_ops_register(&peer->sink_stream, &unicast_stream_ops);
440+
441+
ARRAY_FOR_EACH_PTR(peer->sink_streams, stream) {
442+
bt_cap_stream_ops_register(stream, &unicast_stream_ops);
443+
}
442444

443445
if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SRC)) {
444446
static bool thread_started;
@@ -459,5 +461,8 @@ int init_cap_acceptor_unicast(struct peer_config *peer)
459461
k_sem_init(&peer->source_stream_sem, 0, 1);
460462
k_sem_init(&peer->sink_stream_sem, 0, 1);
461463

464+
total_unicast_rx_iso_packet_count = 0U;
465+
total_unicast_tx_iso_packet_count = 0U;
466+
462467
return 0;
463468
}

samples/bluetooth/cap_acceptor/src/main.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <zephyr/kernel.h>
2727
#include <zephyr/logging/log.h>
2828
#include <zephyr/logging/log_core.h>
29+
#include <zephyr/sys/__assert.h>
2930
#include <zephyr/sys/util.h>
3031
#include <zephyr/sys/util_macro.h>
3132

@@ -140,21 +141,32 @@ static int advertise(void)
140141

141142
struct bt_cap_stream *stream_alloc(enum bt_audio_dir dir)
142143
{
143-
if (dir == BT_AUDIO_DIR_SINK && peer.sink_stream.bap_stream.ep == NULL) {
144-
return &peer.sink_stream;
144+
struct bt_cap_stream *ret_stream;
145+
146+
if (dir == BT_AUDIO_DIR_SINK) {
147+
ret_stream = NULL;
148+
ARRAY_FOR_EACH_PTR(peer.sink_streams, stream) {
149+
if (stream->bap_stream.ep == NULL) {
150+
ret_stream = stream;
151+
}
152+
}
145153
} else if (dir == BT_AUDIO_DIR_SOURCE && peer.source_stream.bap_stream.ep == NULL) {
146-
return &peer.source_stream;
154+
ret_stream = &peer.source_stream;
155+
} else {
156+
ret_stream = NULL;
147157
}
148158

149-
return NULL;
159+
return ret_stream;
150160
}
151161

152162
void stream_released(const struct bt_cap_stream *cap_stream)
153163
{
154164
if (cap_stream == &peer.source_stream) {
155165
k_sem_give(&peer.source_stream_sem);
156-
} else if (cap_stream == &peer.sink_stream) {
166+
} else if (IS_ARRAY_ELEMENT(peer.sink_streams, cap_stream)) {
157167
k_sem_give(&peer.sink_stream_sem);
168+
} else {
169+
__ASSERT(false, "Invalid stream: %p", cap_stream);
158170
}
159171
}
160172

@@ -201,11 +213,13 @@ static int reset_cap_acceptor(void)
201213
}
202214
}
203215

204-
if (peer.sink_stream.bap_stream.ep != NULL) {
205-
err = k_sem_take(&peer.sink_stream_sem, SEM_TIMEOUT);
206-
if (err != 0) {
207-
LOG_ERR("Timeout on sink_stream_sem: %d", err);
208-
return err;
216+
ARRAY_FOR_EACH_PTR(peer.sink_streams, stream) {
217+
if (stream->bap_stream.ep != NULL) {
218+
err = k_sem_take(&peer.sink_stream_sem, SEM_TIMEOUT);
219+
if (err != 0) {
220+
LOG_ERR("Timeout on sink_stream_sem: %d", err);
221+
return err;
222+
}
209223
}
210224
}
211225

tests/bsim/bluetooth/audio_samples/cap/acceptor/src/cap_acceptor_sample_test.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023-2024 Nordic Semiconductor ASA
2+
* Copyright (c) 2023-2025 Nordic Semiconductor ASA
33
* Copyright (c) 2017-2019 Oticon A/S
44
*
55
* SPDX-License-Identifier: Apache-2.0
@@ -51,13 +51,14 @@ static void test_cap_acceptor_sample_tick(bs_time_t HW_device_time)
5151
extern uint64_t total_unicast_tx_iso_packet_count;
5252

5353
bs_trace_info_time(2, "%" PRIu64 " unicast packets received, expected >= %i\n",
54-
total_unicast_tx_iso_packet_count, PASS_THRESHOLD);
54+
total_unicast_rx_iso_packet_count, PASS_THRESHOLD);
5555
bs_trace_info_time(2, "%" PRIu64 " unicast packets sent, expected >= %i\n",
5656
total_unicast_tx_iso_packet_count, PASS_THRESHOLD);
5757

58-
if (total_unicast_rx_iso_packet_count < PASS_THRESHOLD ||
58+
/* Fail if we neither sent or receive any ISO packets */
59+
if (total_unicast_rx_iso_packet_count < PASS_THRESHOLD &&
5960
total_unicast_tx_iso_packet_count < PASS_THRESHOLD) {
60-
FAIL("cap_acceptor FAILED with(Did not pass after %d seconds)\n ",
61+
FAIL("cap_acceptor unicast FAILED (Did not pass after %d seconds)\n ",
6162
WAIT_TIME);
6263
return;
6364
}
@@ -70,7 +71,7 @@ static void test_cap_acceptor_sample_tick(bs_time_t HW_device_time)
7071
total_broadcast_rx_iso_packet_count, PASS_THRESHOLD);
7172

7273
if (total_broadcast_rx_iso_packet_count < PASS_THRESHOLD) {
73-
FAIL("cap_acceptor FAILED with (Did not pass after %d seconds)\n ",
74+
FAIL("cap_acceptor broadcast FAILED (Did not pass after %d seconds)\n ",
7475
WAIT_TIME);
7576
return;
7677
}

0 commit comments

Comments
 (0)