1 /* @file
2 * @brief Bluetooth ASCS
3 */
4 /*
5 * Copyright (c) 2020 Intel Corporation
6 * Copyright (c) 2022-2023 Nordic Semiconductor ASA
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/sys/check.h>
14
15 #include <zephyr/bluetooth/bluetooth.h>
16 #include <zephyr/bluetooth/conn.h>
17 #include <zephyr/bluetooth/gatt.h>
18 #include "zephyr/bluetooth/iso.h"
19 #include <zephyr/bluetooth/audio/audio.h>
20 #include <zephyr/bluetooth/audio/bap.h>
21 #include <zephyr/bluetooth/audio/pacs.h>
22
23 #include <zephyr/logging/log.h>
24
25 LOG_MODULE_REGISTER(bt_ascs, CONFIG_BT_ASCS_LOG_LEVEL);
26
27 #include "common/bt_str.h"
28 #include "common/assert.h"
29
30 #include "../host/att_internal.h"
31
32 #include "audio_internal.h"
33 #include "bap_iso.h"
34 #include "bap_endpoint.h"
35 #include "bap_unicast_server.h"
36 #include "pacs_internal.h"
37 #include "cap_internal.h"
38
39 #define ASE_BUF_SEM_TIMEOUT K_MSEC(CONFIG_BT_ASCS_ASE_BUF_TIMEOUT)
40
41 #define MAX_ASES_SESSIONS CONFIG_BT_MAX_CONN * \
42 (CONFIG_BT_ASCS_ASE_SNK_COUNT + \
43 CONFIG_BT_ASCS_ASE_SRC_COUNT)
44
45 BUILD_ASSERT(CONFIG_BT_ASCS_MAX_ACTIVE_ASES <= MAX(MAX_ASES_SESSIONS,
46 CONFIG_BT_ISO_MAX_CHAN),
47 "Max active ASEs are set to more than actual number of ASEs or ISOs");
48
49 #if defined(CONFIG_BT_BAP_UNICAST_SERVER)
50
51 #define ASE_ID(_ase) ase->ep.status.id
52 #define ASE_DIR(_id) \
53 (_id > CONFIG_BT_ASCS_ASE_SNK_COUNT ? BT_AUDIO_DIR_SOURCE : BT_AUDIO_DIR_SINK)
54 #define ASE_UUID(_id) \
55 (_id > CONFIG_BT_ASCS_ASE_SNK_COUNT ? BT_UUID_ASCS_ASE_SRC : BT_UUID_ASCS_ASE_SNK)
56 #define ASE_COUNT (CONFIG_BT_ASCS_ASE_SNK_COUNT + CONFIG_BT_ASCS_ASE_SRC_COUNT)
57
58 static struct bt_ascs_ase {
59 struct bt_conn *conn;
60 struct bt_bap_ep ep;
61 const struct bt_gatt_attr *attr;
62 struct k_work_delayable disconnect_work;
63 } ase_pool[CONFIG_BT_ASCS_MAX_ACTIVE_ASES];
64
65 #define MAX_CODEC_CONFIG \
66 MIN(UINT8_MAX, \
67 CONFIG_BT_CODEC_MAX_DATA_COUNT * CONFIG_BT_CODEC_MAX_DATA_LEN)
68 #define MAX_METADATA \
69 MIN(UINT8_MAX, \
70 CONFIG_BT_CODEC_MAX_METADATA_COUNT * CONFIG_BT_CODEC_MAX_DATA_LEN)
71
72 /* Minimum state size when in the codec configured state */
73 #define MIN_CONFIG_STATE_SIZE (1 + 1 + 1 + 1 + 1 + 2 + 3 + 3 + 3 + 3 + 5 + 1)
74 /* Minimum state size when in the QoS configured state */
75 #define MIN_QOS_STATE_SIZE (1 + 1 + 1 + 1 + 3 + 1 + 1 + 2 + 1 + 2 + 3 + 1 + 1 + 1)
76
77 /* Calculate the size requirement of the ASE BUF, based on the maximum possible
78 * size of the Codec Configured state or the QoS Configured state, as either
79 * of them can be the largest state
80 */
81 #define ASE_BUF_SIZE MIN(BT_ATT_MAX_ATTRIBUTE_LEN, \
82 MAX(MIN_CONFIG_STATE_SIZE + MAX_CODEC_CONFIG, \
83 MIN_QOS_STATE_SIZE + MAX_METADATA))
84
85 /* Verify that the prepare count is large enough to cover the maximum value we support a client
86 * writing
87 */
88 BUILD_ASSERT(
89 BT_ATT_BUF_SIZE - 3 >= ASE_BUF_SIZE ||
90 DIV_ROUND_UP(ASE_BUF_SIZE, (BT_ATT_BUF_SIZE - 3)) <= CONFIG_BT_ATT_PREPARE_COUNT,
91 "CONFIG_BT_ATT_PREPARE_COUNT not large enough to cover the maximum supported ASCS value");
92
93 /* It is mandatory to support long writes in ASCS unconditionally, and thus
94 * CONFIG_BT_ATT_PREPARE_COUNT must be at least 1 to support the feature
95 */
96 BUILD_ASSERT(CONFIG_BT_ATT_PREPARE_COUNT > 0, "CONFIG_BT_ATT_PREPARE_COUNT shall be at least 1");
97
98 static const struct bt_bap_unicast_server_cb *unicast_server_cb;
99
100 static K_SEM_DEFINE(ase_buf_sem, 1, 1);
101 NET_BUF_SIMPLE_DEFINE_STATIC(ase_buf, ASE_BUF_SIZE);
102
103 static int control_point_notify(struct bt_conn *conn, const void *data, uint16_t len);
104 static int ascs_ep_get_status(struct bt_bap_ep *ep, struct net_buf_simple *buf);
105
is_valid_ase_id(uint8_t ase_id)106 static bool is_valid_ase_id(uint8_t ase_id)
107 {
108 return IN_RANGE(ase_id, 1, ASE_COUNT);
109 }
110
ascs_ep_get_state(struct bt_bap_ep * ep)111 static enum bt_bap_ep_state ascs_ep_get_state(struct bt_bap_ep *ep)
112 {
113 return ep->status.state;
114 }
115
ase_free(struct bt_ascs_ase * ase)116 static void ase_free(struct bt_ascs_ase *ase)
117 {
118 __ASSERT(ase && ase->conn, "Non-existing ASE");
119
120 LOG_DBG("conn %p ase %p id 0x%02x", (void *)ase->conn, ase, ase->ep.status.id);
121
122 bt_conn_unref(ase->conn);
123 ase->conn = NULL;
124 }
125
ase_status_changed(struct bt_bap_ep * ep,uint8_t old_state,uint8_t state)126 static void ase_status_changed(struct bt_bap_ep *ep, uint8_t old_state, uint8_t state)
127 {
128 struct bt_ascs_ase *ase = CONTAINER_OF(ep, struct bt_ascs_ase, ep);
129 struct bt_conn *conn = ase->conn;
130
131 LOG_DBG("ase %p, ep %p", ase, ep);
132
133 if (conn != NULL) {
134 struct bt_conn_info conn_info;
135 int err;
136
137 err = bt_conn_get_info(conn, &conn_info);
138 if (err != 0) {
139 LOG_ERR("Failed to get conn %p info: %d", (void *)conn, err);
140
141 return;
142 }
143
144 if (conn_info.state == BT_CONN_STATE_CONNECTED) {
145 const uint8_t att_ntf_header_size = 3; /* opcode (1) + handle (2) */
146 const uint16_t max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size;
147 uint16_t ntf_size;
148 int err;
149
150 err = k_sem_take(&ase_buf_sem, ASE_BUF_SEM_TIMEOUT);
151 if (err != 0) {
152 LOG_DBG("Failed to take ase_buf_sem: %d", err);
153
154 return;
155 }
156
157 ascs_ep_get_status(ep, &ase_buf);
158
159 ntf_size = MIN(max_ntf_size, ase_buf.len);
160 if (ntf_size < ase_buf.len) {
161 LOG_DBG("Sending truncated notification (%u / %u)",
162 ntf_size, ase_buf.len);
163 }
164
165 bt_gatt_notify(conn, ase->attr, ase_buf.data, ntf_size);
166
167 k_sem_give(&ase_buf_sem);
168 }
169 }
170 }
171
ascs_disconnect_stream_work_handler(struct k_work * work)172 static void ascs_disconnect_stream_work_handler(struct k_work *work)
173 {
174 struct k_work_delayable *d_work = k_work_delayable_from_work(work);
175 struct bt_ascs_ase *ase = CONTAINER_OF(d_work, struct bt_ascs_ase,
176 disconnect_work);
177 struct bt_bap_ep *ep = &ase->ep;
178 struct bt_bap_stream *stream = ep->stream;
179 struct bt_bap_stream *pair_stream;
180
181 __ASSERT(ep != NULL && ep->iso && stream != NULL,
182 "Invalid endpoint %p, iso %p or stream %p",
183 ep, ep == NULL ? NULL : ep->iso, stream);
184
185 if (ep->dir == BT_AUDIO_DIR_SINK) {
186 pair_stream = ep->iso->tx.stream;
187 } else {
188 pair_stream = ep->iso->rx.stream;
189 }
190
191 LOG_DBG("ase %p ep %p stream %p pair_stream %p",
192 ase, ep, stream, pair_stream);
193
194 if (pair_stream != NULL) {
195 struct bt_ascs_ase *pair_ase;
196
197 __ASSERT(pair_stream->ep != NULL, "Invalid pair_stream %p",
198 pair_stream);
199
200 if (pair_stream->ep->status.state == BT_BAP_EP_STATE_STREAMING) {
201 /* Should not disconnect ISO if the stream is paired
202 * with another one in the streaming state
203 */
204
205 return;
206 }
207
208 pair_ase = CONTAINER_OF(pair_stream->ep, struct bt_ascs_ase,
209 ep);
210
211 /* Cancel pair ASE disconnect work if pending */
212 (void)k_work_cancel_delayable(&pair_ase->disconnect_work);
213 }
214
215
216 if (stream != NULL &&
217 ep->iso != NULL &&
218 ep->iso->chan.state == BT_ISO_STATE_CONNECTED) {
219 const int err = bt_bap_stream_disconnect(stream);
220
221 if (err != 0) {
222 LOG_ERR("Failed to disconnect CIS %p: %d",
223 stream, err);
224 }
225 }
226 }
227
ascs_disconnect_stream(struct bt_bap_stream * stream)228 static int ascs_disconnect_stream(struct bt_bap_stream *stream)
229 {
230 struct bt_ascs_ase *ase = CONTAINER_OF(stream->ep, struct bt_ascs_ase,
231 ep);
232
233 LOG_DBG("%p", stream);
234
235 return k_work_reschedule(&ase->disconnect_work,
236 K_MSEC(CONFIG_BT_ASCS_ISO_DISCONNECT_DELAY));
237 }
238
ascs_ep_set_state(struct bt_bap_ep * ep,uint8_t state)239 void ascs_ep_set_state(struct bt_bap_ep *ep, uint8_t state)
240 {
241 struct bt_bap_stream *stream;
242 bool state_changed;
243 uint8_t old_state;
244
245 if (!ep) {
246 return;
247 }
248
249 /* TODO: Verify state changes */
250
251 old_state = ep->status.state;
252 ep->status.state = state;
253 state_changed = old_state != state;
254
255 LOG_DBG("ep %p id 0x%02x %s -> %s", ep, ep->status.id, bt_bap_ep_state_str(old_state),
256 bt_bap_ep_state_str(state));
257
258 /* Notify clients*/
259 ase_status_changed(ep, old_state, state);
260
261 if (ep->stream == NULL) {
262 return;
263 }
264
265 stream = ep->stream;
266
267 if (stream->ops != NULL) {
268 const struct bt_bap_stream_ops *ops = stream->ops;
269
270 switch (state) {
271 case BT_BAP_EP_STATE_IDLE:
272 ep->receiver_ready = false;
273 bt_bap_stream_reset(stream);
274
275 if (ops->released != NULL) {
276 ops->released(stream);
277 }
278 struct bt_ascs_ase *ase = CONTAINER_OF(ep, struct bt_ascs_ase, ep);
279
280 ase_free(ase);
281
282 break;
283 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
284 switch (old_state) {
285 case BT_BAP_EP_STATE_IDLE:
286 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
287 case BT_BAP_EP_STATE_QOS_CONFIGURED:
288 case BT_BAP_EP_STATE_RELEASING:
289 break;
290 default:
291 BT_ASSERT_MSG(false, "Invalid state transition: %s -> %s",
292 bt_bap_ep_state_str(old_state),
293 bt_bap_ep_state_str(ep->status.state));
294 return;
295 }
296
297 ep->receiver_ready = false;
298
299 if (ops->configured != NULL) {
300 ops->configured(stream, &ep->qos_pref);
301 }
302
303 break;
304 case BT_BAP_EP_STATE_QOS_CONFIGURED:
305 /* QoS configured have different allowed states
306 * depending on the endpoint type
307 */
308 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
309 switch (old_state) {
310 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
311 case BT_BAP_EP_STATE_QOS_CONFIGURED:
312 case BT_BAP_EP_STATE_DISABLING:
313 break;
314 default:
315 BT_ASSERT_MSG(false, "Invalid state transition: %s -> %s",
316 bt_bap_ep_state_str(old_state),
317 bt_bap_ep_state_str(ep->status.state));
318 return;
319 }
320 } else {
321 switch (old_state) {
322 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
323 case BT_BAP_EP_STATE_QOS_CONFIGURED:
324 case BT_BAP_EP_STATE_ENABLING:
325 case BT_BAP_EP_STATE_STREAMING:
326 break;
327 default:
328 BT_ASSERT_MSG(false, "Invalid state transition: %s -> %s",
329 bt_bap_ep_state_str(old_state),
330 bt_bap_ep_state_str(ep->status.state));
331 return;
332 }
333 }
334
335 ep->receiver_ready = false;
336
337 if (ops->qos_set != NULL) {
338 ops->qos_set(stream);
339 }
340
341 break;
342 case BT_BAP_EP_STATE_ENABLING:
343 switch (old_state) {
344 case BT_BAP_EP_STATE_QOS_CONFIGURED:
345 case BT_BAP_EP_STATE_ENABLING:
346 break;
347 default:
348 BT_ASSERT_MSG(false, "Invalid state transition: %s -> %s",
349 bt_bap_ep_state_str(old_state),
350 bt_bap_ep_state_str(ep->status.state));
351 return;
352 }
353
354 if (state_changed && ops->enabled != NULL) {
355 ops->enabled(stream);
356 } else if (!state_changed && ops->metadata_updated) {
357 ops->metadata_updated(stream);
358 }
359
360 /* SINK ASEs can autonomously go into the streaming state if
361 * the CIS is connected
362 */
363 if (ep->dir == BT_AUDIO_DIR_SINK &&
364 ep->receiver_ready &&
365 ep->iso != NULL &&
366 ep->iso->chan.state == BT_ISO_STATE_CONNECTED) {
367 ascs_ep_set_state(ep, BT_BAP_EP_STATE_STREAMING);
368 }
369
370 break;
371 case BT_BAP_EP_STATE_STREAMING:
372 switch (old_state) {
373 case BT_BAP_EP_STATE_ENABLING:
374 case BT_BAP_EP_STATE_STREAMING:
375 break;
376 default:
377 BT_ASSERT_MSG(false, "Invalid state transition: %s -> %s",
378 bt_bap_ep_state_str(old_state),
379 bt_bap_ep_state_str(ep->status.state));
380 return;
381 }
382
383 if (state_changed && ops->started != NULL) {
384 ops->started(stream);
385 } else if (!state_changed && ops->metadata_updated) {
386 ops->metadata_updated(stream);
387 }
388
389 break;
390 case BT_BAP_EP_STATE_DISABLING:
391 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
392 switch (old_state) {
393 case BT_BAP_EP_STATE_ENABLING:
394 case BT_BAP_EP_STATE_STREAMING:
395 break;
396 default:
397 BT_ASSERT_MSG(false, "Invalid state transition: %s -> %s",
398 bt_bap_ep_state_str(old_state),
399 bt_bap_ep_state_str(ep->status.state));
400 return;
401 }
402 } else {
403 /* Sinks cannot go into the disabling state */
404 BT_ASSERT_MSG(false, "Invalid state transition: %s -> %s",
405 bt_bap_ep_state_str(old_state),
406 bt_bap_ep_state_str(ep->status.state));
407 return;
408 }
409
410 ep->receiver_ready = false;
411
412 if (ops->disabled != NULL) {
413 ops->disabled(stream);
414 }
415
416 break;
417 case BT_BAP_EP_STATE_RELEASING:
418 switch (old_state) {
419 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
420 case BT_BAP_EP_STATE_QOS_CONFIGURED:
421 case BT_BAP_EP_STATE_ENABLING:
422 case BT_BAP_EP_STATE_STREAMING:
423 break;
424 case BT_BAP_EP_STATE_DISABLING:
425 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
426 break;
427 } /* else fall through for sink */
428
429 /* fall through */
430 default:
431 BT_ASSERT_MSG(false, "Invalid state transition: %s -> %s",
432 bt_bap_ep_state_str(old_state),
433 bt_bap_ep_state_str(ep->status.state));
434 return;
435 }
436
437 ep->receiver_ready = false;
438
439 if (bt_bap_stream_can_disconnect(stream)) {
440 /* Either the client or the server may disconnect the
441 * CISes when entering the releasing state.
442 */
443 const int err = ascs_disconnect_stream(stream);
444
445 if (err < 0) {
446 LOG_ERR("Failed to disconnect stream %p: %d",
447 stream, err);
448 }
449 } else {
450 ascs_ep_set_state(ep, BT_BAP_EP_STATE_IDLE);
451 }
452
453 break;
454 default:
455 LOG_ERR("Invalid state: %u", state);
456 break;
457 }
458 }
459 }
460
ascs_codec_data_add(struct net_buf_simple * buf,const char * prefix,uint8_t num,struct bt_codec_data * data)461 static void ascs_codec_data_add(struct net_buf_simple *buf, const char *prefix,
462 uint8_t num, struct bt_codec_data *data)
463 {
464 struct bt_ascs_codec_config *cc;
465 int i;
466
467 for (i = 0; i < num; i++) {
468 struct bt_data *d = &data[i].data;
469
470 LOG_DBG("#%u: %s type 0x%02x len %u", i, prefix, d->type, d->data_len);
471 LOG_HEXDUMP_DBG(d->data, d->data_len, prefix);
472
473 cc = net_buf_simple_add(buf, sizeof(*cc));
474 cc->len = d->data_len + sizeof(cc->type);
475 cc->type = d->type;
476 net_buf_simple_add_mem(buf, d->data, d->data_len);
477 }
478 }
479
ascs_ep_get_status_config(struct bt_bap_ep * ep,struct net_buf_simple * buf)480 static void ascs_ep_get_status_config(struct bt_bap_ep *ep, struct net_buf_simple *buf)
481 {
482 struct bt_ascs_ase_status_config *cfg;
483 struct bt_codec_qos_pref *pref = &ep->qos_pref;
484
485 cfg = net_buf_simple_add(buf, sizeof(*cfg));
486 cfg->framing = pref->unframed_supported ? BT_ASCS_QOS_FRAMING_UNFRAMED
487 : BT_ASCS_QOS_FRAMING_FRAMED;
488 cfg->phy = pref->phy;
489 cfg->rtn = pref->rtn;
490 cfg->latency = sys_cpu_to_le16(pref->latency);
491 sys_put_le24(pref->pd_min, cfg->pd_min);
492 sys_put_le24(pref->pd_max, cfg->pd_max);
493 sys_put_le24(pref->pref_pd_min, cfg->prefer_pd_min);
494 sys_put_le24(pref->pref_pd_max, cfg->prefer_pd_max);
495 cfg->codec.id = ep->codec.id;
496 cfg->codec.cid = sys_cpu_to_le16(ep->codec.cid);
497 cfg->codec.vid = sys_cpu_to_le16(ep->codec.vid);
498
499 LOG_DBG("dir %s unframed_supported 0x%02x phy 0x%02x rtn %u "
500 "latency %u pd_min %u pd_max %u pref_pd_min %u pref_pd_max %u codec 0x%02x",
501 bt_audio_dir_str(ep->dir), pref->unframed_supported, pref->phy, pref->rtn,
502 pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max,
503 ep->stream->codec->id);
504
505 cfg->cc_len = buf->len;
506 ascs_codec_data_add(buf, "data", ep->codec.data_count, ep->codec.data);
507 cfg->cc_len = buf->len - cfg->cc_len;
508 }
509
ascs_ep_get_status_qos(struct bt_bap_ep * ep,struct net_buf_simple * buf)510 static void ascs_ep_get_status_qos(struct bt_bap_ep *ep, struct net_buf_simple *buf)
511 {
512 struct bt_ascs_ase_status_qos *qos;
513
514 qos = net_buf_simple_add(buf, sizeof(*qos));
515 qos->cig_id = ep->cig_id;
516 qos->cis_id = ep->cis_id;
517 sys_put_le24(ep->stream->qos->interval, qos->interval);
518 qos->framing = ep->stream->qos->framing;
519 qos->phy = ep->stream->qos->phy;
520 qos->sdu = sys_cpu_to_le16(ep->stream->qos->sdu);
521 qos->rtn = ep->stream->qos->rtn;
522 qos->latency = sys_cpu_to_le16(ep->stream->qos->latency);
523 sys_put_le24(ep->stream->qos->pd, qos->pd);
524
525 LOG_DBG("dir %s codec 0x%02x interval %u framing 0x%02x phy 0x%02x "
526 "rtn %u latency %u pd %u",
527 bt_audio_dir_str(ep->dir), ep->stream->codec->id,
528 ep->stream->qos->interval, ep->stream->qos->framing,
529 ep->stream->qos->phy, ep->stream->qos->rtn,
530 ep->stream->qos->latency, ep->stream->qos->pd);
531 }
532
ascs_ep_get_status_enable(struct bt_bap_ep * ep,struct net_buf_simple * buf)533 static void ascs_ep_get_status_enable(struct bt_bap_ep *ep, struct net_buf_simple *buf)
534 {
535 struct bt_ascs_ase_status_enable *enable;
536
537 enable = net_buf_simple_add(buf, sizeof(*enable));
538 enable->cig_id = ep->cig_id;
539 enable->cis_id = ep->cis_id;
540
541 enable->metadata_len = buf->len;
542 ascs_codec_data_add(buf, "meta", ep->codec.meta_count, ep->codec.meta);
543 enable->metadata_len = buf->len - enable->metadata_len;
544
545 LOG_DBG("dir %s cig 0x%02x cis 0x%02x",
546 bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id);
547 }
548
ascs_ep_get_status_idle(uint8_t ase_id,struct net_buf_simple * buf)549 static int ascs_ep_get_status_idle(uint8_t ase_id, struct net_buf_simple *buf)
550 {
551 struct bt_ascs_ase_status *status;
552
553 if (!buf || ase_id > ASE_COUNT) {
554 return -EINVAL;
555 }
556
557 net_buf_simple_reset(buf);
558
559 status = net_buf_simple_add(buf, sizeof(*status));
560 status->id = ase_id;
561 status->state = BT_BAP_EP_STATE_IDLE;
562
563 LOG_DBG("id 0x%02x state %s", ase_id, bt_bap_ep_state_str(status->state));
564
565 return 0;
566 }
567
ascs_ep_get_status(struct bt_bap_ep * ep,struct net_buf_simple * buf)568 static int ascs_ep_get_status(struct bt_bap_ep *ep, struct net_buf_simple *buf)
569 {
570 if (!ep || !buf) {
571 return -EINVAL;
572 }
573
574 LOG_DBG("ep %p id 0x%02x state %s", ep, ep->status.id,
575 bt_bap_ep_state_str(ep->status.state));
576
577 /* Reset if buffer before using */
578 net_buf_simple_reset(buf);
579
580 (void)net_buf_simple_add_mem(buf, &ep->status, sizeof(ep->status));
581
582 switch (ep->status.state) {
583 case BT_BAP_EP_STATE_IDLE:
584 /* Fallthrough */
585 case BT_BAP_EP_STATE_RELEASING:
586 break;
587 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
588 ascs_ep_get_status_config(ep, buf);
589 break;
590 case BT_BAP_EP_STATE_QOS_CONFIGURED:
591 ascs_ep_get_status_qos(ep, buf);
592 break;
593 case BT_BAP_EP_STATE_ENABLING:
594 /* Fallthrough */
595 case BT_BAP_EP_STATE_STREAMING:
596 /* Fallthrough */
597 case BT_BAP_EP_STATE_DISABLING:
598 ascs_ep_get_status_enable(ep, buf);
599 break;
600 default:
601 LOG_ERR("Invalid Endpoint state");
602 break;
603 }
604
605 return 0;
606 }
607
ascs_iso_accept(const struct bt_iso_accept_info * info,struct bt_iso_chan ** iso_chan)608 static int ascs_iso_accept(const struct bt_iso_accept_info *info, struct bt_iso_chan **iso_chan)
609 {
610 LOG_DBG("conn %p", (void *)info->acl);
611
612 for (size_t i = 0; i < ARRAY_SIZE(ase_pool); i++) {
613 struct bt_ascs_ase *ase = &ase_pool[i];
614 enum bt_bap_ep_state state;
615 struct bt_iso_chan *chan;
616
617 if (ase->conn != info->acl ||
618 ase->ep.cig_id != info->cig_id ||
619 ase->ep.cis_id != info->cis_id) {
620 continue;
621 }
622
623 state = ascs_ep_get_state(&ase->ep);
624 if (state != BT_BAP_EP_STATE_ENABLING && state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
625 LOG_WRN("ase %p cannot accept ISO connection", ase);
626 break;
627 }
628
629 __ASSERT(ase->ep.iso != NULL, "ep %p not bound with ISO", &ase->ep);
630
631 chan = &ase->ep.iso->chan;
632 if (chan->iso != NULL) {
633 LOG_WRN("ase %p chan %p already connected", ase, chan);
634 return -EALREADY;
635 }
636
637 *iso_chan = chan;
638
639 LOG_DBG("iso_chan %p", *iso_chan);
640
641 return 0;
642 }
643
644 return -EACCES;
645 }
646
647 #if defined(CONFIG_BT_AUDIO_RX)
ascs_iso_recv(struct bt_iso_chan * chan,const struct bt_iso_recv_info * info,struct net_buf * buf)648 static void ascs_iso_recv(struct bt_iso_chan *chan,
649 const struct bt_iso_recv_info *info,
650 struct net_buf *buf)
651 {
652 struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
653 const struct bt_bap_stream_ops *ops;
654 struct bt_bap_stream *stream;
655 struct bt_bap_ep *ep;
656
657 ep = iso->rx.ep;
658 if (ep == NULL) {
659 /* In the case that the CIS has been setup as bidirectional, and
660 * only one of the directions have an ASE configured yet,
661 * we should only care about valid ISO packets when doing this
662 * check. The reason is that some controllers send HCI ISO data
663 * packets to the host, even if no SDU was sent on the remote
664 * side. This basically means that empty PDUs are sent to the
665 * host as HCI ISO data packets, which we should just ignore
666 */
667 if ((info->flags & BT_ISO_FLAGS_VALID) != 0) {
668 LOG_ERR("iso %p not bound with ep", chan);
669 }
670
671 return;
672 }
673
674 if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA) &&
675 ep->status.state != BT_BAP_EP_STATE_STREAMING) {
676 LOG_DBG("ep %p is not in the streaming state: %s", ep,
677 bt_bap_ep_state_str(ep->status.state));
678 return;
679 }
680
681 stream = ep->stream;
682 if (stream == NULL) {
683 LOG_ERR("No stream for ep %p", ep);
684 return;
685 }
686
687 ops = stream->ops;
688
689 if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
690 LOG_DBG("stream %p ep %p len %zu", stream, stream->ep, net_buf_frags_len(buf));
691 }
692
693 if (ops != NULL && ops->recv != NULL) {
694 ops->recv(stream, info, buf);
695 } else {
696 LOG_WRN("No callback for recv set");
697 }
698 }
699 #endif /* CONFIG_BT_AUDIO_RX */
700
701 #if defined(CONFIG_BT_AUDIO_TX)
ascs_iso_sent(struct bt_iso_chan * chan)702 static void ascs_iso_sent(struct bt_iso_chan *chan)
703 {
704 struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
705 const struct bt_bap_stream_ops *ops;
706 struct bt_bap_stream *stream;
707 struct bt_bap_ep *ep;
708
709 ep = iso->tx.ep;
710 if (ep == NULL) {
711 LOG_ERR("iso %p not bound with ep", chan);
712 return;
713 }
714
715 stream = ep->stream;
716 if (stream == NULL) {
717 LOG_ERR("No stream for ep %p", ep);
718 return;
719 }
720
721 ops = stream->ops;
722
723 if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
724 LOG_DBG("stream %p ep %p", stream, stream->ep);
725 }
726
727 if (ops != NULL && ops->sent != NULL) {
728 ops->sent(stream);
729 }
730 }
731 #endif /* CONFIG_BT_AUDIO_TX */
732
ascs_ep_iso_connected(struct bt_bap_ep * ep)733 static void ascs_ep_iso_connected(struct bt_bap_ep *ep)
734 {
735 struct bt_bap_stream *stream;
736
737 if (ep->status.state != BT_BAP_EP_STATE_ENABLING) {
738 LOG_DBG("ep %p not in enabling state: %s", ep,
739 bt_bap_ep_state_str(ep->status.state));
740 return;
741 }
742
743 stream = ep->stream;
744 if (stream == NULL) {
745 LOG_ERR("No stream for ep %p", ep);
746 return;
747 }
748
749 if (ep->dir == BT_AUDIO_DIR_SINK && ep->receiver_ready) {
750 /* Source ASEs shall be ISO connected first, and then receive
751 * the receiver start ready command to enter the streaming
752 * state
753 */
754 ascs_ep_set_state(ep, BT_BAP_EP_STATE_STREAMING);
755 }
756
757 LOG_DBG("stream %p ep %p dir %s", stream, ep, bt_audio_dir_str(ep->dir));
758 }
759
ascs_iso_connected(struct bt_iso_chan * chan)760 static void ascs_iso_connected(struct bt_iso_chan *chan)
761 {
762 struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
763
764 if (iso->rx.ep == NULL && iso->tx.ep == NULL) {
765 LOG_ERR("iso %p not bound with ep", chan);
766 return;
767 }
768
769 if (iso->rx.ep != NULL) {
770 ascs_ep_iso_connected(iso->rx.ep);
771 }
772
773 if (iso->tx.ep != NULL) {
774 ascs_ep_iso_connected(iso->tx.ep);
775 }
776 }
777
ascs_ep_iso_disconnected(struct bt_bap_ep * ep,uint8_t reason)778 static void ascs_ep_iso_disconnected(struct bt_bap_ep *ep, uint8_t reason)
779 {
780 struct bt_ascs_ase *ase = CONTAINER_OF(ep, struct bt_ascs_ase, ep);
781 const struct bt_bap_stream_ops *ops;
782 struct bt_bap_stream *stream;
783
784 stream = ep->stream;
785 if (stream == NULL) {
786 LOG_ERR("No stream for ep %p", ep);
787 return;
788 }
789
790 ops = stream->ops;
791
792 LOG_DBG("stream %p ep %p reason 0x%02x", stream, stream->ep, reason);
793
794 if (ep->status.state == BT_BAP_EP_STATE_ENABLING &&
795 reason == BT_HCI_ERR_CONN_FAIL_TO_ESTAB) {
796 LOG_DBG("Waiting for retry");
797 return;
798 }
799
800 /* Cancel ASE disconnect work if pending */
801 (void)k_work_cancel_delayable(&ase->disconnect_work);
802
803 if (ops != NULL && ops->stopped != NULL) {
804 ops->stopped(stream, reason);
805 } else {
806 LOG_WRN("No callback for stopped set");
807 }
808
809 if (ep->status.state == BT_BAP_EP_STATE_RELEASING) {
810 ascs_ep_set_state(ep, BT_BAP_EP_STATE_IDLE);
811 } else {
812 /* The ASE state machine goes into different states from this operation
813 * based on whether it is a source or a sink ASE.
814 */
815 if (ep->status.state == BT_BAP_EP_STATE_STREAMING ||
816 ep->status.state == BT_BAP_EP_STATE_ENABLING) {
817 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
818 ascs_ep_set_state(ep, BT_BAP_EP_STATE_DISABLING);
819 } else {
820 ascs_ep_set_state(ep, BT_BAP_EP_STATE_QOS_CONFIGURED);
821 }
822 }
823 }
824 }
825
ascs_iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)826 static void ascs_iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
827 {
828 struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
829
830 if (iso->rx.ep == NULL && iso->tx.ep == NULL) {
831 LOG_ERR("iso %p not bound with ep", chan);
832 return;
833 }
834
835 if (iso->rx.ep != NULL) {
836 ascs_ep_iso_disconnected(iso->rx.ep, reason);
837 }
838
839 if (iso->tx.ep != NULL) {
840 ascs_ep_iso_disconnected(iso->tx.ep, reason);
841 }
842 }
843
844 static struct bt_iso_chan_ops ascs_iso_ops = {
845 #if defined(CONFIG_BT_AUDIO_RX)
846 .recv = ascs_iso_recv,
847 #endif /* CONFIG_BT_AUDIO_RX */
848 #if defined(CONFIG_BT_AUDIO_TX)
849 .sent = ascs_iso_sent,
850 #endif /* CONFIG_BT_AUDIO_TX */
851 .connected = ascs_iso_connected,
852 .disconnected = ascs_iso_disconnected,
853 };
854
ascs_ase_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)855 static void ascs_ase_cfg_changed(const struct bt_gatt_attr *attr,
856 uint16_t value)
857 {
858 LOG_DBG("attr %p value 0x%04x", attr, value);
859 }
860
861 NET_BUF_SIMPLE_DEFINE_STATIC(rsp_buf, CONFIG_BT_L2CAP_TX_MTU);
862
ascs_cp_rsp_init(uint8_t op)863 static void ascs_cp_rsp_init(uint8_t op)
864 {
865 struct bt_ascs_cp_rsp *rsp;
866
867 net_buf_simple_reset(&rsp_buf);
868
869 rsp = net_buf_simple_add(&rsp_buf, sizeof(*rsp));
870 rsp->op = op;
871 rsp->num_ase = 0;
872 }
873
874 /* Add response to an opcode/ASE ID */
ascs_cp_rsp_add(uint8_t id,uint8_t code,uint8_t reason)875 static void ascs_cp_rsp_add(uint8_t id, uint8_t code, uint8_t reason)
876 {
877 struct bt_ascs_cp_rsp *rsp = (void *)rsp_buf.__buf;
878 struct bt_ascs_cp_ase_rsp *ase_rsp;
879
880 LOG_DBG("id 0x%02x code %s (0x%02x) reason %s (0x%02x)", id,
881 bt_ascs_rsp_str(code), code, bt_ascs_reason_str(reason), reason);
882
883 if (rsp->num_ase == 0xff) {
884 return;
885 }
886
887 switch (code) {
888 /* If the Response_Code value is 0x01 or 0x02, Number_of_ASEs shall be
889 * set to 0xFF.
890 */
891 case BT_BAP_ASCS_RSP_CODE_NOT_SUPPORTED:
892 case BT_BAP_ASCS_RSP_CODE_INVALID_LENGTH:
893 rsp->num_ase = BT_ASCS_UNSUPP_OR_LENGTH_ERR_NUM_ASE;
894 break;
895 default:
896 rsp->num_ase++;
897 break;
898 }
899
900 ase_rsp = net_buf_simple_add(&rsp_buf, sizeof(*ase_rsp));
901 ase_rsp->id = id;
902 ase_rsp->code = code;
903 ase_rsp->reason = reason;
904 }
905
ascs_cp_rsp_success(uint8_t id)906 static void ascs_cp_rsp_success(uint8_t id)
907 {
908 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
909 }
910
ase_release(struct bt_ascs_ase * ase)911 static void ase_release(struct bt_ascs_ase *ase)
912 {
913 uint8_t ase_id = ASE_ID(ase);
914 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
915 BT_BAP_ASCS_REASON_NONE);
916 int err;
917
918 LOG_DBG("ase %p state %s", ase, bt_bap_ep_state_str(ase->ep.status.state));
919
920 if (ase->ep.status.state == BT_BAP_EP_STATE_RELEASING) {
921 /* already releasing */
922 return;
923 }
924
925 if (unicast_server_cb != NULL && unicast_server_cb->release != NULL) {
926 err = unicast_server_cb->release(ase->ep.stream, &rsp);
927 } else {
928 err = -ENOTSUP;
929 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
930 BT_BAP_ASCS_REASON_NONE);
931 }
932
933 if (err) {
934 if (rsp.code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
935 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
936 BT_BAP_ASCS_REASON_NONE);
937 }
938
939 LOG_ERR("Release failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
940 ascs_cp_rsp_add(ase_id, rsp.code, rsp.reason);
941 return;
942 }
943
944 ascs_ep_set_state(&ase->ep, BT_BAP_EP_STATE_RELEASING);
945 /* At this point, `ase` object might have been free'd if automously went to Idle */
946
947 ascs_cp_rsp_success(ase_id);
948 }
949
ase_disable(struct bt_ascs_ase * ase)950 static void ase_disable(struct bt_ascs_ase *ase)
951 {
952 struct bt_bap_stream *stream;
953 struct bt_bap_ep *ep;
954 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
955 BT_BAP_ASCS_REASON_NONE);
956 int err;
957
958 LOG_DBG("ase %p", ase);
959
960 ep = &ase->ep;
961
962 switch (ep->status.state) {
963 /* Valid only if ASE_State field = 0x03 (Enabling) */
964 case BT_BAP_EP_STATE_ENABLING:
965 /* or 0x04 (Streaming) */
966 case BT_BAP_EP_STATE_STREAMING:
967 break;
968 default:
969 LOG_WRN("Invalid operation in state: %s", bt_bap_ep_state_str(ep->status.state));
970 ascs_cp_rsp_add(ASE_ID(ase), BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
971 BT_BAP_ASCS_REASON_NONE);
972 return;
973 }
974
975 stream = ep->stream;
976
977 if (unicast_server_cb != NULL && unicast_server_cb->disable != NULL) {
978 err = unicast_server_cb->disable(stream, &rsp);
979 } else {
980 err = -ENOTSUP;
981 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
982 BT_BAP_ASCS_REASON_NONE);
983 }
984
985 if (err) {
986 if (rsp.code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
987 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
988 BT_BAP_ASCS_REASON_NONE);
989 }
990
991 LOG_ERR("Disable failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
992 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
993 return;
994 }
995
996 /* The ASE state machine goes into different states from this operation
997 * based on whether it is a source or a sink ASE.
998 */
999 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
1000 ascs_ep_set_state(ep, BT_BAP_EP_STATE_DISABLING);
1001 } else {
1002 ascs_ep_set_state(ep, BT_BAP_EP_STATE_QOS_CONFIGURED);
1003 }
1004
1005 ascs_cp_rsp_success(ASE_ID(ase));
1006 }
1007
disconnected(struct bt_conn * conn,uint8_t reason)1008 static void disconnected(struct bt_conn *conn, uint8_t reason)
1009 {
1010 for (size_t i = 0; i < ARRAY_SIZE(ase_pool); i++) {
1011 struct bt_ascs_ase *ase = &ase_pool[i];
1012
1013 if (ase->conn != conn) {
1014 continue;
1015 }
1016
1017 if (ase->ep.status.state != BT_BAP_EP_STATE_IDLE) {
1018 ase_release(ase);
1019 /* At this point, `ase` object have been free'd */
1020 }
1021 }
1022 }
1023
1024 BT_CONN_CB_DEFINE(conn_cb) = {
1025 .disconnected = disconnected,
1026 };
1027
1028 struct bap_iso_find_params {
1029 struct bt_conn *acl;
1030 uint8_t cig_id;
1031 uint8_t cis_id;
1032 };
1033
bap_iso_find_func(struct bt_bap_iso * iso,void * user_data)1034 static bool bap_iso_find_func(struct bt_bap_iso *iso, void *user_data)
1035 {
1036 struct bap_iso_find_params *params = user_data;
1037 const struct bt_bap_ep *ep;
1038
1039 if (iso->rx.ep != NULL) {
1040 ep = iso->rx.ep;
1041 } else if (iso->tx.ep != NULL) {
1042 ep = iso->tx.ep;
1043 } else {
1044 return false;
1045 }
1046
1047 return ep->stream->conn == params->acl &&
1048 ep->cig_id == params->cig_id &&
1049 ep->cis_id == params->cis_id;
1050 }
1051
bap_iso_get_or_new(struct bt_conn * conn,uint8_t cig_id,uint8_t cis_id)1052 static struct bt_bap_iso *bap_iso_get_or_new(struct bt_conn *conn, uint8_t cig_id, uint8_t cis_id)
1053 {
1054 struct bt_bap_iso *iso;
1055 struct bap_iso_find_params params = {
1056 .acl = bt_conn_ref(conn),
1057 .cig_id = cig_id,
1058 .cis_id = cis_id,
1059 };
1060
1061 iso = bt_bap_iso_find(bap_iso_find_func, ¶ms);
1062 bt_conn_unref(conn);
1063
1064 if (iso) {
1065 return iso;
1066 }
1067
1068 iso = bt_bap_iso_new();
1069 if (!iso) {
1070 return NULL;
1071 }
1072
1073 bt_bap_iso_init(iso, &ascs_iso_ops);
1074
1075 return iso;
1076 }
1077
ase_attr_cb(const struct bt_gatt_attr * attr,uint16_t handle,void * user_data)1078 static uint8_t ase_attr_cb(const struct bt_gatt_attr *attr, uint16_t handle,
1079 void *user_data)
1080 {
1081 struct bt_ascs_ase *ase = user_data;
1082
1083 if (ase->ep.status.id == POINTER_TO_UINT(BT_AUDIO_CHRC_USER_DATA(attr))) {
1084 ase->attr = attr;
1085
1086 return BT_GATT_ITER_STOP;
1087 }
1088
1089 return BT_GATT_ITER_CONTINUE;
1090 }
1091
ascs_ep_init(struct bt_bap_ep * ep,uint8_t id)1092 void ascs_ep_init(struct bt_bap_ep *ep, uint8_t id)
1093 {
1094 LOG_DBG("ep %p id 0x%02x", ep, id);
1095
1096 (void)memset(ep, 0, sizeof(*ep));
1097 ep->status.id = id;
1098 ep->dir = ASE_DIR(id);
1099 }
1100
ase_init(struct bt_ascs_ase * ase,struct bt_conn * conn,uint8_t id)1101 static void ase_init(struct bt_ascs_ase *ase, struct bt_conn *conn, uint8_t id)
1102 {
1103 memset(ase, 0, sizeof(*ase));
1104
1105 ascs_ep_init(&ase->ep, id);
1106
1107 ase->conn = bt_conn_ref(conn);
1108
1109 /* Lookup ASE characteristic */
1110 bt_gatt_foreach_attr_type(0x0001, 0xffff, ASE_UUID(id), NULL, 0, ase_attr_cb, ase);
1111
1112 __ASSERT(ase->attr, "ASE characteristic not found\n");
1113
1114 k_work_init_delayable(&ase->disconnect_work,
1115 ascs_disconnect_stream_work_handler);
1116 }
1117
ase_new(struct bt_conn * conn,uint8_t id)1118 static struct bt_ascs_ase *ase_new(struct bt_conn *conn, uint8_t id)
1119 {
1120 struct bt_ascs_ase *ase = NULL;
1121
1122 __ASSERT(id > 0 && id <= ASE_COUNT, "invalid ASE_ID 0x%02x", id);
1123
1124 for (size_t i = 0; i < ARRAY_SIZE(ase_pool); i++) {
1125 if (ase_pool[i].conn == NULL) {
1126 ase = &ase_pool[i];
1127 break;
1128 }
1129 }
1130
1131 if (ase == NULL) {
1132 return NULL;
1133 }
1134
1135 ase_init(ase, conn, id);
1136
1137 LOG_DBG("conn %p new ase %p id 0x%02x", (void *)conn, ase, id);
1138
1139 return ase;
1140 }
1141
ase_find(struct bt_conn * conn,uint8_t id)1142 static struct bt_ascs_ase *ase_find(struct bt_conn *conn, uint8_t id)
1143 {
1144 for (size_t i = 0; i < ARRAY_SIZE(ase_pool); i++) {
1145 struct bt_ascs_ase *ase = &ase_pool[i];
1146
1147 if (ase->conn == conn && ase->ep.status.id == id) {
1148 return ase;
1149 }
1150 }
1151
1152 return NULL;
1153 }
1154
ascs_ase_read(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)1155 static ssize_t ascs_ase_read(struct bt_conn *conn,
1156 const struct bt_gatt_attr *attr, void *buf,
1157 uint16_t len, uint16_t offset)
1158 {
1159 uint8_t ase_id = POINTER_TO_UINT(BT_AUDIO_CHRC_USER_DATA(attr));
1160 struct bt_ascs_ase *ase = NULL;
1161 ssize_t ret_val;
1162 int err;
1163
1164 LOG_DBG("conn %p attr %p buf %p len %u offset %u", (void *)conn, attr, buf, len, offset);
1165
1166 /* The callback can be used locally to read the ASE_ID in which case conn won't be set. */
1167 if (conn != NULL) {
1168 ase = ase_find(conn, ase_id);
1169 }
1170
1171 err = k_sem_take(&ase_buf_sem, ASE_BUF_SEM_TIMEOUT);
1172 if (err != 0) {
1173 LOG_DBG("Failed to take ase_buf_sem: %d", err);
1174
1175 return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES);
1176 }
1177
1178 /* If NULL, we haven't assigned an ASE, this also means that we are currently in IDLE */
1179 if (!ase) {
1180 ascs_ep_get_status_idle(ase_id, &ase_buf);
1181 } else {
1182 ascs_ep_get_status(&ase->ep, &ase_buf);
1183 }
1184
1185 ret_val = bt_gatt_attr_read(conn, attr, buf, len, offset, ase_buf.data, ase_buf.len);
1186
1187 k_sem_give(&ase_buf_sem);
1188
1189 return ret_val;
1190 }
1191
ascs_cp_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)1192 static void ascs_cp_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
1193 {
1194 LOG_DBG("attr %p value 0x%04x", attr, value);
1195 }
1196
ascs_codec_config_store(struct bt_data * data,void * user_data)1197 static bool ascs_codec_config_store(struct bt_data *data, void *user_data)
1198 {
1199 struct bt_codec *codec = user_data;
1200 struct bt_codec_data *cdata;
1201
1202 if (codec->data_count >= ARRAY_SIZE(codec->data)) {
1203 LOG_ERR("No slot available for Codec Config");
1204 return false;
1205 }
1206
1207 cdata = &codec->data[codec->data_count];
1208
1209 if (data->data_len > sizeof(cdata->value)) {
1210 LOG_ERR("Not enough space for Codec Config: %u > %zu", data->data_len,
1211 sizeof(cdata->value));
1212 return false;
1213 }
1214
1215 LOG_DBG("#%u type 0x%02x len %u", codec->data_count, data->type, data->data_len);
1216
1217 cdata->data.type = data->type;
1218 cdata->data.data_len = data->data_len;
1219
1220 /* Deep copy data contents */
1221 cdata->data.data = cdata->value;
1222 (void)memcpy(cdata->value, data->data, data->data_len);
1223
1224 LOG_HEXDUMP_DBG(cdata->value, data->data_len, "data");
1225
1226 codec->data_count++;
1227
1228 return true;
1229 }
1230
1231 struct codec_lookup_id_data {
1232 uint8_t id;
1233 uint16_t cid;
1234 uint16_t vid;
1235 struct bt_codec *codec;
1236 };
1237
codec_lookup_id(const struct bt_pacs_cap * cap,void * user_data)1238 static bool codec_lookup_id(const struct bt_pacs_cap *cap, void *user_data)
1239 {
1240 struct codec_lookup_id_data *data = user_data;
1241
1242 if (cap->codec->id == data->id && cap->codec->cid == data->cid &&
1243 cap->codec->vid == data->vid) {
1244 data->codec = cap->codec;
1245
1246 return false;
1247 }
1248
1249 return true;
1250 }
1251
ascs_ep_set_codec(struct bt_bap_ep * ep,uint8_t id,uint16_t cid,uint16_t vid,uint8_t * cc,uint8_t len,struct bt_bap_ascs_rsp * rsp)1252 static int ascs_ep_set_codec(struct bt_bap_ep *ep, uint8_t id, uint16_t cid, uint16_t vid,
1253 uint8_t *cc, uint8_t len, struct bt_bap_ascs_rsp *rsp)
1254 {
1255 struct net_buf_simple ad;
1256 struct bt_codec *codec;
1257 struct codec_lookup_id_data lookup_data = {
1258 .id = id,
1259 .cid = cid,
1260 .vid = vid,
1261 };
1262
1263 if (ep == NULL) {
1264 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID,
1265 BT_BAP_ASCS_REASON_CODEC_DATA);
1266 return -EINVAL;
1267 }
1268
1269 codec = &ep->codec;
1270
1271 LOG_DBG("ep %p dir %s codec id 0x%02x cid 0x%04x vid 0x%04x len %u",
1272 ep, bt_audio_dir_str(ep->dir), id, cid, vid, len);
1273
1274 bt_pacs_cap_foreach(ep->dir, codec_lookup_id, &lookup_data);
1275
1276 if (lookup_data.codec == NULL) {
1277 LOG_DBG("Codec with id %u for dir %s is not supported by our capabilities",
1278 id, bt_audio_dir_str(ep->dir));
1279
1280 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID,
1281 BT_BAP_ASCS_REASON_CODEC);
1282 return -ENOENT;
1283 }
1284
1285 codec->id = id;
1286 codec->cid = cid;
1287 codec->vid = vid;
1288 codec->data_count = 0;
1289 codec->path_id = lookup_data.codec->path_id;
1290
1291 if (len == 0) {
1292 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
1293 return 0;
1294 }
1295
1296 net_buf_simple_init_with_data(&ad, cc, len);
1297
1298 /* Parse LTV entries */
1299 bt_data_parse(&ad, ascs_codec_config_store, codec);
1300
1301 /* Check if all entries could be parsed */
1302 if (ad.len) {
1303 LOG_ERR("Unable to parse Codec Config: len %u", ad.len);
1304 (void)memset(codec, 0, sizeof(*codec));
1305 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID,
1306 BT_BAP_ASCS_REASON_CODEC_DATA);
1307 return -EINVAL;
1308 }
1309
1310 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
1311 return 0;
1312 }
1313
ase_config(struct bt_ascs_ase * ase,const struct bt_ascs_config * cfg)1314 static int ase_config(struct bt_ascs_ase *ase, const struct bt_ascs_config *cfg)
1315 {
1316 struct bt_bap_stream *stream;
1317 struct bt_codec codec;
1318 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
1319 BT_BAP_ASCS_REASON_NONE);
1320 int err;
1321
1322 LOG_DBG("ase %p latency 0x%02x phy 0x%02x codec 0x%02x "
1323 "cid 0x%04x vid 0x%04x codec config len 0x%02x", ase,
1324 cfg->latency, cfg->phy, cfg->codec.id, cfg->codec.cid,
1325 cfg->codec.vid, cfg->cc_len);
1326
1327 if (cfg->latency < BT_ASCS_CONFIG_LATENCY_LOW ||
1328 cfg->latency > BT_ASCS_CONFIG_LATENCY_HIGH) {
1329 LOG_WRN("Invalid latency: 0x%02x", cfg->latency);
1330 ascs_cp_rsp_add(ASE_ID(ase), BT_BAP_ASCS_RSP_CODE_CONF_INVALID,
1331 BT_BAP_ASCS_REASON_LATENCY);
1332 return -EINVAL;
1333 }
1334
1335 if (cfg->phy < BT_ASCS_CONFIG_PHY_LE_1M ||
1336 cfg->phy > BT_ASCS_CONFIG_PHY_LE_CODED) {
1337 LOG_WRN("Invalid PHY: 0x%02x", cfg->phy);
1338 ascs_cp_rsp_add(ASE_ID(ase), BT_BAP_ASCS_RSP_CODE_CONF_INVALID,
1339 BT_BAP_ASCS_REASON_PHY);
1340 return -EINVAL;
1341 }
1342
1343 switch (ase->ep.status.state) {
1344 /* Valid only if ASE_State field = 0x00 (Idle) */
1345 case BT_BAP_EP_STATE_IDLE:
1346 /* or 0x01 (Codec Configured) */
1347 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1348 /* or 0x02 (QoS Configured) */
1349 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1350 break;
1351 default:
1352 LOG_WRN("Invalid operation in state: %s",
1353 bt_bap_ep_state_str(ase->ep.status.state));
1354 ascs_cp_rsp_add(ASE_ID(ase), BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
1355 BT_BAP_ASCS_REASON_NONE);
1356 return -EINVAL;
1357 }
1358
1359 /* Store current codec configuration to be able to restore it
1360 * in case of error.
1361 */
1362 (void)memcpy(&codec, &ase->ep.codec, sizeof(codec));
1363
1364 err = ascs_ep_set_codec(&ase->ep, cfg->codec.id,
1365 sys_le16_to_cpu(cfg->codec.cid),
1366 sys_le16_to_cpu(cfg->codec.vid),
1367 (uint8_t *)cfg->cc, cfg->cc_len, &rsp);
1368 if (err) {
1369 (void)memcpy(&ase->ep.codec, &codec, sizeof(codec));
1370 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
1371 return err;
1372 }
1373
1374 if (ase->ep.stream != NULL) {
1375 if (unicast_server_cb != NULL &&
1376 unicast_server_cb->reconfig != NULL) {
1377 err = unicast_server_cb->reconfig(ase->ep.stream,
1378 ase->ep.dir,
1379 &ase->ep.codec,
1380 &ase->ep.qos_pref,
1381 &rsp);
1382 } else {
1383 err = -ENOTSUP;
1384 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
1385 BT_BAP_ASCS_REASON_NONE);
1386 }
1387
1388 if (err) {
1389 if (rsp.code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
1390 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
1391 BT_BAP_ASCS_REASON_NONE);
1392 }
1393
1394 LOG_ERR("Reconfig failed: err %d, code %u, reason %u",
1395 err, rsp.code, rsp.reason);
1396
1397 (void)memcpy(&ase->ep.codec, &codec, sizeof(codec));
1398 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
1399
1400 return err;
1401 }
1402
1403 stream = ase->ep.stream;
1404 } else {
1405 stream = NULL;
1406 if (unicast_server_cb != NULL &&
1407 unicast_server_cb->config != NULL) {
1408 err = unicast_server_cb->config(ase->conn, &ase->ep, ase->ep.dir,
1409 &ase->ep.codec, &stream,
1410 &ase->ep.qos_pref, &rsp);
1411 } else {
1412 err = -ENOTSUP;
1413 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
1414 BT_BAP_ASCS_REASON_NONE);
1415 }
1416
1417 if (err || stream == NULL) {
1418 if (rsp.code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
1419 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
1420 BT_BAP_ASCS_REASON_NONE);
1421 }
1422
1423 LOG_ERR("Config failed: err %d, stream %p, code %u, reason %u",
1424 err, stream, rsp.code, rsp.reason);
1425
1426 (void)memcpy(&ase->ep.codec, &codec, sizeof(codec));
1427 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
1428
1429 return err ? err : -ENOMEM;
1430 }
1431
1432 bt_bap_stream_init(stream);
1433 }
1434
1435 ascs_cp_rsp_success(ASE_ID(ase));
1436
1437 bt_bap_stream_attach(ase->conn, stream, &ase->ep, &ase->ep.codec);
1438
1439 ascs_ep_set_state(&ase->ep, BT_BAP_EP_STATE_CODEC_CONFIGURED);
1440
1441 return 0;
1442 }
1443
bt_ascs_config_ase(struct bt_conn * conn,struct bt_bap_stream * stream,struct bt_codec * codec,const struct bt_codec_qos_pref * qos_pref)1444 int bt_ascs_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream, struct bt_codec *codec,
1445 const struct bt_codec_qos_pref *qos_pref)
1446 {
1447 int err;
1448 struct bt_ascs_ase *ase;
1449 struct bt_bap_ep *ep;
1450 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
1451 BT_BAP_ASCS_REASON_NONE);
1452
1453 CHECKIF(conn == NULL || stream == NULL || codec == NULL || qos_pref == NULL) {
1454 LOG_DBG("NULL value(s) supplied)");
1455 return -EINVAL;
1456 }
1457
1458 ep = stream->ep;
1459
1460 if (stream->ep != NULL) {
1461 LOG_DBG("Stream already configured for conn %p", (void *)stream->conn);
1462 return -EALREADY;
1463 }
1464
1465 /* Get a free ASE or NULL if all ASE instances are aready in use */
1466 for (int i = 1; i <= ASE_COUNT; i++) {
1467 ase = ase_find(conn, i);
1468 if (ase == NULL) {
1469 ase = ase_new(conn, i);
1470 break;
1471 }
1472 }
1473
1474 if (ase == NULL) {
1475 LOG_WRN("No free ASE found.");
1476 return -ENOTSUP;
1477 }
1478
1479 ep = &ase->ep;
1480
1481 if (ep->status.state != BT_BAP_EP_STATE_IDLE) {
1482 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1483 return -EBADMSG;
1484 }
1485
1486 err = ascs_ep_set_codec(ep, codec->id, sys_le16_to_cpu(codec->cid),
1487 sys_le16_to_cpu(codec->vid), NULL, 0, &rsp);
1488 if (err) {
1489 return err;
1490 }
1491
1492 ep->qos_pref = *qos_pref;
1493
1494 bt_bap_stream_attach(conn, stream, ep, &ep->codec);
1495
1496 ascs_ep_set_state(ep, BT_BAP_EP_STATE_CODEC_CONFIGURED);
1497
1498 return 0;
1499 }
1500
is_valid_config_len(struct net_buf_simple * buf)1501 static bool is_valid_config_len(struct net_buf_simple *buf)
1502 {
1503 const struct bt_ascs_config_op *op;
1504 struct net_buf_simple_state state;
1505
1506 net_buf_simple_save(buf, &state);
1507
1508 if (buf->len < sizeof(*op)) {
1509 LOG_WRN("Invalid length %u < %zu", buf->len, sizeof(*op));
1510 return false;
1511 }
1512
1513 op = net_buf_simple_pull_mem(buf, sizeof(*op));
1514 if (op->num_ases < 1) {
1515 LOG_WRN("Number_of_ASEs parameter value is less than 1");
1516 return false;
1517 }
1518
1519 for (uint8_t i = 0U; i < op->num_ases; i++) {
1520 const struct bt_ascs_config *config;
1521
1522 if (buf->len < sizeof(*config)) {
1523 LOG_WRN("Malformed params array");
1524 return false;
1525 }
1526
1527 config = net_buf_simple_pull_mem(buf, sizeof(*config));
1528 if (buf->len < config->cc_len) {
1529 LOG_WRN("Malformed codec specific config");
1530 return false;
1531 }
1532
1533 (void)net_buf_simple_pull_mem(buf, config->cc_len);
1534 }
1535
1536 if (buf->len > 0) {
1537 LOG_WRN("Unexpected data");
1538 return false;
1539 }
1540
1541 net_buf_simple_restore(buf, &state);
1542
1543 return true;
1544 }
1545
ascs_config(struct bt_conn * conn,struct net_buf_simple * buf)1546 static ssize_t ascs_config(struct bt_conn *conn, struct net_buf_simple *buf)
1547 {
1548 const struct bt_ascs_config_op *req;
1549 const struct bt_ascs_config *cfg;
1550
1551 if (!is_valid_config_len(buf)) {
1552 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1553 }
1554
1555 req = net_buf_simple_pull_mem(buf, sizeof(*req));
1556
1557 LOG_DBG("num_ases %u", req->num_ases);
1558
1559 for (uint8_t i = 0; i < req->num_ases; i++) {
1560 struct bt_ascs_ase *ase;
1561 int err;
1562
1563 cfg = net_buf_simple_pull_mem(buf, sizeof(*cfg));
1564 (void)net_buf_simple_pull(buf, cfg->cc_len);
1565
1566 LOG_DBG("ase 0x%02x cc_len %u", cfg->ase, cfg->cc_len);
1567
1568 if (!cfg->ase || cfg->ase > ASE_COUNT) {
1569 LOG_WRN("Invalid ASE ID: %u", cfg->ase);
1570 ascs_cp_rsp_add(cfg->ase, BT_BAP_ASCS_RSP_CODE_INVALID_ASE,
1571 BT_BAP_ASCS_REASON_NONE);
1572 continue;
1573 }
1574
1575 ase = ase_find(conn, cfg->ase);
1576 if (ase != NULL) {
1577 ase_config(ase, cfg);
1578 continue;
1579 }
1580
1581 ase = ase_new(conn, cfg->ase);
1582 if (!ase) {
1583 ascs_cp_rsp_add(cfg->ase, BT_BAP_ASCS_RSP_CODE_NO_MEM,
1584 BT_BAP_ASCS_REASON_NONE);
1585 LOG_WRN("No free ASE found for config ASE ID 0x%02x", cfg->ase);
1586 continue;
1587 }
1588
1589 err = ase_config(ase, cfg);
1590 if (err != 0) {
1591 ase_free(ase);
1592 }
1593 }
1594
1595 return buf->size;
1596 }
1597
bt_ascs_foreach_ep(struct bt_conn * conn,bt_bap_ep_func_t func,void * user_data)1598 void bt_ascs_foreach_ep(struct bt_conn *conn, bt_bap_ep_func_t func, void *user_data)
1599 {
1600 for (size_t i = 0; i < ARRAY_SIZE(ase_pool); i++) {
1601 struct bt_ascs_ase *ase = &ase_pool[i];
1602
1603 if (ase->conn == conn) {
1604 func(&ase->ep, user_data);
1605 }
1606 }
1607 }
1608
ase_stream_qos(struct bt_bap_stream * stream,struct bt_codec_qos * qos,struct bt_conn * conn,uint8_t cig_id,uint8_t cis_id,struct bt_bap_ascs_rsp * rsp)1609 static int ase_stream_qos(struct bt_bap_stream *stream, struct bt_codec_qos *qos,
1610 struct bt_conn *conn, uint8_t cig_id, uint8_t cis_id,
1611 struct bt_bap_ascs_rsp *rsp)
1612 {
1613 struct bt_bap_ep *ep;
1614 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
1615
1616 CHECKIF(stream == NULL || stream->ep == NULL || qos == NULL) {
1617 LOG_DBG("Invalid input stream, ep or qos pointers");
1618 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
1619 BT_BAP_ASCS_REASON_NONE);
1620 return -EINVAL;
1621 }
1622
1623 LOG_DBG("stream %p ep %p qos %p", stream, stream->ep, qos);
1624
1625 ep = stream->ep;
1626
1627 switch (ep->status.state) {
1628 /* Valid only if ASE_State field = 0x01 (Codec Configured) */
1629 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1630 /* or 0x02 (QoS Configured) */
1631 case BT_BAP_EP_STATE_QOS_CONFIGURED:
1632 break;
1633 default:
1634 LOG_WRN("Invalid operation in state: %s", bt_bap_ep_state_str(ep->status.state));
1635 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
1636 BT_BAP_ASCS_REASON_NONE);
1637 return -EBADMSG;
1638 }
1639
1640 rsp->reason = bt_audio_verify_qos(qos);
1641 if (rsp->reason != BT_BAP_ASCS_REASON_NONE) {
1642 rsp->code = BT_BAP_ASCS_RSP_CODE_CONF_INVALID;
1643 return -EINVAL;
1644 }
1645
1646 rsp->reason = bt_bap_stream_verify_qos(stream, qos);
1647 if (rsp->reason != BT_BAP_ASCS_REASON_NONE) {
1648 rsp->code = BT_BAP_ASCS_RSP_CODE_CONF_INVALID;
1649 return -EINVAL;
1650 }
1651
1652 if (unicast_server_cb != NULL && unicast_server_cb->qos != NULL) {
1653 int err = unicast_server_cb->qos(stream, qos, rsp);
1654
1655 if (err) {
1656 if (rsp->code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
1657 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
1658 BT_BAP_ASCS_REASON_NONE);
1659 }
1660
1661 LOG_DBG("Application returned error: err %d status %u reason %u",
1662 err, rsp->code, rsp->reason);
1663 return err;
1664 }
1665 }
1666
1667 /* QoS->QoS transition. Unbind ISO if CIG/CIS changed. */
1668 if (ep->iso != NULL && (ep->cig_id != cig_id || ep->cis_id != cis_id)) {
1669 bt_bap_iso_unbind_ep(ep->iso, ep);
1670 }
1671
1672 if (ep->iso == NULL) {
1673 struct bt_bap_iso *iso;
1674
1675 iso = bap_iso_get_or_new(conn, cig_id, cis_id);
1676 if (iso == NULL) {
1677 LOG_ERR("Could not allocate bap_iso");
1678 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM,
1679 BT_BAP_ASCS_REASON_NONE);
1680 return -ENOMEM;
1681 }
1682
1683 if (bt_bap_iso_get_ep(false, iso, ep->dir) != NULL) {
1684 LOG_ERR("iso %p already in use in dir %s",
1685 &iso->chan, bt_audio_dir_str(ep->dir));
1686 bt_bap_iso_unref(iso);
1687 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID,
1688 BT_BAP_ASCS_REASON_CIS);
1689 return -EALREADY;
1690 }
1691
1692 bt_bap_iso_bind_ep(iso, ep);
1693 bt_bap_iso_unref(iso);
1694 }
1695
1696 stream->qos = qos;
1697
1698 /* We setup the data path here, as this is the earliest where
1699 * we have the ISO <-> EP coupling completed (due to setting
1700 * the CIS ID in the QoS procedure).
1701 */
1702 if (ep->dir == BT_AUDIO_DIR_SINK) {
1703 bt_audio_codec_to_iso_path(&ep->iso->rx.path, stream->codec);
1704 } else {
1705 bt_audio_codec_to_iso_path(&ep->iso->tx.path, stream->codec);
1706 }
1707
1708 ep->cig_id = cig_id;
1709 ep->cis_id = cis_id;
1710
1711 ascs_ep_set_state(ep, BT_BAP_EP_STATE_QOS_CONFIGURED);
1712
1713 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
1714 return 0;
1715 }
1716
ase_qos(struct bt_ascs_ase * ase,const struct bt_ascs_qos * qos)1717 static void ase_qos(struct bt_ascs_ase *ase, const struct bt_ascs_qos *qos)
1718 {
1719 struct bt_bap_ep *ep = &ase->ep;
1720 struct bt_bap_stream *stream = ep->stream;
1721 struct bt_codec_qos *cqos = &ep->qos;
1722 const uint8_t cig_id = qos->cig;
1723 const uint8_t cis_id = qos->cis;
1724 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
1725 BT_BAP_ASCS_REASON_NONE);
1726 int err;
1727
1728 cqos->interval = sys_get_le24(qos->interval);
1729 cqos->framing = qos->framing;
1730 cqos->phy = qos->phy;
1731 cqos->sdu = sys_le16_to_cpu(qos->sdu);
1732 cqos->rtn = qos->rtn;
1733 cqos->latency = sys_le16_to_cpu(qos->latency);
1734 cqos->pd = sys_get_le24(qos->pd);
1735
1736 LOG_DBG("ase %p cig 0x%02x cis 0x%02x interval %u framing 0x%02x "
1737 "phy 0x%02x sdu %u rtn %u latency %u pd %u", ase, qos->cig,
1738 qos->cis, cqos->interval, cqos->framing, cqos->phy, cqos->sdu,
1739 cqos->rtn, cqos->latency, cqos->pd);
1740
1741 err = ase_stream_qos(stream, cqos, ase->conn, cig_id, cis_id, &rsp);
1742 if (err) {
1743 if (rsp.code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
1744 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
1745 BT_BAP_ASCS_REASON_NONE);
1746 }
1747 LOG_ERR("QoS failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
1748 memset(cqos, 0, sizeof(*cqos));
1749
1750 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
1751 return;
1752 }
1753
1754 ascs_cp_rsp_success(ASE_ID(ase));
1755 }
1756
is_valid_qos_len(struct net_buf_simple * buf)1757 static bool is_valid_qos_len(struct net_buf_simple *buf)
1758 {
1759 const struct bt_ascs_qos_op *op;
1760 struct net_buf_simple_state state;
1761 size_t params_size;
1762
1763 net_buf_simple_save(buf, &state);
1764
1765 if (buf->len < sizeof(*op)) {
1766 LOG_WRN("Invalid length %u < %zu", buf->len, sizeof(*op));
1767 return false;
1768 }
1769
1770 op = net_buf_simple_pull_mem(buf, sizeof(*op));
1771 if (op->num_ases < 1) {
1772 LOG_WRN("Number_of_ASEs parameter value is less than 1");
1773 return false;
1774 }
1775
1776 params_size = sizeof(struct bt_ascs_qos) * op->num_ases;
1777 if (buf->len < params_size) {
1778 LOG_WRN("Malformed params array");
1779 return false;
1780 }
1781
1782 (void)net_buf_simple_pull_mem(buf, params_size);
1783
1784 if (buf->len > 0) {
1785 LOG_WRN("Unexpected data");
1786 return false;
1787 }
1788
1789 net_buf_simple_restore(buf, &state);
1790
1791 return true;
1792 }
1793
ascs_qos(struct bt_conn * conn,struct net_buf_simple * buf)1794 static ssize_t ascs_qos(struct bt_conn *conn, struct net_buf_simple *buf)
1795 {
1796 const struct bt_ascs_qos_op *req;
1797 const struct bt_ascs_qos *qos;
1798 int i;
1799
1800 if (!is_valid_qos_len(buf)) {
1801 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1802 }
1803
1804 req = net_buf_simple_pull_mem(buf, sizeof(*req));
1805
1806 LOG_DBG("num_ases %u", req->num_ases);
1807
1808 for (i = 0; i < req->num_ases; i++) {
1809 struct bt_ascs_ase *ase;
1810
1811 qos = net_buf_simple_pull_mem(buf, sizeof(*qos));
1812
1813 LOG_DBG("ase 0x%02x", qos->ase);
1814
1815 if (!is_valid_ase_id(qos->ase)) {
1816 ascs_cp_rsp_add(qos->ase, BT_BAP_ASCS_RSP_CODE_INVALID_ASE,
1817 BT_BAP_ASCS_REASON_NONE);
1818 LOG_WRN("Unknown ase 0x%02x", qos->ase);
1819 continue;
1820 }
1821
1822 ase = ase_find(conn, qos->ase);
1823 if (!ase) {
1824 LOG_DBG("Invalid operation for idle ASE");
1825 ascs_cp_rsp_add(qos->ase, BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
1826 BT_BAP_ASCS_REASON_NONE);
1827 continue;
1828 }
1829
1830 ase_qos(ase, qos);
1831 }
1832
1833 return buf->size;
1834 }
1835
ascs_codec_store_metadata(struct bt_data * data,void * user_data)1836 static bool ascs_codec_store_metadata(struct bt_data *data, void *user_data)
1837 {
1838 struct bt_codec *codec = user_data;
1839 struct bt_codec_data *meta;
1840
1841 meta = &codec->meta[codec->meta_count];
1842 meta->data.type = data->type;
1843 meta->data.data_len = data->data_len;
1844
1845 /* Deep copy data contents */
1846 meta->data.data = meta->value;
1847 (void)memcpy(meta->value, data->data, data->data_len);
1848
1849 LOG_DBG("#%zu: data: %s", codec->meta_count, bt_hex(meta->value, data->data_len));
1850
1851 codec->meta_count++;
1852
1853 return true;
1854 }
1855
1856 struct ascs_parse_result {
1857 int err;
1858 struct bt_bap_ascs_rsp *rsp;
1859 size_t count;
1860 const struct bt_bap_ep *ep;
1861 };
1862
ascs_parse_metadata(struct bt_data * data,void * user_data)1863 static bool ascs_parse_metadata(struct bt_data *data, void *user_data)
1864 {
1865 struct ascs_parse_result *result = user_data;
1866 const struct bt_bap_ep *ep = result->ep;
1867 const uint8_t data_len = data->data_len;
1868 const uint8_t data_type = data->type;
1869 const uint8_t *data_value = data->data;
1870
1871 result->count++;
1872
1873 LOG_DBG("#%u type 0x%02x len %u", result->count, data_type, data_len);
1874
1875 if (result->count > CONFIG_BT_CODEC_MAX_METADATA_COUNT) {
1876 LOG_ERR("Not enough buffers for Codec Config Metadata: %zu > %zu", result->count,
1877 CONFIG_BT_CODEC_MAX_DATA_LEN);
1878 *result->rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM,
1879 BT_BAP_ASCS_REASON_NONE);
1880 result->err = -ENOMEM;
1881
1882 return false;
1883 }
1884
1885 if (data_len > CONFIG_BT_CODEC_MAX_DATA_LEN) {
1886 LOG_ERR("Not enough space for Codec Config Metadata: %u > %zu", data->data_len,
1887 CONFIG_BT_CODEC_MAX_DATA_LEN);
1888 *result->rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM,
1889 BT_BAP_ASCS_REASON_NONE);
1890 result->err = -ENOMEM;
1891
1892 return false;
1893 }
1894
1895 /* The CAP acceptor shall not accept metadata with
1896 * unsupported stream context.
1897 */
1898 if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR)) {
1899 if (data_type == BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT) {
1900 const uint16_t context = sys_get_le16(data_value);
1901
1902 if (!bt_pacs_context_available(ep->dir, context)) {
1903 LOG_WRN("Context 0x%04x is unavailable", context);
1904 *result->rsp = BT_BAP_ASCS_RSP(
1905 BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED, data_type);
1906 result->err = -EACCES;
1907
1908 return false;
1909 }
1910 } else if (data_type == BT_AUDIO_METADATA_TYPE_CCID_LIST) {
1911 /* Verify that the CCID is a known CCID on the
1912 * writing device
1913 */
1914 for (uint8_t i = 0; i < data_len; i++) {
1915 const uint8_t ccid = data_value[i];
1916
1917 if (!bt_cap_acceptor_ccid_exist(ep->stream->conn,
1918 ccid)) {
1919 LOG_WRN("CCID %u is unknown", ccid);
1920
1921 /* TBD:
1922 * Should we reject the Metadata?
1923 *
1924 * Should unknown CCIDs trigger a
1925 * discovery procedure for TBS or MCS?
1926 *
1927 * Or should we just accept as is, and
1928 * then let the application decide?
1929 */
1930 }
1931 }
1932 }
1933 }
1934
1935 return true;
1936 }
1937
ascs_verify_metadata(const struct net_buf_simple * buf,struct bt_bap_ep * ep,struct bt_bap_ascs_rsp * rsp)1938 static int ascs_verify_metadata(const struct net_buf_simple *buf, struct bt_bap_ep *ep,
1939 struct bt_bap_ascs_rsp *rsp)
1940 {
1941 struct ascs_parse_result result = {
1942 .rsp = rsp,
1943 .count = 0U,
1944 .err = 0,
1945 .ep = ep
1946 };
1947 struct net_buf_simple meta_ltv;
1948
1949 /* Clone the buf to avoid pulling data from the original buffer */
1950 net_buf_simple_clone(buf, &meta_ltv);
1951
1952 /* Parse LTV entries */
1953 bt_data_parse(&meta_ltv, ascs_parse_metadata, &result);
1954
1955 /* Check if all entries could be parsed */
1956 if (meta_ltv.len != 0) {
1957 LOG_ERR("Unable to parse Metadata: len %u", meta_ltv.len);
1958
1959 if (meta_ltv.len > 2) {
1960 /* Value of the Metadata Type field in error */
1961 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_INVALID,
1962 meta_ltv.data[2]);
1963 return meta_ltv.data[2];
1964 }
1965
1966 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_INVALID,
1967 BT_BAP_ASCS_REASON_NONE);
1968 return -EINVAL;
1969 }
1970
1971 return result.err;
1972 }
1973
ascs_ep_set_metadata(struct bt_bap_ep * ep,uint8_t * data,uint8_t len,struct bt_codec * codec,struct bt_bap_ascs_rsp * rsp)1974 static int ascs_ep_set_metadata(struct bt_bap_ep *ep, uint8_t *data, uint8_t len,
1975 struct bt_codec *codec, struct bt_bap_ascs_rsp *rsp)
1976 {
1977 struct net_buf_simple meta_ltv;
1978 int err;
1979 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
1980
1981 if (ep == NULL && codec == NULL) {
1982 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
1983 BT_BAP_ASCS_REASON_NONE);
1984 return -EINVAL;
1985 }
1986
1987 LOG_DBG("ep %p len %u codec %p", ep, len, codec);
1988
1989 if (len == 0) {
1990 (void)memset(codec->meta, 0, sizeof(codec->meta));
1991 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
1992 return 0;
1993 }
1994
1995 if (codec == NULL) {
1996 codec = &ep->codec;
1997 }
1998
1999 /* Extract metadata LTV for this specific endpoint */
2000 net_buf_simple_init_with_data(&meta_ltv, data, len);
2001
2002 err = ascs_verify_metadata(&meta_ltv, ep, rsp);
2003 if (err != 0) {
2004 return err;
2005 }
2006
2007 /* reset cached metadata */
2008 ep->codec.meta_count = 0;
2009
2010 /* store data contents */
2011 bt_data_parse(&meta_ltv, ascs_codec_store_metadata, codec);
2012
2013 return 0;
2014 }
2015
ase_metadata(struct bt_ascs_ase * ase,struct bt_ascs_metadata * meta)2016 static void ase_metadata(struct bt_ascs_ase *ase, struct bt_ascs_metadata *meta)
2017 {
2018 struct bt_codec_data metadata_backup[CONFIG_BT_CODEC_MAX_DATA_COUNT];
2019 struct bt_bap_stream *stream;
2020 struct bt_bap_ep *ep;
2021 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
2022 BT_BAP_ASCS_REASON_NONE);
2023 uint8_t state;
2024 int err;
2025
2026 LOG_DBG("ase %p meta->len %u", ase, meta->len);
2027
2028 ep = &ase->ep;
2029 state = ep->status.state;
2030
2031 switch (state) {
2032 /* Valid for an ASE only if ASE_State field = 0x03 (Enabling) */
2033 case BT_BAP_EP_STATE_ENABLING:
2034 /* or 0x04 (Streaming) */
2035 case BT_BAP_EP_STATE_STREAMING:
2036 break;
2037 default:
2038 LOG_WRN("Invalid operation in state: %s", bt_bap_ep_state_str(state));
2039 ascs_cp_rsp_add(ASE_ID(ase), BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2040 BT_BAP_ASCS_REASON_NONE);
2041 return;
2042 }
2043
2044 if (!meta->len) {
2045 goto done;
2046 }
2047
2048 /* Backup existing metadata */
2049 (void)memcpy(metadata_backup, ep->codec.meta, sizeof(metadata_backup));
2050 err = ascs_ep_set_metadata(ep, meta->data, meta->len, &ep->codec, &rsp);
2051 if (err) {
2052 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
2053 return;
2054 }
2055
2056 stream = ep->stream;
2057 if (unicast_server_cb != NULL && unicast_server_cb->metadata != NULL) {
2058 err = unicast_server_cb->metadata(stream, ep->codec.meta,
2059 ep->codec.meta_count, &rsp);
2060 } else {
2061 err = -ENOTSUP;
2062 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
2063 BT_BAP_ASCS_REASON_NONE);
2064 }
2065
2066 if (err) {
2067 if (rsp.code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
2068 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
2069 BT_BAP_ASCS_REASON_NONE);
2070 }
2071
2072 /* Restore backup */
2073 (void)memcpy(ep->codec.meta, metadata_backup, sizeof(metadata_backup));
2074
2075 LOG_ERR("Metadata failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
2076 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
2077 return;
2078 }
2079
2080 /* Set the state to the same state to trigger the notifications */
2081 ascs_ep_set_state(ep, ep->status.state);
2082 done:
2083 ascs_cp_rsp_success(ASE_ID(ase));
2084 }
2085
ase_enable(struct bt_ascs_ase * ase,struct bt_ascs_metadata * meta)2086 static int ase_enable(struct bt_ascs_ase *ase, struct bt_ascs_metadata *meta)
2087 {
2088 struct bt_bap_stream *stream;
2089 struct bt_bap_ep *ep;
2090 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
2091 BT_BAP_ASCS_REASON_NONE);
2092 int err;
2093
2094 LOG_DBG("ase %p meta->len %u", ase, meta->len);
2095
2096 ep = &ase->ep;
2097
2098 /* Valid for an ASE only if ASE_State field = 0x02 (QoS Configured) */
2099 if (ep->status.state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
2100 err = -EBADMSG;
2101 LOG_WRN("Invalid operation in state: %s", bt_bap_ep_state_str(ep->status.state));
2102 ascs_cp_rsp_add(ASE_ID(ase), BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2103 BT_BAP_ASCS_REASON_NONE);
2104 return err;
2105 }
2106
2107 err = ascs_ep_set_metadata(ep, meta->data, meta->len, &ep->codec, &rsp);
2108 if (err) {
2109 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
2110 return err;
2111 }
2112
2113 stream = ep->stream;
2114 if (unicast_server_cb != NULL && unicast_server_cb->enable != NULL) {
2115 err = unicast_server_cb->enable(stream, ep->codec.meta,
2116 ep->codec.meta_count, &rsp);
2117 } else {
2118 err = -ENOTSUP;
2119 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
2120 BT_BAP_ASCS_REASON_NONE);
2121 }
2122
2123 if (err) {
2124 if (rsp.code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
2125 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
2126 BT_BAP_ASCS_REASON_NONE);
2127 }
2128
2129 LOG_ERR("Enable rejected: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
2130 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
2131
2132 return -EFAULT;
2133 }
2134
2135 ascs_ep_set_state(ep, BT_BAP_EP_STATE_ENABLING);
2136
2137 ascs_cp_rsp_success(ASE_ID(ase));
2138
2139 return 0;
2140 }
2141
is_valid_enable_len(struct net_buf_simple * buf)2142 static bool is_valid_enable_len(struct net_buf_simple *buf)
2143 {
2144 const struct bt_ascs_enable_op *op;
2145 struct net_buf_simple_state state;
2146
2147 net_buf_simple_save(buf, &state);
2148
2149 if (buf->len < sizeof(*op)) {
2150 LOG_WRN("Invalid length %u < %zu", buf->len, sizeof(*op));
2151 return false;
2152 }
2153
2154 op = net_buf_simple_pull_mem(buf, sizeof(*op));
2155 if (op->num_ases < 1) {
2156 LOG_WRN("Number_of_ASEs parameter value is less than 1");
2157 return false;
2158 }
2159
2160 for (uint8_t i = 0U; i < op->num_ases; i++) {
2161 const struct bt_ascs_metadata *metadata;
2162
2163 if (buf->len < sizeof(*metadata)) {
2164 LOG_WRN("Malformed params array");
2165 return false;
2166 }
2167
2168 metadata = net_buf_simple_pull_mem(buf, sizeof(*metadata));
2169 if (buf->len < metadata->len) {
2170 LOG_WRN("Malformed metadata");
2171 return false;
2172 }
2173
2174 (void)net_buf_simple_pull_mem(buf, metadata->len);
2175 }
2176
2177 if (buf->len > 0) {
2178 LOG_WRN("Unexpected data");
2179 return false;
2180 }
2181
2182 net_buf_simple_restore(buf, &state);
2183
2184 return true;
2185 }
2186
ascs_enable(struct bt_conn * conn,struct net_buf_simple * buf)2187 static ssize_t ascs_enable(struct bt_conn *conn, struct net_buf_simple *buf)
2188 {
2189 const struct bt_ascs_enable_op *req;
2190 struct bt_ascs_metadata *meta;
2191 int i;
2192
2193 if (!is_valid_enable_len(buf)) {
2194 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
2195 }
2196
2197 req = net_buf_simple_pull_mem(buf, sizeof(*req));
2198
2199 LOG_DBG("num_ases %u", req->num_ases);
2200
2201 for (i = 0; i < req->num_ases; i++) {
2202 struct bt_ascs_ase *ase;
2203
2204 meta = net_buf_simple_pull_mem(buf, sizeof(*meta));
2205 (void)net_buf_simple_pull(buf, meta->len);
2206
2207 if (!is_valid_ase_id(meta->ase)) {
2208 ascs_cp_rsp_add(meta->ase, BT_BAP_ASCS_RSP_CODE_INVALID_ASE,
2209 BT_BAP_ASCS_REASON_NONE);
2210 LOG_WRN("Unknown ase 0x%02x", meta->ase);
2211 continue;
2212 }
2213
2214 ase = ase_find(conn, meta->ase);
2215 if (!ase) {
2216 LOG_DBG("Invalid operation for idle ase 0x%02x", meta->ase);
2217 ascs_cp_rsp_add(meta->ase, BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2218 BT_BAP_ASCS_REASON_NONE);
2219 continue;
2220 }
2221
2222 ase_enable(ase, meta);
2223 }
2224
2225 return buf->size;
2226 }
2227
ase_start(struct bt_ascs_ase * ase)2228 static void ase_start(struct bt_ascs_ase *ase)
2229 {
2230 struct bt_bap_ep *ep;
2231 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
2232 BT_BAP_ASCS_REASON_NONE);
2233 int err;
2234
2235 LOG_DBG("ase %p", ase);
2236
2237 ep = &ase->ep;
2238
2239 /* Valid for an ASE only if ASE_State field = 0x02 (QoS Configured) */
2240 if (ep->status.state != BT_BAP_EP_STATE_ENABLING) {
2241 LOG_WRN("Invalid operation in state: %s", bt_bap_ep_state_str(ep->status.state));
2242 ascs_cp_rsp_add(ASE_ID(ase), BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2243 BT_BAP_ASCS_REASON_NONE);
2244 return;
2245 }
2246
2247 if (ep->iso->chan.state != BT_ISO_STATE_CONNECTED) {
2248 /* An ASE may not go into the streaming state unless the CIS
2249 * is connected
2250 */
2251 LOG_WRN("Start failed: CIS not connected: %u",
2252 ep->iso->chan.state);
2253 ascs_cp_rsp_add(ASE_ID(ase), BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2254 BT_BAP_ASCS_REASON_NONE);
2255 return;
2256 }
2257
2258 if (unicast_server_cb != NULL && unicast_server_cb->start != NULL) {
2259 err = unicast_server_cb->start(ep->stream, &rsp);
2260 } else {
2261 err = -ENOTSUP;
2262 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
2263 BT_BAP_ASCS_REASON_NONE);
2264 }
2265
2266 if (err) {
2267 if (rsp.code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
2268 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
2269 BT_BAP_ASCS_REASON_NONE);
2270 }
2271
2272 LOG_ERR("Start failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
2273 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
2274
2275 return;
2276 }
2277
2278 ep->receiver_ready = true;
2279
2280 ascs_ep_set_state(ep, BT_BAP_EP_STATE_STREAMING);
2281
2282 ascs_cp_rsp_success(ASE_ID(ase));
2283 }
2284
is_valid_start_len(struct net_buf_simple * buf)2285 static bool is_valid_start_len(struct net_buf_simple *buf)
2286 {
2287 const struct bt_ascs_start_op *op;
2288 struct net_buf_simple_state state;
2289
2290 net_buf_simple_save(buf, &state);
2291
2292 if (buf->len < sizeof(*op)) {
2293 LOG_WRN("Invalid length %u < %zu", buf->len, sizeof(*op));
2294 return false;
2295 }
2296
2297 op = net_buf_simple_pull_mem(buf, sizeof(*op));
2298 if (op->num_ases < 1) {
2299 LOG_WRN("Number_of_ASEs parameter value is less than 1");
2300 return false;
2301 }
2302
2303 if (buf->len != op->num_ases) {
2304 LOG_WRN("Number_of_ASEs mismatch");
2305 return false;
2306 }
2307
2308 net_buf_simple_restore(buf, &state);
2309
2310 return true;
2311 }
2312
ascs_start(struct bt_conn * conn,struct net_buf_simple * buf)2313 static ssize_t ascs_start(struct bt_conn *conn, struct net_buf_simple *buf)
2314 {
2315 const struct bt_ascs_start_op *req;
2316 int i;
2317
2318 if (!is_valid_start_len(buf)) {
2319 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
2320 }
2321
2322 req = net_buf_simple_pull_mem(buf, sizeof(*req));
2323
2324 LOG_DBG("num_ases %u", req->num_ases);
2325
2326 for (i = 0; i < req->num_ases; i++) {
2327 struct bt_ascs_ase *ase;
2328 uint8_t id;
2329
2330 id = net_buf_simple_pull_u8(buf);
2331
2332 LOG_DBG("ase 0x%02x", id);
2333
2334 if (!is_valid_ase_id(id)) {
2335 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_ASE,
2336 BT_BAP_ASCS_REASON_NONE);
2337 LOG_WRN("Unknown ase 0x%02x", id);
2338 continue;
2339 }
2340
2341 /* If the ASE_ID written by the client represents a Sink ASE, the
2342 * server shall not accept the Receiver Start Ready operation for that
2343 * ASE. The server shall send a notification of the ASE Control Point
2344 * characteristic to the client, and the server shall set the
2345 * Response_Code value for that ASE to 0x05 (Invalid ASE direction).
2346 */
2347 if (ASE_DIR(id) == BT_AUDIO_DIR_SINK) {
2348 LOG_WRN("Start failed: invalid operation for Sink");
2349 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_DIR,
2350 BT_BAP_ASCS_REASON_NONE);
2351 continue;
2352 }
2353
2354 ase = ase_find(conn, id);
2355 if (!ase) {
2356 LOG_DBG("Invalid operation for idle ASE");
2357 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2358 BT_BAP_ASCS_REASON_NONE);
2359 continue;
2360 }
2361
2362 ase_start(ase);
2363 }
2364
2365 return buf->size;
2366 }
2367
is_valid_disable_len(struct net_buf_simple * buf)2368 static bool is_valid_disable_len(struct net_buf_simple *buf)
2369 {
2370 const struct bt_ascs_disable_op *op;
2371 struct net_buf_simple_state state;
2372
2373 net_buf_simple_save(buf, &state);
2374
2375 if (buf->len < sizeof(*op)) {
2376 LOG_WRN("Invalid length %u < %zu", buf->len, sizeof(*op));
2377 return false;
2378 }
2379
2380 op = net_buf_simple_pull_mem(buf, sizeof(*op));
2381 if (op->num_ases < 1) {
2382 LOG_WRN("Number_of_ASEs parameter value is less than 1");
2383 return false;
2384 }
2385
2386 if (buf->len != op->num_ases) {
2387 LOG_WRN("Number_of_ASEs mismatch");
2388 return false;
2389 }
2390
2391 net_buf_simple_restore(buf, &state);
2392
2393 return true;
2394 }
2395
ascs_disable(struct bt_conn * conn,struct net_buf_simple * buf)2396 static ssize_t ascs_disable(struct bt_conn *conn, struct net_buf_simple *buf)
2397 {
2398 const struct bt_ascs_disable_op *req;
2399 int i;
2400
2401 if (!is_valid_disable_len(buf)) {
2402 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
2403 }
2404
2405 req = net_buf_simple_pull_mem(buf, sizeof(*req));
2406
2407 LOG_DBG("num_ases %u", req->num_ases);
2408
2409 for (i = 0; i < req->num_ases; i++) {
2410 struct bt_ascs_ase *ase;
2411 uint8_t id;
2412
2413 id = net_buf_simple_pull_u8(buf);
2414
2415 LOG_DBG("ase 0x%02x", id);
2416
2417 if (!is_valid_ase_id(id)) {
2418 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_ASE,
2419 BT_BAP_ASCS_REASON_NONE);
2420 LOG_WRN("Unknown ase 0x%02x", id);
2421 continue;
2422 }
2423
2424 ase = ase_find(conn, id);
2425 if (!ase) {
2426 LOG_DBG("Invalid operation for idle ASE");
2427 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2428 BT_BAP_ASCS_REASON_NONE);
2429 continue;
2430 }
2431
2432 ase_disable(ase);
2433 }
2434
2435 return buf->size;
2436 }
2437
ase_stop(struct bt_ascs_ase * ase)2438 static void ase_stop(struct bt_ascs_ase *ase)
2439 {
2440 struct bt_bap_stream *stream;
2441 struct bt_bap_ep *ep;
2442 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
2443 BT_BAP_ASCS_REASON_NONE);
2444 int err;
2445
2446 LOG_DBG("ase %p", ase);
2447
2448 ep = &ase->ep;
2449
2450 if (ep->status.state != BT_BAP_EP_STATE_DISABLING) {
2451 LOG_WRN("Invalid operation in state: %s", bt_bap_ep_state_str(ep->status.state));
2452 ascs_cp_rsp_add(ASE_ID(ase), BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2453 BT_BAP_ASCS_REASON_NONE);
2454 return;
2455 }
2456
2457 stream = ep->stream;
2458 if (unicast_server_cb != NULL && unicast_server_cb->stop != NULL) {
2459 err = unicast_server_cb->stop(stream, &rsp);
2460 } else {
2461 err = -ENOTSUP;
2462 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
2463 BT_BAP_ASCS_REASON_NONE);
2464 }
2465
2466 if (err) {
2467 if (rsp.code == BT_BAP_ASCS_RSP_CODE_SUCCESS) {
2468 rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_UNSPECIFIED,
2469 BT_BAP_ASCS_REASON_NONE);
2470 }
2471
2472 LOG_ERR("Stop failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
2473 ascs_cp_rsp_add(ASE_ID(ase), rsp.code, rsp.reason);
2474 return;
2475 }
2476
2477 /* If the Receiver Stop Ready operation has completed successfully the
2478 * Unicast Client or the Unicast Server may terminate a CIS established
2479 * for that ASE by following the Connected Isochronous Stream Terminate
2480 * procedure defined in Volume 3, Part C, Section 9.3.15.
2481 */
2482 if (bt_bap_stream_can_disconnect(stream)) {
2483 err = ascs_disconnect_stream(stream);
2484 if (err < 0) {
2485 LOG_ERR("Failed to disconnect stream %p: %d", stream, err);
2486 return;
2487 }
2488 }
2489
2490 ascs_ep_set_state(ep, BT_BAP_EP_STATE_QOS_CONFIGURED);
2491
2492 ascs_cp_rsp_success(ASE_ID(ase));
2493 }
2494
is_valid_stop_len(struct net_buf_simple * buf)2495 static bool is_valid_stop_len(struct net_buf_simple *buf)
2496 {
2497 const struct bt_ascs_stop_op *op;
2498 struct net_buf_simple_state state;
2499
2500 net_buf_simple_save(buf, &state);
2501
2502 if (buf->len < sizeof(*op)) {
2503 LOG_WRN("Invalid length %u < %zu", buf->len, sizeof(*op));
2504 return false;
2505 }
2506
2507 op = net_buf_simple_pull_mem(buf, sizeof(*op));
2508 if (op->num_ases < 1) {
2509 LOG_WRN("Number_of_ASEs parameter value is less than 1");
2510 return false;
2511 }
2512
2513 if (buf->len != op->num_ases) {
2514 LOG_WRN("Number_of_ASEs mismatch");
2515 return false;
2516 }
2517
2518 net_buf_simple_restore(buf, &state);
2519
2520 return true;
2521 }
2522
ascs_stop(struct bt_conn * conn,struct net_buf_simple * buf)2523 static ssize_t ascs_stop(struct bt_conn *conn, struct net_buf_simple *buf)
2524 {
2525 const struct bt_ascs_start_op *req;
2526 int i;
2527
2528 if (!is_valid_stop_len(buf)) {
2529 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
2530 }
2531
2532 req = net_buf_simple_pull_mem(buf, sizeof(*req));
2533
2534 LOG_DBG("num_ases %u", req->num_ases);
2535
2536 for (i = 0; i < req->num_ases; i++) {
2537 struct bt_ascs_ase *ase;
2538 uint8_t id;
2539
2540 id = net_buf_simple_pull_u8(buf);
2541
2542 LOG_DBG("ase 0x%02x", id);
2543
2544 if (!is_valid_ase_id(id)) {
2545 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_ASE,
2546 BT_BAP_ASCS_REASON_NONE);
2547 LOG_WRN("Unknown ase 0x%02x", id);
2548 continue;
2549 }
2550
2551 /* If the ASE_ID written by the client represents a Sink ASE, the
2552 * server shall not accept the Receiver Stop Ready operation for that
2553 * ASE. The server shall send a notification of the ASE Control Point
2554 * characteristic to the client, and the server shall set the
2555 * Response_Code value for that ASE to 0x05 (Invalid ASE direction).
2556 */
2557 if (ASE_DIR(id) == BT_AUDIO_DIR_SINK) {
2558 LOG_WRN("Stop failed: invalid operation for Sink");
2559 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_DIR,
2560 BT_BAP_ASCS_REASON_NONE);
2561 continue;
2562 }
2563
2564 ase = ase_find(conn, id);
2565 if (!ase) {
2566 LOG_DBG("Invalid operation for idle ASE");
2567 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2568 BT_BAP_ASCS_REASON_NONE);
2569 continue;
2570 }
2571
2572 ase_stop(ase);
2573 }
2574
2575 return buf->size;
2576 }
2577
is_valid_metadata_len(struct net_buf_simple * buf)2578 static bool is_valid_metadata_len(struct net_buf_simple *buf)
2579 {
2580 const struct bt_ascs_metadata_op *op;
2581 struct net_buf_simple_state state;
2582
2583 net_buf_simple_save(buf, &state);
2584
2585 if (buf->len < sizeof(*op)) {
2586 LOG_WRN("Invalid length %u < %zu", buf->len, sizeof(*op));
2587 return false;
2588 }
2589
2590 op = net_buf_simple_pull_mem(buf, sizeof(*op));
2591 if (op->num_ases < 1) {
2592 LOG_WRN("Number_of_ASEs parameter value is less than 1");
2593 return false;
2594 }
2595
2596 for (uint8_t i = 0U; i < op->num_ases; i++) {
2597 const struct bt_ascs_metadata *metadata;
2598
2599 if (buf->len < sizeof(*metadata)) {
2600 LOG_WRN("Malformed params array");
2601 return false;
2602 }
2603
2604 metadata = net_buf_simple_pull_mem(buf, sizeof(*metadata));
2605 if (buf->len < metadata->len) {
2606 LOG_WRN("Malformed metadata");
2607 return false;
2608 }
2609
2610 (void)net_buf_simple_pull_mem(buf, metadata->len);
2611 }
2612
2613 if (buf->len > 0) {
2614 LOG_WRN("Unexpected data");
2615 return false;
2616 }
2617
2618 net_buf_simple_restore(buf, &state);
2619
2620 return true;
2621 }
2622
ascs_metadata(struct bt_conn * conn,struct net_buf_simple * buf)2623 static ssize_t ascs_metadata(struct bt_conn *conn, struct net_buf_simple *buf)
2624 {
2625 const struct bt_ascs_metadata_op *req;
2626 struct bt_ascs_metadata *meta;
2627 int i;
2628
2629 if (!is_valid_metadata_len(buf)) {
2630 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
2631 }
2632
2633 req = net_buf_simple_pull_mem(buf, sizeof(*req));
2634
2635 LOG_DBG("num_ases %u", req->num_ases);
2636
2637 for (i = 0; i < req->num_ases; i++) {
2638 struct bt_ascs_ase *ase;
2639
2640 meta = net_buf_simple_pull_mem(buf, sizeof(*meta));
2641 (void)net_buf_simple_pull(buf, meta->len);
2642
2643 if (!is_valid_ase_id(meta->ase)) {
2644 ascs_cp_rsp_add(meta->ase, BT_BAP_ASCS_RSP_CODE_INVALID_ASE,
2645 BT_BAP_ASCS_REASON_NONE);
2646 LOG_WRN("Unknown ase 0x%02x", meta->ase);
2647 continue;
2648 }
2649
2650 ase = ase_find(conn, meta->ase);
2651 if (!ase) {
2652 LOG_DBG("Invalid operation for idle ase 0x%02x", meta->ase);
2653 ascs_cp_rsp_add(meta->ase, BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2654 BT_BAP_ASCS_REASON_NONE);
2655 continue;
2656 }
2657
2658 ase_metadata(ase, meta);
2659 }
2660
2661 return buf->size;
2662 }
2663
is_valid_release_len(struct net_buf_simple * buf)2664 static bool is_valid_release_len(struct net_buf_simple *buf)
2665 {
2666 const struct bt_ascs_release_op *op;
2667 struct net_buf_simple_state state;
2668
2669 net_buf_simple_save(buf, &state);
2670
2671 if (buf->len < sizeof(*op)) {
2672 LOG_WRN("Invalid length %u < %zu", buf->len, sizeof(*op));
2673 return false;
2674 }
2675
2676 op = net_buf_simple_pull_mem(buf, sizeof(*op));
2677 if (op->num_ases < 1) {
2678 LOG_WRN("Number_of_ASEs parameter value is less than 1");
2679 return false;
2680 }
2681
2682 if (buf->len != op->num_ases) {
2683 LOG_WRN("Number_of_ASEs mismatch");
2684 return false;
2685 }
2686
2687 net_buf_simple_restore(buf, &state);
2688
2689 return true;
2690 }
2691
ascs_release(struct bt_conn * conn,struct net_buf_simple * buf)2692 static ssize_t ascs_release(struct bt_conn *conn, struct net_buf_simple *buf)
2693 {
2694 const struct bt_ascs_release_op *req;
2695 int i;
2696
2697 if (!is_valid_release_len(buf)) {
2698 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
2699 }
2700
2701 req = net_buf_simple_pull_mem(buf, sizeof(*req));
2702
2703 LOG_DBG("num_ases %u", req->num_ases);
2704
2705 for (i = 0; i < req->num_ases; i++) {
2706 uint8_t id;
2707 struct bt_ascs_ase *ase;
2708
2709 id = net_buf_simple_pull_u8(buf);
2710
2711 LOG_DBG("ase 0x%02x", id);
2712
2713 if (!is_valid_ase_id(id)) {
2714 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_ASE,
2715 BT_BAP_ASCS_REASON_NONE);
2716 LOG_WRN("Unknown ase 0x%02x", id);
2717 continue;
2718 }
2719
2720 ase = ase_find(conn, id);
2721 if (!ase) {
2722 LOG_DBG("Invalid operation for idle ASE");
2723 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2724 BT_BAP_ASCS_REASON_NONE);
2725 continue;
2726 }
2727
2728 if (ase->ep.status.state == BT_BAP_EP_STATE_IDLE ||
2729 ase->ep.status.state == BT_BAP_EP_STATE_RELEASING) {
2730 LOG_WRN("Invalid operation in state: %s",
2731 bt_bap_ep_state_str(ase->ep.status.state));
2732 ascs_cp_rsp_add(id, BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE,
2733 BT_BAP_ASCS_REASON_NONE);
2734 continue;
2735 }
2736
2737 ase_release(ase);
2738 }
2739
2740 return buf->size;
2741 }
2742
ascs_cp_write(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * data,uint16_t len,uint16_t offset,uint8_t flags)2743 static ssize_t ascs_cp_write(struct bt_conn *conn,
2744 const struct bt_gatt_attr *attr, const void *data,
2745 uint16_t len, uint16_t offset, uint8_t flags)
2746 {
2747 const struct bt_ascs_ase_cp *req;
2748 struct net_buf_simple buf;
2749 ssize_t ret;
2750
2751 if (flags & BT_GATT_WRITE_FLAG_PREPARE) {
2752 /* Return 0 to allow long writes */
2753 return 0;
2754 }
2755
2756 if (offset != 0 && (flags & BT_GATT_WRITE_FLAG_EXECUTE) == 0) {
2757 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
2758 }
2759
2760 if (len < sizeof(*req)) {
2761 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
2762 }
2763
2764 net_buf_simple_init_with_data(&buf, (void *) data, len);
2765
2766 req = net_buf_simple_pull_mem(&buf, sizeof(*req));
2767
2768 LOG_DBG("conn %p attr %p buf %p len %u op %s (0x%02x)",
2769 (void *)conn, attr, data, len, bt_ascs_op_str(req->op), req->op);
2770
2771 ascs_cp_rsp_init(req->op);
2772
2773 switch (req->op) {
2774 case BT_ASCS_CONFIG_OP:
2775 ret = ascs_config(conn, &buf);
2776 break;
2777 case BT_ASCS_QOS_OP:
2778 ret = ascs_qos(conn, &buf);
2779 break;
2780 case BT_ASCS_ENABLE_OP:
2781 ret = ascs_enable(conn, &buf);
2782 break;
2783 case BT_ASCS_START_OP:
2784 ret = ascs_start(conn, &buf);
2785 break;
2786 case BT_ASCS_DISABLE_OP:
2787 ret = ascs_disable(conn, &buf);
2788 break;
2789 case BT_ASCS_STOP_OP:
2790 ret = ascs_stop(conn, &buf);
2791 break;
2792 case BT_ASCS_METADATA_OP:
2793 ret = ascs_metadata(conn, &buf);
2794 break;
2795 case BT_ASCS_RELEASE_OP:
2796 ret = ascs_release(conn, &buf);
2797 break;
2798 default:
2799 ascs_cp_rsp_add(BT_ASCS_ASE_ID_NONE, BT_BAP_ASCS_RSP_CODE_NOT_SUPPORTED,
2800 BT_BAP_ASCS_REASON_NONE);
2801 LOG_DBG("Unknown opcode");
2802 goto respond;
2803 }
2804
2805 if (ret == BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN)) {
2806 ascs_cp_rsp_add(BT_ASCS_ASE_ID_NONE, BT_BAP_ASCS_RSP_CODE_INVALID_LENGTH,
2807 BT_BAP_ASCS_REASON_NONE);
2808 }
2809
2810 respond:
2811 control_point_notify(conn, rsp_buf.data, rsp_buf.len);
2812
2813 return len;
2814 }
2815
2816 #define BT_ASCS_ASE_DEFINE(_uuid, _id) \
2817 BT_AUDIO_CHRC(_uuid, \
2818 BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
2819 BT_GATT_PERM_READ_ENCRYPT, \
2820 ascs_ase_read, NULL, UINT_TO_POINTER(_id)), \
2821 BT_AUDIO_CCC(ascs_ase_cfg_changed)
2822 #define BT_ASCS_ASE_SNK_DEFINE(_n, ...) BT_ASCS_ASE_DEFINE(BT_UUID_ASCS_ASE_SNK, (_n) + 1)
2823 #define BT_ASCS_ASE_SRC_DEFINE(_n, ...) BT_ASCS_ASE_DEFINE(BT_UUID_ASCS_ASE_SRC, (_n) + 1 + \
2824 CONFIG_BT_ASCS_ASE_SNK_COUNT)
2825
2826 BT_GATT_SERVICE_DEFINE(ascs_svc,
2827 BT_GATT_PRIMARY_SERVICE(BT_UUID_ASCS),
2828 BT_AUDIO_CHRC(BT_UUID_ASCS_ASE_CP,
2829 BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY,
2830 BT_GATT_PERM_WRITE_ENCRYPT | BT_GATT_PERM_PREPARE_WRITE,
2831 NULL, ascs_cp_write, NULL),
2832 BT_AUDIO_CCC(ascs_cp_cfg_changed),
2833 #if CONFIG_BT_ASCS_ASE_SNK_COUNT > 0
2834 LISTIFY(CONFIG_BT_ASCS_ASE_SNK_COUNT, BT_ASCS_ASE_SNK_DEFINE, (,)),
2835 #endif /* CONFIG_BT_ASCS_ASE_SNK_COUNT > 0 */
2836 #if CONFIG_BT_ASCS_ASE_SRC_COUNT > 0
2837 LISTIFY(CONFIG_BT_ASCS_ASE_SRC_COUNT, BT_ASCS_ASE_SRC_DEFINE, (,)),
2838 #endif /* CONFIG_BT_ASCS_ASE_SRC_COUNT > 0 */
2839 );
2840
control_point_notify(struct bt_conn * conn,const void * data,uint16_t len)2841 static int control_point_notify(struct bt_conn *conn, const void *data, uint16_t len)
2842 {
2843 return bt_gatt_notify_uuid(conn, BT_UUID_ASCS_ASE_CP, ascs_svc.attrs, data, len);
2844 }
2845
2846 static struct bt_iso_server iso_server = {
2847 .sec_level = BT_SECURITY_L2,
2848 .accept = ascs_iso_accept,
2849 };
2850
bt_ascs_init(const struct bt_bap_unicast_server_cb * cb)2851 int bt_ascs_init(const struct bt_bap_unicast_server_cb *cb)
2852 {
2853 int err;
2854
2855 if (unicast_server_cb != NULL) {
2856 return -EALREADY;
2857 }
2858
2859 err = bt_iso_server_register(&iso_server);
2860 if (err) {
2861 LOG_ERR("Failed to register ISO server %d", err);
2862 return err;
2863 }
2864
2865 unicast_server_cb = cb;
2866
2867 return 0;
2868 }
2869
ase_cleanup(struct bt_ascs_ase * ase)2870 static void ase_cleanup(struct bt_ascs_ase *ase)
2871 {
2872 struct bt_bap_ascs_rsp rsp;
2873 struct bt_bap_stream *stream;
2874 enum bt_bap_ep_state state;
2875
2876 state = ascs_ep_get_state(&ase->ep);
2877 if (state == BT_BAP_EP_STATE_IDLE || state == BT_BAP_EP_STATE_RELEASING) {
2878 return;
2879 }
2880
2881 stream = ase->ep.stream;
2882 __ASSERT(stream != NULL, "ep.stream is NULL");
2883
2884 if (unicast_server_cb != NULL && unicast_server_cb->release != NULL) {
2885 unicast_server_cb->release(stream, &rsp);
2886 }
2887
2888 ascs_ep_set_state(&ase->ep, BT_BAP_EP_STATE_RELEASING);
2889 }
2890
bt_ascs_cleanup(void)2891 void bt_ascs_cleanup(void)
2892 {
2893 for (size_t i = 0; i < ARRAY_SIZE(ase_pool); i++) {
2894 struct bt_ascs_ase *ase = &ase_pool[i];
2895
2896 if (ase->conn == NULL) {
2897 continue;
2898 }
2899
2900 ase_cleanup(ase);
2901 }
2902
2903 if (unicast_server_cb != NULL) {
2904 bt_iso_server_unregister(&iso_server);
2905 unicast_server_cb = NULL;
2906 }
2907 }
2908 #endif /* BT_BAP_UNICAST_SERVER */
2909