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