1 /* @file
2 * @brief Bluetooth Unicast Client
3 */
4
5 /*
6 * Copyright (c) 2020 Intel Corporation
7 * Copyright (c) 2022-2023 Nordic Semiconductor ASA
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #include <errno.h>
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 #include <string.h>
17
18 #include <zephyr/autoconf.h>
19 #include <zephyr/bluetooth/att.h>
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/conn.h>
22 #include <zephyr/bluetooth/gap.h>
23 #include <zephyr/bluetooth/gatt.h>
24 #include <zephyr/bluetooth/hci.h>
25 #include <zephyr/bluetooth/audio/audio.h>
26 #include <zephyr/bluetooth/audio/bap.h>
27 #include <zephyr/bluetooth/hci_types.h>
28 #include <zephyr/bluetooth/iso.h>
29 #include <zephyr/bluetooth/uuid.h>
30 #include <zephyr/kernel.h>
31 #include <zephyr/logging/log.h>
32 #include <zephyr/net/buf.h>
33 #include <zephyr/sys/__assert.h>
34 #include <zephyr/sys/atomic.h>
35 #include <zephyr/sys/byteorder.h>
36 #include <zephyr/sys/check.h>
37 #include <zephyr/sys/slist.h>
38 #include <zephyr/sys/util.h>
39 #include <zephyr/sys/util_macro.h>
40 #include <zephyr/toolchain.h>
41
42 #include "../host/hci_core.h"
43 #include "../host/conn_internal.h"
44 #include "../host/iso_internal.h"
45
46 #include "ascs_internal.h"
47 #include "audio_internal.h"
48 #include "bap_iso.h"
49 #include "bap_endpoint.h"
50 #include "bap_unicast_client_internal.h"
51 #include "pacs_internal.h"
52
53 BUILD_ASSERT(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 ||
54 CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0,
55 "CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT or "
56 "CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT shall be non-zero");
57
58 BUILD_ASSERT(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT == 0 ||
59 CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1,
60 "CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT shall be either 0 or > 1");
61
62 BUILD_ASSERT(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT == 0 ||
63 CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1,
64 "CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT shall be either 0 or > 1");
65
66 LOG_MODULE_REGISTER(bt_bap_unicast_client, CONFIG_BT_BAP_UNICAST_CLIENT_LOG_LEVEL);
67
68 #define PAC_DIR_UNUSED(dir) ((dir) != BT_AUDIO_DIR_SINK && (dir) != BT_AUDIO_DIR_SOURCE)
69 struct bt_bap_unicast_client_ep {
70 uint16_t handle;
71 uint16_t cp_handle;
72 struct bt_gatt_subscribe_params subscribe;
73 struct bt_gatt_discover_params discover;
74 struct bt_bap_ep ep;
75 struct k_work_delayable ase_read_work;
76
77 /* Bool to help handle different order of CP and ASE notification when releasing */
78 bool release_requested;
79 bool cp_ntf_pending;
80 };
81
82 static const struct bt_uuid *snk_uuid = BT_UUID_PACS_SNK;
83 static const struct bt_uuid *src_uuid = BT_UUID_PACS_SRC;
84 static const struct bt_uuid *pacs_context_uuid = BT_UUID_PACS_SUPPORTED_CONTEXT;
85 static const struct bt_uuid *pacs_snk_loc_uuid = BT_UUID_PACS_SNK_LOC;
86 static const struct bt_uuid *pacs_src_loc_uuid = BT_UUID_PACS_SRC_LOC;
87 static const struct bt_uuid *pacs_avail_ctx_uuid = BT_UUID_PACS_AVAILABLE_CONTEXT;
88 static const struct bt_uuid *ase_snk_uuid = BT_UUID_ASCS_ASE_SNK;
89 static const struct bt_uuid *ase_src_uuid = BT_UUID_ASCS_ASE_SRC;
90 static const struct bt_uuid *cp_uuid = BT_UUID_ASCS_ASE_CP;
91
92 static struct bt_bap_unicast_group unicast_groups[UNICAST_GROUP_CNT];
93
94 static struct unicast_client {
95 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
96 struct bt_bap_unicast_client_ep snks[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
97 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
98 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
99 struct bt_bap_unicast_client_ep srcs[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
100 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
101
102 struct bt_gatt_subscribe_params cp_subscribe;
103 struct bt_gatt_subscribe_params snk_loc_subscribe;
104 struct bt_gatt_subscribe_params src_loc_subscribe;
105 struct bt_gatt_subscribe_params avail_ctx_subscribe;
106
107 /* TODO: We should be able to reduce the number of discover params for
108 * CCCD discovery, but requires additional work if it is to support an
109 * arbitrary number of EATT bearers, as control point and location CCCD
110 * discovery needs to be done in serial to avoid using the same discover
111 * parameters twice
112 */
113 struct bt_gatt_discover_params loc_cc_disc;
114 struct bt_gatt_discover_params avail_ctx_cc_disc;
115
116 /* Discovery parameters */
117 enum bt_audio_dir dir;
118 bool busy;
119 union {
120 struct bt_gatt_read_params read_params;
121 struct bt_gatt_discover_params disc_params;
122 struct bt_gatt_write_params write_params;
123 };
124
125 /* The att_buf needs to use the maximum ATT attribute size as a single
126 * PAC record may use the full size
127 */
128 uint8_t att_buf[BT_ATT_MAX_ATTRIBUTE_LEN];
129 struct net_buf_simple net_buf;
130 } uni_cli_insts[CONFIG_BT_MAX_CONN];
131
132 static const struct bt_bap_unicast_client_cb *unicast_client_cbs;
133
134 /* TODO: Move the functions to avoid these prototypes */
135 static int unicast_client_ep_set_metadata(struct bt_bap_ep *ep, void *data, uint8_t len,
136 struct bt_audio_codec_cfg *codec_cfg);
137
138 static int unicast_client_ep_set_codec_cfg(struct bt_bap_ep *ep, uint8_t id, uint16_t cid,
139 uint16_t vid, void *data, uint8_t len,
140 struct bt_audio_codec_cfg *codec_cfg);
141 static int unicast_client_ep_start(struct bt_bap_ep *ep,
142 struct net_buf_simple *buf);
143
144 static int unicast_client_ase_discover(struct bt_conn *conn, uint16_t start_handle);
145
146 static void unicast_client_reset(struct bt_bap_ep *ep, uint8_t reason);
147
148 static void delayed_ase_read_handler(struct k_work *work);
149 static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_simple *buf);
150
unicast_client_send_start(struct bt_bap_ep * ep)151 static int unicast_client_send_start(struct bt_bap_ep *ep)
152 {
153 if (ep->receiver_ready != true || ep->dir != BT_AUDIO_DIR_SOURCE) {
154 LOG_DBG("Invalid ep %p %u %s",
155 ep, ep->receiver_ready, bt_audio_dir_str(ep->dir));
156
157 return -EINVAL;
158 }
159
160 struct bt_ascs_start_op *req;
161 struct net_buf_simple *buf;
162 int err;
163
164 buf = bt_bap_unicast_client_ep_create_pdu(ep->stream->conn, BT_ASCS_START_OP);
165 if (buf == NULL) {
166 LOG_DBG("Could not create PDU");
167 return -EBUSY;
168 }
169
170 req = net_buf_simple_add(buf, sizeof(*req));
171 req->num_ases = 1U;
172
173 err = unicast_client_ep_start(ep, buf);
174 if (err != 0) {
175 LOG_DBG("unicast_client_ep_start failed: %d",
176 err);
177
178 return err;
179 }
180
181 err = bt_bap_unicast_client_ep_send(ep->stream->conn, ep, buf);
182 if (err != 0) {
183 LOG_DBG("bt_bap_unicast_client_ep_send failed: %d", err);
184
185 return err;
186 }
187
188 return 0;
189 }
190
191 static void unicast_client_ep_idle_state(struct bt_bap_ep *ep);
192
audio_stream_by_ep_id(const struct bt_conn * conn,uint8_t id)193 static struct bt_bap_stream *audio_stream_by_ep_id(const struct bt_conn *conn,
194 uint8_t id)
195 {
196 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 || CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
197 const uint8_t conn_index = bt_conn_index(conn);
198 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 || \
199 * CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 \
200 */
201
202 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
203 for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[conn_index].snks); i++) {
204 const struct bt_bap_unicast_client_ep *client_ep =
205 &uni_cli_insts[conn_index].snks[i];
206
207 if (client_ep->ep.status.id == id) {
208 return client_ep->ep.stream;
209 }
210 }
211 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
212
213 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
214 for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[conn_index].srcs); i++) {
215 const struct bt_bap_unicast_client_ep *client_ep =
216 &uni_cli_insts[conn_index].srcs[i];
217
218 if (client_ep->ep.status.id == id) {
219 return client_ep->ep.stream;
220 }
221 }
222 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
223
224 return NULL;
225 }
226
reset_att_buf(struct unicast_client * client)227 static void reset_att_buf(struct unicast_client *client)
228 {
229 net_buf_simple_init_with_data(&client->net_buf, &client->att_buf, sizeof(client->att_buf));
230 net_buf_simple_reset(&client->net_buf);
231 }
232
233 #if defined(CONFIG_BT_AUDIO_RX)
unicast_client_ep_iso_recv(struct bt_iso_chan * chan,const struct bt_iso_recv_info * info,struct net_buf * buf)234 static void unicast_client_ep_iso_recv(struct bt_iso_chan *chan,
235 const struct bt_iso_recv_info *info, struct net_buf *buf)
236 {
237 struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
238 const struct bt_bap_stream_ops *ops;
239 struct bt_bap_stream *stream;
240 struct bt_bap_ep *ep = iso->rx.ep;
241
242 if (ep == NULL) {
243 /* In the case that the CIS has been setup as bidirectional, and
244 * only one of the directions have an ASE configured yet,
245 * we should only care about valid ISO packets when doing this
246 * check. The reason is that some controllers send HCI ISO data
247 * packets to the host, even if no SDU was sent on the remote
248 * side. This basically means that empty PDUs are sent to the
249 * host as HCI ISO data packets, which we should just ignore
250 */
251 if ((info->flags & BT_ISO_FLAGS_VALID) != 0) {
252 LOG_DBG("Valid ISO packet of len %zu received for iso %p not bound with ep",
253 net_buf_frags_len(buf), chan);
254 }
255
256 return;
257 }
258
259 if (ep->status.state != BT_BAP_EP_STATE_STREAMING) {
260 if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
261 LOG_DBG("ep %p is not in the streaming state: %s", ep,
262 bt_bap_ep_state_str(ep->status.state));
263 }
264
265 return;
266 }
267
268 stream = ep->stream;
269 if (stream == NULL) {
270 LOG_ERR("No stream for ep %p", ep);
271 return;
272 }
273
274 ops = stream->ops;
275
276 if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
277 LOG_DBG("stream %p ep %p len %zu", stream, ep, net_buf_frags_len(buf));
278 }
279
280 if (ops != NULL && ops->recv != NULL) {
281 ops->recv(stream, info, buf);
282 } else {
283 LOG_WRN("No callback for recv set");
284 }
285 }
286 #endif /* CONFIG_BT_AUDIO_RX */
287
288 #if defined(CONFIG_BT_AUDIO_TX)
unicast_client_ep_iso_sent(struct bt_iso_chan * chan)289 static void unicast_client_ep_iso_sent(struct bt_iso_chan *chan)
290 {
291 struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
292 struct bt_bap_stream *stream;
293 struct bt_bap_ep *ep = iso->tx.ep;
294
295 if (ep == NULL) {
296 LOG_ERR("iso %p not bound with ep", chan);
297 return;
298 }
299
300 stream = ep->stream;
301 if (stream == NULL) {
302 LOG_ERR("No stream for ep %p", ep);
303 return;
304 }
305
306 if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
307 LOG_DBG("stream %p ep %p", stream, ep);
308 }
309
310 if (stream->ops != NULL && stream->ops->sent != NULL) {
311 stream->ops->sent(stream);
312 }
313 }
314 #endif /* CONFIG_BT_AUDIO_TX */
315
unicast_client_ep_iso_connected(struct bt_bap_ep * ep)316 static void unicast_client_ep_iso_connected(struct bt_bap_ep *ep)
317 {
318 const struct bt_bap_stream_ops *stream_ops;
319 struct bt_bap_stream *stream;
320
321 if (ep->status.state != BT_BAP_EP_STATE_ENABLING) {
322 LOG_DBG("endpoint not in enabling state: %s",
323 bt_bap_ep_state_str(ep->status.state));
324 return;
325 }
326
327 stream = ep->stream;
328 if (stream == NULL) {
329 LOG_ERR("No stream for ep %p", ep);
330 return;
331 }
332
333 LOG_DBG("stream %p ep %p dir %s receiver_ready %u",
334 stream, ep, bt_audio_dir_str(ep->dir), ep->receiver_ready);
335
336 #if defined(CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM)
337 /* reset sequence number */
338 stream->_prev_seq_num = 0U;
339 #endif /* CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM */
340
341 stream_ops = stream->ops;
342 if (stream_ops != NULL && stream_ops->connected != NULL) {
343 stream_ops->connected(stream);
344 }
345 }
346
unicast_client_iso_connected(struct bt_iso_chan * chan)347 static void unicast_client_iso_connected(struct bt_iso_chan *chan)
348 {
349 struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
350
351 if (iso->rx.ep == NULL && iso->tx.ep == NULL) {
352 LOG_ERR("iso %p not bound with ep", chan);
353 return;
354 }
355
356 if (iso->rx.ep != NULL) {
357 unicast_client_ep_iso_connected(iso->rx.ep);
358 }
359
360 if (iso->tx.ep != NULL) {
361 unicast_client_ep_iso_connected(iso->tx.ep);
362 }
363 }
364
unicast_client_ep_iso_disconnected(struct bt_bap_ep * ep,uint8_t reason)365 static void unicast_client_ep_iso_disconnected(struct bt_bap_ep *ep, uint8_t reason)
366 {
367 const struct bt_bap_stream_ops *stream_ops;
368 struct bt_bap_stream *stream;
369
370 stream = ep->stream;
371 if (stream == NULL) {
372 LOG_ERR("Stream not associated with an ep");
373 return;
374 }
375
376 LOG_DBG("stream %p ep %p reason 0x%02x", stream, ep, reason);
377 ep->reason = reason;
378
379 stream_ops = stream->ops;
380 if (stream_ops != NULL && stream_ops->disconnected != NULL) {
381 stream_ops->disconnected(stream, reason);
382 }
383
384 /* If we were in the idle state when we started the ISO disconnection
385 * then we need to call unicast_client_ep_idle_state again when
386 * the ISO has finalized the disconnection
387 */
388 if (ep->status.state == BT_BAP_EP_STATE_IDLE) {
389
390 unicast_client_ep_idle_state(ep);
391
392 if (stream->conn != NULL) {
393 struct bt_conn_info conn_info;
394 int err;
395
396 err = bt_conn_get_info(stream->conn, &conn_info);
397 if (err != 0 || conn_info.state == BT_CONN_STATE_DISCONNECTED) {
398 /* Retrigger the reset of the EP if the ACL is disconnected before
399 * the ISO is disconnected
400 */
401 unicast_client_reset(ep, reason);
402 }
403 }
404 }
405 }
406
unicast_client_iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)407 static void unicast_client_iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
408 {
409 struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
410
411 if (iso->rx.ep == NULL && iso->tx.ep == NULL) {
412 LOG_ERR("iso %p not bound with ep", chan);
413 return;
414 }
415
416 if (iso->rx.ep != NULL) {
417 unicast_client_ep_iso_disconnected(iso->rx.ep, reason);
418 }
419
420 if (iso->tx.ep != NULL) {
421 unicast_client_ep_iso_disconnected(iso->tx.ep, reason);
422 }
423 }
424
425 static struct bt_iso_chan_ops unicast_client_iso_ops = {
426 #if defined(CONFIG_BT_AUDIO_RX)
427 .recv = unicast_client_ep_iso_recv,
428 #endif /* CONFIG_BT_AUDIO_RX */
429 #if defined(CONFIG_BT_AUDIO_TX)
430 .sent = unicast_client_ep_iso_sent,
431 #endif /* CONFIG_BT_AUDIO_TX */
432 .connected = unicast_client_iso_connected,
433 .disconnected = unicast_client_iso_disconnected,
434 };
435
bt_bap_ep_is_unicast_client(const struct bt_bap_ep * ep)436 bool bt_bap_ep_is_unicast_client(const struct bt_bap_ep *ep)
437 {
438 for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts); i++) {
439 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
440 if (PART_OF_ARRAY(uni_cli_insts[i].snks, ep)) {
441 return true;
442 }
443 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
444
445 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
446 if (PART_OF_ARRAY(uni_cli_insts[i].srcs, ep)) {
447 return true;
448 }
449 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
450 }
451
452 return false;
453 }
454
unicast_client_ep_init(struct bt_bap_ep * ep,uint16_t handle,uint8_t dir)455 static void unicast_client_ep_init(struct bt_bap_ep *ep, uint16_t handle, uint8_t dir)
456 {
457 struct bt_bap_unicast_client_ep *client_ep;
458
459 LOG_DBG("ep %p dir %s handle 0x%04x", ep, bt_audio_dir_str(dir), handle);
460
461 client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
462
463 (void)memset(ep, 0, sizeof(*ep));
464 client_ep->handle = handle;
465 ep->status.id = 0U;
466 ep->dir = dir;
467 ep->reason = BT_HCI_ERR_SUCCESS;
468 k_work_init_delayable(&client_ep->ase_read_work, delayed_ase_read_handler);
469 }
470
unicast_client_ep_find(struct bt_conn * conn,uint16_t handle)471 static struct bt_bap_ep *unicast_client_ep_find(struct bt_conn *conn, uint16_t handle)
472 {
473 uint8_t index;
474
475 index = bt_conn_index(conn);
476
477 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
478 for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].snks); i++) {
479 struct bt_bap_unicast_client_ep *client_ep = &uni_cli_insts[index].snks[i];
480
481 if ((handle && client_ep->handle == handle) || (!handle && client_ep->handle)) {
482 return &client_ep->ep;
483 }
484 }
485 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
486
487 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
488 for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].srcs); i++) {
489 struct bt_bap_unicast_client_ep *client_ep = &uni_cli_insts[index].srcs[i];
490
491 if ((handle && client_ep->handle == handle) || (!handle && client_ep->handle)) {
492 return &client_ep->ep;
493 }
494 }
495 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
496
497 return NULL;
498 }
499
bt_bap_unicast_client_new_audio_iso(void)500 struct bt_bap_iso *bt_bap_unicast_client_new_audio_iso(void)
501 {
502 struct bt_bap_iso *bap_iso;
503
504 bap_iso = bt_bap_iso_new();
505 if (bap_iso == NULL) {
506 return NULL;
507 }
508
509 bt_bap_iso_init(bap_iso, &unicast_client_iso_ops);
510
511 LOG_DBG("New bap_iso %p", bap_iso);
512
513 return bap_iso;
514 }
515
unicast_client_ep_new(struct bt_conn * conn,enum bt_audio_dir dir,uint16_t handle)516 static struct bt_bap_ep *unicast_client_ep_new(struct bt_conn *conn, enum bt_audio_dir dir,
517 uint16_t handle)
518 {
519 size_t i, size;
520 uint8_t index;
521 struct bt_bap_unicast_client_ep *cache;
522
523 index = bt_conn_index(conn);
524
525 switch (dir) {
526 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
527 case BT_AUDIO_DIR_SINK:
528 cache = uni_cli_insts[index].snks;
529 size = ARRAY_SIZE(uni_cli_insts[index].snks);
530 break;
531 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
532 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
533 case BT_AUDIO_DIR_SOURCE:
534 cache = uni_cli_insts[index].srcs;
535 size = ARRAY_SIZE(uni_cli_insts[index].srcs);
536 break;
537 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
538 default:
539 return NULL;
540 }
541
542 for (i = 0; i < size; i++) {
543 struct bt_bap_unicast_client_ep *client_ep = &cache[i];
544
545 if (!client_ep->handle) {
546 unicast_client_ep_init(&client_ep->ep, handle, dir);
547 return &client_ep->ep;
548 }
549 }
550
551 return NULL;
552 }
553
unicast_client_ep_get(struct bt_conn * conn,enum bt_audio_dir dir,uint16_t handle)554 static struct bt_bap_ep *unicast_client_ep_get(struct bt_conn *conn, enum bt_audio_dir dir,
555 uint16_t handle)
556 {
557 struct bt_bap_ep *ep;
558
559 ep = unicast_client_ep_find(conn, handle);
560 if (ep || !handle) {
561 return ep;
562 }
563
564 return unicast_client_ep_new(conn, dir, handle);
565 }
566
unicast_client_ep_set_local_idle_state(struct bt_bap_ep * ep)567 static void unicast_client_ep_set_local_idle_state(struct bt_bap_ep *ep)
568 {
569 struct bt_ascs_ase_status status = {
570 .id = ep->status.id,
571 .state = BT_BAP_EP_STATE_IDLE,
572 };
573 struct net_buf_simple buf;
574
575 net_buf_simple_init_with_data(&buf, &status, sizeof(status));
576
577 unicast_client_ep_set_status(ep, &buf);
578 }
579
unicast_client_ep_idle_state(struct bt_bap_ep * ep)580 static void unicast_client_ep_idle_state(struct bt_bap_ep *ep)
581 {
582 struct bt_bap_unicast_client_ep *client_ep =
583 CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
584 struct bt_bap_stream *stream = ep->stream;
585 const struct bt_bap_stream_ops *ops;
586
587 ep->receiver_ready = false;
588
589 if (stream == NULL) {
590 return;
591 }
592
593 /* If CIS is connected, disconnect and wait for CIS disconnection */
594 if (bt_bap_stream_can_disconnect(stream)) {
595 int err;
596
597 LOG_DBG("Disconnecting stream");
598 err = bt_bap_stream_disconnect(stream);
599
600 if (err != 0) {
601 LOG_ERR("Failed to disconnect stream: %d", err);
602 }
603
604 return;
605 } else if (ep->iso != NULL && ep->iso->chan.state == BT_ISO_STATE_DISCONNECTING) {
606 /* Wait for disconnection */
607 return;
608 }
609
610 bt_bap_stream_reset(stream);
611
612 /* Notify upper layer */
613 if (client_ep->release_requested) {
614 client_ep->release_requested = false;
615
616 if (client_ep->cp_ntf_pending) {
617 /* In case that we get the idle state notification before the CP
618 * notification we trigger the CP callback now, as after this we won't be
619 * able to find the stream by the ASE ID
620 */
621 client_ep->cp_ntf_pending = false;
622
623 if (unicast_client_cbs != NULL && unicast_client_cbs->release != NULL) {
624 unicast_client_cbs->release(stream, BT_BAP_ASCS_RSP_CODE_SUCCESS,
625 BT_BAP_ASCS_REASON_NONE);
626 }
627 }
628 }
629
630 ops = stream->ops;
631 if (ops != NULL && ops->released != NULL) {
632 ops->released(stream);
633 } else {
634 LOG_WRN("No callback for released set");
635 }
636 }
637
unicast_client_ep_qos_update(struct bt_bap_ep * ep,const struct bt_ascs_ase_status_qos * qos)638 static void unicast_client_ep_qos_update(struct bt_bap_ep *ep,
639 const struct bt_ascs_ase_status_qos *qos)
640 {
641 struct bt_iso_chan_io_qos *iso_io_qos;
642
643 LOG_DBG("ep %p dir %s bap_iso %p", ep, bt_audio_dir_str(ep->dir), ep->iso);
644
645 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
646 /* If the endpoint is a source, then we need to
647 * reset our RX parameters
648 */
649 iso_io_qos = &ep->iso->rx.qos;
650 } else if (ep->dir == BT_AUDIO_DIR_SINK) {
651 /* If the endpoint is a sink, then we need to
652 * reset our TX parameters
653 */
654 iso_io_qos = &ep->iso->tx.qos;
655 } else {
656 __ASSERT(false, "Invalid ep->dir: %u", ep->dir);
657 return;
658 }
659
660 iso_io_qos->phy = qos->phy;
661 iso_io_qos->sdu = sys_le16_to_cpu(qos->sdu);
662 iso_io_qos->rtn = qos->rtn;
663 }
664
unicast_client_ep_config_state(struct bt_bap_ep * ep,struct net_buf_simple * buf)665 static void unicast_client_ep_config_state(struct bt_bap_ep *ep, struct net_buf_simple *buf)
666 {
667 struct bt_bap_unicast_client_ep *client_ep =
668 CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
669 struct bt_ascs_ase_status_config *cfg;
670 struct bt_audio_codec_qos_pref *pref;
671 struct bt_bap_stream *stream;
672 void *cc;
673
674 ep->receiver_ready = false;
675
676 if (client_ep->release_requested) {
677 LOG_DBG("Released was requested, change local state to idle");
678 ep->reason = BT_HCI_ERR_LOCALHOST_TERM_CONN;
679 unicast_client_ep_set_local_idle_state(ep);
680 return;
681 }
682
683 if (buf->len < sizeof(*cfg)) {
684 LOG_ERR("Config status too short");
685 return;
686 }
687
688 stream = ep->stream;
689 if (stream == NULL) {
690 LOG_WRN("No stream active for endpoint");
691 return;
692 }
693
694 cfg = net_buf_simple_pull_mem(buf, sizeof(*cfg));
695
696 if (stream->codec_cfg == NULL) {
697 LOG_ERR("Stream %p does not have a codec configured", stream);
698 return;
699 } else if (stream->codec_cfg->id != cfg->codec.id) {
700 LOG_ERR("Codec configuration mismatched: %u, %u", stream->codec_cfg->id,
701 cfg->codec.id);
702 /* TODO: Release the stream? */
703 return;
704 }
705
706 if (buf->len < cfg->cc_len) {
707 LOG_ERR("Malformed ASE Config status: buf->len %u < %u cc_len", buf->len,
708 cfg->cc_len);
709 return;
710 }
711
712 cc = net_buf_simple_pull_mem(buf, cfg->cc_len);
713
714 pref = &stream->ep->qos_pref;
715
716 /* Convert to interval representation so they can be matched by QoS */
717 pref->unframed_supported = cfg->framing == BT_ASCS_QOS_FRAMING_UNFRAMED;
718 pref->phy = cfg->phy;
719 pref->rtn = cfg->rtn;
720 pref->latency = sys_le16_to_cpu(cfg->latency);
721 pref->pd_min = sys_get_le24(cfg->pd_min);
722 pref->pd_max = sys_get_le24(cfg->pd_max);
723 pref->pref_pd_min = sys_get_le24(cfg->prefer_pd_min);
724 pref->pref_pd_max = sys_get_le24(cfg->prefer_pd_max);
725
726 LOG_DBG("dir %s unframed_supported 0x%02x phy 0x%02x rtn %u "
727 "latency %u pd_min %u pd_max %u pref_pd_min %u pref_pd_max %u codec 0x%02x ",
728 bt_audio_dir_str(ep->dir), pref->unframed_supported, pref->phy, pref->rtn,
729 pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max,
730 stream->codec_cfg->id);
731
732 unicast_client_ep_set_codec_cfg(ep, cfg->codec.id, sys_le16_to_cpu(cfg->codec.cid),
733 sys_le16_to_cpu(cfg->codec.vid), cc, cfg->cc_len, NULL);
734
735 /* Notify upper layer */
736 if (stream->ops != NULL && stream->ops->configured != NULL) {
737 stream->ops->configured(stream, pref);
738 } else {
739 LOG_WRN("No callback for configured set");
740 }
741 }
742
unicast_client_ep_qos_state(struct bt_bap_ep * ep,struct net_buf_simple * buf,uint8_t old_state)743 static void unicast_client_ep_qos_state(struct bt_bap_ep *ep, struct net_buf_simple *buf,
744 uint8_t old_state)
745 {
746 const struct bt_bap_stream_ops *ops;
747 struct bt_ascs_ase_status_qos *qos;
748 struct bt_bap_stream *stream;
749
750 ep->receiver_ready = false;
751
752 if (buf->len < sizeof(*qos)) {
753 LOG_ERR("QoS status too short");
754 return;
755 }
756
757 stream = ep->stream;
758 if (stream == NULL) {
759 LOG_ERR("No stream active for endpoint");
760 return;
761 }
762 ops = stream->ops;
763
764 if (ops != NULL) {
765 if (ep->dir == BT_AUDIO_DIR_SINK && ops->disabled != NULL) {
766 /* If the old state was enabling or streaming, then the sink
767 * ASE has been disabled. Since the sink ASE does not have a
768 * disabling state, we can check if by comparing the old_state
769 */
770 const bool disabled = old_state == BT_BAP_EP_STATE_ENABLING ||
771 old_state == BT_BAP_EP_STATE_STREAMING;
772
773 if (disabled) {
774 ops->disabled(stream);
775 }
776 } else if (ep->dir == BT_AUDIO_DIR_SOURCE &&
777 old_state == BT_BAP_EP_STATE_DISABLING && ops->stopped != NULL) {
778 /* We left the disabling state, let the upper layers know that the stream is
779 * stopped
780 */
781 uint8_t reason = ep->reason;
782
783 if (reason == BT_HCI_ERR_SUCCESS) {
784 /* Default to BT_HCI_ERR_UNSPECIFIED if no other reason is set */
785 reason = BT_HCI_ERR_UNSPECIFIED;
786 } else {
787 /* Reset reason */
788 ep->reason = BT_HCI_ERR_SUCCESS;
789 }
790
791 ops->stopped(stream, reason);
792 }
793 }
794
795 qos = net_buf_simple_pull_mem(buf, sizeof(*qos));
796
797 /* Update existing QoS configuration */
798 unicast_client_ep_qos_update(ep, qos);
799
800 ep->cig_id = qos->cig_id;
801 ep->cis_id = qos->cis_id;
802 (void)memcpy(&stream->qos->interval, sys_le24_to_cpu(qos->interval), sizeof(qos->interval));
803 stream->qos->framing = qos->framing;
804 stream->qos->phy = qos->phy;
805 stream->qos->sdu = sys_le16_to_cpu(qos->sdu);
806 stream->qos->rtn = qos->rtn;
807 stream->qos->latency = sys_le16_to_cpu(qos->latency);
808 (void)memcpy(&stream->qos->pd, sys_le24_to_cpu(qos->pd), sizeof(qos->pd));
809
810 LOG_DBG("dir %s cig 0x%02x cis 0x%02x codec 0x%02x interval %u "
811 "framing 0x%02x phy 0x%02x rtn %u latency %u pd %u",
812 bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id, stream->codec_cfg->id,
813 stream->qos->interval, stream->qos->framing, stream->qos->phy, stream->qos->rtn,
814 stream->qos->latency, stream->qos->pd);
815
816 /* Disconnect ISO if connected */
817 if (bt_bap_stream_can_disconnect(stream)) {
818 const int err = bt_bap_stream_disconnect(stream);
819
820 if (err != 0) {
821 LOG_ERR("Failed to disconnect stream: %d", err);
822 }
823 } else {
824 /* We setup the data path here, as this is the earliest where
825 * we have the ISO <-> EP coupling completed (due to setting
826 * the CIS ID in the QoS procedure).
827 */
828
829 bt_bap_iso_configure_data_path(ep, stream->codec_cfg);
830 }
831
832 /* Notify upper layer */
833 if (stream->ops != NULL && stream->ops->qos_set != NULL) {
834 stream->ops->qos_set(stream);
835 } else {
836 LOG_WRN("No callback for qos_set set");
837 }
838 }
839
unicast_client_ep_enabling_state(struct bt_bap_ep * ep,struct net_buf_simple * buf,bool state_changed)840 static void unicast_client_ep_enabling_state(struct bt_bap_ep *ep, struct net_buf_simple *buf,
841 bool state_changed)
842 {
843 struct bt_ascs_ase_status_enable *enable;
844 struct bt_bap_stream *stream;
845 void *metadata;
846
847 if (buf->len < sizeof(*enable)) {
848 LOG_ERR("Enabling status too short");
849 return;
850 }
851
852 stream = ep->stream;
853 if (stream == NULL) {
854 LOG_ERR("No stream active for endpoint");
855 return;
856 }
857
858 enable = net_buf_simple_pull_mem(buf, sizeof(*enable));
859
860 if (buf->len < enable->metadata_len) {
861 LOG_ERR("Malformed PDU: remaining len %u expected %u", buf->len,
862 enable->metadata_len);
863 return;
864 }
865
866 metadata = net_buf_simple_pull_mem(buf, enable->metadata_len);
867
868 LOG_DBG("dir %s cig 0x%02x cis 0x%02x", bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id);
869
870 unicast_client_ep_set_metadata(ep, metadata, enable->metadata_len, NULL);
871
872 /* Notify upper layer
873 *
874 * If the state did not change then only the metadata was changed
875 */
876 if (state_changed) {
877 if (stream->ops != NULL && stream->ops->enabled != NULL) {
878 stream->ops->enabled(stream);
879 } else {
880 LOG_WRN("No callback for enabled set");
881 }
882 } else {
883 if (stream->ops != NULL && stream->ops->metadata_updated != NULL) {
884 stream->ops->metadata_updated(stream);
885 } else {
886 LOG_WRN("No callback for metadata_updated set");
887 }
888 }
889 }
890
unicast_client_ep_streaming_state(struct bt_bap_ep * ep,struct net_buf_simple * buf,bool state_changed)891 static void unicast_client_ep_streaming_state(struct bt_bap_ep *ep, struct net_buf_simple *buf,
892 bool state_changed)
893 {
894 struct bt_ascs_ase_status_stream *stream_status;
895 struct bt_bap_stream *stream;
896
897 if (buf->len < sizeof(*stream_status)) {
898 LOG_ERR("Streaming status too short");
899 return;
900 }
901
902 stream = ep->stream;
903 if (stream == NULL) {
904 LOG_ERR("No stream active for endpoint");
905 return;
906 }
907
908 stream_status = net_buf_simple_pull_mem(buf, sizeof(*stream_status));
909
910 LOG_DBG("dir %s cig 0x%02x cis 0x%02x", bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id);
911
912 /* Notify upper layer
913 *
914 * If the state did not change then only the metadata was changed
915 */
916 if (state_changed) {
917 if (stream->ops != NULL && stream->ops->started != NULL) {
918 stream->ops->started(stream);
919 } else {
920 LOG_WRN("No callback for started set");
921 }
922 } else {
923 if (stream->ops != NULL && stream->ops->metadata_updated != NULL) {
924 stream->ops->metadata_updated(stream);
925 } else {
926 LOG_WRN("No callback for metadata_updated set");
927 }
928 }
929 }
930
unicast_client_ep_disabling_state(struct bt_bap_ep * ep,struct net_buf_simple * buf)931 static void unicast_client_ep_disabling_state(struct bt_bap_ep *ep, struct net_buf_simple *buf)
932 {
933 struct bt_ascs_ase_status_disable *disable;
934 struct bt_bap_stream *stream;
935
936 ep->receiver_ready = false;
937
938 if (buf->len < sizeof(*disable)) {
939 LOG_ERR("Disabling status too short");
940 return;
941 }
942
943 stream = ep->stream;
944 if (stream == NULL) {
945 LOG_ERR("No stream active for endpoint");
946 return;
947 }
948
949 disable = net_buf_simple_pull_mem(buf, sizeof(*disable));
950
951 LOG_DBG("dir %s cig 0x%02x cis 0x%02x", bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id);
952
953 /* Notify upper layer */
954 if (stream->ops != NULL && stream->ops->disabled != NULL) {
955 stream->ops->disabled(stream);
956 } else {
957 LOG_WRN("No callback for disabled set");
958 }
959 }
960
unicast_client_ep_releasing_state(struct bt_bap_ep * ep,struct net_buf_simple * buf)961 static void unicast_client_ep_releasing_state(struct bt_bap_ep *ep, struct net_buf_simple *buf)
962 {
963 struct bt_bap_stream *stream;
964
965 ep->receiver_ready = false;
966
967 stream = ep->stream;
968 if (stream == NULL) {
969 LOG_ERR("No stream active for endpoint");
970 return;
971 }
972
973 LOG_DBG("dir %s", bt_audio_dir_str(ep->dir));
974
975 if (bt_bap_stream_can_disconnect(stream)) {
976 /* The Unicast Client shall terminate any CIS established for
977 * that ASE by following the Connected Isochronous Stream
978 * Terminate procedure defined in Volume 3, Part C,
979 * Section 9.3.15 in when the Unicast Client has determined
980 * that the ASE is in the Releasing state.
981 */
982 const int err = bt_bap_stream_disconnect(stream);
983
984 if (err != 0) {
985 LOG_ERR("Failed to disconnect stream: %d", err);
986 }
987 }
988 }
989
unicast_client_ep_set_status(struct bt_bap_ep * ep,struct net_buf_simple * buf)990 static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_simple *buf)
991 {
992 struct bt_ascs_ase_status *status;
993 struct bt_bap_unicast_client_ep *client_ep;
994 bool state_changed;
995 uint8_t old_state;
996
997 if (!ep) {
998 return;
999 }
1000
1001 client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
1002
1003 status = net_buf_simple_pull_mem(buf, sizeof(*status));
1004
1005 old_state = ep->status.state;
1006 ep->status = *status;
1007 state_changed = old_state != ep->status.state;
1008
1009 if (state_changed && old_state == BT_BAP_EP_STATE_STREAMING) {
1010 /* We left the streaming state, let the upper layers know that the stream is stopped
1011 */
1012 struct bt_bap_stream *stream = ep->stream;
1013
1014 if (stream != NULL) {
1015 struct bt_bap_stream_ops *ops = stream->ops;
1016 uint8_t reason = ep->reason;
1017
1018 if (reason == BT_HCI_ERR_SUCCESS) {
1019 /* Default to BT_HCI_ERR_UNSPECIFIED if no other reason is set */
1020 reason = BT_HCI_ERR_UNSPECIFIED;
1021 } else {
1022 /* Reset reason */
1023 ep->reason = BT_HCI_ERR_SUCCESS;
1024 }
1025
1026 if (ops != NULL && ops->stopped != NULL) {
1027 ops->stopped(stream, reason);
1028 } else {
1029 LOG_WRN("No callback for stopped set");
1030 }
1031 }
1032 }
1033
1034 LOG_DBG("ep %p handle 0x%04x id 0x%02x dir %s state %s -> %s", ep, client_ep->handle,
1035 status->id, bt_audio_dir_str(ep->dir), bt_bap_ep_state_str(old_state),
1036 bt_bap_ep_state_str(status->state));
1037
1038 switch (status->state) {
1039 case BT_BAP_EP_STATE_IDLE:
1040 unicast_client_ep_idle_state(ep);
1041 break;
1042 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1043 switch (old_state) {
1044 /* Valid only if ASE_State field = 0x00 (Idle) */
1045 case BT_BAP_EP_STATE_IDLE:
1046 /* or 0x01 (Codec Configured) */
1047 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1048 /* or 0x02 (QoS Configured) */
1049 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1050 /* or 0x06 (Releasing) */
1051 case BT_BAP_EP_STATE_RELEASING:
1052 break;
1053 default:
1054 LOG_WRN("Invalid state transition: %s -> %s",
1055 bt_bap_ep_state_str(old_state),
1056 bt_bap_ep_state_str(ep->status.state));
1057 return;
1058 }
1059
1060 unicast_client_ep_config_state(ep, buf);
1061 break;
1062 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1063 /* QoS configured have different allowed states depending on the endpoint type */
1064 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
1065 switch (old_state) {
1066 /* Valid only if ASE_State field = 0x01 (Codec Configured) */
1067 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1068 /* or 0x02 (QoS Configured) */
1069 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1070 /* or 0x04 (Streaming) if there is a disconnect */
1071 case BT_BAP_EP_STATE_STREAMING:
1072 /* or 0x05 (Disabling) */
1073 case BT_BAP_EP_STATE_DISABLING:
1074 break;
1075 default:
1076 LOG_WRN("Invalid state transition: %s -> %s",
1077 bt_bap_ep_state_str(old_state),
1078 bt_bap_ep_state_str(ep->status.state));
1079 return;
1080 }
1081 } else {
1082 switch (old_state) {
1083 /* Valid only if ASE_State field = 0x01 (Codec Configured) */
1084 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1085 /* or 0x02 (QoS Configured) */
1086 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1087 /* or 0x03 (Enabling) */
1088 case BT_BAP_EP_STATE_ENABLING:
1089 /* or 0x04 (Streaming)*/
1090 case BT_BAP_EP_STATE_STREAMING:
1091 break;
1092 default:
1093 LOG_WRN("Invalid state transition: %s -> %s",
1094 bt_bap_ep_state_str(old_state),
1095 bt_bap_ep_state_str(ep->status.state));
1096 return;
1097 }
1098 }
1099
1100 unicast_client_ep_qos_state(ep, buf, old_state);
1101 break;
1102 case BT_BAP_EP_STATE_ENABLING:
1103 switch (old_state) {
1104 /* Valid only if ASE_State field = 0x02 (QoS Configured) */
1105 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1106 /* or 0x03 (Enabling) */
1107 case BT_BAP_EP_STATE_ENABLING:
1108 break;
1109 default:
1110 LOG_WRN("Invalid state transition: %s -> %s",
1111 bt_bap_ep_state_str(old_state),
1112 bt_bap_ep_state_str(ep->status.state));
1113 return;
1114 }
1115
1116 unicast_client_ep_enabling_state(ep, buf, state_changed);
1117 break;
1118 case BT_BAP_EP_STATE_STREAMING:
1119 switch (old_state) {
1120 /* Valid only if ASE_State field = 0x03 (Enabling)*/
1121 case BT_BAP_EP_STATE_ENABLING:
1122 /* or 0x04 (Streaming)*/
1123 case BT_BAP_EP_STATE_STREAMING:
1124 break;
1125 default:
1126 LOG_WRN("Invalid state transition: %s -> %s",
1127 bt_bap_ep_state_str(old_state),
1128 bt_bap_ep_state_str(ep->status.state));
1129 return;
1130 }
1131
1132 unicast_client_ep_streaming_state(ep, buf, state_changed);
1133 break;
1134 case BT_BAP_EP_STATE_DISABLING:
1135 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
1136 switch (old_state) {
1137 /* Valid only if ASE_State field = 0x03 (Enabling) */
1138 case BT_BAP_EP_STATE_ENABLING:
1139 /* or 0x04 (Streaming) */
1140 case BT_BAP_EP_STATE_STREAMING:
1141 break;
1142 default:
1143 LOG_WRN("Invalid state transition: %s -> %s",
1144 bt_bap_ep_state_str(old_state),
1145 bt_bap_ep_state_str(ep->status.state));
1146 return;
1147 }
1148 } else {
1149 /* Sinks cannot go into the disabling state */
1150 LOG_WRN("Invalid state transition: %s -> %s",
1151 bt_bap_ep_state_str(old_state),
1152 bt_bap_ep_state_str(ep->status.state));
1153 return;
1154 }
1155
1156 unicast_client_ep_disabling_state(ep, buf);
1157 break;
1158 case BT_BAP_EP_STATE_RELEASING:
1159 switch (old_state) {
1160 /* Valid only if ASE_State field = 0x01 (Codec Configured) */
1161 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1162 /* or 0x02 (QoS Configured) */
1163 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1164 /* or 0x03 (Enabling) */
1165 case BT_BAP_EP_STATE_ENABLING:
1166 /* or 0x04 (Streaming) */
1167 case BT_BAP_EP_STATE_STREAMING:
1168 break;
1169 /* or 0x04 (Disabling) */
1170 case BT_BAP_EP_STATE_DISABLING:
1171 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
1172 break;
1173 } /* else fall through for sink */
1174
1175 /* fall through */
1176 default:
1177 LOG_WRN("Invalid state transition: %s -> %s",
1178 bt_bap_ep_state_str(old_state),
1179 bt_bap_ep_state_str(ep->status.state));
1180 return;
1181 }
1182
1183 unicast_client_ep_releasing_state(ep, buf);
1184 break;
1185 }
1186 }
1187
valid_ltv_cb(struct bt_data * data,void * user_data)1188 static bool valid_ltv_cb(struct bt_data *data, void *user_data)
1189 {
1190 /* just return true to continue parsing as bt_data_parse will validate for us */
1191 return true;
1192 }
1193
unicast_client_ep_set_codec_cfg(struct bt_bap_ep * ep,uint8_t id,uint16_t cid,uint16_t vid,void * data,uint8_t len,struct bt_audio_codec_cfg * codec_cfg)1194 static int unicast_client_ep_set_codec_cfg(struct bt_bap_ep *ep, uint8_t id, uint16_t cid,
1195 uint16_t vid, void *data, uint8_t len,
1196 struct bt_audio_codec_cfg *codec_cfg)
1197 {
1198 if (!ep && !codec_cfg) {
1199 return -EINVAL;
1200 }
1201
1202 LOG_DBG("ep %p codec id 0x%02x cid 0x%04x vid 0x%04x len %u", ep, id, cid, vid, len);
1203
1204 if (!codec_cfg) {
1205 codec_cfg = &ep->codec_cfg;
1206 }
1207
1208 if (len > sizeof(codec_cfg->data)) {
1209 LOG_DBG("Cannot store %u octets of codec data", len);
1210
1211 return -ENOMEM;
1212 }
1213
1214 codec_cfg->id = id;
1215 codec_cfg->cid = cid;
1216 codec_cfg->vid = vid;
1217
1218 codec_cfg->data_len = len;
1219 memcpy(codec_cfg->data, data, len);
1220
1221 return 0;
1222 }
1223
unicast_client_set_codec_cap(uint8_t id,uint16_t cid,uint16_t vid,void * data,uint8_t data_len,void * meta,uint8_t meta_len,struct bt_audio_codec_cap * codec_cap)1224 static int unicast_client_set_codec_cap(uint8_t id, uint16_t cid, uint16_t vid, void *data,
1225 uint8_t data_len, void *meta, uint8_t meta_len,
1226 struct bt_audio_codec_cap *codec_cap)
1227 {
1228 struct net_buf_simple buf;
1229
1230 if (!codec_cap) {
1231 return -EINVAL;
1232 }
1233
1234 LOG_DBG("codec id 0x%02x cid 0x%04x vid 0x%04x data_len %u meta_len %u", id, cid, vid,
1235 data_len, meta_len);
1236
1237 /* Reset current data */
1238 (void)memset(codec_cap, 0, sizeof(*codec_cap));
1239
1240 codec_cap->id = id;
1241 codec_cap->cid = cid;
1242 codec_cap->vid = vid;
1243
1244 if (data_len > 0U) {
1245 if (data_len > sizeof(codec_cap->data)) {
1246 return -ENOMEM;
1247 }
1248
1249 net_buf_simple_init_with_data(&buf, data, data_len);
1250
1251 /* If codec is LC3, then it shall be LTV encoded - We verify this before storing the
1252 * data For any non-LC3 codecs, we cannot verify anything
1253 */
1254 if (id == BT_HCI_CODING_FORMAT_LC3) {
1255 bt_data_parse(&buf, valid_ltv_cb, NULL);
1256
1257 /* Check if all entries could be parsed */
1258 if (buf.len) {
1259 LOG_ERR("Unable to parse Codec capabilities: len %u", buf.len);
1260 return -EINVAL;
1261 }
1262 }
1263 memcpy(codec_cap->data, data, data_len);
1264 codec_cap->data_len = data_len;
1265 }
1266
1267 if (meta_len > 0U) {
1268 if (meta_len > sizeof(codec_cap->meta)) {
1269 return -ENOMEM;
1270 }
1271
1272 net_buf_simple_init_with_data(&buf, meta, meta_len);
1273
1274 bt_data_parse(&buf, valid_ltv_cb, NULL);
1275
1276 /* Check if all entries could be parsed */
1277 if (buf.len) {
1278 LOG_ERR("Unable to parse Codec metadata: len %u", buf.len);
1279 return -EINVAL;
1280 }
1281
1282 memcpy(codec_cap->meta, meta, meta_len);
1283 codec_cap->meta_len = meta_len;
1284 }
1285
1286 return 0;
1287 }
1288
unicast_client_ep_set_metadata(struct bt_bap_ep * ep,void * data,uint8_t len,struct bt_audio_codec_cfg * codec_cfg)1289 static int unicast_client_ep_set_metadata(struct bt_bap_ep *ep, void *data, uint8_t len,
1290 struct bt_audio_codec_cfg *codec_cfg)
1291 {
1292 if (!ep && !codec_cfg) {
1293 return -EINVAL;
1294 }
1295
1296 LOG_DBG("ep %p len %u codec_cfg %p", ep, len, codec_cfg);
1297
1298 if (!codec_cfg) {
1299 codec_cfg = &ep->codec_cfg;
1300 }
1301
1302 if (len > sizeof(codec_cfg->meta)) {
1303 LOG_DBG("Cannot store %u octets of metadata", len);
1304
1305 return -ENOMEM;
1306 }
1307
1308 /* Reset current metadata */
1309 codec_cfg->meta_len = len;
1310 (void)memcpy(codec_cfg->meta, data, len);
1311
1312 return 0;
1313 }
1314
unicast_client_cp_notify(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)1315 static uint8_t unicast_client_cp_notify(struct bt_conn *conn,
1316 struct bt_gatt_subscribe_params *params, const void *data,
1317 uint16_t length)
1318 {
1319 struct bt_ascs_cp_rsp *rsp;
1320 struct net_buf_simple buf;
1321
1322 LOG_DBG("conn %p len %u", conn, length);
1323
1324 if (!data) {
1325 LOG_DBG("Unsubscribed");
1326 params->value_handle = 0x0000;
1327 return BT_GATT_ITER_STOP;
1328 }
1329
1330 net_buf_simple_init_with_data(&buf, (void *)data, length);
1331
1332 if (buf.len < sizeof(*rsp)) {
1333 LOG_ERR("Control Point Notification too small");
1334 return BT_GATT_ITER_STOP;
1335 }
1336
1337 rsp = net_buf_simple_pull_mem(&buf, sizeof(*rsp));
1338
1339 if (rsp->num_ase == BT_ASCS_UNSUPP_OR_LENGTH_ERR_NUM_ASE) {
1340 /* This is a special case where num_ase == BT_ASCS_UNSUPP_OR_LENGTH_ERR_NUM_ASE
1341 * but really there is only one ASE response
1342 */
1343 rsp->num_ase = 1U;
1344 }
1345
1346 for (uint8_t i = 0U; i < rsp->num_ase; i++) {
1347 struct bt_bap_unicast_client_ep *client_ep = NULL;
1348 struct bt_ascs_cp_ase_rsp *ase_rsp;
1349 struct bt_bap_stream *stream;
1350
1351 if (buf.len < sizeof(*ase_rsp)) {
1352 LOG_ERR("Control Point Notification too small: %u", buf.len);
1353 return BT_GATT_ITER_STOP;
1354 }
1355
1356 ase_rsp = net_buf_simple_pull_mem(&buf, sizeof(*ase_rsp));
1357
1358 LOG_DBG("op %s (0x%02x) id 0x%02x code %s (0x%02x) "
1359 "reason %s (0x%02x)", bt_ascs_op_str(rsp->op), rsp->op,
1360 ase_rsp->id, bt_ascs_rsp_str(ase_rsp->code),
1361 ase_rsp->code, bt_ascs_reason_str(ase_rsp->reason),
1362 ase_rsp->reason);
1363
1364 if (unicast_client_cbs == NULL) {
1365 continue;
1366 }
1367
1368 stream = audio_stream_by_ep_id(conn, ase_rsp->id);
1369 if (stream == NULL) {
1370 LOG_DBG("Could not find stream by id %u", ase_rsp->id);
1371 } else {
1372 client_ep = CONTAINER_OF(stream->ep, struct bt_bap_unicast_client_ep, ep);
1373 client_ep->cp_ntf_pending = false;
1374 }
1375
1376 switch (rsp->op) {
1377 case BT_ASCS_CONFIG_OP:
1378 if (unicast_client_cbs->config != NULL) {
1379 unicast_client_cbs->config(stream, ase_rsp->code, ase_rsp->reason);
1380 }
1381 break;
1382 case BT_ASCS_QOS_OP:
1383 if (unicast_client_cbs->qos != NULL) {
1384 unicast_client_cbs->qos(stream, ase_rsp->code, ase_rsp->reason);
1385 }
1386 break;
1387 case BT_ASCS_ENABLE_OP:
1388 if (unicast_client_cbs->enable != NULL) {
1389 unicast_client_cbs->enable(stream, ase_rsp->code, ase_rsp->reason);
1390 }
1391 break;
1392 case BT_ASCS_START_OP:
1393 if (unicast_client_cbs->start != NULL) {
1394 unicast_client_cbs->start(stream, ase_rsp->code, ase_rsp->reason);
1395 }
1396 break;
1397 case BT_ASCS_DISABLE_OP:
1398 if (unicast_client_cbs->disable != NULL) {
1399 unicast_client_cbs->disable(stream, ase_rsp->code, ase_rsp->reason);
1400 }
1401 break;
1402 case BT_ASCS_STOP_OP:
1403 if (unicast_client_cbs->stop != NULL) {
1404 unicast_client_cbs->stop(stream, ase_rsp->code, ase_rsp->reason);
1405 }
1406 break;
1407 case BT_ASCS_METADATA_OP:
1408 if (unicast_client_cbs->metadata != NULL) {
1409 unicast_client_cbs->metadata(stream, ase_rsp->code,
1410 ase_rsp->reason);
1411 }
1412 break;
1413 case BT_ASCS_RELEASE_OP:
1414 /* client_ep->release_requested is set to false if handled by the
1415 * endpoint notification handler
1416 */
1417 if (client_ep != NULL && client_ep->release_requested) {
1418 /* If request was reject, do not expect endpoint notifications */
1419 if (ase_rsp->code != BT_BAP_ASCS_RSP_CODE_SUCCESS) {
1420 client_ep->cp_ntf_pending = false;
1421 client_ep->release_requested = false;
1422 }
1423
1424 if (unicast_client_cbs->release != NULL) {
1425 unicast_client_cbs->release(stream, ase_rsp->code,
1426 ase_rsp->reason);
1427 }
1428 }
1429 break;
1430 default:
1431 break;
1432 }
1433 }
1434
1435 return BT_GATT_ITER_CONTINUE;
1436 }
1437
unicast_client_ase_ntf_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)1438 static uint8_t unicast_client_ase_ntf_read_func(struct bt_conn *conn, uint8_t err,
1439 struct bt_gatt_read_params *read, const void *data,
1440 uint16_t length)
1441 {
1442 uint16_t handle = read->single.handle;
1443 struct net_buf_simple buf_clone;
1444 struct unicast_client *client;
1445 struct net_buf_simple *buf;
1446 struct bt_bap_ep *ep;
1447
1448 LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
1449
1450 if (err) {
1451 LOG_DBG("Failed to read ASE: %u", err);
1452
1453 return BT_GATT_ITER_STOP;
1454 }
1455
1456 LOG_DBG("handle 0x%04x", handle);
1457
1458 client = &uni_cli_insts[bt_conn_index(conn)];
1459 buf = &client->net_buf;
1460
1461 if (data != NULL) {
1462 if (net_buf_simple_tailroom(buf) < length) {
1463 LOG_DBG("Buffer full, invalid server response of size %u",
1464 length + client->net_buf.len);
1465 client->busy = false;
1466 reset_att_buf(client);
1467
1468 return BT_GATT_ITER_STOP;
1469 }
1470
1471 /* store data*/
1472 net_buf_simple_add_mem(buf, data, length);
1473
1474 return BT_GATT_ITER_CONTINUE;
1475 }
1476
1477 memset(read, 0, sizeof(*read));
1478
1479 if (buf->len < sizeof(struct bt_ascs_ase_status)) {
1480 LOG_DBG("Read response too small (%u)", buf->len);
1481 reset_att_buf(client);
1482 client->busy = false;
1483
1484 return BT_GATT_ITER_STOP;
1485 }
1486
1487 /* Clone the buffer so that we can reset it while still providing the data to the upper
1488 * layers
1489 */
1490 net_buf_simple_clone(buf, &buf_clone);
1491 reset_att_buf(client);
1492 client->busy = false;
1493
1494 ep = unicast_client_ep_get(conn, client->dir, handle);
1495 if (!ep) {
1496 LOG_DBG("Unknown %s ep for handle 0x%04X", bt_audio_dir_str(client->dir), handle);
1497 } else {
1498 /* Set reason in case this exits the streaming state, unless already set */
1499 if (ep->reason == BT_HCI_ERR_SUCCESS) {
1500 ep->reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN;
1501 }
1502
1503 unicast_client_ep_set_status(ep, &buf_clone);
1504 }
1505
1506 return BT_GATT_ITER_STOP;
1507 }
1508
long_ase_read(struct bt_bap_unicast_client_ep * client_ep)1509 static void long_ase_read(struct bt_bap_unicast_client_ep *client_ep)
1510 {
1511 /* Perform long read if notification is maximum size */
1512 struct bt_conn *conn = client_ep->ep.stream->conn;
1513 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1514 struct net_buf_simple *long_read_buf = &client->net_buf;
1515 int err;
1516
1517 LOG_DBG("conn %p ep %p 0x%04X busy %u", conn, &client_ep->ep, client_ep->handle,
1518 client->busy);
1519
1520 if (client->busy) {
1521 /* If the client is busy reading or writing something else, reschedule the
1522 * long read.
1523 */
1524 struct bt_conn_info conn_info;
1525
1526 err = bt_conn_get_info(conn, &conn_info);
1527 if (err != 0) {
1528 LOG_DBG("Failed to get conn info, use default interval");
1529
1530 conn_info.le.interval = BT_GAP_INIT_CONN_INT_MIN;
1531 }
1532
1533 /* Wait a connection interval to retry */
1534 err = k_work_reschedule(&client_ep->ase_read_work,
1535 K_USEC(BT_CONN_INTERVAL_TO_US(conn_info.le.interval)));
1536 if (err < 0) {
1537 LOG_DBG("Failed to reschedule ASE long read work: %d", err);
1538 }
1539
1540 return;
1541 }
1542
1543 client->read_params.func = unicast_client_ase_ntf_read_func;
1544 client->read_params.handle_count = 1U;
1545 client->read_params.single.handle = client_ep->handle;
1546 client->read_params.single.offset = long_read_buf->len;
1547
1548 err = bt_gatt_read(conn, &client->read_params);
1549 if (err != 0) {
1550 LOG_DBG("Failed to read ASE: %d", err);
1551 } else {
1552 client->busy = true;
1553 }
1554 }
1555
delayed_ase_read_handler(struct k_work * work)1556 static void delayed_ase_read_handler(struct k_work *work)
1557 {
1558 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
1559 struct bt_bap_unicast_client_ep *client_ep =
1560 CONTAINER_OF(dwork, struct bt_bap_unicast_client_ep, ase_read_work);
1561
1562 LOG_DBG("ep %p 0x%04X", &client_ep->ep, client_ep->handle);
1563
1564 /* Try reading again */
1565 long_ase_read(client_ep);
1566 }
1567
unicast_client_ep_notify(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)1568 static uint8_t unicast_client_ep_notify(struct bt_conn *conn,
1569 struct bt_gatt_subscribe_params *params, const void *data,
1570 uint16_t length)
1571 {
1572 struct net_buf_simple buf;
1573 struct bt_bap_unicast_client_ep *client_ep;
1574 const uint8_t att_ntf_header_size = 3; /* opcode (1) + handle (2) */
1575 uint16_t max_ntf_size;
1576 struct bt_bap_ep *ep;
1577
1578 client_ep = CONTAINER_OF(params, struct bt_bap_unicast_client_ep, subscribe);
1579 ep = &client_ep->ep;
1580
1581 LOG_DBG("conn %p ep %p len %u", conn, ep, length);
1582
1583 /* Cancel any pending long reads for the endpoint */
1584 (void)k_work_cancel_delayable(&client_ep->ase_read_work);
1585
1586 if (!data) {
1587 LOG_DBG("Unsubscribed");
1588 params->value_handle = 0x0000;
1589 return BT_GATT_ITER_STOP;
1590 }
1591
1592 max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size;
1593
1594 if (length == max_ntf_size) {
1595 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1596
1597 if (!client->busy) {
1598 struct net_buf_simple *long_read_buf = &client->net_buf;
1599
1600 /* store data*/
1601 net_buf_simple_add_mem(long_read_buf, data, length);
1602 }
1603
1604 long_ase_read(client_ep);
1605
1606 return BT_GATT_ITER_CONTINUE;
1607 }
1608
1609 net_buf_simple_init_with_data(&buf, (void *)data, length);
1610
1611 if (buf.len < sizeof(struct bt_ascs_ase_status)) {
1612 LOG_ERR("Notification too small");
1613 return BT_GATT_ITER_STOP;
1614 }
1615
1616 /* Set reason in case this exits the streaming state, unless already set */
1617 if (ep->reason == BT_HCI_ERR_SUCCESS) {
1618 ep->reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN;
1619 }
1620
1621 unicast_client_ep_set_status(ep, &buf);
1622
1623 return BT_GATT_ITER_CONTINUE;
1624 }
1625
unicast_client_ep_subscribe(struct bt_conn * conn,struct bt_bap_ep * ep)1626 static int unicast_client_ep_subscribe(struct bt_conn *conn, struct bt_bap_ep *ep)
1627 {
1628 struct bt_bap_unicast_client_ep *client_ep;
1629 int err;
1630
1631 client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
1632
1633 LOG_DBG("ep %p handle 0x%02x", ep, client_ep->handle);
1634
1635 if (client_ep->subscribe.value_handle) {
1636 return 0;
1637 }
1638
1639 client_ep->subscribe.value_handle = client_ep->handle;
1640 client_ep->subscribe.ccc_handle = 0x0000;
1641 client_ep->subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1642 client_ep->subscribe.disc_params = &client_ep->discover;
1643 client_ep->subscribe.notify = unicast_client_ep_notify;
1644 client_ep->subscribe.value = BT_GATT_CCC_NOTIFY;
1645 atomic_set_bit(client_ep->subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
1646
1647 err = bt_gatt_subscribe(conn, &client_ep->subscribe);
1648 if (err != 0 && err != -EALREADY) {
1649 return err;
1650 }
1651
1652 return 0;
1653 }
1654
pac_record_cb(struct bt_conn * conn,const struct bt_audio_codec_cap * codec_cap)1655 static void pac_record_cb(struct bt_conn *conn, const struct bt_audio_codec_cap *codec_cap)
1656 {
1657 if (unicast_client_cbs != NULL && unicast_client_cbs->pac_record != NULL) {
1658 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1659 const enum bt_audio_dir dir = client->dir;
1660
1661 /* TBD: Since the PAC records are optionally notifiable we may want to supply the
1662 * index and total count of records in the callback, so that it easier for the
1663 * upper layers to determine when a new set of PAC records is being reported.
1664 */
1665 unicast_client_cbs->pac_record(conn, dir, codec_cap);
1666 }
1667 }
1668
endpoint_cb(struct bt_conn * conn,struct bt_bap_ep * ep)1669 static void endpoint_cb(struct bt_conn *conn, struct bt_bap_ep *ep)
1670 {
1671 if (unicast_client_cbs != NULL && unicast_client_cbs->endpoint != NULL) {
1672 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1673 const enum bt_audio_dir dir = client->dir;
1674
1675 unicast_client_cbs->endpoint(conn, dir, ep);
1676 }
1677 }
1678
discover_cb(struct bt_conn * conn,int err)1679 static void discover_cb(struct bt_conn *conn, int err)
1680 {
1681 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1682 const enum bt_audio_dir dir = client->dir;
1683
1684 /* Discover complete - Reset discovery values */
1685 client->dir = 0U;
1686 reset_att_buf(client);
1687 client->busy = false;
1688
1689 if (unicast_client_cbs != NULL && unicast_client_cbs->discover != NULL) {
1690 unicast_client_cbs->discover(conn, err, dir);
1691 }
1692 }
1693
unicast_client_cp_sub_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_subscribe_params * sub_params)1694 static void unicast_client_cp_sub_cb(struct bt_conn *conn, uint8_t err,
1695 struct bt_gatt_subscribe_params *sub_params)
1696 {
1697
1698 LOG_DBG("conn %p err %u", conn, err);
1699
1700 discover_cb(conn, err);
1701 }
1702
unicast_client_ep_set_cp(struct bt_conn * conn,uint16_t handle)1703 static void unicast_client_ep_set_cp(struct bt_conn *conn, uint16_t handle)
1704 {
1705 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1706
1707 LOG_DBG("conn %p 0x%04x", conn, handle);
1708
1709 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
1710 for (size_t i = 0U; i < ARRAY_SIZE(client->snks); i++) {
1711 struct bt_bap_unicast_client_ep *client_ep = &client->snks[i];
1712
1713 if (client_ep->handle) {
1714 client_ep->cp_handle = handle;
1715 }
1716 }
1717 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
1718
1719 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
1720 for (size_t i = 0U; i < ARRAY_SIZE(client->srcs); i++) {
1721 struct bt_bap_unicast_client_ep *client_ep = &client->srcs[i];
1722
1723 if (client_ep->handle) {
1724 client_ep->cp_handle = handle;
1725 }
1726 }
1727 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
1728
1729 if (!client->cp_subscribe.value_handle) {
1730 int err;
1731
1732 client->cp_subscribe.value_handle = handle;
1733 client->cp_subscribe.ccc_handle = 0x0000;
1734 client->cp_subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1735 client->cp_subscribe.disc_params = &client->disc_params;
1736 client->cp_subscribe.notify = unicast_client_cp_notify;
1737 client->cp_subscribe.value = BT_GATT_CCC_NOTIFY;
1738 client->cp_subscribe.subscribe = unicast_client_cp_sub_cb;
1739 atomic_set_bit(client->cp_subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
1740
1741 err = bt_gatt_subscribe(conn, &client->cp_subscribe);
1742 if (err != 0 && err != -EALREADY) {
1743 LOG_DBG("Failed to subscribe: %d", err);
1744
1745 discover_cb(conn, err);
1746
1747 return;
1748 }
1749 } else { /* already subscribed */
1750 discover_cb(conn, 0);
1751 }
1752 }
1753
bt_bap_unicast_client_ep_create_pdu(struct bt_conn * conn,uint8_t op)1754 struct net_buf_simple *bt_bap_unicast_client_ep_create_pdu(struct bt_conn *conn, uint8_t op)
1755 {
1756 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1757 struct bt_ascs_ase_cp *hdr;
1758
1759 if (client->busy) {
1760 return NULL;
1761 }
1762
1763 hdr = net_buf_simple_add(&client->net_buf, sizeof(*hdr));
1764 hdr->op = op;
1765
1766 return &client->net_buf;
1767 }
1768
unicast_client_ep_config(struct bt_bap_ep * ep,struct net_buf_simple * buf,const struct bt_audio_codec_cfg * codec_cfg)1769 static int unicast_client_ep_config(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1770 const struct bt_audio_codec_cfg *codec_cfg)
1771 {
1772 struct bt_ascs_config *req;
1773
1774 LOG_DBG("ep %p buf %p codec %p", ep, buf, codec_cfg);
1775
1776 if (!ep) {
1777 return -EINVAL;
1778 }
1779
1780 switch (ep->status.state) {
1781 /* Valid only if ASE_State field = 0x00 (Idle) */
1782 case BT_BAP_EP_STATE_IDLE:
1783 /* or 0x01 (Codec Configured) */
1784 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1785 /* or 0x02 (QoS Configured) */
1786 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1787 break;
1788 default:
1789 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1790 return -EINVAL;
1791 }
1792
1793 LOG_DBG("id 0x%02x dir %s codec 0x%02x", ep->status.id, bt_audio_dir_str(ep->dir),
1794 codec_cfg->id);
1795
1796 req = net_buf_simple_add(buf, sizeof(*req));
1797 req->ase = ep->status.id;
1798 req->latency = 0x02; /* TODO: Select target latency based on additional input? */
1799 req->phy = 0x02; /* TODO: Select target PHY based on additional input? */
1800 req->codec.id = codec_cfg->id;
1801 req->codec.cid = codec_cfg->cid;
1802 req->codec.vid = codec_cfg->vid;
1803
1804 req->cc_len = codec_cfg->data_len;
1805 net_buf_simple_add_mem(buf, codec_cfg->data, codec_cfg->data_len);
1806
1807 return 0;
1808 }
1809
bt_bap_unicast_client_ep_qos(struct bt_bap_ep * ep,struct net_buf_simple * buf,struct bt_audio_codec_qos * qos)1810 int bt_bap_unicast_client_ep_qos(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1811 struct bt_audio_codec_qos *qos)
1812 {
1813 struct bt_ascs_qos *req;
1814 struct bt_conn_iso *conn_iso;
1815
1816 LOG_DBG("ep %p buf %p qos %p", ep, buf, qos);
1817
1818 if (!ep) {
1819 return -EINVAL;
1820 }
1821
1822 switch (ep->status.state) {
1823 /* Valid only if ASE_State field = 0x01 (Codec Configured) */
1824 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1825 /* or 0x02 (QoS Configured) */
1826 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1827 break;
1828 default:
1829 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1830 return -EINVAL;
1831 }
1832
1833 conn_iso = &ep->iso->chan.iso->iso;
1834
1835 LOG_DBG("id 0x%02x cig 0x%02x cis 0x%02x interval %u framing 0x%02x "
1836 "phy 0x%02x sdu %u rtn %u latency %u pd %u",
1837 ep->status.id, conn_iso->cig_id, conn_iso->cis_id, qos->interval, qos->framing,
1838 qos->phy, qos->sdu, qos->rtn, qos->latency, qos->pd);
1839
1840 req = net_buf_simple_add(buf, sizeof(*req));
1841 req->ase = ep->status.id;
1842 /* TODO: don't hardcode CIG and CIS, they should come from ISO */
1843 req->cig = conn_iso->cig_id;
1844 req->cis = conn_iso->cis_id;
1845 sys_put_le24(qos->interval, req->interval);
1846 req->framing = qos->framing;
1847 req->phy = qos->phy;
1848 req->sdu = qos->sdu;
1849 req->rtn = qos->rtn;
1850 req->latency = sys_cpu_to_le16(qos->latency);
1851 sys_put_le24(qos->pd, req->pd);
1852
1853 return 0;
1854 }
1855
unicast_client_ep_enable(struct bt_bap_ep * ep,struct net_buf_simple * buf,const uint8_t meta[],size_t meta_len)1856 static int unicast_client_ep_enable(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1857 const uint8_t meta[], size_t meta_len)
1858 {
1859 struct bt_ascs_metadata *req;
1860
1861 LOG_DBG("ep %p buf %p meta_len %zu", ep, buf, meta_len);
1862
1863 if (!ep) {
1864 return -EINVAL;
1865 }
1866
1867 if (ep->status.state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
1868 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1869 return -EINVAL;
1870 }
1871
1872 LOG_DBG("id 0x%02x", ep->status.id);
1873
1874 req = net_buf_simple_add(buf, sizeof(*req));
1875 req->ase = ep->status.id;
1876
1877 req->len = meta_len;
1878 net_buf_simple_add_mem(buf, meta, meta_len);
1879
1880 return 0;
1881 }
1882
unicast_client_ep_metadata(struct bt_bap_ep * ep,struct net_buf_simple * buf,const uint8_t meta[],size_t meta_len)1883 static int unicast_client_ep_metadata(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1884 const uint8_t meta[], size_t meta_len)
1885 {
1886 struct bt_ascs_metadata *req;
1887
1888 LOG_DBG("ep %p buf %p meta_len %zu", ep, buf, meta_len);
1889
1890 if (!ep) {
1891 return -EINVAL;
1892 }
1893
1894 switch (ep->status.state) {
1895 /* Valid for an ASE only if ASE_State field = 0x03 (Enabling) */
1896 case BT_BAP_EP_STATE_ENABLING:
1897 /* or 0x04 (Streaming) */
1898 case BT_BAP_EP_STATE_STREAMING:
1899 break;
1900 default:
1901 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1902 return -EINVAL;
1903 }
1904
1905 LOG_DBG("id 0x%02x", ep->status.id);
1906
1907 req = net_buf_simple_add(buf, sizeof(*req));
1908 req->ase = ep->status.id;
1909
1910 req->len = meta_len;
1911 net_buf_simple_add_mem(buf, meta, meta_len);
1912
1913 return 0;
1914 }
1915
unicast_client_ep_start(struct bt_bap_ep * ep,struct net_buf_simple * buf)1916 static int unicast_client_ep_start(struct bt_bap_ep *ep, struct net_buf_simple *buf)
1917 {
1918 LOG_DBG("ep %p buf %p", ep, buf);
1919
1920 if (!ep) {
1921 return -EINVAL;
1922 }
1923
1924 if (ep->status.state != BT_BAP_EP_STATE_ENABLING &&
1925 ep->status.state != BT_BAP_EP_STATE_DISABLING) {
1926 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1927 return -EINVAL;
1928 }
1929
1930 LOG_DBG("id 0x%02x", ep->status.id);
1931
1932 net_buf_simple_add_u8(buf, ep->status.id);
1933
1934 return 0;
1935 }
1936
unicast_client_ep_disable(struct bt_bap_ep * ep,struct net_buf_simple * buf)1937 static int unicast_client_ep_disable(struct bt_bap_ep *ep, struct net_buf_simple *buf)
1938 {
1939 LOG_DBG("ep %p buf %p", ep, buf);
1940
1941 if (!ep) {
1942 return -EINVAL;
1943 }
1944
1945 switch (ep->status.state) {
1946 /* Valid only if ASE_State field = 0x03 (Enabling) */
1947 case BT_BAP_EP_STATE_ENABLING:
1948 /* or 0x04 (Streaming) */
1949 case BT_BAP_EP_STATE_STREAMING:
1950 break;
1951 default:
1952 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1953 return -EINVAL;
1954 }
1955
1956 LOG_DBG("id 0x%02x", ep->status.id);
1957
1958 net_buf_simple_add_u8(buf, ep->status.id);
1959
1960 return 0;
1961 }
1962
unicast_client_ep_stop(struct bt_bap_ep * ep,struct net_buf_simple * buf)1963 static int unicast_client_ep_stop(struct bt_bap_ep *ep, struct net_buf_simple *buf)
1964 {
1965 LOG_DBG("ep %p buf %p", ep, buf);
1966
1967 if (!ep) {
1968 return -EINVAL;
1969 }
1970
1971 /* Valid only if ASE_State field value = 0x05 (Disabling). */
1972 if (ep->status.state != BT_BAP_EP_STATE_DISABLING) {
1973 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1974 return -EINVAL;
1975 }
1976
1977 LOG_DBG("id 0x%02x", ep->status.id);
1978
1979 net_buf_simple_add_u8(buf, ep->status.id);
1980
1981 return 0;
1982 }
1983
unicast_client_ep_release(struct bt_bap_ep * ep,struct net_buf_simple * buf)1984 static int unicast_client_ep_release(struct bt_bap_ep *ep, struct net_buf_simple *buf)
1985 {
1986 LOG_DBG("ep %p buf %p", ep, buf);
1987
1988 if (!ep) {
1989 return -EINVAL;
1990 }
1991
1992 switch (ep->status.state) {
1993 /* Valid only if ASE_State field = 0x01 (Codec Configured) */
1994 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1995 /* or 0x02 (QoS Configured) */
1996 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1997 /* or 0x03 (Enabling) */
1998 case BT_BAP_EP_STATE_ENABLING:
1999 /* or 0x04 (Streaming) */
2000 case BT_BAP_EP_STATE_STREAMING:
2001 /* or 0x05 (Disabling) */
2002 case BT_BAP_EP_STATE_DISABLING:
2003 break;
2004 default:
2005 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2006 return -EINVAL;
2007 }
2008
2009 LOG_DBG("id 0x%02x", ep->status.id);
2010
2011 net_buf_simple_add_u8(buf, ep->status.id);
2012
2013 return 0;
2014 }
2015
gatt_write_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_write_params * params)2016 static void gatt_write_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_write_params *params)
2017 {
2018 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
2019
2020 LOG_DBG("conn %p err %u", conn, err);
2021
2022 memset(params, 0, sizeof(*params));
2023 reset_att_buf(client);
2024 client->busy = false;
2025
2026 /* TBD: Should we do anything in case of error here? */
2027 }
2028
bt_bap_unicast_client_ep_send(struct bt_conn * conn,struct bt_bap_ep * ep,struct net_buf_simple * buf)2029 int bt_bap_unicast_client_ep_send(struct bt_conn *conn, struct bt_bap_ep *ep,
2030 struct net_buf_simple *buf)
2031 {
2032 const uint8_t att_write_header_size = 3; /* opcode (1) + handle (2) */
2033 const uint16_t max_write_size = bt_gatt_get_mtu(conn) - att_write_header_size;
2034 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
2035 struct bt_bap_unicast_client_ep *client_ep =
2036 CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
2037 int err;
2038
2039 LOG_DBG("conn %p ep %p buf %p len %u", conn, ep, buf, buf->len);
2040
2041 if (buf->len > max_write_size) {
2042 if (client->busy) {
2043 LOG_DBG("Client connection is busy");
2044 return -EBUSY;
2045 }
2046
2047 client->write_params.func = gatt_write_cb;
2048 client->write_params.handle = client_ep->cp_handle;
2049 client->write_params.offset = 0U;
2050 client->write_params.data = buf->data;
2051 client->write_params.length = buf->len;
2052 #if defined(CONFIG_BT_EATT)
2053 client->write_params.chan_opt = BT_ATT_CHAN_OPT_NONE;
2054 #endif /* CONFIG_BT_EATT */
2055
2056 err = bt_gatt_write(conn, &client->write_params);
2057 if (err != 0) {
2058 LOG_DBG("bt_gatt_write failed: %d", err);
2059 }
2060
2061 client->busy = true;
2062 } else {
2063 err = bt_gatt_write_without_response(conn, client_ep->cp_handle, buf->data,
2064 buf->len, false);
2065 if (err != 0) {
2066 LOG_DBG("bt_gatt_write_without_response failed: %d", err);
2067 }
2068
2069 /* No callback for writing without response, so reset the buffer here */
2070 reset_att_buf(client);
2071 }
2072
2073 if (err == 0) {
2074 client_ep->cp_ntf_pending = true;
2075 }
2076
2077 return err;
2078 }
2079
unicast_client_reset(struct bt_bap_ep * ep,uint8_t reason)2080 static void unicast_client_reset(struct bt_bap_ep *ep, uint8_t reason)
2081 {
2082 struct bt_bap_unicast_client_ep *client_ep =
2083 CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
2084
2085 LOG_DBG("ep %p", ep);
2086 ep->reason = reason;
2087
2088 /* Pretend we received an idle state notification from the server to trigger all cleanup */
2089 unicast_client_ep_set_local_idle_state(ep);
2090
2091 if (ep->iso != NULL && ep->iso->chan.state == BT_ISO_STATE_DISCONNECTING) {
2092 /* Wait for ISO disconnected event */
2093 return;
2094 }
2095
2096 (void)k_work_cancel_delayable(&client_ep->ase_read_work);
2097 (void)memset(ep, 0, sizeof(*ep));
2098
2099 client_ep->cp_handle = 0U;
2100 client_ep->handle = 0U;
2101 (void)memset(&client_ep->discover, 0, sizeof(client_ep->discover));
2102 client_ep->release_requested = false;
2103 client_ep->cp_ntf_pending = false;
2104 /* Need to keep the subscribe params intact for the callback */
2105 }
2106
unicast_client_ep_reset(struct bt_conn * conn,uint8_t reason)2107 static void unicast_client_ep_reset(struct bt_conn *conn, uint8_t reason)
2108 {
2109 struct unicast_client *client;
2110 uint8_t index;
2111
2112 LOG_DBG("conn %p", conn);
2113
2114 index = bt_conn_index(conn);
2115
2116 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
2117 for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].snks); i++) {
2118 struct bt_bap_ep *ep = &uni_cli_insts[index].snks[i].ep;
2119
2120 unicast_client_reset(ep, reason);
2121 }
2122 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
2123
2124 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
2125 for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].srcs); i++) {
2126 struct bt_bap_ep *ep = &uni_cli_insts[index].srcs[i].ep;
2127
2128 unicast_client_reset(ep, reason);
2129 }
2130 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
2131
2132 client = &uni_cli_insts[index];
2133 client->busy = false;
2134 client->dir = 0U;
2135 reset_att_buf(client);
2136 }
2137
bt_audio_codec_qos_to_cig_param(struct bt_iso_cig_param * cig_param,const struct bt_audio_codec_qos * qos,const struct bt_bap_unicast_group_param * group_param)2138 static void bt_audio_codec_qos_to_cig_param(struct bt_iso_cig_param *cig_param,
2139 const struct bt_audio_codec_qos *qos,
2140 const struct bt_bap_unicast_group_param *group_param)
2141 {
2142 cig_param->framing = qos->framing;
2143 cig_param->packing = BT_ISO_PACKING_SEQUENTIAL; /* TODO: Add to QoS struct */
2144 cig_param->c_to_p_interval = qos->interval;
2145 cig_param->p_to_c_interval = qos->interval;
2146 cig_param->c_to_p_latency = qos->latency;
2147 cig_param->p_to_c_latency = qos->latency;
2148 cig_param->sca = BT_GAP_SCA_UNKNOWN;
2149
2150 if (group_param != NULL) {
2151 cig_param->packing = group_param->packing;
2152 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
2153 cig_param->c_to_p_ft = group_param->c_to_p_ft;
2154 cig_param->p_to_c_ft = group_param->p_to_c_ft;
2155 cig_param->iso_interval = group_param->iso_interval;
2156 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
2157 }
2158 }
2159
2160 /* FIXME: Remove `qos` parameter. Some of the QoS related CIG can be different
2161 * between CIS'es. The implementation shall take the CIG parameters from
2162 * unicast_group instead.
2163 */
bt_audio_cig_create(struct bt_bap_unicast_group * group,const struct bt_audio_codec_qos * qos,const struct bt_bap_unicast_group_param * group_param)2164 static int bt_audio_cig_create(struct bt_bap_unicast_group *group,
2165 const struct bt_audio_codec_qos *qos,
2166 const struct bt_bap_unicast_group_param *group_param)
2167 {
2168 struct bt_iso_cig_param param;
2169 uint8_t cis_count;
2170 int err;
2171
2172 LOG_DBG("group %p qos %p", group, qos);
2173
2174 cis_count = 0U;
2175 for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2176 if (group->cis[i] == NULL) {
2177 /* A NULL CIS acts as a NULL terminator */
2178 break;
2179 }
2180
2181 cis_count++;
2182 }
2183
2184 param.num_cis = cis_count;
2185 param.cis_channels = group->cis;
2186 bt_audio_codec_qos_to_cig_param(¶m, qos, group_param);
2187
2188 err = bt_iso_cig_create(¶m, &group->cig);
2189 if (err != 0) {
2190 LOG_ERR("bt_iso_cig_create failed: %d", err);
2191 return err;
2192 }
2193
2194 group->qos = qos;
2195
2196 return 0;
2197 }
2198
bt_audio_cig_reconfigure(struct bt_bap_unicast_group * group,const struct bt_audio_codec_qos * qos)2199 static int bt_audio_cig_reconfigure(struct bt_bap_unicast_group *group,
2200 const struct bt_audio_codec_qos *qos)
2201 {
2202 struct bt_iso_cig_param param;
2203 uint8_t cis_count;
2204 int err;
2205
2206 LOG_DBG("group %p qos %p", group, qos);
2207
2208 cis_count = 0U;
2209 for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2210 if (group->cis[i] == NULL) {
2211 /* A NULL CIS acts as a NULL terminator */
2212 break;
2213 }
2214
2215 cis_count++;
2216 }
2217
2218 param.num_cis = cis_count;
2219 param.cis_channels = group->cis;
2220 bt_audio_codec_qos_to_cig_param(¶m, qos, NULL);
2221
2222 err = bt_iso_cig_reconfigure(group->cig, ¶m);
2223 if (err != 0) {
2224 LOG_ERR("bt_iso_cig_create failed: %d", err);
2225 return err;
2226 }
2227
2228 group->qos = qos;
2229
2230 return 0;
2231 }
2232
audio_stream_qos_cleanup(const struct bt_conn * conn,struct bt_bap_unicast_group * group)2233 static void audio_stream_qos_cleanup(const struct bt_conn *conn,
2234 struct bt_bap_unicast_group *group)
2235 {
2236 struct bt_bap_stream *stream;
2237
2238 SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
2239 if (stream->conn != conn) {
2240 /* Channel not part of this ACL, skip */
2241 continue;
2242 }
2243
2244 if (stream->ep == NULL) {
2245 /* Stream did not have a endpoint configured yet */
2246 continue;
2247 }
2248
2249 bt_bap_iso_unbind_ep(stream->ep->iso, stream->ep);
2250 }
2251 }
2252
unicast_client_cig_terminate(struct bt_bap_unicast_group * group)2253 static int unicast_client_cig_terminate(struct bt_bap_unicast_group *group)
2254 {
2255 LOG_DBG("group %p", group);
2256
2257 return bt_iso_cig_terminate(group->cig);
2258 }
2259
unicast_group_add_iso(struct bt_bap_unicast_group * group,struct bt_bap_iso * iso)2260 static int unicast_group_add_iso(struct bt_bap_unicast_group *group, struct bt_bap_iso *iso)
2261 {
2262 struct bt_iso_chan **chan_slot = NULL;
2263
2264 __ASSERT_NO_MSG(group != NULL);
2265 __ASSERT_NO_MSG(iso != NULL);
2266
2267 /* Append iso channel to the group->cis array */
2268 for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2269 /* Return if already there */
2270 if (group->cis[i] == &iso->chan) {
2271 return 0;
2272 }
2273
2274 if (chan_slot == NULL && group->cis[i] == NULL) {
2275 chan_slot = &group->cis[i];
2276 }
2277 }
2278
2279 if (chan_slot == NULL) {
2280 return -ENOMEM;
2281 }
2282
2283 *chan_slot = &iso->chan;
2284
2285 return 0;
2286 }
2287
unicast_group_del_iso(struct bt_bap_unicast_group * group,struct bt_bap_iso * iso)2288 static void unicast_group_del_iso(struct bt_bap_unicast_group *group, struct bt_bap_iso *iso)
2289 {
2290 struct bt_bap_stream *stream;
2291
2292 __ASSERT_NO_MSG(group != NULL);
2293 __ASSERT_NO_MSG(iso != NULL);
2294
2295 SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
2296 if (stream->ep->iso == iso) {
2297 /* still in use by some other stream */
2298 return;
2299 }
2300 }
2301
2302 for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2303 if (group->cis[i] == &iso->chan) {
2304 group->cis[i] = NULL;
2305 return;
2306 }
2307 }
2308 }
2309
unicast_client_codec_qos_to_iso_qos(struct bt_bap_iso * iso,const struct bt_audio_codec_qos * qos,enum bt_audio_dir dir)2310 static void unicast_client_codec_qos_to_iso_qos(struct bt_bap_iso *iso,
2311 const struct bt_audio_codec_qos *qos,
2312 enum bt_audio_dir dir)
2313 {
2314 struct bt_iso_chan_io_qos *io_qos;
2315 struct bt_iso_chan_io_qos *other_io_qos;
2316
2317 if (dir == BT_AUDIO_DIR_SINK) {
2318 /* If the endpoint is a sink, then we need to
2319 * configure our TX parameters
2320 */
2321 io_qos = iso->chan.qos->tx;
2322 if (bt_bap_iso_get_ep(true, iso, BT_AUDIO_DIR_SOURCE) == NULL) {
2323 other_io_qos = iso->chan.qos->rx;
2324 } else {
2325 other_io_qos = NULL;
2326 }
2327 } else {
2328 /* If the endpoint is a source, then we need to
2329 * configure our RX parameters
2330 */
2331 io_qos = iso->chan.qos->rx;
2332 if (bt_bap_iso_get_ep(true, iso, BT_AUDIO_DIR_SINK) == NULL) {
2333 other_io_qos = iso->chan.qos->tx;
2334 } else {
2335 other_io_qos = NULL;
2336 }
2337 }
2338
2339 bt_audio_codec_qos_to_iso_qos(io_qos, qos);
2340 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
2341 iso->chan.qos->num_subevents = qos->num_subevents;
2342 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
2343
2344 if (other_io_qos != NULL) {
2345 /* If the opposing ASE of the CIS is not yet configured, we
2346 * still need to set the PHY value when creating the CIG.
2347 */
2348 other_io_qos->phy = io_qos->phy;
2349 }
2350 }
2351
unicast_group_add_stream(struct bt_bap_unicast_group * group,struct bt_bap_unicast_group_stream_param * param,struct bt_bap_iso * iso,enum bt_audio_dir dir)2352 static void unicast_group_add_stream(struct bt_bap_unicast_group *group,
2353 struct bt_bap_unicast_group_stream_param *param,
2354 struct bt_bap_iso *iso, enum bt_audio_dir dir)
2355 {
2356 struct bt_bap_stream *stream = param->stream;
2357 struct bt_audio_codec_qos *qos = param->qos;
2358
2359 LOG_DBG("group %p stream %p qos %p iso %p dir %u", group, stream, qos, iso, dir);
2360
2361 __ASSERT_NO_MSG(stream->ep == NULL || (stream->ep != NULL && stream->ep->iso == NULL));
2362
2363 stream->qos = qos;
2364 stream->group = group;
2365
2366 /* iso initialized already */
2367 bt_bap_iso_bind_stream(iso, stream, dir);
2368 if (stream->ep != NULL) {
2369 bt_bap_iso_bind_ep(iso, stream->ep);
2370 }
2371
2372 /* Store the Codec QoS in the bap_iso */
2373 unicast_client_codec_qos_to_iso_qos(iso, qos, dir);
2374
2375 sys_slist_append(&group->streams, &stream->_node);
2376 }
2377
unicast_group_add_stream_pair(struct bt_bap_unicast_group * group,struct bt_bap_unicast_group_stream_pair_param * param)2378 static int unicast_group_add_stream_pair(struct bt_bap_unicast_group *group,
2379 struct bt_bap_unicast_group_stream_pair_param *param)
2380 {
2381 struct bt_bap_iso *iso;
2382 int err;
2383
2384 __ASSERT_NO_MSG(group != NULL);
2385 __ASSERT_NO_MSG(param != NULL);
2386 __ASSERT_NO_MSG(param->rx_param != NULL || param->tx_param != NULL);
2387
2388 iso = bt_bap_unicast_client_new_audio_iso();
2389 if (iso == NULL) {
2390 return -ENOMEM;
2391 }
2392
2393 err = unicast_group_add_iso(group, iso);
2394 if (err < 0) {
2395 bt_bap_iso_unref(iso);
2396 return err;
2397 }
2398
2399 if (param->rx_param != NULL) {
2400 unicast_group_add_stream(group, param->rx_param, iso, BT_AUDIO_DIR_SOURCE);
2401 }
2402
2403 if (param->tx_param != NULL) {
2404 unicast_group_add_stream(group, param->tx_param, iso, BT_AUDIO_DIR_SINK);
2405 }
2406
2407 bt_bap_iso_unref(iso);
2408
2409 return 0;
2410 }
2411
unicast_group_del_stream(struct bt_bap_unicast_group * group,struct bt_bap_stream * stream,enum bt_audio_dir dir)2412 static void unicast_group_del_stream(struct bt_bap_unicast_group *group,
2413 struct bt_bap_stream *stream, enum bt_audio_dir dir)
2414 {
2415 __ASSERT_NO_MSG(group != NULL);
2416 __ASSERT_NO_MSG(stream != NULL);
2417
2418 if (sys_slist_find_and_remove(&group->streams, &stream->_node)) {
2419 struct bt_bap_ep *ep = stream->ep;
2420
2421 if (stream->bap_iso != NULL) {
2422 bt_bap_iso_unbind_stream(stream->bap_iso, stream, dir);
2423 }
2424
2425 if (ep != NULL && ep->iso != NULL) {
2426 unicast_group_del_iso(group, ep->iso);
2427
2428 bt_bap_iso_unbind_ep(ep->iso, ep);
2429 }
2430
2431 stream->group = NULL;
2432 }
2433 }
2434
unicast_group_del_stream_pair(struct bt_bap_unicast_group * group,struct bt_bap_unicast_group_stream_pair_param * param)2435 static void unicast_group_del_stream_pair(struct bt_bap_unicast_group *group,
2436 struct bt_bap_unicast_group_stream_pair_param *param)
2437 {
2438 __ASSERT_NO_MSG(group != NULL);
2439 __ASSERT_NO_MSG(param != NULL);
2440 __ASSERT_NO_MSG(param->rx_param != NULL || param->tx_param != NULL);
2441
2442 if (param->rx_param != NULL) {
2443 __ASSERT_NO_MSG(param->rx_param->stream);
2444 unicast_group_del_stream(group, param->rx_param->stream, BT_AUDIO_DIR_SOURCE);
2445 }
2446
2447 if (param->tx_param != NULL) {
2448 __ASSERT_NO_MSG(param->tx_param->stream);
2449 unicast_group_del_stream(group, param->tx_param->stream, BT_AUDIO_DIR_SINK);
2450 }
2451 }
2452
unicast_group_alloc(void)2453 static struct bt_bap_unicast_group *unicast_group_alloc(void)
2454 {
2455 struct bt_bap_unicast_group *group = NULL;
2456
2457 for (size_t i = 0U; i < ARRAY_SIZE(unicast_groups); i++) {
2458 if (!unicast_groups[i].allocated) {
2459 group = &unicast_groups[i];
2460
2461 (void)memset(group, 0, sizeof(*group));
2462
2463 group->allocated = true;
2464 group->index = i;
2465
2466 break;
2467 }
2468 }
2469
2470 return group;
2471 }
2472
unicast_group_free(struct bt_bap_unicast_group * group)2473 static void unicast_group_free(struct bt_bap_unicast_group *group)
2474 {
2475 struct bt_bap_stream *stream, *next;
2476
2477 __ASSERT_NO_MSG(group != NULL);
2478
2479 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&group->streams, stream, next, _node) {
2480 struct bt_bap_iso *bap_iso = stream->bap_iso;
2481 struct bt_bap_ep *ep = stream->ep;
2482
2483 stream->group = NULL;
2484 if (bap_iso != NULL) {
2485 if (bap_iso->rx.stream == stream) {
2486 bt_bap_iso_unbind_stream(stream->bap_iso, stream,
2487 BT_AUDIO_DIR_SOURCE);
2488 } else if (bap_iso->tx.stream == stream) {
2489 bt_bap_iso_unbind_stream(stream->bap_iso, stream,
2490 BT_AUDIO_DIR_SINK);
2491 } else {
2492 __ASSERT_PRINT("stream %p has invalid bap_iso %p", stream, bap_iso);
2493 }
2494 }
2495
2496 if (ep != NULL && ep->iso != NULL) {
2497 bt_bap_iso_unbind_ep(ep->iso, ep);
2498 }
2499
2500 sys_slist_remove(&group->streams, NULL, &stream->_node);
2501 }
2502
2503 group->allocated = false;
2504 }
2505
stream_param_check(const struct bt_bap_unicast_group_stream_param * param)2506 static int stream_param_check(const struct bt_bap_unicast_group_stream_param *param)
2507 {
2508 CHECKIF(param->stream == NULL)
2509 {
2510 LOG_DBG("param->stream is NULL");
2511 return -EINVAL;
2512 }
2513
2514 CHECKIF(param->qos == NULL)
2515 {
2516 LOG_DBG("param->qos is NULL");
2517 return -EINVAL;
2518 }
2519
2520 if (param->stream != NULL && param->stream->group != NULL) {
2521 LOG_DBG("stream %p already part of group %p", param->stream, param->stream->group);
2522 return -EALREADY;
2523 }
2524
2525 CHECKIF(bt_audio_verify_qos(param->qos) != BT_BAP_ASCS_REASON_NONE)
2526 {
2527 LOG_DBG("Invalid QoS");
2528 return -EINVAL;
2529 }
2530
2531 return 0;
2532 }
2533
stream_pair_param_check(const struct bt_bap_unicast_group_stream_pair_param * param)2534 static int stream_pair_param_check(const struct bt_bap_unicast_group_stream_pair_param *param)
2535 {
2536 int err;
2537
2538 CHECKIF(param->rx_param == NULL && param->tx_param == NULL)
2539 {
2540 LOG_DBG("Invalid stream parameters");
2541 return -EINVAL;
2542 }
2543
2544 if (param->rx_param != NULL) {
2545 err = stream_param_check(param->rx_param);
2546 if (err < 0) {
2547 return err;
2548 }
2549 }
2550
2551 if (param->tx_param != NULL) {
2552 err = stream_param_check(param->tx_param);
2553 if (err < 0) {
2554 return err;
2555 }
2556 }
2557
2558 return 0;
2559 }
2560
group_qos_common_set(const struct bt_audio_codec_qos ** group_qos,const struct bt_bap_unicast_group_stream_pair_param * param)2561 static int group_qos_common_set(const struct bt_audio_codec_qos **group_qos,
2562 const struct bt_bap_unicast_group_stream_pair_param *param)
2563 {
2564 if (param->rx_param != NULL && *group_qos == NULL) {
2565 *group_qos = param->rx_param->qos;
2566 }
2567
2568 if (param->tx_param != NULL && *group_qos == NULL) {
2569 *group_qos = param->tx_param->qos;
2570 }
2571
2572 return 0;
2573 }
2574
bt_bap_unicast_group_create(struct bt_bap_unicast_group_param * param,struct bt_bap_unicast_group ** out_unicast_group)2575 int bt_bap_unicast_group_create(struct bt_bap_unicast_group_param *param,
2576 struct bt_bap_unicast_group **out_unicast_group)
2577 {
2578 struct bt_bap_unicast_group *unicast_group;
2579 const struct bt_audio_codec_qos *group_qos = NULL;
2580 int err;
2581
2582 CHECKIF(out_unicast_group == NULL)
2583 {
2584 LOG_DBG("out_unicast_group is NULL");
2585 return -EINVAL;
2586 }
2587 /* Set out_unicast_group to NULL until the source has actually been created */
2588 *out_unicast_group = NULL;
2589
2590 CHECKIF(param == NULL)
2591 {
2592 LOG_DBG("streams is NULL");
2593 return -EINVAL;
2594 }
2595
2596 CHECKIF(param->params_count > UNICAST_GROUP_STREAM_CNT)
2597 {
2598 LOG_DBG("Too many streams provided: %u/%u", param->params_count,
2599 UNICAST_GROUP_STREAM_CNT);
2600 return -EINVAL;
2601 }
2602
2603 unicast_group = unicast_group_alloc();
2604 if (unicast_group == NULL) {
2605 LOG_DBG("Could not allocate any more unicast groups");
2606 return -ENOMEM;
2607 }
2608
2609 for (size_t i = 0U; i < param->params_count; i++) {
2610 struct bt_bap_unicast_group_stream_pair_param *stream_param;
2611
2612 stream_param = ¶m->params[i];
2613
2614 err = stream_pair_param_check(stream_param);
2615 if (err < 0) {
2616 return err;
2617 }
2618
2619 err = group_qos_common_set(&group_qos, stream_param);
2620 if (err < 0) {
2621 return err;
2622 }
2623
2624 err = unicast_group_add_stream_pair(unicast_group, stream_param);
2625 if (err < 0) {
2626 LOG_DBG("unicast_group_add_stream failed: %d", err);
2627 unicast_group_free(unicast_group);
2628
2629 return err;
2630 }
2631 }
2632
2633 err = bt_audio_cig_create(unicast_group, group_qos, param);
2634 if (err != 0) {
2635 LOG_DBG("bt_audio_cig_create failed: %d", err);
2636 unicast_group_free(unicast_group);
2637
2638 return err;
2639 }
2640
2641 *out_unicast_group = unicast_group;
2642
2643 return 0;
2644 }
2645
bt_bap_unicast_group_add_streams(struct bt_bap_unicast_group * unicast_group,struct bt_bap_unicast_group_stream_pair_param params[],size_t num_param)2646 int bt_bap_unicast_group_add_streams(struct bt_bap_unicast_group *unicast_group,
2647 struct bt_bap_unicast_group_stream_pair_param params[],
2648 size_t num_param)
2649 {
2650 const struct bt_audio_codec_qos *group_qos = unicast_group->qos;
2651 struct bt_bap_stream *tmp_stream;
2652 size_t total_stream_cnt;
2653 struct bt_iso_cig *cig;
2654 size_t num_added;
2655 int err;
2656
2657 CHECKIF(unicast_group == NULL)
2658 {
2659 LOG_DBG("unicast_group is NULL");
2660 return -EINVAL;
2661 }
2662
2663 CHECKIF(params == NULL)
2664 {
2665 LOG_DBG("params is NULL");
2666 return -EINVAL;
2667 }
2668
2669 CHECKIF(num_param == 0)
2670 {
2671 LOG_DBG("num_param is 0");
2672 return -EINVAL;
2673 }
2674
2675 total_stream_cnt = num_param;
2676 SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) {
2677 total_stream_cnt++;
2678 }
2679
2680 if (total_stream_cnt > UNICAST_GROUP_STREAM_CNT) {
2681 LOG_DBG("Too many streams provided: %u/%u", total_stream_cnt,
2682 UNICAST_GROUP_STREAM_CNT);
2683 return -EINVAL;
2684 }
2685
2686 /* We can just check the CIG state to see if any streams have started as
2687 * that would start the ISO connection procedure
2688 */
2689 cig = unicast_group->cig;
2690 if (cig != NULL && cig->state != BT_ISO_CIG_STATE_CONFIGURED) {
2691 LOG_DBG("At least one unicast group stream is started");
2692 return -EBADMSG;
2693 }
2694
2695 for (num_added = 0U; num_added < num_param; num_added++) {
2696 struct bt_bap_unicast_group_stream_pair_param *stream_param;
2697
2698 stream_param = ¶ms[num_added];
2699
2700 err = stream_pair_param_check(stream_param);
2701 if (err < 0) {
2702 return err;
2703 }
2704
2705 err = group_qos_common_set(&group_qos, stream_param);
2706 if (err < 0) {
2707 return err;
2708 }
2709
2710 err = unicast_group_add_stream_pair(unicast_group, stream_param);
2711 if (err < 0) {
2712 LOG_DBG("unicast_group_add_stream failed: %d", err);
2713 goto fail;
2714 }
2715 }
2716
2717 err = bt_audio_cig_reconfigure(unicast_group, group_qos);
2718 if (err != 0) {
2719 LOG_DBG("bt_audio_cig_reconfigure failed: %d", err);
2720 goto fail;
2721 }
2722
2723 return 0;
2724
2725 fail:
2726 /* Restore group by removing the newly added streams */
2727 while (num_added--) {
2728 unicast_group_del_stream_pair(unicast_group, ¶ms[num_added]);
2729 }
2730
2731 return err;
2732 }
2733
bt_bap_unicast_group_delete(struct bt_bap_unicast_group * unicast_group)2734 int bt_bap_unicast_group_delete(struct bt_bap_unicast_group *unicast_group)
2735 {
2736 struct bt_bap_stream *stream;
2737
2738 CHECKIF(unicast_group == NULL)
2739 {
2740 LOG_DBG("unicast_group is NULL");
2741 return -EINVAL;
2742 }
2743
2744 SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, stream, _node) {
2745 /* If a stream has an endpoint, it is not ready to be removed
2746 * from a group, as it is not in an idle state
2747 */
2748 if (stream->ep != NULL) {
2749 LOG_DBG("stream %p is not released", stream);
2750 return -EINVAL;
2751 }
2752 }
2753
2754 if (unicast_group->cig != NULL) {
2755 const int err = unicast_client_cig_terminate(unicast_group);
2756
2757 if (err != 0) {
2758 LOG_DBG("unicast_client_cig_terminate failed with err %d", err);
2759
2760 return err;
2761 }
2762 }
2763
2764 unicast_group_free(unicast_group);
2765
2766 return 0;
2767 }
2768
bt_bap_unicast_client_config(struct bt_bap_stream * stream,const struct bt_audio_codec_cfg * codec_cfg)2769 int bt_bap_unicast_client_config(struct bt_bap_stream *stream,
2770 const struct bt_audio_codec_cfg *codec_cfg)
2771 {
2772 struct bt_bap_ep *ep = stream->ep;
2773 struct bt_ascs_config_op *op;
2774 struct net_buf_simple *buf;
2775 int err;
2776
2777 LOG_DBG("stream %p", stream);
2778
2779 if (stream->conn == NULL) {
2780 LOG_DBG("Stream %p does not have a connection", stream);
2781
2782 return -ENOTCONN;
2783 }
2784
2785 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_CONFIG_OP);
2786 if (buf == NULL) {
2787 LOG_DBG("Could not create PDU");
2788 return -EBUSY;
2789 }
2790
2791 op = net_buf_simple_add(buf, sizeof(*op));
2792 op->num_ases = 0x01;
2793
2794 err = unicast_client_ep_config(ep, buf, codec_cfg);
2795 if (err != 0) {
2796 return err;
2797 }
2798
2799 err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
2800 if (err != 0) {
2801 return err;
2802 }
2803
2804 return 0;
2805 }
2806
bt_bap_unicast_client_qos(struct bt_conn * conn,struct bt_bap_unicast_group * group)2807 int bt_bap_unicast_client_qos(struct bt_conn *conn, struct bt_bap_unicast_group *group)
2808 {
2809 struct bt_bap_stream *stream;
2810 struct bt_ascs_config_op *op;
2811 struct net_buf_simple *buf;
2812 struct bt_bap_ep *ep;
2813 bool conn_stream_found;
2814 int err;
2815
2816 if (conn == NULL) {
2817 LOG_DBG("conn is NULL");
2818
2819 return -ENOTCONN;
2820 }
2821
2822 /* Used to determine if a stream for the supplied connection pointer
2823 * was actually found
2824 */
2825 conn_stream_found = false;
2826
2827 /* Validate streams before starting the QoS execution */
2828 SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
2829 if (stream->conn != conn) {
2830 /* Channel not part of this ACL, skip */
2831 continue;
2832 }
2833 conn_stream_found = true;
2834
2835 ep = stream->ep;
2836 if (ep == NULL) {
2837 LOG_DBG("stream->ep is NULL");
2838 return -EINVAL;
2839 }
2840
2841 /* Can only be done if all the streams are in the codec
2842 * configured state or the QoS configured state
2843 */
2844 switch (ep->status.state) {
2845 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
2846 case BT_BAP_EP_STATE_QOS_CONFIGURED:
2847 break;
2848 default:
2849 LOG_DBG("Invalid state: %s", bt_bap_ep_state_str(stream->ep->status.state));
2850 return -EINVAL;
2851 }
2852
2853 if (bt_bap_stream_verify_qos(stream, stream->qos) != BT_BAP_ASCS_REASON_NONE) {
2854 return -EINVAL;
2855 }
2856
2857 /* Verify ep->dir */
2858 switch (ep->dir) {
2859 case BT_AUDIO_DIR_SINK:
2860 case BT_AUDIO_DIR_SOURCE:
2861 break;
2862 default:
2863 __ASSERT(false, "invalid endpoint dir: %u", ep->dir);
2864 return -EINVAL;
2865 }
2866
2867 if (stream->bap_iso == NULL) {
2868 /* This can only happen if the stream was somehow added
2869 * to a group without the bap_iso being bound to it
2870 */
2871 LOG_ERR("Could not find bap_iso for stream %p", stream);
2872 return -EINVAL;
2873 }
2874 }
2875
2876 if (!conn_stream_found) {
2877 LOG_DBG("No streams in the group %p for conn %p", group, conn);
2878 return -EINVAL;
2879 }
2880
2881 /* Generate the control point write */
2882 buf = bt_bap_unicast_client_ep_create_pdu(conn, BT_ASCS_QOS_OP);
2883 if (buf == NULL) {
2884 LOG_DBG("Could not create PDU");
2885 return -EBUSY;
2886 }
2887
2888 op = net_buf_simple_add(buf, sizeof(*op));
2889
2890 (void)memset(op, 0, sizeof(*op));
2891 ep = NULL; /* Needed to find the control point handle */
2892 SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
2893 if (stream->conn != conn) {
2894 /* Channel not part of this ACL, skip */
2895 continue;
2896 }
2897
2898 op->num_ases++;
2899
2900 if (stream->ep->iso == NULL) {
2901 /* Not yet bound with the bap_iso */
2902 bt_bap_iso_bind_ep(stream->bap_iso, stream->ep);
2903 }
2904
2905 err = bt_bap_unicast_client_ep_qos(stream->ep, buf, stream->qos);
2906 if (err != 0) {
2907 audio_stream_qos_cleanup(conn, group);
2908
2909 return err;
2910 }
2911
2912 if (ep == NULL) {
2913 ep = stream->ep;
2914 }
2915 }
2916
2917 err = bt_bap_unicast_client_ep_send(conn, ep, buf);
2918 if (err != 0) {
2919 LOG_DBG("Could not send config QoS: %d", err);
2920 audio_stream_qos_cleanup(conn, group);
2921
2922 return err;
2923 }
2924
2925 return 0;
2926 }
2927
bt_bap_unicast_client_enable(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)2928 int bt_bap_unicast_client_enable(struct bt_bap_stream *stream, const uint8_t meta[],
2929 size_t meta_len)
2930 {
2931 struct bt_bap_ep *ep = stream->ep;
2932 struct net_buf_simple *buf;
2933 struct bt_ascs_enable_op *req;
2934 int err;
2935
2936 LOG_DBG("stream %p", stream);
2937
2938 if (stream->conn == NULL) {
2939 LOG_DBG("Stream %p does not have a connection", stream);
2940
2941 return -ENOTCONN;
2942 }
2943
2944 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_ENABLE_OP);
2945 if (buf == NULL) {
2946 LOG_DBG("Could not create PDU");
2947 return -EBUSY;
2948 }
2949
2950 req = net_buf_simple_add(buf, sizeof(*req));
2951 req->num_ases = 0x01;
2952
2953 err = unicast_client_ep_enable(ep, buf, meta, meta_len);
2954 if (err) {
2955 return err;
2956 }
2957
2958 return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
2959 }
2960
bt_bap_unicast_client_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)2961 int bt_bap_unicast_client_metadata(struct bt_bap_stream *stream, const uint8_t meta[],
2962 size_t meta_len)
2963 {
2964 struct bt_bap_ep *ep = stream->ep;
2965 struct net_buf_simple *buf;
2966 struct bt_ascs_enable_op *req;
2967 int err;
2968
2969 LOG_DBG("stream %p", stream);
2970
2971 if (stream->conn == NULL) {
2972 LOG_DBG("Stream %p does not have a connection", stream);
2973
2974 return -ENOTCONN;
2975 }
2976
2977 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_METADATA_OP);
2978 if (buf == NULL) {
2979 LOG_DBG("Could not create PDU");
2980 return -EBUSY;
2981 }
2982
2983 req = net_buf_simple_add(buf, sizeof(*req));
2984 req->num_ases = 0x01;
2985
2986 err = unicast_client_ep_metadata(ep, buf, meta, meta_len);
2987 if (err) {
2988 return err;
2989 }
2990
2991 return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
2992 }
2993
bt_bap_unicast_client_connect(struct bt_bap_stream * stream)2994 int bt_bap_unicast_client_connect(struct bt_bap_stream *stream)
2995 {
2996 struct bt_iso_connect_param param;
2997 struct bt_iso_chan *iso_chan;
2998 enum bt_iso_state iso_state;
2999
3000 LOG_DBG("stream %p", stream);
3001
3002 if (stream == NULL) {
3003 LOG_DBG("stream is NULL");
3004
3005 return -EINVAL;
3006 }
3007
3008 iso_chan = bt_bap_stream_iso_chan_get(stream);
3009 if (iso_chan == NULL) {
3010 LOG_DBG("iso_chan is NULL");
3011
3012 return -EINVAL;
3013 }
3014
3015 LOG_DBG("stream %p iso %p", stream, iso_chan);
3016
3017 param.acl = stream->conn;
3018 param.iso_chan = iso_chan;
3019
3020 iso_state = iso_chan->state;
3021 if (iso_state == BT_ISO_STATE_DISCONNECTED) {
3022 const int err = bt_iso_chan_connect(¶m, 1);
3023
3024 if (err == 0 || err == -EBUSY) { /* Expected / known return values */
3025 return err;
3026 }
3027
3028 /* unknown return value*/
3029 LOG_DBG("Unexpected err %d from bt_iso_chan_connect", err);
3030
3031 return -ENOEXEC;
3032 } else if (iso_state == BT_ISO_STATE_CONNECTING || iso_state == BT_ISO_STATE_CONNECTED) {
3033 LOG_DBG("iso_chan %p already connecting or connected (%u)", iso_chan, iso_state);
3034
3035 return -EALREADY;
3036 }
3037
3038 LOG_DBG("iso_chan %p in invalid state state (%u), cannot connect", iso_chan, iso_state);
3039
3040 return -EBADMSG;
3041 }
3042
bt_bap_unicast_client_start(struct bt_bap_stream * stream)3043 int bt_bap_unicast_client_start(struct bt_bap_stream *stream)
3044 {
3045 struct bt_bap_ep *ep = stream->ep;
3046 int err;
3047
3048 LOG_DBG("stream %p", stream);
3049
3050 if (stream->conn == NULL) {
3051 LOG_DBG("Stream %p does not have a connection", stream);
3052
3053 return -ENOTCONN;
3054 }
3055
3056 /* As per the ASCS spec, only source streams can be started by the client */
3057 if (ep->dir == BT_AUDIO_DIR_SINK) {
3058 LOG_DBG("Stream %p is not a source stream", stream);
3059
3060 return -EINVAL;
3061 }
3062
3063 ep->receiver_ready = true;
3064
3065 err = unicast_client_send_start(ep);
3066 if (err != 0) {
3067 LOG_DBG("Failed to send start: %d", err);
3068
3069 /* TBD: Should we release the stream then? */
3070 ep->receiver_ready = false;
3071
3072 return err;
3073 }
3074
3075 return 0;
3076 }
3077
bt_bap_unicast_client_disable(struct bt_bap_stream * stream)3078 int bt_bap_unicast_client_disable(struct bt_bap_stream *stream)
3079 {
3080 struct bt_bap_ep *ep = stream->ep;
3081 struct net_buf_simple *buf;
3082 struct bt_ascs_disable_op *req;
3083 int err;
3084
3085 LOG_DBG("stream %p", stream);
3086
3087 if (stream->conn == NULL) {
3088 LOG_DBG("Stream %p does not have a connection", stream);
3089
3090 return -ENOTCONN;
3091 }
3092
3093 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_DISABLE_OP);
3094 if (buf == NULL) {
3095 LOG_DBG("Could not create PDU");
3096 return -EBUSY;
3097 }
3098
3099 req = net_buf_simple_add(buf, sizeof(*req));
3100 req->num_ases = 0x01;
3101
3102 err = unicast_client_ep_disable(ep, buf);
3103 if (err) {
3104 return err;
3105 }
3106
3107 return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3108 }
3109
bt_bap_unicast_client_stop(struct bt_bap_stream * stream)3110 int bt_bap_unicast_client_stop(struct bt_bap_stream *stream)
3111 {
3112 struct bt_bap_ep *ep = stream->ep;
3113 struct net_buf_simple *buf;
3114 struct bt_ascs_start_op *req;
3115 int err;
3116
3117 LOG_DBG("stream %p", stream);
3118
3119 if (stream->conn == NULL) {
3120 LOG_DBG("Stream %p does not have a connection", stream);
3121
3122 return -ENOTCONN;
3123 }
3124
3125 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_STOP_OP);
3126 if (buf == NULL) {
3127 LOG_DBG("Could not create PDU");
3128 return -EBUSY;
3129 }
3130
3131 req = net_buf_simple_add(buf, sizeof(*req));
3132 req->num_ases = 0x00;
3133
3134 /* When initiated by the client, valid only if Direction field
3135 * parameter value = 0x02 (Server is Audio Source)
3136 */
3137 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
3138 err = unicast_client_ep_stop(ep, buf);
3139 if (err) {
3140 return err;
3141 }
3142 req->num_ases++;
3143
3144 return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3145 }
3146
3147 return 0;
3148 }
3149
bt_bap_unicast_client_release(struct bt_bap_stream * stream)3150 int bt_bap_unicast_client_release(struct bt_bap_stream *stream)
3151 {
3152 struct bt_bap_unicast_client_ep *client_ep;
3153 struct bt_bap_ep *ep = stream->ep;
3154 struct net_buf_simple *buf;
3155 struct bt_ascs_disable_op *req;
3156 int err, len;
3157
3158 LOG_DBG("stream %p", stream);
3159
3160 if (stream->conn == NULL) {
3161 LOG_DBG("Stream %p does not have a connection", stream);
3162
3163 return -ENOTCONN;
3164 }
3165
3166 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_RELEASE_OP);
3167 if (buf == NULL) {
3168 LOG_DBG("Could not create PDU");
3169 return -EBUSY;
3170 }
3171
3172 req = net_buf_simple_add(buf, sizeof(*req));
3173 req->num_ases = 0x01;
3174 len = buf->len;
3175
3176 /* Only attempt to release if not IDLE already */
3177 if (stream->ep->status.state == BT_BAP_EP_STATE_IDLE) {
3178 bt_bap_stream_reset(stream);
3179 } else {
3180 err = unicast_client_ep_release(ep, buf);
3181 if (err) {
3182 return err;
3183 }
3184 }
3185
3186 /* Check if anything needs to be send */
3187 if (len == buf->len) {
3188 return 0;
3189 }
3190
3191 err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3192 if (err != 0) {
3193 return err;
3194 }
3195
3196 client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
3197 client_ep->release_requested = true;
3198
3199 return 0;
3200 }
3201
unicast_client_cp_discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3202 static uint8_t unicast_client_cp_discover_func(struct bt_conn *conn,
3203 const struct bt_gatt_attr *attr,
3204 struct bt_gatt_discover_params *discover)
3205 {
3206 struct bt_gatt_chrc *chrc;
3207 uint16_t value_handle;
3208
3209 if (!attr) {
3210 LOG_ERR("Unable to find ASE Control Point");
3211
3212 discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
3213 return BT_GATT_ITER_STOP;
3214 }
3215
3216 chrc = attr->user_data;
3217 value_handle = chrc->value_handle;
3218 memset(discover, 0, sizeof(*discover));
3219
3220 LOG_DBG("conn %p attr %p handle 0x%04x", conn, attr, value_handle);
3221
3222 unicast_client_ep_set_cp(conn, value_handle);
3223
3224 return BT_GATT_ITER_STOP;
3225 }
3226
unicast_client_ase_cp_discover(struct bt_conn * conn)3227 static int unicast_client_ase_cp_discover(struct bt_conn *conn)
3228 {
3229 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3230
3231 LOG_DBG("conn %p", conn);
3232
3233 client->disc_params.uuid = cp_uuid;
3234 client->disc_params.func = unicast_client_cp_discover_func;
3235 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
3236 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3237 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3238
3239 return bt_gatt_discover(conn, &client->disc_params);
3240 }
3241
unicast_client_ase_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)3242 static uint8_t unicast_client_ase_read_func(struct bt_conn *conn, uint8_t err,
3243 struct bt_gatt_read_params *read, const void *data,
3244 uint16_t length)
3245 {
3246 uint16_t handle = read->single.handle;
3247 struct unicast_client *client;
3248 struct net_buf_simple *buf;
3249 struct bt_bap_ep *ep;
3250 int cb_err;
3251
3252 LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
3253
3254 if (err) {
3255 cb_err = err;
3256 goto fail;
3257 }
3258
3259 LOG_DBG("handle 0x%04x", handle);
3260
3261 client = &uni_cli_insts[bt_conn_index(conn)];
3262 buf = &client->net_buf;
3263
3264 if (data != NULL) {
3265 if (net_buf_simple_tailroom(buf) < length) {
3266 LOG_DBG("Buffer full, invalid server response of size %u",
3267 length + client->net_buf.len);
3268
3269 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3270
3271 goto fail;
3272 }
3273
3274 /* store data*/
3275 net_buf_simple_add_mem(buf, data, length);
3276
3277 return BT_GATT_ITER_CONTINUE;
3278 }
3279
3280 memset(read, 0, sizeof(*read));
3281
3282 if (buf->len < sizeof(struct bt_ascs_ase_status)) {
3283 LOG_DBG("Read response too small (%u)", buf->len);
3284
3285 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3286
3287 goto fail;
3288 }
3289
3290 ep = unicast_client_ep_get(conn, client->dir, handle);
3291 if (!ep) {
3292 /* The BAP spec declares that the unicast client shall subscribe to all ASEs.
3293 * In case that we cannot support this due to memory restrictions, we should
3294 * consider the discovery procedure as failing.
3295 */
3296 LOG_WRN("No space left to parse ASE");
3297 cb_err = -ENOMEM;
3298
3299 goto fail;
3300 }
3301
3302 unicast_client_ep_set_status(ep, buf);
3303 cb_err = unicast_client_ep_subscribe(conn, ep);
3304 if (cb_err != 0) {
3305 LOG_DBG("Failed to subscribe to ep %p: %d", ep, cb_err);
3306 goto fail;
3307 }
3308
3309 reset_att_buf(client);
3310
3311 endpoint_cb(conn, ep);
3312
3313 cb_err = unicast_client_ase_discover(conn, handle);
3314 if (cb_err != 0) {
3315 LOG_DBG("Failed to read ASE: %d", cb_err);
3316 goto fail;
3317 }
3318
3319 return BT_GATT_ITER_STOP;
3320
3321 fail:
3322 discover_cb(conn, cb_err);
3323 return BT_GATT_ITER_STOP;
3324 }
3325
unicast_client_ase_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3326 static uint8_t unicast_client_ase_discover_cb(struct bt_conn *conn,
3327 const struct bt_gatt_attr *attr,
3328 struct bt_gatt_discover_params *discover)
3329 {
3330 struct unicast_client *client;
3331 struct bt_gatt_chrc *chrc;
3332 uint16_t value_handle;
3333 int err;
3334
3335 if (attr == NULL) {
3336 err = unicast_client_ase_cp_discover(conn);
3337 if (err != 0) {
3338 LOG_ERR("Unable to discover ASE Control Point");
3339
3340 discover_cb(conn, err);
3341 }
3342
3343 return BT_GATT_ITER_STOP;
3344 }
3345
3346 chrc = attr->user_data;
3347 value_handle = chrc->value_handle;
3348 memset(discover, 0, sizeof(*discover));
3349
3350 client = &uni_cli_insts[bt_conn_index(conn)];
3351
3352 LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle,
3353 bt_audio_dir_str(client->dir));
3354
3355 client->read_params.func = unicast_client_ase_read_func;
3356 client->read_params.handle_count = 1U;
3357 client->read_params.single.handle = value_handle;
3358 client->read_params.single.offset = 0U;
3359
3360 err = bt_gatt_read(conn, &client->read_params);
3361 if (err != 0) {
3362 LOG_DBG("Failed to read PAC records: %d", err);
3363
3364 discover_cb(conn, err);
3365 }
3366
3367 return BT_GATT_ITER_STOP;
3368 }
3369
unicast_client_ase_discover(struct bt_conn * conn,uint16_t start_handle)3370 static int unicast_client_ase_discover(struct bt_conn *conn, uint16_t start_handle)
3371 {
3372 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3373
3374 LOG_DBG("conn %p ", conn);
3375
3376 if (client->dir == BT_AUDIO_DIR_SINK) {
3377 client->disc_params.uuid = ase_snk_uuid;
3378 } else if (client->dir == BT_AUDIO_DIR_SOURCE) {
3379 client->disc_params.uuid = ase_src_uuid;
3380 } else {
3381 return -EINVAL;
3382 }
3383
3384 client->disc_params.func = unicast_client_ase_discover_cb;
3385 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3386 client->disc_params.start_handle = start_handle;
3387 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3388
3389 return bt_gatt_discover(conn, &client->disc_params);
3390 }
3391
unicast_client_pacs_avail_ctx_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)3392 static uint8_t unicast_client_pacs_avail_ctx_read_func(struct bt_conn *conn, uint8_t err,
3393 struct bt_gatt_read_params *read,
3394 const void *data, uint16_t length)
3395 {
3396 struct bt_pacs_context context;
3397 struct net_buf_simple buf;
3398 int cb_err;
3399
3400 memset(read, 0, sizeof(*read));
3401
3402 LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
3403
3404 if (err || data == NULL || length != sizeof(context)) {
3405 LOG_DBG("Could not read available context: %d, %p, %u", err, data, length);
3406
3407 if (err == BT_ATT_ERR_SUCCESS) {
3408 err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3409 }
3410
3411 discover_cb(conn, err);
3412
3413 return BT_GATT_ITER_STOP;
3414 }
3415
3416 net_buf_simple_init_with_data(&buf, (void *)data, length);
3417 context.snk = net_buf_simple_pull_le16(&buf);
3418 context.src = net_buf_simple_pull_le16(&buf);
3419
3420 LOG_DBG("sink context %u, source context %u", context.snk, context.src);
3421
3422 if (unicast_client_cbs != NULL && unicast_client_cbs->available_contexts != NULL) {
3423 unicast_client_cbs->available_contexts(conn, context.snk, context.src);
3424 }
3425
3426 /* Read ASE instances */
3427 cb_err = unicast_client_ase_discover(conn, BT_ATT_FIRST_ATTRIBUTE_HANDLE);
3428 if (cb_err != 0) {
3429 LOG_ERR("Unable to read ASE: %d", cb_err);
3430
3431 discover_cb(conn, cb_err);
3432 }
3433
3434 return BT_GATT_ITER_STOP;
3435 }
3436
unicast_client_pacs_avail_ctx_notify_cb(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)3437 static uint8_t unicast_client_pacs_avail_ctx_notify_cb(struct bt_conn *conn,
3438 struct bt_gatt_subscribe_params *params,
3439 const void *data, uint16_t length)
3440 {
3441 struct bt_pacs_context context;
3442 struct net_buf_simple buf;
3443
3444 LOG_DBG("conn %p len %u", conn, length);
3445
3446 if (!data) {
3447 LOG_DBG("Unsubscribed");
3448 params->value_handle = 0x0000;
3449 return BT_GATT_ITER_STOP;
3450 }
3451
3452 /* Terminate early if there's no callbacks */
3453 if (unicast_client_cbs == NULL || unicast_client_cbs->available_contexts == NULL) {
3454 return BT_GATT_ITER_CONTINUE;
3455 }
3456
3457 net_buf_simple_init_with_data(&buf, (void *)data, length);
3458
3459 if (buf.len != sizeof(context)) {
3460 LOG_ERR("Avail_ctx notification incorrect size: %u", length);
3461 return BT_GATT_ITER_STOP;
3462 }
3463
3464 net_buf_simple_init_with_data(&buf, (void *)data, length);
3465 context.snk = net_buf_simple_pull_le16(&buf);
3466 context.src = net_buf_simple_pull_le16(&buf);
3467
3468 LOG_DBG("sink context %u, source context %u", context.snk, context.src);
3469
3470 if (unicast_client_cbs != NULL && unicast_client_cbs->available_contexts != NULL) {
3471 unicast_client_cbs->available_contexts(conn, context.snk, context.src);
3472 }
3473
3474 return BT_GATT_ITER_CONTINUE;
3475 }
3476
unicast_client_pacs_avail_ctx_read(struct bt_conn * conn,uint16_t handle)3477 static int unicast_client_pacs_avail_ctx_read(struct bt_conn *conn, uint16_t handle)
3478 {
3479 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3480
3481 LOG_DBG("conn %p", conn);
3482
3483 client->read_params.func = unicast_client_pacs_avail_ctx_read_func;
3484 client->read_params.handle_count = 1U;
3485 client->read_params.single.handle = handle;
3486 client->read_params.single.offset = 0U;
3487
3488 return bt_gatt_read(conn, &client->read_params);
3489 }
3490
unicast_client_pacs_avail_ctx_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3491 static uint8_t unicast_client_pacs_avail_ctx_discover_cb(struct bt_conn *conn,
3492 const struct bt_gatt_attr *attr,
3493 struct bt_gatt_discover_params *discover)
3494 {
3495 uint8_t index = bt_conn_index(conn);
3496 const struct bt_gatt_chrc *chrc;
3497 uint8_t chrc_properties;
3498 uint16_t value_handle;
3499 int err;
3500
3501 if (!attr) {
3502 /* If available_ctx is not found, we terminate the discovery as
3503 * the characteristic is mandatory
3504 */
3505
3506 discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
3507
3508 return BT_GATT_ITER_STOP;
3509 }
3510
3511 chrc = attr->user_data;
3512 chrc_properties = chrc->properties;
3513 value_handle = chrc->value_handle;
3514 memset(discover, 0, sizeof(*discover));
3515
3516 LOG_DBG("conn %p attr %p handle 0x%04x", conn, attr, value_handle);
3517
3518 if (chrc_properties & BT_GATT_CHRC_NOTIFY) {
3519 struct bt_gatt_subscribe_params *sub_params;
3520
3521 sub_params = &uni_cli_insts[index].avail_ctx_subscribe;
3522
3523 if (sub_params->value_handle == 0) {
3524 LOG_DBG("Subscribing to handle %u", value_handle);
3525 sub_params->value_handle = value_handle;
3526 sub_params->ccc_handle = 0x0000; /* auto discover ccc */
3527 sub_params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3528 sub_params->disc_params = &uni_cli_insts[index].avail_ctx_cc_disc;
3529 sub_params->notify = unicast_client_pacs_avail_ctx_notify_cb;
3530 sub_params->value = BT_GATT_CCC_NOTIFY;
3531 atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
3532
3533 err = bt_gatt_subscribe(conn, sub_params);
3534 if (err != 0 && err != -EALREADY) {
3535 LOG_ERR("Failed to subscribe to avail_ctx: %d", err);
3536 }
3537 } /* else already subscribed */
3538 } else {
3539 LOG_DBG("Invalid chrc->properties: %u", chrc_properties);
3540 /* If the characteristic is not subscribable we terminate the
3541 * discovery as BT_GATT_CHRC_NOTIFY is mandatory
3542 */
3543 discover_cb(conn, BT_ATT_ERR_NOT_SUPPORTED);
3544
3545 return BT_GATT_ITER_STOP;
3546 }
3547
3548 err = unicast_client_pacs_avail_ctx_read(conn, value_handle);
3549 if (err != 0) {
3550 LOG_DBG("Failed to read PACS avail_ctx: %d", err);
3551
3552 discover_cb(conn, err);
3553 }
3554
3555 return BT_GATT_ITER_STOP;
3556 }
3557
unicast_client_pacs_avail_ctx_discover(struct bt_conn * conn)3558 static int unicast_client_pacs_avail_ctx_discover(struct bt_conn *conn)
3559 {
3560 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3561
3562 LOG_DBG("conn %p", conn);
3563
3564 client->disc_params.uuid = pacs_avail_ctx_uuid;
3565 client->disc_params.func = unicast_client_pacs_avail_ctx_discover_cb;
3566 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
3567 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3568 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3569
3570 return bt_gatt_discover(conn, &client->disc_params);
3571 }
3572
unicast_client_pacs_location_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)3573 static uint8_t unicast_client_pacs_location_read_func(struct bt_conn *conn, uint8_t err,
3574 struct bt_gatt_read_params *read,
3575 const void *data, uint16_t length)
3576 {
3577 struct unicast_client *client;
3578 struct net_buf_simple buf;
3579 uint32_t location;
3580 int cb_err;
3581
3582 memset(read, 0, sizeof(*read));
3583
3584 client = &uni_cli_insts[bt_conn_index(conn)];
3585
3586 LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
3587
3588 if (err || data == NULL || length != sizeof(location)) {
3589 LOG_DBG("Unable to read PACS location for dir %s: %u, %p, %u",
3590 bt_audio_dir_str(client->dir), err, data, length);
3591
3592 if (err == BT_ATT_ERR_SUCCESS) {
3593 err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3594 }
3595
3596 discover_cb(conn, err);
3597
3598 return BT_GATT_ITER_STOP;
3599 }
3600
3601 net_buf_simple_init_with_data(&buf, (void *)data, length);
3602 location = net_buf_simple_pull_le32(&buf);
3603
3604 LOG_DBG("dir %s loc %X", bt_audio_dir_str(client->dir), location);
3605
3606 if (unicast_client_cbs != NULL && unicast_client_cbs->location != NULL) {
3607 unicast_client_cbs->location(conn, client->dir, (enum bt_audio_location)location);
3608 }
3609
3610 /* Read available contexts */
3611 cb_err = unicast_client_pacs_avail_ctx_discover(conn);
3612 if (cb_err != 0) {
3613 LOG_ERR("Unable to read available contexts: %d", cb_err);
3614
3615 discover_cb(conn, cb_err);
3616 }
3617
3618 return BT_GATT_ITER_STOP;
3619 }
3620
unicast_client_pacs_location_notify_cb(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)3621 static uint8_t unicast_client_pacs_location_notify_cb(struct bt_conn *conn,
3622 struct bt_gatt_subscribe_params *params,
3623 const void *data, uint16_t length)
3624 {
3625 struct net_buf_simple buf;
3626 enum bt_audio_dir dir;
3627 uint32_t location;
3628
3629 LOG_DBG("conn %p len %u", conn, length);
3630
3631 if (!data) {
3632 LOG_DBG("Unsubscribed");
3633 params->value_handle = 0x0000;
3634 return BT_GATT_ITER_STOP;
3635 }
3636
3637 /* Terminate early if there's no callbacks */
3638 if (unicast_client_cbs == NULL || unicast_client_cbs->location == NULL) {
3639 return BT_GATT_ITER_CONTINUE;
3640 }
3641
3642 net_buf_simple_init_with_data(&buf, (void *)data, length);
3643
3644 if (buf.len != sizeof(location)) {
3645 LOG_ERR("Location notification incorrect size: %u", length);
3646 return BT_GATT_ITER_STOP;
3647 }
3648
3649 if (params == &uni_cli_insts[bt_conn_index(conn)].snk_loc_subscribe) {
3650 dir = BT_AUDIO_DIR_SINK;
3651 } else if (params == &uni_cli_insts[bt_conn_index(conn)].src_loc_subscribe) {
3652 dir = BT_AUDIO_DIR_SOURCE;
3653 } else {
3654 LOG_ERR("Invalid notification");
3655
3656 return BT_GATT_ITER_CONTINUE;
3657 }
3658
3659 net_buf_simple_init_with_data(&buf, (void *)data, length);
3660 location = net_buf_simple_pull_le32(&buf);
3661
3662 LOG_DBG("dir %s loc %X", bt_audio_dir_str(dir), location);
3663
3664 if (unicast_client_cbs != NULL && unicast_client_cbs->location != NULL) {
3665 unicast_client_cbs->location(conn, dir, (enum bt_audio_location)location);
3666 }
3667
3668 return BT_GATT_ITER_CONTINUE;
3669 }
3670
unicast_client_pacs_location_read(struct bt_conn * conn,uint16_t handle)3671 static int unicast_client_pacs_location_read(struct bt_conn *conn, uint16_t handle)
3672 {
3673 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3674
3675 LOG_DBG("conn %p", conn);
3676
3677 client->read_params.func = unicast_client_pacs_location_read_func;
3678 client->read_params.handle_count = 1U;
3679 client->read_params.single.handle = handle;
3680 client->read_params.single.offset = 0U;
3681
3682 return bt_gatt_read(conn, &client->read_params);
3683 }
3684
unicast_client_pacs_location_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3685 static uint8_t unicast_client_pacs_location_discover_cb(struct bt_conn *conn,
3686 const struct bt_gatt_attr *attr,
3687 struct bt_gatt_discover_params *discover)
3688 {
3689 uint8_t index = bt_conn_index(conn);
3690 const struct bt_gatt_chrc *chrc;
3691 uint16_t value_handle;
3692 int err;
3693
3694 if (!attr) {
3695 /* If location is not found, we just continue reading the
3696 * available contexts, as location is optional.
3697 */
3698 err = unicast_client_pacs_avail_ctx_discover(conn);
3699 if (err != 0) {
3700 LOG_ERR("Unable to read available contexts: %d", err);
3701
3702 discover_cb(conn, err);
3703 }
3704
3705 return BT_GATT_ITER_STOP;
3706 }
3707
3708 chrc = attr->user_data;
3709 value_handle = chrc->value_handle;
3710 memset(discover, 0, sizeof(*discover));
3711
3712 LOG_DBG("conn %p attr %p handle 0x%04x", conn, attr, value_handle);
3713
3714 if (chrc->properties & BT_GATT_CHRC_NOTIFY) {
3715 const struct unicast_client *client = &uni_cli_insts[index];
3716 struct bt_gatt_subscribe_params *sub_params;
3717
3718 if (client->dir == BT_AUDIO_DIR_SINK) {
3719 sub_params = &uni_cli_insts[index].snk_loc_subscribe;
3720 } else {
3721 sub_params = &uni_cli_insts[index].src_loc_subscribe;
3722 }
3723
3724 sub_params->value_handle = value_handle;
3725 sub_params->ccc_handle = 0x0000; /* auto discover ccc */
3726 sub_params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3727 sub_params->disc_params = &uni_cli_insts[index].loc_cc_disc;
3728 sub_params->notify = unicast_client_pacs_location_notify_cb;
3729 sub_params->value = BT_GATT_CCC_NOTIFY;
3730 atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
3731
3732 err = bt_gatt_subscribe(conn, sub_params);
3733 if (err != 0 && err != -EALREADY) {
3734 LOG_ERR("Failed to subscribe to location: %d", err);
3735 }
3736 }
3737
3738 err = unicast_client_pacs_location_read(conn, value_handle);
3739 if (err != 0) {
3740 LOG_DBG("Failed to read PACS location: %d", err);
3741
3742 discover_cb(conn, err);
3743 }
3744
3745 return BT_GATT_ITER_STOP;
3746 }
3747
unicast_client_pacs_location_discover(struct bt_conn * conn)3748 static int unicast_client_pacs_location_discover(struct bt_conn *conn)
3749 {
3750 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3751
3752 LOG_DBG("conn %p dir %s", conn, bt_audio_dir_str(client->dir));
3753
3754 if (client->dir == BT_AUDIO_DIR_SINK) {
3755 client->disc_params.uuid = pacs_snk_loc_uuid;
3756 } else if (client->dir == BT_AUDIO_DIR_SOURCE) {
3757 client->disc_params.uuid = pacs_src_loc_uuid;
3758 } else {
3759 return -EINVAL;
3760 }
3761
3762 client->disc_params.func = unicast_client_pacs_location_discover_cb;
3763 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
3764 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3765 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3766
3767 return bt_gatt_discover(conn, &client->disc_params);
3768 }
3769
unicast_client_pacs_context_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)3770 static uint8_t unicast_client_pacs_context_read_func(struct bt_conn *conn, uint8_t err,
3771 struct bt_gatt_read_params *read,
3772 const void *data, uint16_t length)
3773 {
3774 struct net_buf_simple buf;
3775 struct bt_pacs_context *context;
3776 int cb_err;
3777
3778 memset(read, 0, sizeof(*read));
3779
3780 LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
3781
3782 if (err || length < sizeof(uint16_t) * 2) {
3783 goto discover_loc;
3784 }
3785
3786 net_buf_simple_init_with_data(&buf, (void *)data, length);
3787 context = net_buf_simple_pull_mem(&buf, sizeof(*context));
3788
3789 discover_loc:
3790 /* Read ASE instances */
3791 cb_err = unicast_client_pacs_location_discover(conn);
3792 if (cb_err != 0) {
3793 LOG_ERR("Unable to read PACS location: %d", cb_err);
3794
3795 discover_cb(conn, cb_err);
3796 }
3797
3798 return BT_GATT_ITER_STOP;
3799 }
3800
unicast_client_pacs_context_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3801 static uint8_t unicast_client_pacs_context_discover_cb(struct bt_conn *conn,
3802 const struct bt_gatt_attr *attr,
3803 struct bt_gatt_discover_params *discover)
3804 {
3805 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3806 struct bt_gatt_chrc *chrc;
3807 uint16_t value_handle;
3808 int err;
3809
3810 if (attr == NULL) {
3811 LOG_ERR("Unable to find %s PAC context", bt_audio_dir_str(client->dir));
3812
3813 discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
3814
3815 return BT_GATT_ITER_STOP;
3816 }
3817
3818 chrc = attr->user_data;
3819 value_handle = chrc->value_handle;
3820 memset(discover, 0, sizeof(*discover));
3821
3822 LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle,
3823 bt_audio_dir_str(client->dir));
3824
3825 /* TODO: Subscribe to PAC context */
3826
3827 client->read_params.func = unicast_client_pacs_context_read_func;
3828 client->read_params.handle_count = 1U;
3829 client->read_params.single.handle = value_handle;
3830 client->read_params.single.offset = 0U;
3831
3832 err = bt_gatt_read(conn, &client->read_params);
3833 if (err != 0) {
3834 LOG_DBG("Failed to read PAC records: %d", err);
3835
3836 discover_cb(conn, err);
3837 }
3838
3839 return BT_GATT_ITER_STOP;
3840 }
3841
unicast_client_pacs_context_discover(struct bt_conn * conn)3842 static int unicast_client_pacs_context_discover(struct bt_conn *conn)
3843 {
3844 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3845
3846 LOG_DBG("conn %p", conn);
3847
3848 client->disc_params.uuid = pacs_context_uuid;
3849 client->disc_params.func = unicast_client_pacs_context_discover_cb;
3850 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3851 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
3852 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3853
3854 return bt_gatt_discover(conn, &client->disc_params);
3855 }
3856
unicast_client_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)3857 static uint8_t unicast_client_read_func(struct bt_conn *conn, uint8_t err,
3858 struct bt_gatt_read_params *read, const void *data,
3859 uint16_t length)
3860 {
3861 uint16_t handle = read->single.handle;
3862 struct unicast_client *client;
3863 struct bt_pacs_read_rsp *rsp;
3864 struct net_buf_simple *buf;
3865 int cb_err = err;
3866 uint8_t i;
3867
3868 LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
3869
3870 if (cb_err != BT_ATT_ERR_SUCCESS) {
3871 goto fail;
3872 }
3873
3874 LOG_DBG("handle 0x%04x", handle);
3875
3876 client = &uni_cli_insts[bt_conn_index(conn)];
3877 buf = &client->net_buf;
3878
3879 if (data != NULL) {
3880 if (net_buf_simple_tailroom(buf) < length) {
3881 LOG_DBG("Buffer full, invalid server response of size %u",
3882 length + client->net_buf.len);
3883
3884 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3885
3886 goto fail;
3887 }
3888
3889 /* store data*/
3890 net_buf_simple_add_mem(buf, data, length);
3891
3892 return BT_GATT_ITER_CONTINUE;
3893 }
3894
3895 memset(read, 0, sizeof(*read));
3896
3897 if (buf->len < sizeof(*rsp)) {
3898 LOG_DBG("Read response too small (%u)", buf->len);
3899
3900 cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3901
3902 goto fail;
3903 }
3904
3905 rsp = net_buf_simple_pull_mem(buf, sizeof(*rsp));
3906
3907 /* If no PAC was found don't bother discovering ASE and ASE CP */
3908 if (!rsp->num_pac) {
3909 goto fail;
3910 }
3911
3912 for (i = 0U; i < rsp->num_pac; i++) {
3913 struct bt_audio_codec_cap codec_cap;
3914 struct bt_pac_codec *pac_codec;
3915 struct bt_pac_ltv_data *meta, *cc;
3916 void *cc_ltv, *meta_ltv;
3917
3918 LOG_DBG("pac #%u/%u", i + 1, rsp->num_pac);
3919
3920 if (buf->len < sizeof(*pac_codec)) {
3921 LOG_ERR("Malformed PAC: remaining len %u expected %zu",
3922 buf->len, sizeof(*pac_codec));
3923 break;
3924 }
3925
3926 pac_codec = net_buf_simple_pull_mem(buf, sizeof(*pac_codec));
3927
3928 if (buf->len < sizeof(*cc)) {
3929 LOG_ERR("Malformed PAC: remaining len %u expected %zu",
3930 buf->len, sizeof(*cc));
3931 break;
3932 }
3933
3934 cc = net_buf_simple_pull_mem(buf, sizeof(*cc));
3935 if (buf->len < cc->len) {
3936 LOG_ERR("Malformed PAC: remaining len %u expected %zu",
3937 buf->len, cc->len);
3938 break;
3939 }
3940
3941 cc_ltv = net_buf_simple_pull_mem(buf, cc->len);
3942
3943 if (buf->len < sizeof(*meta)) {
3944 LOG_ERR("Malformed PAC: remaining len %u expected %zu",
3945 buf->len, sizeof(*meta));
3946 break;
3947 }
3948
3949 meta = net_buf_simple_pull_mem(buf, sizeof(*meta));
3950 if (buf->len < meta->len) {
3951 LOG_ERR("Malformed PAC: remaining len %u expected %u",
3952 buf->len, meta->len);
3953 break;
3954 }
3955
3956 meta_ltv = net_buf_simple_pull_mem(buf, meta->len);
3957
3958 if (unicast_client_set_codec_cap(pac_codec->id, sys_le16_to_cpu(pac_codec->cid),
3959 sys_le16_to_cpu(pac_codec->vid), cc_ltv, cc->len,
3960 meta_ltv, meta->len, &codec_cap)) {
3961 LOG_ERR("Unable to parse Codec");
3962 break;
3963 }
3964
3965 LOG_DBG("codec 0x%02x capabilities len %u meta len %u ", codec_cap.id,
3966 codec_cap.data_len, codec_cap.meta_len);
3967
3968 pac_record_cb(conn, &codec_cap);
3969 }
3970
3971 reset_att_buf(client);
3972
3973 if (i != rsp->num_pac) {
3974 LOG_DBG("Failed to process all PAC records (%u/%u)", i, rsp->num_pac);
3975 cb_err = BT_ATT_ERR_INVALID_PDU;
3976 goto fail;
3977 }
3978
3979 /* Read PACS contexts */
3980 cb_err = unicast_client_pacs_context_discover(conn);
3981 if (cb_err != 0) {
3982 LOG_ERR("Unable to read PACS context: %d", cb_err);
3983 goto fail;
3984 }
3985
3986 return BT_GATT_ITER_STOP;
3987
3988 fail:
3989 discover_cb(conn, cb_err);
3990 return BT_GATT_ITER_STOP;
3991 }
3992
unicast_client_pac_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3993 static uint8_t unicast_client_pac_discover_cb(struct bt_conn *conn,
3994 const struct bt_gatt_attr *attr,
3995 struct bt_gatt_discover_params *discover)
3996 {
3997 struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3998 struct bt_gatt_chrc *chrc;
3999 uint16_t value_handle;
4000 int err;
4001
4002 if (attr == NULL) {
4003 LOG_DBG("Unable to find %s PAC", bt_audio_dir_str(client->dir));
4004
4005 discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
4006
4007 return BT_GATT_ITER_STOP;
4008 }
4009
4010 chrc = attr->user_data;
4011 value_handle = chrc->value_handle;
4012 memset(discover, 0, sizeof(*discover));
4013
4014 LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle,
4015 bt_audio_dir_str(client->dir));
4016
4017 /* TODO: Subscribe to PAC */
4018
4019 /* Reset to use for long read */
4020 reset_att_buf(client);
4021
4022 client->read_params.func = unicast_client_read_func;
4023 client->read_params.handle_count = 1U;
4024 client->read_params.single.handle = value_handle;
4025 client->read_params.single.offset = 0U;
4026
4027 err = bt_gatt_read(conn, &client->read_params);
4028 if (err != 0) {
4029 LOG_DBG("Failed to read PAC records: %d", err);
4030
4031 discover_cb(conn, err);
4032 }
4033
4034 return BT_GATT_ITER_STOP;
4035 }
4036
unicast_client_disconnected(struct bt_conn * conn,uint8_t reason)4037 static void unicast_client_disconnected(struct bt_conn *conn, uint8_t reason)
4038 {
4039 LOG_DBG("conn %p reason 0x%02x", conn, reason);
4040
4041 unicast_client_ep_reset(conn, reason);
4042 }
4043
4044 static struct bt_conn_cb conn_cbs = {
4045 .disconnected = unicast_client_disconnected,
4046 };
4047
bt_bap_unicast_client_discover(struct bt_conn * conn,enum bt_audio_dir dir)4048 int bt_bap_unicast_client_discover(struct bt_conn *conn, enum bt_audio_dir dir)
4049 {
4050 struct unicast_client *client;
4051 static bool conn_cb_registered;
4052 uint8_t role;
4053 int err;
4054
4055 if (!conn || conn->state != BT_CONN_CONNECTED) {
4056 return -ENOTCONN;
4057 }
4058
4059 role = conn->role;
4060 if (role != BT_HCI_ROLE_CENTRAL) {
4061 LOG_DBG("Invalid conn role: %u, shall be central", role);
4062 return -EINVAL;
4063 }
4064
4065 client = &uni_cli_insts[bt_conn_index(conn)];
4066 if (client->busy) {
4067 LOG_DBG("Client connection is busy");
4068 return -EBUSY;
4069 }
4070
4071 if (dir == BT_AUDIO_DIR_SINK) {
4072 client->disc_params.uuid = snk_uuid;
4073 } else if (dir == BT_AUDIO_DIR_SOURCE) {
4074 client->disc_params.uuid = src_uuid;
4075 } else {
4076 return -EINVAL;
4077 }
4078
4079 client->disc_params.func = unicast_client_pac_discover_cb;
4080 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
4081 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
4082 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
4083
4084 if (!conn_cb_registered) {
4085 bt_conn_cb_register(&conn_cbs);
4086 conn_cb_registered = true;
4087 }
4088
4089 err = bt_gatt_discover(conn, &client->disc_params);
4090 if (err != 0) {
4091 return err;
4092 }
4093
4094 client->dir = dir;
4095 client->busy = true;
4096
4097 return 0;
4098 }
4099
bt_bap_unicast_client_register_cb(const struct bt_bap_unicast_client_cb * cbs)4100 int bt_bap_unicast_client_register_cb(const struct bt_bap_unicast_client_cb *cbs)
4101 {
4102 CHECKIF(cbs == NULL) {
4103 LOG_DBG("cbs is NULL");
4104 return -EINVAL;
4105 }
4106
4107 if (unicast_client_cbs != NULL) {
4108 LOG_DBG("Callbacks already registered");
4109 return -EALREADY;
4110 }
4111
4112 unicast_client_cbs = cbs;
4113
4114 return 0;
4115 }
4116