1 /* Bluetooth BAP Broadcast Assistant */
2
3 /*
4 * Copyright (c) 2019 Bose Corporation
5 * Copyright (c) 2022-2023 Nordic Semiconductor ASA
6 * Copyright (c) 2024 Demant A/S
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #include <errno.h>
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 #include <string.h>
16
17 #include <zephyr/autoconf.h>
18 #include <zephyr/bluetooth/addr.h>
19 #include <zephyr/bluetooth/audio/audio.h>
20 #include <zephyr/bluetooth/audio/bap.h>
21 #include <zephyr/bluetooth/bluetooth.h>
22 #include <zephyr/bluetooth/conn.h>
23 #include <zephyr/bluetooth/gap.h>
24 #include <zephyr/bluetooth/gatt.h>
25 #include <zephyr/bluetooth/att.h>
26 #include <zephyr/bluetooth/hci_types.h>
27 #include <zephyr/bluetooth/iso.h>
28 #include <zephyr/bluetooth/l2cap.h>
29 #include <zephyr/bluetooth/buf.h>
30 #include <zephyr/bluetooth/uuid.h>
31 #include <zephyr/device.h>
32 #include <zephyr/init.h>
33 #include <zephyr/kernel.h>
34 #include <zephyr/net_buf.h>
35 #include <zephyr/sys/__assert.h>
36 #include <zephyr/sys/atomic.h>
37 #include <zephyr/sys/byteorder.h>
38 #include <zephyr/sys/check.h>
39 #include <zephyr/sys/slist.h>
40 #include <zephyr/sys/util.h>
41 #include <zephyr/sys/util_macro.h>
42 #include <zephyr/types.h>
43
44 #include <zephyr/logging/log.h>
45 #include <sys/errno.h>
46
47 LOG_MODULE_REGISTER(bt_bap_broadcast_assistant, CONFIG_BT_BAP_BROADCAST_ASSISTANT_LOG_LEVEL);
48
49 #include "common/bt_str.h"
50
51 #include "audio_internal.h"
52 #include "bap_internal.h"
53
54 #define MINIMUM_RECV_STATE_LEN 15
55
56 struct bap_broadcast_assistant_recv_state_info {
57 uint8_t src_id;
58 /** Cached PAST available */
59 bool past_avail;
60 uint8_t adv_sid;
61 uint32_t broadcast_id;
62 bt_addr_le_t addr;
63 };
64
65 enum bap_broadcast_assistant_flag {
66 BAP_BA_FLAG_BUSY,
67 BAP_BA_FLAG_DISCOVER_IN_PROGRESS,
68 BAP_BA_FLAG_SCANNING,
69
70 BAP_BA_FLAG_NUM_FLAGS, /* keep as last */
71 };
72
73 struct bap_broadcast_assistant_instance {
74 struct bt_conn *conn;
75 bool scanning;
76 uint8_t pa_sync;
77 uint8_t recv_state_cnt;
78
79 uint16_t start_handle;
80 uint16_t end_handle;
81 uint16_t cp_handle;
82 uint16_t recv_state_handles[CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT];
83
84 struct bt_gatt_subscribe_params recv_state_sub_params
85 [CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT];
86 struct bt_gatt_discover_params
87 recv_state_disc_params[CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT];
88
89 /* We ever only allow a single outstanding operation per instance, so we can resuse the
90 * memory for the GATT params
91 */
92 union {
93 struct bt_gatt_read_params read_params;
94 struct bt_gatt_write_params write_params;
95 struct bt_gatt_discover_params disc_params;
96 };
97
98 struct k_work_delayable bap_read_work;
99 uint16_t long_read_handle;
100
101 struct bap_broadcast_assistant_recv_state_info
102 recv_states[CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT];
103
104 ATOMIC_DEFINE(flags, BAP_BA_FLAG_NUM_FLAGS);
105 };
106
107 static sys_slist_t broadcast_assistant_cbs = SYS_SLIST_STATIC_INIT(&broadcast_assistant_cbs);
108
109 static struct bap_broadcast_assistant_instance broadcast_assistants[CONFIG_BT_MAX_CONN];
110 static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0);
111
112 #define ATT_BUF_SIZE BT_ATT_MAX_ATTRIBUTE_LEN
113 NET_BUF_SIMPLE_DEFINE_STATIC(att_buf, ATT_BUF_SIZE);
114
115 static int read_recv_state(struct bap_broadcast_assistant_instance *inst, uint8_t idx);
116
lookup_index_by_handle(struct bap_broadcast_assistant_instance * inst,uint16_t handle)117 static int16_t lookup_index_by_handle(struct bap_broadcast_assistant_instance *inst,
118 uint16_t handle)
119 {
120 for (size_t i = 0U; i < ARRAY_SIZE(inst->recv_state_handles); i++) {
121 if (inst->recv_state_handles[i] == handle) {
122 return i;
123 }
124 }
125
126 LOG_ERR("Unknown handle 0x%04x", handle);
127
128 return -1;
129 }
130
inst_by_conn(struct bt_conn * conn)131 static struct bap_broadcast_assistant_instance *inst_by_conn(struct bt_conn *conn)
132 {
133 struct bap_broadcast_assistant_instance *inst;
134
135 if (conn == NULL) {
136 LOG_DBG("NULL conn");
137 return NULL;
138 }
139
140 inst = &broadcast_assistants[bt_conn_index(conn)];
141
142 if (inst->conn == conn) {
143 return inst;
144 }
145
146 return NULL;
147 }
148
bap_broadcast_assistant_discover_complete(struct bt_conn * conn,int err,uint8_t recv_state_count)149 static void bap_broadcast_assistant_discover_complete(struct bt_conn *conn, int err,
150 uint8_t recv_state_count)
151 {
152 struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn);
153 struct bt_bap_broadcast_assistant_cb *listener, *next;
154
155 net_buf_simple_reset(&att_buf);
156 if (inst != NULL) {
157 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
158 atomic_clear_bit(inst->flags, BAP_BA_FLAG_DISCOVER_IN_PROGRESS);
159 }
160
161 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&broadcast_assistant_cbs,
162 listener, next, _node) {
163 if (listener->discover) {
164 listener->discover(conn, err, recv_state_count);
165 }
166 }
167 }
168
bap_broadcast_assistant_recv_state_changed(struct bt_conn * conn,int err,const struct bt_bap_scan_delegator_recv_state * state)169 static void bap_broadcast_assistant_recv_state_changed(
170 struct bt_conn *conn, int err, const struct bt_bap_scan_delegator_recv_state *state)
171 {
172 struct bt_bap_broadcast_assistant_cb *listener, *next;
173
174 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&broadcast_assistant_cbs,
175 listener, next, _node) {
176 if (listener->recv_state) {
177 listener->recv_state(conn, err, state);
178 }
179 }
180 }
181
bap_broadcast_assistant_recv_state_removed(struct bt_conn * conn,uint8_t src_id)182 static void bap_broadcast_assistant_recv_state_removed(struct bt_conn *conn, uint8_t src_id)
183 {
184 struct bt_bap_broadcast_assistant_cb *listener, *next;
185
186 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&broadcast_assistant_cbs,
187 listener, next, _node) {
188 if (listener->recv_state_removed) {
189 listener->recv_state_removed(conn, src_id);
190 }
191 }
192 }
193
bap_broadcast_assistant_scan_results(const struct bt_le_scan_recv_info * info,uint32_t broadcast_id)194 static void bap_broadcast_assistant_scan_results(const struct bt_le_scan_recv_info *info,
195 uint32_t broadcast_id)
196 {
197 struct bt_bap_broadcast_assistant_cb *listener, *next;
198
199 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&broadcast_assistant_cbs, listener, next, _node) {
200 if (listener->scan) {
201 listener->scan(info, broadcast_id);
202 }
203 }
204 }
205
past_available(const struct bt_conn * conn,const bt_addr_le_t * adv_addr,uint8_t sid)206 static bool past_available(const struct bt_conn *conn,
207 const bt_addr_le_t *adv_addr,
208 uint8_t sid)
209 {
210 if (IS_ENABLED(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER)) {
211 struct bt_le_local_features local_features;
212 struct bt_conn_remote_info remote_info;
213 int err;
214
215 err = bt_le_get_local_features(&local_features);
216 if (err != 0) {
217 LOG_DBG("Failed to get local features: %d", err);
218 return false;
219 }
220
221 err = bt_conn_get_remote_info(conn, &remote_info);
222 if (err != 0) {
223 LOG_DBG("Failed to get remote info: %d", err);
224 return false;
225 }
226
227 LOG_DBG("%p remote %s PAST, local %s PAST", (void *)conn,
228 BT_FEAT_LE_PAST_RECV(remote_info.le.features) ? "supports"
229 : "does not support",
230 BT_FEAT_LE_PAST_SEND(local_features.features) ? "supports"
231 : "does not support");
232
233 return BT_FEAT_LE_PAST_RECV(remote_info.le.features) &&
234 BT_FEAT_LE_PAST_SEND(local_features.features) &&
235 bt_le_per_adv_sync_lookup_addr(adv_addr, sid) != NULL;
236 } else {
237 return false;
238 }
239 }
240
parse_recv_state(const void * data,uint16_t length,struct bt_bap_scan_delegator_recv_state * recv_state)241 static int parse_recv_state(const void *data, uint16_t length,
242 struct bt_bap_scan_delegator_recv_state *recv_state)
243 {
244 struct net_buf_simple buf;
245 bt_addr_t *addr;
246
247 __ASSERT(recv_state, "NULL receive state");
248
249 if (data == NULL || length == 0) {
250 LOG_DBG("NULL data");
251 return -EINVAL;
252 }
253
254 if (length < MINIMUM_RECV_STATE_LEN) {
255 LOG_DBG("Invalid receive state length %u, expected at least %u",
256 length, MINIMUM_RECV_STATE_LEN);
257 return -EINVAL;
258 }
259
260 net_buf_simple_init_with_data(&buf, (void *)data, length);
261
262 (void)memset(recv_state, 0, sizeof(*recv_state));
263
264 recv_state->src_id = net_buf_simple_pull_u8(&buf);
265 recv_state->addr.type = net_buf_simple_pull_u8(&buf);
266 addr = net_buf_simple_pull_mem(&buf, sizeof(*addr));
267 bt_addr_copy(&recv_state->addr.a, addr);
268 recv_state->adv_sid = net_buf_simple_pull_u8(&buf);
269 recv_state->broadcast_id = net_buf_simple_pull_le24(&buf);
270 recv_state->pa_sync_state = net_buf_simple_pull_u8(&buf);
271 recv_state->encrypt_state = net_buf_simple_pull_u8(&buf);
272 if (recv_state->encrypt_state == BT_BAP_BIG_ENC_STATE_BAD_CODE) {
273 uint8_t *broadcast_code;
274 const size_t minimum_size = sizeof(recv_state->bad_code) +
275 sizeof(recv_state->num_subgroups);
276
277 if (buf.len < minimum_size) {
278 LOG_DBG("Invalid receive state length %u, expected at least %zu",
279 buf.len, minimum_size);
280 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
281 }
282
283 broadcast_code = net_buf_simple_pull_mem(&buf, BT_ISO_BROADCAST_CODE_SIZE);
284 (void)memcpy(recv_state->bad_code, broadcast_code,
285 sizeof(recv_state->bad_code));
286 }
287
288 recv_state->num_subgroups = net_buf_simple_pull_u8(&buf);
289 if (recv_state->num_subgroups > CONFIG_BT_BAP_BASS_MAX_SUBGROUPS) {
290 LOG_DBG("Cannot parse %u subgroups (max %d)", recv_state->num_subgroups,
291 CONFIG_BT_BAP_BASS_MAX_SUBGROUPS);
292
293 return -ENOMEM;
294 }
295
296 for (int i = 0; i < recv_state->num_subgroups; i++) {
297 struct bt_bap_bass_subgroup *subgroup = &recv_state->subgroups[i];
298 uint8_t *metadata;
299
300 if (buf.len < sizeof(subgroup->bis_sync)) {
301 LOG_DBG("Invalid receive state length %u, expected at least %zu",
302 buf.len, buf.len + sizeof(subgroup->bis_sync));
303 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
304 }
305
306 subgroup->bis_sync = net_buf_simple_pull_le32(&buf);
307
308 if (buf.len < sizeof(subgroup->metadata_len)) {
309 LOG_DBG("Invalid receive state length %u, expected at least %zu",
310 buf.len, buf.len + sizeof(subgroup->metadata_len));
311 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
312 }
313 subgroup->metadata_len = net_buf_simple_pull_u8(&buf);
314
315 if (buf.len < subgroup->metadata_len) {
316 LOG_DBG("Invalid receive state length %u, expected at least %u",
317 buf.len, buf.len + subgroup->metadata_len);
318 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
319 }
320
321 if (subgroup->metadata_len > sizeof(subgroup->metadata)) {
322 LOG_DBG("Metadata too long: %u/%zu",
323 subgroup->metadata_len,
324 sizeof(subgroup->metadata));
325 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
326 }
327
328 metadata = net_buf_simple_pull_mem(&buf,
329 subgroup->metadata_len);
330 (void)memcpy(subgroup->metadata, metadata,
331 subgroup->metadata_len);
332 }
333
334 if (buf.len != 0) {
335 LOG_DBG("Invalid receive state length %u, but only %u was parsed",
336 length, length - buf.len);
337 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
338 }
339
340 return 0;
341 }
342
bap_long_read_reset(struct bap_broadcast_assistant_instance * inst)343 static void bap_long_read_reset(struct bap_broadcast_assistant_instance *inst)
344 {
345 inst->long_read_handle = 0;
346 net_buf_simple_reset(&att_buf);
347 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
348 }
349
parse_and_send_recv_state(struct bt_conn * conn,uint16_t handle,const void * data,uint16_t length,struct bt_bap_scan_delegator_recv_state * recv_state)350 static uint8_t parse_and_send_recv_state(struct bt_conn *conn, uint16_t handle,
351 const void *data, uint16_t length,
352 struct bt_bap_scan_delegator_recv_state *recv_state)
353 {
354 int err;
355 int16_t index;
356 struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn);
357
358 if (inst == NULL) {
359 return BT_GATT_ITER_STOP;
360 }
361
362 err = parse_recv_state(data, length, recv_state);
363 if (err != 0) {
364 LOG_WRN("Invalid receive state received");
365
366 return BT_GATT_ITER_STOP;
367 }
368
369 index = lookup_index_by_handle(inst, handle);
370 if (index < 0) {
371 LOG_DBG("Invalid index");
372
373 return BT_GATT_ITER_STOP;
374 }
375
376 inst->recv_states[index].src_id = recv_state->src_id;
377 inst->recv_states[index].past_avail = past_available(conn, &recv_state->addr,
378 recv_state->adv_sid);
379
380 bap_broadcast_assistant_recv_state_changed(conn, 0, recv_state);
381
382 return BT_GATT_ITER_CONTINUE;
383 }
384
broadcast_assistant_bap_ntf_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)385 static uint8_t broadcast_assistant_bap_ntf_read_func(struct bt_conn *conn, uint8_t err,
386 struct bt_gatt_read_params *read,
387 const void *data, uint16_t length)
388 {
389 struct bt_bap_scan_delegator_recv_state recv_state;
390 uint16_t handle = read->single.handle;
391 uint16_t data_length;
392 struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn);
393
394 if (inst == NULL) {
395 return BT_GATT_ITER_STOP;
396 }
397
398 LOG_DBG("conn %p err 0x%02x len %u", (void *)conn, err, length);
399
400 if (err) {
401 LOG_DBG("Failed to read: %u", err);
402 memset(read, 0, sizeof(*read));
403 bap_long_read_reset(inst);
404
405 return BT_GATT_ITER_STOP;
406 }
407
408 LOG_DBG("handle 0x%04x", handle);
409
410 if (data != NULL) {
411 if (net_buf_simple_tailroom(&att_buf) < length) {
412 LOG_DBG("Buffer full, invalid server response of size %u",
413 length + att_buf.len);
414 memset(read, 0, sizeof(*read));
415 bap_long_read_reset(inst);
416
417 return BT_GATT_ITER_STOP;
418 }
419
420 /* store data*/
421 net_buf_simple_add_mem(&att_buf, data, length);
422
423 return BT_GATT_ITER_CONTINUE;
424 }
425
426 /* we reset the buffer so that it is ready for new data */
427 memset(read, 0, sizeof(*read));
428 data_length = att_buf.len;
429 bap_long_read_reset(inst);
430
431 /* do the parse and callback to send notify to application*/
432 parse_and_send_recv_state(conn, handle, att_buf.data, data_length, &recv_state);
433
434 return BT_GATT_ITER_STOP;
435 }
436
long_bap_read(struct bt_conn * conn,uint16_t handle)437 static void long_bap_read(struct bt_conn *conn, uint16_t handle)
438 {
439 int err;
440 struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn);
441
442 if (inst == NULL) {
443 return;
444 }
445
446 if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
447 LOG_DBG("conn %p", (void *)conn);
448
449 /* If the client is busy reading reschedule the long read */
450 struct bt_conn_info conn_info;
451
452 err = bt_conn_get_info(conn, &conn_info);
453 if (err != 0) {
454 LOG_DBG("Failed to get conn info, use default interval");
455
456 conn_info.le.interval = BT_GAP_INIT_CONN_INT_MIN;
457 }
458
459 /* Wait a connection interval to retry */
460 err = k_work_reschedule(&inst->bap_read_work,
461 K_USEC(BT_CONN_INTERVAL_TO_US(conn_info.le.interval)));
462 if (err < 0) {
463 LOG_DBG("Failed to reschedule read work: %d", err);
464 bap_long_read_reset(inst);
465 }
466
467 return;
468 }
469
470 inst->read_params.func = broadcast_assistant_bap_ntf_read_func;
471 inst->read_params.handle_count = 1U;
472 inst->read_params.single.handle = handle;
473 inst->read_params.single.offset = att_buf.len;
474
475 err = bt_gatt_read(conn, &inst->read_params);
476 if (err != 0) {
477 /* TODO: If read failed due to buffers, retry */
478 LOG_DBG("Failed to read: %d", err);
479 bap_long_read_reset(inst);
480 }
481 }
482
delayed_bap_read_handler(struct k_work * work)483 static void delayed_bap_read_handler(struct k_work *work)
484 {
485 struct bap_broadcast_assistant_instance *inst =
486 CONTAINER_OF((struct k_work_delayable *)work,
487 struct bap_broadcast_assistant_instance, bap_read_work);
488 long_bap_read(inst->conn, inst->long_read_handle);
489 }
490
491 /** @brief Handles notifications and indications from the server */
notify_handler(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)492 static uint8_t notify_handler(struct bt_conn *conn,
493 struct bt_gatt_subscribe_params *params,
494 const void *data, uint16_t length)
495 {
496 uint16_t handle = params->value_handle;
497 struct bt_bap_scan_delegator_recv_state recv_state;
498 int16_t index;
499 struct bap_broadcast_assistant_instance *inst;
500
501 if (conn == NULL) {
502 /* Indicates that the CCC has been removed - no-op */
503 return BT_GATT_ITER_CONTINUE;
504 }
505
506 inst = inst_by_conn(conn);
507
508 if (inst == NULL) {
509 return BT_GATT_ITER_STOP;
510 }
511
512 if (atomic_test_bit(inst->flags, BAP_BA_FLAG_DISCOVER_IN_PROGRESS)) {
513 /* If we are discovering then we ignore notifications as the handles may change */
514 return BT_GATT_ITER_CONTINUE;
515 }
516
517 if (data == NULL) {
518 LOG_DBG("[UNSUBSCRIBED] %u", handle);
519 params->value_handle = 0U;
520
521 return BT_GATT_ITER_STOP;
522 }
523
524 LOG_HEXDUMP_DBG(data, length, "Receive state notification:");
525
526 index = lookup_index_by_handle(inst, handle);
527 if (index < 0) {
528 LOG_DBG("Invalid index");
529
530 return BT_GATT_ITER_STOP;
531 }
532
533 if (length != 0) {
534 const uint16_t max_ntf_size = bt_audio_get_max_ntf_size(conn);
535
536 /* Cancel any pending long reads containing now obsolete information */
537 (void)k_work_cancel_delayable(&inst->bap_read_work);
538
539 if (length == max_ntf_size) {
540 /* TODO: if we are busy we should not overwrite the long_read_handle,
541 * we'll have to keep track of the handle and parameters separately
542 * for each characteristic, similar to the bt_bap_unicast_client_ep
543 * struct for the unicast client
544 */
545 inst->long_read_handle = handle;
546
547 if (!atomic_test_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
548 net_buf_simple_add_mem(&att_buf, data, length);
549 }
550
551 long_bap_read(conn, handle);
552 } else {
553 return parse_and_send_recv_state(conn, handle, data, length, &recv_state);
554 }
555 } else {
556 inst->recv_states[index].past_avail = false;
557 bap_broadcast_assistant_recv_state_removed(conn, inst->recv_states[index].src_id);
558 }
559
560 return BT_GATT_ITER_CONTINUE;
561 }
562
read_recv_state_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)563 static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err,
564 struct bt_gatt_read_params *params,
565 const void *data, uint16_t length)
566 {
567 struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn);
568
569 if (inst == NULL) {
570 return BT_GATT_ITER_STOP;
571 }
572
573 uint16_t handle = params->single.handle;
574 uint8_t last_handle_index = inst->recv_state_cnt - 1;
575 uint16_t last_handle = inst->recv_state_handles[last_handle_index];
576 struct bt_bap_scan_delegator_recv_state recv_state;
577 int cb_err = err;
578 bool active_recv_state = data != NULL && length != 0;
579
580 /* TODO: Split discovery and receive state characteristic read */
581
582 (void)memset(params, 0, sizeof(*params));
583
584 LOG_DBG("%s receive state", active_recv_state ? "Active " : "Inactive");
585
586 if (cb_err == 0 && active_recv_state) {
587 int16_t index;
588
589 index = lookup_index_by_handle(inst, handle);
590 if (index < 0) {
591 cb_err = BT_GATT_ERR(BT_ATT_ERR_INVALID_HANDLE);
592 } else {
593 cb_err = parse_recv_state(data, length, &recv_state);
594
595 if (cb_err != 0) {
596 LOG_DBG("Invalid receive state");
597 } else {
598 struct bap_broadcast_assistant_recv_state_info *stored_state =
599 &inst->recv_states[index];
600
601 stored_state->src_id = recv_state.src_id;
602 stored_state->adv_sid = recv_state.adv_sid;
603 stored_state->broadcast_id = recv_state.broadcast_id;
604 bt_addr_le_copy(&stored_state->addr, &recv_state.addr);
605 inst->recv_states[index].past_avail =
606 past_available(conn, &recv_state.addr,
607 recv_state.adv_sid);
608 }
609 }
610 }
611
612 if (cb_err != 0) {
613 LOG_DBG("err %d", cb_err);
614
615 if (atomic_test_bit(inst->flags, BAP_BA_FLAG_DISCOVER_IN_PROGRESS)) {
616 bap_broadcast_assistant_discover_complete(conn, cb_err, 0);
617 } else {
618 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
619 bap_broadcast_assistant_recv_state_changed(conn, cb_err, NULL);
620 }
621 } else if (handle == last_handle) {
622 if (atomic_test_bit(inst->flags, BAP_BA_FLAG_DISCOVER_IN_PROGRESS)) {
623 const uint8_t recv_state_cnt = inst->recv_state_cnt;
624
625 bap_broadcast_assistant_discover_complete(conn, cb_err, recv_state_cnt);
626 } else {
627 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
628 bap_broadcast_assistant_recv_state_changed(conn, cb_err,
629 active_recv_state ?
630 &recv_state : NULL);
631 }
632 } else {
633 for (uint8_t i = 0U; i < inst->recv_state_cnt; i++) {
634 if (handle != inst->recv_state_handles[i]) {
635 continue;
636 }
637
638 if (i + 1 < ARRAY_SIZE(inst->recv_state_handles)) {
639 cb_err = read_recv_state(inst, i + 1);
640 if (cb_err != 0) {
641 LOG_DBG("Failed to read receive state: %d", cb_err);
642
643 if (atomic_test_bit(inst->flags,
644 BAP_BA_FLAG_DISCOVER_IN_PROGRESS)) {
645 bap_broadcast_assistant_discover_complete(
646 conn, cb_err, 0);
647 } else {
648 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
649 bap_broadcast_assistant_recv_state_changed(
650 conn, cb_err, NULL);
651 }
652 }
653 }
654 break;
655 }
656 }
657
658 return BT_GATT_ITER_STOP;
659 }
660
discover_init(struct bap_broadcast_assistant_instance * inst)661 static void discover_init(struct bap_broadcast_assistant_instance *inst)
662 {
663 k_work_init_delayable(&inst->bap_read_work, delayed_bap_read_handler);
664 net_buf_simple_reset(&att_buf);
665 atomic_set_bit(inst->flags, BAP_BA_FLAG_DISCOVER_IN_PROGRESS);
666 }
667
668 /**
669 * @brief This will discover all characteristics on the server, retrieving the
670 * handles of the writeable characteristics and subscribing to all notify and
671 * indicate characteristics.
672 */
char_discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)673 static uint8_t char_discover_func(struct bt_conn *conn,
674 const struct bt_gatt_attr *attr,
675 struct bt_gatt_discover_params *params)
676 {
677 struct bt_gatt_subscribe_params *sub_params = NULL;
678 int err;
679 struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn);
680
681 if (inst == NULL) {
682 return BT_GATT_ITER_STOP;
683 }
684
685 if (attr == NULL) {
686 LOG_DBG("Found %u BASS receive states", inst->recv_state_cnt);
687 (void)memset(params, 0, sizeof(*params));
688
689 err = read_recv_state(inst, 0);
690 if (err != 0) {
691 bap_broadcast_assistant_discover_complete(conn, err, 0);
692 }
693
694 return BT_GATT_ITER_STOP;
695 }
696
697 LOG_DBG("[ATTRIBUTE] handle 0x%04X", attr->handle);
698
699 if (params->type == BT_GATT_DISCOVER_CHARACTERISTIC) {
700 struct bt_gatt_chrc *chrc =
701 (struct bt_gatt_chrc *)attr->user_data;
702
703 if (bt_uuid_cmp(chrc->uuid, BT_UUID_BASS_CONTROL_POINT) == 0) {
704 LOG_DBG("Control Point");
705 inst->cp_handle = attr->handle + 1;
706 } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_BASS_RECV_STATE) == 0) {
707 if (inst->recv_state_cnt <
708 CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT) {
709 uint8_t idx = inst->recv_state_cnt++;
710
711 LOG_DBG("Receive State %u", inst->recv_state_cnt);
712 inst->recv_state_handles[idx] =
713 attr->handle + 1;
714 sub_params = &inst->recv_state_sub_params[idx];
715 sub_params->disc_params = &inst->recv_state_disc_params[idx];
716 }
717 }
718
719 if (sub_params != NULL) {
720 sub_params->end_handle = inst->end_handle;
721 sub_params->ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
722 sub_params->value = BT_GATT_CCC_NOTIFY;
723 sub_params->value_handle = attr->handle + 1;
724 sub_params->notify = notify_handler;
725 atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
726
727 err = bt_gatt_subscribe(conn, sub_params);
728 if (err != 0) {
729 LOG_DBG("Could not subscribe to handle 0x%04x: %d",
730 sub_params->value_handle, err);
731
732 bap_broadcast_assistant_discover_complete(conn, err, 0);
733
734 return BT_GATT_ITER_STOP;
735 }
736 }
737 }
738
739 return BT_GATT_ITER_CONTINUE;
740 }
741
service_discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)742 static uint8_t service_discover_func(struct bt_conn *conn,
743 const struct bt_gatt_attr *attr,
744 struct bt_gatt_discover_params *params)
745 {
746 int err;
747 struct bt_gatt_service_val *prim_service;
748 struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn);
749
750 if (inst == NULL) {
751 return BT_GATT_ITER_STOP;
752 }
753
754 if (attr == NULL) {
755 LOG_DBG("Could not discover BASS");
756 (void)memset(params, 0, sizeof(*params));
757
758 err = BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED);
759
760 bap_broadcast_assistant_discover_complete(conn, err, 0);
761
762 return BT_GATT_ITER_STOP;
763 }
764
765 LOG_DBG("[ATTRIBUTE] handle 0x%04X", attr->handle);
766
767 if (params->type == BT_GATT_DISCOVER_PRIMARY) {
768 prim_service = (struct bt_gatt_service_val *)attr->user_data;
769 inst->start_handle = attr->handle + 1;
770 inst->end_handle = prim_service->end_handle;
771
772 inst->disc_params.uuid = NULL;
773 inst->disc_params.start_handle = inst->start_handle;
774 inst->disc_params.end_handle = inst->end_handle;
775 inst->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
776 inst->disc_params.func = char_discover_func;
777
778 err = bt_gatt_discover(conn, &inst->disc_params);
779 if (err != 0) {
780 LOG_DBG("Discover failed (err %d)", err);
781 bap_broadcast_assistant_discover_complete(conn, err, 0);
782 }
783 }
784
785 return BT_GATT_ITER_STOP;
786 }
787
bap_broadcast_assistant_write_cp_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_write_params * params)788 static void bap_broadcast_assistant_write_cp_cb(struct bt_conn *conn, uint8_t err,
789 struct bt_gatt_write_params *params)
790 {
791 struct bt_bap_broadcast_assistant_cb *listener, *next;
792 uint8_t opcode = net_buf_simple_pull_u8(&att_buf);
793 struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn);
794
795 if (inst == NULL) {
796 return;
797 }
798
799 /* we reset the buffer, so that we are ready for new notifications and writes */
800 net_buf_simple_reset(&att_buf);
801
802 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
803
804 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&broadcast_assistant_cbs, listener, next, _node) {
805 switch (opcode) {
806 case BT_BAP_BASS_OP_SCAN_STOP:
807 if (listener->scan_stop != NULL) {
808 listener->scan_stop(conn, err);
809 }
810 break;
811 case BT_BAP_BASS_OP_SCAN_START:
812 if (listener->scan_start != NULL) {
813 listener->scan_start(conn, err);
814 }
815 break;
816 case BT_BAP_BASS_OP_ADD_SRC:
817 if (listener->add_src != NULL) {
818 listener->add_src(conn, err);
819 }
820 break;
821 case BT_BAP_BASS_OP_MOD_SRC:
822 if (listener->mod_src != NULL) {
823 listener->mod_src(conn, err);
824 }
825 break;
826 case BT_BAP_BASS_OP_BROADCAST_CODE:
827 if (listener->broadcast_code != NULL) {
828 listener->broadcast_code(conn, err);
829 }
830 break;
831 case BT_BAP_BASS_OP_REM_SRC:
832 if (listener->rem_src != NULL) {
833 listener->rem_src(conn, err);
834 }
835 break;
836 default:
837 LOG_DBG("Unknown opcode 0x%02x", opcode);
838 break;
839 }
840 }
841 }
842
bt_bap_broadcast_assistant_common_cp(struct bt_conn * conn,const struct net_buf_simple * buf)843 static int bt_bap_broadcast_assistant_common_cp(struct bt_conn *conn,
844 const struct net_buf_simple *buf)
845 {
846 int err;
847 struct bap_broadcast_assistant_instance *inst;
848
849 if (conn == NULL) {
850 LOG_DBG("conn is NULL");
851
852 return -EINVAL;
853 }
854
855 inst = inst_by_conn(conn);
856
857 if (inst == NULL) {
858 return -EINVAL;
859 }
860
861 if (inst->cp_handle == 0) {
862 LOG_DBG("Handle not set");
863 return -EINVAL;
864 }
865
866 inst->write_params.offset = 0;
867 inst->write_params.data = buf->data;
868 inst->write_params.length = buf->len;
869 inst->write_params.handle = inst->cp_handle;
870 inst->write_params.func = bap_broadcast_assistant_write_cp_cb;
871
872 err = bt_gatt_write(conn, &inst->write_params);
873 if (err != 0) {
874 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
875
876 /* Report expected possible errors */
877 if (err == -ENOTCONN || err == -ENOMEM) {
878 return err;
879 }
880
881 return -ENOEXEC;
882 }
883
884 return 0;
885 }
886
887
broadcast_source_found(struct bt_data * data,void * user_data)888 static bool broadcast_source_found(struct bt_data *data, void *user_data)
889 {
890 const struct bt_le_scan_recv_info *info = user_data;
891 struct bt_uuid_16 adv_uuid;
892 uint32_t broadcast_id;
893
894 if (data->type != BT_DATA_SVC_DATA16) {
895 return true;
896 }
897
898 if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) {
899 return true;
900 }
901
902 if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) {
903 return true;
904 }
905
906 if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO) != 0) {
907 return true;
908 }
909
910 broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16);
911
912 LOG_DBG("Found BIS advertiser with address %s SID 0x%02X and broadcast_id 0x%06X",
913 bt_addr_le_str(info->addr), info->sid, broadcast_id);
914
915 bap_broadcast_assistant_scan_results(info, broadcast_id);
916
917 return false;
918 }
919
scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * ad)920 void scan_recv(const struct bt_le_scan_recv_info *info,
921 struct net_buf_simple *ad)
922 {
923 /* We are only interested in non-connectable periodic advertisers */
924 if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0 ||
925 info->interval == 0) {
926 return;
927 }
928
929 bt_data_parse(ad, broadcast_source_found, (void *)info);
930 }
931
932 static struct bt_le_scan_cb scan_cb = {
933 .recv = scan_recv
934 };
935
936 /* BAP 6.5.4 states that the Broadcast Assistant shall not initiate the Add Source operation
937 * if the operation would result in duplicate values for the combined Source_Address_Type,
938 * Source_Adv_SID, and Broadcast_ID fields of any Broadcast Receive State characteristic exposed
939 * by the Scan Delegator.
940 */
broadcast_src_is_duplicate(struct bap_broadcast_assistant_instance * inst,uint32_t broadcast_id,uint8_t adv_sid,uint8_t addr_type)941 static bool broadcast_src_is_duplicate(struct bap_broadcast_assistant_instance *inst,
942 uint32_t broadcast_id, uint8_t adv_sid, uint8_t addr_type)
943 {
944 for (size_t i = 0; i < ARRAY_SIZE(inst->recv_states); i++) {
945 const struct bap_broadcast_assistant_recv_state_info *state =
946 &inst->recv_states[i];
947
948 if (state != NULL && state->broadcast_id == broadcast_id &&
949 state->adv_sid == adv_sid && state->addr.type == addr_type) {
950 LOG_DBG("recv_state already exists at src_id=0x%02X", state->src_id);
951
952 return true;
953 }
954 }
955
956 return false;
957 }
958
959 /****************************** PUBLIC API ******************************/
960
broadcast_assistant_reset(struct bap_broadcast_assistant_instance * inst)961 static int broadcast_assistant_reset(struct bap_broadcast_assistant_instance *inst)
962 {
963 inst->scanning = false;
964 inst->pa_sync = 0U;
965 inst->recv_state_cnt = 0U;
966 inst->start_handle = 0U;
967 inst->end_handle = 0U;
968 inst->cp_handle = 0U;
969 inst->long_read_handle = 0;
970 (void)k_work_cancel_delayable(&inst->bap_read_work);
971
972 for (int i = 0U; i < CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT; i++) {
973 memset(&inst->recv_states[i], 0, sizeof(inst->recv_states[i]));
974 inst->recv_states[i].broadcast_id = BT_BAP_INVALID_BROADCAST_ID;
975 inst->recv_states[i].adv_sid = BT_HCI_LE_EXT_ADV_SID_INVALID;
976 inst->recv_states[i].past_avail = false;
977 inst->recv_state_handles[i] = 0U;
978 }
979
980 if (inst->conn != NULL) {
981 struct bt_conn *conn = inst->conn;
982 struct bt_conn_info info;
983 int err;
984
985 err = bt_conn_get_info(conn, &info);
986 if (err != 0) {
987 return err;
988 }
989
990 if (info.state == BT_CONN_STATE_CONNECTED) {
991 for (size_t i = 0U; i < ARRAY_SIZE(inst->recv_state_sub_params); i++) {
992 /* It's okay if this fail with -EINVAL as that means that they are
993 * not currently subscribed
994 */
995 err = bt_gatt_unsubscribe(conn, &inst->recv_state_sub_params[i]);
996 if (err != 0 && err != -EINVAL) {
997 LOG_DBG("Failed to unsubscribe to state: %d", err);
998
999 return err;
1000 }
1001 }
1002 }
1003
1004 bt_conn_unref(conn);
1005 inst->conn = NULL;
1006 }
1007
1008 /* The subscribe parameters must remain instact so they can get cleaned up by GATT */
1009 memset(&inst->disc_params, 0, sizeof(inst->disc_params));
1010 memset(&inst->recv_state_disc_params, 0, sizeof(inst->recv_state_disc_params));
1011 memset(&inst->read_params, 0, sizeof(inst->read_params));
1012 memset(&inst->write_params, 0, sizeof(inst->write_params));
1013
1014 return 0;
1015 }
1016
disconnected_cb(struct bt_conn * conn,uint8_t reason)1017 static void disconnected_cb(struct bt_conn *conn, uint8_t reason)
1018 {
1019 struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn);
1020
1021 if (inst) {
1022 (void)broadcast_assistant_reset(inst);
1023 }
1024 }
1025
1026 BT_CONN_CB_DEFINE(conn_callbacks) = {
1027 .disconnected = disconnected_cb,
1028 };
1029
bt_bap_broadcast_assistant_discover(struct bt_conn * conn)1030 int bt_bap_broadcast_assistant_discover(struct bt_conn *conn)
1031 {
1032 int err;
1033 struct bap_broadcast_assistant_instance *inst;
1034
1035 if (conn == NULL) {
1036 LOG_DBG("conn is NULL");
1037
1038 return -EINVAL;
1039 }
1040
1041 inst = &broadcast_assistants[bt_conn_index(conn)];
1042
1043 /* Do not allow new discoveries while we are reading or writing */
1044 if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
1045 LOG_DBG("Instance is busy");
1046 return -EBUSY;
1047 }
1048
1049 err = broadcast_assistant_reset(inst);
1050 if (err != 0) {
1051 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
1052
1053 LOG_DBG("Failed to reset broadcast assistant: %d", err);
1054
1055 return -ENOEXEC;
1056 }
1057
1058 inst->conn = bt_conn_ref(conn);
1059
1060 /* Discover BASS on peer, setup handles and notify */
1061 discover_init(inst);
1062
1063 (void)memcpy(&uuid, BT_UUID_BASS, sizeof(uuid));
1064 inst->disc_params.func = service_discover_func;
1065 inst->disc_params.uuid = &uuid.uuid;
1066 inst->disc_params.type = BT_GATT_DISCOVER_PRIMARY;
1067 inst->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
1068 inst->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1069 err = bt_gatt_discover(conn, &inst->disc_params);
1070 if (err != 0) {
1071 atomic_clear_bit(inst->flags, BAP_BA_FLAG_DISCOVER_IN_PROGRESS);
1072 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
1073
1074 /* Report expected possible errors */
1075 if (err == -ENOTCONN || err == -ENOMEM) {
1076 return err;
1077 }
1078
1079 LOG_DBG("Unexpected err %d from bt_gatt_discover", err);
1080
1081 return -ENOEXEC;
1082 }
1083
1084 return 0;
1085 }
1086
1087 /* TODO: naming is different from e.g. bt_vcp_vol_ctrl_cb_register */
bt_bap_broadcast_assistant_register_cb(struct bt_bap_broadcast_assistant_cb * cb)1088 int bt_bap_broadcast_assistant_register_cb(struct bt_bap_broadcast_assistant_cb *cb)
1089 {
1090 struct bt_bap_broadcast_assistant_cb *tmp;
1091
1092 CHECKIF(cb == NULL) {
1093 return -EINVAL;
1094 }
1095
1096 SYS_SLIST_FOR_EACH_CONTAINER(&broadcast_assistant_cbs, tmp, _node) {
1097 if (tmp == cb) {
1098 LOG_DBG("Already registered");
1099 return -EALREADY;
1100 }
1101 }
1102
1103 sys_slist_append(&broadcast_assistant_cbs, &cb->_node);
1104
1105 return 0;
1106 }
1107
bt_bap_broadcast_assistant_unregister_cb(struct bt_bap_broadcast_assistant_cb * cb)1108 int bt_bap_broadcast_assistant_unregister_cb(struct bt_bap_broadcast_assistant_cb *cb)
1109 {
1110 CHECKIF(cb == NULL) {
1111 return -EINVAL;
1112 }
1113
1114 if (!sys_slist_find_and_remove(&broadcast_assistant_cbs, &cb->_node)) {
1115 return -EALREADY;
1116 }
1117
1118 return 0;
1119 }
1120
bt_bap_broadcast_assistant_scan_start(struct bt_conn * conn,bool start_scan)1121 int bt_bap_broadcast_assistant_scan_start(struct bt_conn *conn, bool start_scan)
1122 {
1123 struct bt_bap_bass_cp_scan_start *cp;
1124 int err;
1125 struct bap_broadcast_assistant_instance *inst;
1126
1127 if (conn == NULL) {
1128 LOG_DBG("conn is NULL");
1129
1130 return -EINVAL;
1131 }
1132
1133 inst = inst_by_conn(conn);
1134 if (inst == NULL) {
1135 return -EINVAL;
1136 }
1137
1138 if (inst->cp_handle == 0) {
1139 LOG_DBG("handle not set");
1140
1141 return -EINVAL;
1142 } else if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
1143 /* Do not allow writes while we are discovering as the handles may change */
1144
1145 LOG_DBG("instance busy");
1146
1147 return -EBUSY;
1148 }
1149
1150 /* TODO: Remove the start_scan parameter and support from the assistant */
1151 if (start_scan) {
1152 static bool cb_registered;
1153
1154 if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_SCANNING)) {
1155 LOG_DBG("Already scanning");
1156
1157 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
1158
1159 return -EALREADY;
1160 }
1161
1162 if (!cb_registered) {
1163 bt_le_scan_cb_register(&scan_cb);
1164 cb_registered = true;
1165 }
1166
1167 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
1168 if (err != 0) {
1169 LOG_DBG("Could not start scan (%d)", err);
1170
1171 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
1172 atomic_clear_bit(inst->flags, BAP_BA_FLAG_SCANNING);
1173
1174 /* Report expected possible errors */
1175 if (err == -EAGAIN) {
1176 return err;
1177 }
1178
1179 LOG_DBG("Unexpected err %d from bt_le_scan_start", err);
1180
1181 return -ENOEXEC;
1182 }
1183 }
1184
1185 /* Reset buffer before using */
1186 net_buf_simple_reset(&att_buf);
1187 cp = net_buf_simple_add(&att_buf, sizeof(*cp));
1188
1189 cp->opcode = BT_BAP_BASS_OP_SCAN_START;
1190
1191 err = bt_bap_broadcast_assistant_common_cp(conn, &att_buf);
1192 if (err != 0 && start_scan) {
1193 /* bt_bap_broadcast_assistant_common_cp clears the busy flag on error */
1194 err = bt_le_scan_stop();
1195 if (err != 0) {
1196 LOG_DBG("Could not stop scan (%d)", err);
1197
1198 return -ENOEXEC;
1199 }
1200
1201 atomic_clear_bit(inst->flags, BAP_BA_FLAG_SCANNING);
1202 }
1203
1204 return err;
1205 }
1206
bt_bap_broadcast_assistant_scan_stop(struct bt_conn * conn)1207 int bt_bap_broadcast_assistant_scan_stop(struct bt_conn *conn)
1208 {
1209 struct bt_bap_bass_cp_scan_stop *cp;
1210 int err;
1211 struct bap_broadcast_assistant_instance *inst;
1212
1213 if (conn == NULL) {
1214 LOG_DBG("conn is NULL");
1215
1216 return -EINVAL;
1217 }
1218
1219 inst = inst_by_conn(conn);
1220 if (inst == NULL) {
1221 return -EINVAL;
1222 }
1223
1224 if (inst->cp_handle == 0) {
1225 LOG_DBG("handle not set");
1226
1227 return -EINVAL;
1228 } else if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
1229 LOG_DBG("instance busy");
1230
1231 return -EBUSY;
1232 }
1233
1234 if (atomic_test_bit(inst->flags, BAP_BA_FLAG_SCANNING)) {
1235 err = bt_le_scan_stop();
1236 if (err != 0) {
1237 LOG_DBG("Could not stop scan (%d)", err);
1238
1239 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
1240
1241 return err;
1242 }
1243
1244 atomic_clear_bit(inst->flags, BAP_BA_FLAG_SCANNING);
1245 }
1246
1247 /* Reset buffer before using */
1248 net_buf_simple_reset(&att_buf);
1249 cp = net_buf_simple_add(&att_buf, sizeof(*cp));
1250
1251 cp->opcode = BT_BAP_BASS_OP_SCAN_STOP;
1252
1253 return bt_bap_broadcast_assistant_common_cp(conn, &att_buf);
1254 }
1255
bis_syncs_unique_or_no_pref(uint32_t requested_bis_syncs,uint32_t aggregated_bis_syncs)1256 static bool bis_syncs_unique_or_no_pref(uint32_t requested_bis_syncs, uint32_t aggregated_bis_syncs)
1257 {
1258 if (requested_bis_syncs == 0U || aggregated_bis_syncs == 0U) {
1259 return true;
1260 }
1261
1262 if (requested_bis_syncs == BT_BAP_BIS_SYNC_NO_PREF &&
1263 aggregated_bis_syncs == BT_BAP_BIS_SYNC_NO_PREF) {
1264 return true;
1265 }
1266
1267 return (requested_bis_syncs & aggregated_bis_syncs) != 0U;
1268 }
1269
valid_subgroup_params(uint8_t pa_sync,const struct bt_bap_bass_subgroup subgroups[],uint8_t num_subgroups)1270 static bool valid_subgroup_params(uint8_t pa_sync, const struct bt_bap_bass_subgroup subgroups[],
1271 uint8_t num_subgroups)
1272 {
1273 uint32_t aggregated_bis_syncs = 0U;
1274
1275 for (uint8_t i = 0U; i < num_subgroups; i++) {
1276 /* BIS sync values of 0 and BT_BAP_BIS_SYNC_NO_PREF are allowed at any time, but any
1277 * other values are only allowed if PA sync state is also set
1278 */
1279 CHECKIF(pa_sync == 0 && (subgroups[i].bis_sync != 0U &&
1280 subgroups[i].bis_sync != BT_BAP_BIS_SYNC_NO_PREF)) {
1281 LOG_DBG("[%u]: Only syncing to BIS is not allowed", i);
1282
1283 return false;
1284 }
1285
1286 /* Verify that the request BIS sync indexes are unique or no preference */
1287 if (!bis_syncs_unique_or_no_pref(subgroups[i].bis_sync, aggregated_bis_syncs)) {
1288 LOG_DBG("[%u]: Duplicate BIS index 0x%08x (aggregated 0x%08x)", i,
1289 subgroups[i].bis_sync, aggregated_bis_syncs);
1290
1291 return false;
1292 }
1293
1294 /* Keep track of BIS sync values to ensure that we do not have duplicates */
1295 if (subgroups[i].bis_sync != BT_BAP_BIS_SYNC_NO_PREF) {
1296 aggregated_bis_syncs |= subgroups[i].bis_sync;
1297 }
1298
1299 #if defined(CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE)
1300 if (subgroups[i].metadata_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) {
1301 LOG_DBG("[%u]: Invalid metadata_len: %u", i, subgroups[i].metadata_len);
1302
1303 return false;
1304 }
1305 }
1306 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE */
1307
1308 return true;
1309 }
1310
valid_add_src_param(const struct bt_bap_broadcast_assistant_add_src_param * param)1311 static bool valid_add_src_param(const struct bt_bap_broadcast_assistant_add_src_param *param)
1312 {
1313 CHECKIF(param == NULL) {
1314 LOG_DBG("param is NULL");
1315 return false;
1316 }
1317
1318 CHECKIF(param->addr.type > BT_ADDR_LE_RANDOM) {
1319 LOG_DBG("Invalid address type %u", param->addr.type);
1320 return false;
1321 }
1322
1323 CHECKIF(param->adv_sid > BT_GAP_SID_MAX) {
1324 LOG_DBG("Invalid adv_sid %u", param->adv_sid);
1325 return false;
1326 }
1327
1328 CHECKIF(!(param->pa_interval != BT_BAP_PA_INTERVAL_UNKNOWN) &&
1329 !IN_RANGE(param->pa_interval, BT_GAP_PER_ADV_MIN_INTERVAL,
1330 BT_GAP_PER_ADV_MAX_INTERVAL)) {
1331 LOG_DBG("Invalid pa_interval 0x%04X", param->pa_interval);
1332 return false;
1333 }
1334
1335 CHECKIF(param->broadcast_id > BT_AUDIO_BROADCAST_ID_MAX) {
1336 LOG_DBG("Invalid broadcast_id 0x%08X", param->broadcast_id);
1337 return false;
1338 }
1339
1340 CHECKIF(param->num_subgroups != 0 && param->subgroups == NULL) {
1341 LOG_DBG("Subgroups are NULL when num_subgroups = %u", param->num_subgroups);
1342 return false;
1343 }
1344
1345 CHECKIF(param->num_subgroups > CONFIG_BT_BAP_BASS_MAX_SUBGROUPS) {
1346 LOG_DBG("Too many subgroups %u/%u", param->num_subgroups,
1347 CONFIG_BT_BAP_BASS_MAX_SUBGROUPS);
1348
1349 return false;
1350 }
1351
1352 CHECKIF(param->subgroups != NULL) {
1353 if (!valid_subgroup_params(param->pa_sync, param->subgroups,
1354 param->num_subgroups)) {
1355 return false;
1356 }
1357 }
1358
1359 return true;
1360 }
1361
bt_bap_broadcast_assistant_add_src(struct bt_conn * conn,const struct bt_bap_broadcast_assistant_add_src_param * param)1362 int bt_bap_broadcast_assistant_add_src(struct bt_conn *conn,
1363 const struct bt_bap_broadcast_assistant_add_src_param *param)
1364 {
1365 struct bt_bap_bass_cp_add_src *cp;
1366 struct bap_broadcast_assistant_instance *inst;
1367
1368 if (conn == NULL) {
1369 LOG_DBG("conn is NULL");
1370
1371 return -EINVAL;
1372 }
1373
1374 inst = inst_by_conn(conn);
1375
1376 if (inst == NULL) {
1377 return -EINVAL;
1378 }
1379
1380 /* Check if this operation would result in a duplicate before proceeding */
1381 if (broadcast_src_is_duplicate(inst, param->broadcast_id, param->adv_sid,
1382 param->addr.type)) {
1383 LOG_DBG("Broadcast source already exists");
1384
1385 return -EINVAL;
1386 }
1387
1388 if (!valid_add_src_param(param)) {
1389 return -EINVAL;
1390 }
1391
1392 if (inst->cp_handle == 0) {
1393 LOG_DBG("handle not set");
1394
1395 return -EINVAL;
1396 } else if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
1397 LOG_DBG("instance busy");
1398
1399 return -EBUSY;
1400 }
1401 /* Reset buffer before using */
1402 net_buf_simple_reset(&att_buf);
1403 cp = net_buf_simple_add(&att_buf, sizeof(*cp));
1404
1405 cp->opcode = BT_BAP_BASS_OP_ADD_SRC;
1406 cp->adv_sid = param->adv_sid;
1407 bt_addr_le_copy(&cp->addr, ¶m->addr);
1408
1409 sys_put_le24(param->broadcast_id, cp->broadcast_id);
1410
1411 if (param->pa_sync) {
1412 if (past_available(conn, ¶m->addr, param->adv_sid)) {
1413 cp->pa_sync = BT_BAP_BASS_PA_REQ_SYNC_PAST;
1414 } else {
1415 cp->pa_sync = BT_BAP_BASS_PA_REQ_SYNC;
1416 }
1417 } else {
1418 cp->pa_sync = BT_BAP_BASS_PA_REQ_NO_SYNC;
1419 }
1420 cp->pa_interval = sys_cpu_to_le16(param->pa_interval);
1421
1422 cp->num_subgroups = param->num_subgroups;
1423 for (int i = 0; i < param->num_subgroups; i++) {
1424 struct bt_bap_bass_cp_subgroup *subgroup;
1425 const size_t subgroup_size = sizeof(subgroup->bis_sync) +
1426 sizeof(subgroup->metadata_len) +
1427 param->subgroups[i].metadata_len;
1428
1429 if (att_buf.len + subgroup_size > att_buf.size) {
1430 LOG_DBG("MTU is too small to send %zu octets", att_buf.len + subgroup_size);
1431
1432 /* TODO: Validate parameters before setting the busy flag to reduce cleanup
1433 */
1434 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
1435
1436 return -EINVAL;
1437 }
1438
1439 subgroup = net_buf_simple_add(&att_buf, subgroup_size);
1440
1441 subgroup->bis_sync = param->subgroups[i].bis_sync;
1442
1443 #if defined(CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE)
1444 if (param->subgroups[i].metadata_len != 0) {
1445 (void)memcpy(subgroup->metadata, param->subgroups[i].metadata,
1446 param->subgroups[i].metadata_len);
1447 subgroup->metadata_len = param->subgroups[i].metadata_len;
1448 } else {
1449 subgroup->metadata_len = 0U;
1450 }
1451 #else
1452 subgroup->metadata_len = 0U;
1453 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE */
1454 }
1455
1456 return bt_bap_broadcast_assistant_common_cp(conn, &att_buf);
1457 }
1458
valid_add_mod_param(const struct bt_bap_broadcast_assistant_mod_src_param * param)1459 static bool valid_add_mod_param(const struct bt_bap_broadcast_assistant_mod_src_param *param)
1460 {
1461 CHECKIF(param == NULL) {
1462 LOG_DBG("param is NULL");
1463 return false;
1464 }
1465
1466 CHECKIF(!(param->pa_interval != BT_BAP_PA_INTERVAL_UNKNOWN) &&
1467 !IN_RANGE(param->pa_interval, BT_GAP_PER_ADV_MIN_INTERVAL,
1468 BT_GAP_PER_ADV_MAX_INTERVAL)) {
1469 LOG_DBG("Invalid pa_interval 0x%04X", param->pa_interval);
1470 return false;
1471 }
1472
1473 CHECKIF(param->num_subgroups != 0 && param->subgroups == NULL) {
1474 LOG_DBG("Subgroups are NULL when num_subgroups = %u", param->num_subgroups);
1475 return false;
1476 }
1477
1478 CHECKIF(param->num_subgroups > CONFIG_BT_BAP_BASS_MAX_SUBGROUPS) {
1479 LOG_DBG("Too many subgroups %u/%u", param->num_subgroups,
1480 CONFIG_BT_BAP_BASS_MAX_SUBGROUPS);
1481
1482 return false;
1483 }
1484
1485 CHECKIF(param->subgroups != NULL) {
1486 if (!valid_subgroup_params(param->pa_sync, param->subgroups,
1487 param->num_subgroups)) {
1488 return false;
1489 }
1490 }
1491
1492 return true;
1493 }
1494
bt_bap_broadcast_assistant_mod_src(struct bt_conn * conn,const struct bt_bap_broadcast_assistant_mod_src_param * param)1495 int bt_bap_broadcast_assistant_mod_src(struct bt_conn *conn,
1496 const struct bt_bap_broadcast_assistant_mod_src_param *param)
1497 {
1498 struct bt_bap_bass_cp_mod_src *cp;
1499 bool known_recv_state;
1500 bool past_avail;
1501 struct bap_broadcast_assistant_instance *inst;
1502
1503 if (conn == NULL) {
1504 LOG_DBG("conn is NULL");
1505
1506 return -EINVAL;
1507 }
1508
1509 if (!valid_add_mod_param(param)) {
1510 return -EINVAL;
1511 }
1512
1513 inst = inst_by_conn(conn);
1514 if (inst == NULL) {
1515 return -EINVAL;
1516 }
1517
1518 if (inst->cp_handle == 0) {
1519 LOG_DBG("handle not set");
1520
1521 return -EINVAL;
1522 } else if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
1523 LOG_DBG("instance busy");
1524
1525 return -EBUSY;
1526 }
1527
1528 /* Reset buffer before using */
1529 net_buf_simple_reset(&att_buf);
1530 cp = net_buf_simple_add(&att_buf, sizeof(*cp));
1531
1532 cp->opcode = BT_BAP_BASS_OP_MOD_SRC;
1533 cp->src_id = param->src_id;
1534
1535 /* Since we do not have the address and SID in this function, we
1536 * rely on cached PAST support information
1537 */
1538 known_recv_state = false;
1539 past_avail = false;
1540 for (size_t i = 0; i < ARRAY_SIZE(inst->recv_states); i++) {
1541 if (inst->recv_states[i].src_id == param->src_id) {
1542 known_recv_state = true;
1543 past_avail = inst->recv_states[i].past_avail;
1544 break;
1545 }
1546 }
1547
1548 if (!known_recv_state) {
1549 LOG_WRN("Attempting to modify unknown receive state: %u",
1550 param->src_id);
1551 }
1552
1553 if (param->pa_sync) {
1554 if (known_recv_state && past_avail) {
1555 cp->pa_sync = BT_BAP_BASS_PA_REQ_SYNC_PAST;
1556 } else {
1557 cp->pa_sync = BT_BAP_BASS_PA_REQ_SYNC;
1558 }
1559 } else {
1560 cp->pa_sync = BT_BAP_BASS_PA_REQ_NO_SYNC;
1561 }
1562
1563 cp->pa_interval = sys_cpu_to_le16(param->pa_interval);
1564
1565 cp->num_subgroups = param->num_subgroups;
1566 for (int i = 0; i < param->num_subgroups; i++) {
1567 struct bt_bap_bass_cp_subgroup *subgroup;
1568 const size_t subgroup_size = sizeof(subgroup->bis_sync) +
1569 sizeof(subgroup->metadata_len) +
1570 param->subgroups[i].metadata_len;
1571
1572 if (att_buf.len + subgroup_size > att_buf.size) {
1573 LOG_DBG("MTU is too small to send %zu octets", att_buf.len + subgroup_size);
1574
1575 /* TODO: Validate parameters before setting the busy flag to reduce cleanup
1576 */
1577 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
1578
1579 return -EINVAL;
1580 }
1581 subgroup = net_buf_simple_add(&att_buf, subgroup_size);
1582
1583 subgroup->bis_sync = param->subgroups[i].bis_sync;
1584
1585 #if defined(CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE)
1586 if (param->subgroups[i].metadata_len != 0) {
1587 (void)memcpy(subgroup->metadata,
1588 param->subgroups[i].metadata,
1589 param->subgroups[i].metadata_len);
1590 subgroup->metadata_len = param->subgroups[i].metadata_len;
1591 } else {
1592 subgroup->metadata_len = 0U;
1593 }
1594 #else
1595 subgroup->metadata_len = 0U;
1596 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE */
1597 }
1598
1599 return bt_bap_broadcast_assistant_common_cp(conn, &att_buf);
1600 }
1601
bt_bap_broadcast_assistant_set_broadcast_code(struct bt_conn * conn,uint8_t src_id,const uint8_t broadcast_code[BT_ISO_BROADCAST_CODE_SIZE])1602 int bt_bap_broadcast_assistant_set_broadcast_code(
1603 struct bt_conn *conn, uint8_t src_id,
1604 const uint8_t broadcast_code[BT_ISO_BROADCAST_CODE_SIZE])
1605 {
1606 struct bt_bap_bass_cp_broadcase_code *cp;
1607 struct bap_broadcast_assistant_instance *inst;
1608
1609 if (conn == NULL) {
1610 LOG_DBG("conn is NULL");
1611
1612 return -EINVAL;
1613 }
1614
1615 inst = inst_by_conn(conn);
1616 if (inst == NULL) {
1617 return -EINVAL;
1618 }
1619
1620 if (inst->cp_handle == 0) {
1621 LOG_DBG("handle not set");
1622
1623 return -EINVAL;
1624 } else if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
1625 LOG_DBG("instance busy");
1626
1627 return -EBUSY;
1628 }
1629
1630 /* Reset buffer before using */
1631 net_buf_simple_reset(&att_buf);
1632 cp = net_buf_simple_add(&att_buf, sizeof(*cp));
1633
1634 cp->opcode = BT_BAP_BASS_OP_BROADCAST_CODE;
1635 cp->src_id = src_id;
1636
1637 (void)memcpy(cp->broadcast_code, broadcast_code, BT_ISO_BROADCAST_CODE_SIZE);
1638
1639 LOG_HEXDUMP_DBG(cp->broadcast_code, BT_ISO_BROADCAST_CODE_SIZE, "broadcast code:");
1640
1641 return bt_bap_broadcast_assistant_common_cp(conn, &att_buf);
1642 }
1643
bt_bap_broadcast_assistant_rem_src(struct bt_conn * conn,uint8_t src_id)1644 int bt_bap_broadcast_assistant_rem_src(struct bt_conn *conn, uint8_t src_id)
1645 {
1646 struct bt_bap_bass_cp_rem_src *cp;
1647 struct bap_broadcast_assistant_instance *inst;
1648
1649 if (conn == NULL) {
1650 LOG_DBG("conn is NULL");
1651
1652 return -EINVAL;
1653 }
1654
1655 inst = inst_by_conn(conn);
1656 if (inst == NULL) {
1657 return -EINVAL;
1658 }
1659
1660 if (inst->cp_handle == 0) {
1661 LOG_DBG("handle not set");
1662
1663 return -EINVAL;
1664 } else if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
1665 LOG_DBG("instance busy");
1666
1667 return -EBUSY;
1668 }
1669
1670 /* Reset buffer before using */
1671 net_buf_simple_reset(&att_buf);
1672 cp = net_buf_simple_add(&att_buf, sizeof(*cp));
1673
1674 cp->opcode = BT_BAP_BASS_OP_REM_SRC;
1675 cp->src_id = src_id;
1676
1677 return bt_bap_broadcast_assistant_common_cp(conn, &att_buf);
1678 }
1679
read_recv_state(struct bap_broadcast_assistant_instance * inst,uint8_t idx)1680 static int read_recv_state(struct bap_broadcast_assistant_instance *inst, uint8_t idx)
1681 {
1682 int err;
1683
1684 inst->read_params.func = read_recv_state_cb;
1685 inst->read_params.handle_count = 1;
1686 inst->read_params.single.handle = inst->recv_state_handles[idx];
1687
1688 err = bt_gatt_read(inst->conn, &inst->read_params);
1689 if (err != 0) {
1690 (void)memset(&inst->read_params, 0, sizeof(inst->read_params));
1691 }
1692
1693 return err;
1694 }
1695
bt_bap_broadcast_assistant_read_recv_state(struct bt_conn * conn,uint8_t idx)1696 int bt_bap_broadcast_assistant_read_recv_state(struct bt_conn *conn,
1697 uint8_t idx)
1698 {
1699 int err;
1700 struct bap_broadcast_assistant_instance *inst;
1701
1702 if (conn == NULL) {
1703 LOG_DBG("conn is NULL");
1704
1705 return -EINVAL;
1706 }
1707
1708 inst = inst_by_conn(conn);
1709 if (inst == NULL) {
1710 return -EINVAL;
1711 }
1712
1713 CHECKIF(idx >= ARRAY_SIZE(inst->recv_state_handles)) {
1714 LOG_DBG("Invalid idx: %u", idx);
1715
1716 return -EINVAL;
1717 }
1718
1719 if (inst->recv_state_handles[idx] == 0) {
1720 LOG_DBG("handle not set");
1721
1722 return -EINVAL;
1723 } else if (atomic_test_and_set_bit(inst->flags, BAP_BA_FLAG_BUSY)) {
1724 LOG_DBG("instance busy");
1725
1726 return -EBUSY;
1727 }
1728
1729 err = read_recv_state(inst, idx);
1730 if (err != 0) {
1731 (void)memset(&inst->read_params, 0,
1732 sizeof(inst->read_params));
1733 atomic_clear_bit(inst->flags, BAP_BA_FLAG_BUSY);
1734 }
1735
1736 return err;
1737 }
1738