1 /*
2  * Copyright (c) 2022-2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <stddef.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 
12 #include <zephyr/autoconf.h>
13 #include <zephyr/bluetooth/audio/audio.h>
14 #include <zephyr/bluetooth/audio/bap.h>
15 #include <zephyr/bluetooth/audio/cap.h>
16 #include <zephyr/bluetooth/conn.h>
17 #include <zephyr/bluetooth/hci_types.h>
18 #include <zephyr/bluetooth/iso.h>
19 #include <zephyr/logging/log.h>
20 #include <zephyr/net_buf.h>
21 #include <zephyr/sys/__assert.h>
22 #include <zephyr/sys/check.h>
23 #include <zephyr/sys/util.h>
24 #include <zephyr/sys/util_macro.h>
25 
26 #include "cap_internal.h"
27 
28 LOG_MODULE_REGISTER(bt_cap_stream, CONFIG_BT_CAP_STREAM_LOG_LEVEL);
29 
stream_is_central(struct bt_bap_stream * bap_stream)30 static bool stream_is_central(struct bt_bap_stream *bap_stream)
31 {
32 	if (IS_ENABLED(CONFIG_BT_CONN)) {
33 		struct bt_conn_info info;
34 		int err;
35 
36 		if (bap_stream->conn == NULL) {
37 			return false;
38 		}
39 
40 		err = bt_conn_get_info(bap_stream->conn, &info);
41 		if (err == 0 && info.role == BT_HCI_ROLE_CENTRAL) {
42 			return true;
43 		}
44 	}
45 
46 	return false;
47 }
48 
49 #if defined(CONFIG_BT_BAP_UNICAST)
cap_stream_configured_cb(struct bt_bap_stream * bap_stream,const struct bt_bap_qos_cfg_pref * pref)50 static void cap_stream_configured_cb(struct bt_bap_stream *bap_stream,
51 				     const struct bt_bap_qos_cfg_pref *pref)
52 {
53 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
54 							struct bt_cap_stream,
55 							bap_stream);
56 	struct bt_bap_stream_ops *ops = cap_stream->ops;
57 
58 	LOG_DBG("%p", cap_stream);
59 
60 	if (ops != NULL && ops->configured != NULL) {
61 		ops->configured(bap_stream, pref);
62 	}
63 
64 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
65 	    stream_is_central(bap_stream)) {
66 		bt_cap_initiator_codec_configured(cap_stream);
67 	}
68 }
69 
cap_stream_qos_set_cb(struct bt_bap_stream * bap_stream)70 static void cap_stream_qos_set_cb(struct bt_bap_stream *bap_stream)
71 {
72 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
73 							struct bt_cap_stream,
74 							bap_stream);
75 	struct bt_bap_stream_ops *ops = cap_stream->ops;
76 
77 	LOG_DBG("%p", cap_stream);
78 
79 	if (ops != NULL && ops->qos_set != NULL) {
80 		ops->qos_set(bap_stream);
81 	}
82 
83 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
84 	    stream_is_central(bap_stream)) {
85 		bt_cap_initiator_qos_configured(cap_stream);
86 	}
87 }
88 
cap_stream_enabled_cb(struct bt_bap_stream * bap_stream)89 static void cap_stream_enabled_cb(struct bt_bap_stream *bap_stream)
90 {
91 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
92 							struct bt_cap_stream,
93 							bap_stream);
94 	struct bt_bap_stream_ops *ops = cap_stream->ops;
95 
96 	LOG_DBG("%p", cap_stream);
97 
98 	if (ops != NULL && ops->enabled != NULL) {
99 		ops->enabled(bap_stream);
100 	}
101 
102 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
103 	    stream_is_central(bap_stream)) {
104 		bt_cap_initiator_enabled(cap_stream);
105 	}
106 }
107 
cap_stream_metadata_updated_cb(struct bt_bap_stream * bap_stream)108 static void cap_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream)
109 {
110 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
111 							struct bt_cap_stream,
112 							bap_stream);
113 	struct bt_bap_stream_ops *ops = cap_stream->ops;
114 
115 	LOG_DBG("%p", cap_stream);
116 
117 	if (ops != NULL && ops->metadata_updated != NULL) {
118 		ops->metadata_updated(bap_stream);
119 	}
120 
121 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
122 	    stream_is_central(bap_stream)) {
123 		bt_cap_initiator_metadata_updated(cap_stream);
124 	}
125 }
126 
cap_stream_disabled_cb(struct bt_bap_stream * bap_stream)127 static void cap_stream_disabled_cb(struct bt_bap_stream *bap_stream)
128 {
129 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
130 							struct bt_cap_stream,
131 							bap_stream);
132 	struct bt_bap_stream_ops *ops = cap_stream->ops;
133 
134 	LOG_DBG("%p", cap_stream);
135 
136 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
137 	    stream_is_central(bap_stream)) {
138 		bt_cap_initiator_disabled(cap_stream);
139 	}
140 
141 	if (ops != NULL && ops->disabled != NULL) {
142 		ops->disabled(bap_stream);
143 	}
144 }
145 
cap_stream_released_cb(struct bt_bap_stream * bap_stream)146 static void cap_stream_released_cb(struct bt_bap_stream *bap_stream)
147 {
148 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
149 							struct bt_cap_stream,
150 							bap_stream);
151 	struct bt_bap_stream_ops *ops = cap_stream->ops;
152 
153 	LOG_DBG("%p", cap_stream);
154 
155 	if (ops != NULL && ops->released != NULL) {
156 		ops->released(bap_stream);
157 	}
158 
159 	/* Here we cannot use stream_is_central as bap_stream->conn is NULL, so fall back to
160 	 * a more generic, less accurate check
161 	 */
162 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT)) {
163 		bt_cap_initiator_released(cap_stream);
164 	}
165 }
166 
167 #endif /* CONFIG_BT_BAP_UNICAST */
168 
cap_stream_started_cb(struct bt_bap_stream * bap_stream)169 static void cap_stream_started_cb(struct bt_bap_stream *bap_stream)
170 {
171 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
172 							struct bt_cap_stream,
173 							bap_stream);
174 	struct bt_bap_stream_ops *ops = cap_stream->ops;
175 
176 	LOG_DBG("%p", cap_stream);
177 
178 	if (ops != NULL && ops->started != NULL) {
179 		ops->started(bap_stream);
180 	}
181 
182 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
183 	    stream_is_central(bap_stream)) {
184 		bt_cap_initiator_started(cap_stream);
185 	}
186 }
187 
cap_stream_stopped_cb(struct bt_bap_stream * bap_stream,uint8_t reason)188 static void cap_stream_stopped_cb(struct bt_bap_stream *bap_stream, uint8_t reason)
189 {
190 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
191 							struct bt_cap_stream,
192 							bap_stream);
193 	struct bt_bap_stream_ops *ops = cap_stream->ops;
194 
195 	LOG_DBG("%p", cap_stream);
196 
197 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
198 	    stream_is_central(bap_stream)) {
199 		bt_cap_initiator_stopped(cap_stream);
200 	}
201 
202 	if (ops != NULL && ops->stopped != NULL) {
203 		ops->stopped(bap_stream, reason);
204 	}
205 }
206 
207 #if defined(CONFIG_BT_AUDIO_RX)
cap_stream_recv_cb(struct bt_bap_stream * bap_stream,const struct bt_iso_recv_info * info,struct net_buf * buf)208 static void cap_stream_recv_cb(struct bt_bap_stream *bap_stream,
209 			       const struct bt_iso_recv_info *info, struct net_buf *buf)
210 {
211 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
212 							struct bt_cap_stream,
213 							bap_stream);
214 	struct bt_bap_stream_ops *ops = cap_stream->ops;
215 
216 	if (ops != NULL && ops->recv != NULL) {
217 		ops->recv(bap_stream, info, buf);
218 	}
219 }
220 #endif /* CONFIG_BT_AUDIO_RX */
221 
222 #if defined(CONFIG_BT_AUDIO_TX)
cap_stream_sent_cb(struct bt_bap_stream * bap_stream)223 static void cap_stream_sent_cb(struct bt_bap_stream *bap_stream)
224 {
225 	struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
226 							struct bt_cap_stream,
227 							bap_stream);
228 	struct bt_bap_stream_ops *ops = cap_stream->ops;
229 
230 	if (ops != NULL && ops->sent != NULL) {
231 		ops->sent(bap_stream);
232 	}
233 }
234 #endif /* CONFIG_BT_AUDIO_TX */
235 
cap_stream_connected_cb(struct bt_bap_stream * bap_stream)236 static void cap_stream_connected_cb(struct bt_bap_stream *bap_stream)
237 {
238 	struct bt_cap_stream *cap_stream =
239 		CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream);
240 	struct bt_bap_stream_ops *ops = cap_stream->ops;
241 
242 	if (ops != NULL && ops->connected != NULL) {
243 		ops->connected(bap_stream);
244 	}
245 
246 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
247 	    stream_is_central(bap_stream)) {
248 		bt_cap_initiator_connected(cap_stream);
249 	}
250 }
251 
cap_stream_disconnected_cb(struct bt_bap_stream * bap_stream,uint8_t reason)252 static void cap_stream_disconnected_cb(struct bt_bap_stream *bap_stream, uint8_t reason)
253 {
254 	struct bt_cap_stream *cap_stream =
255 		CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream);
256 	struct bt_bap_stream_ops *ops = cap_stream->ops;
257 
258 	if (ops != NULL && ops->disconnected != NULL) {
259 		ops->disconnected(bap_stream, reason);
260 	}
261 }
262 
263 static struct bt_bap_stream_ops bap_stream_ops = {
264 #if defined(CONFIG_BT_BAP_UNICAST)
265 	.configured = cap_stream_configured_cb,
266 	.qos_set = cap_stream_qos_set_cb,
267 	.enabled = cap_stream_enabled_cb,
268 	.metadata_updated = cap_stream_metadata_updated_cb,
269 	.disabled = cap_stream_disabled_cb,
270 	.released = cap_stream_released_cb,
271 #endif /* CONFIG_BT_BAP_UNICAST */
272 	.started = cap_stream_started_cb,
273 	.stopped = cap_stream_stopped_cb,
274 #if defined(CONFIG_BT_AUDIO_RX)
275 	.recv = cap_stream_recv_cb,
276 #endif /* CONFIG_BT_AUDIO_RX */
277 #if defined(CONFIG_BT_AUDIO_TX)
278 	.sent = cap_stream_sent_cb,
279 #endif /* CONFIG_BT_AUDIO_TX */
280 	.connected = cap_stream_connected_cb,
281 	.disconnected = cap_stream_disconnected_cb,
282 };
283 
unicast_client_cp_cb(struct bt_bap_stream * bap_stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)284 static void unicast_client_cp_cb(struct bt_bap_stream *bap_stream,
285 				 enum bt_bap_ascs_rsp_code rsp_code, enum bt_bap_ascs_reason reason)
286 {
287 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
288 	    stream_is_central(bap_stream)) {
289 		struct bt_cap_stream *cap_stream =
290 			CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream);
291 
292 		bt_cap_initiator_cp_cb(cap_stream, rsp_code, reason);
293 	}
294 }
295 
bt_cap_stream_ops_register_bap(struct bt_cap_stream * cap_stream)296 void bt_cap_stream_ops_register_bap(struct bt_cap_stream *cap_stream)
297 {
298 	bt_bap_stream_cb_register(&cap_stream->bap_stream, &bap_stream_ops);
299 
300 	if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT)) {
301 		/* The CAP initiator can use the same callback for all of these as the result is the
302 		 * same: Abort current procedure
303 		 */
304 		static struct bt_bap_unicast_client_cb unicast_client_cb = {
305 			.config = unicast_client_cp_cb,
306 			.qos = unicast_client_cp_cb,
307 			.enable = unicast_client_cp_cb,
308 			.start = unicast_client_cp_cb,
309 			.stop = unicast_client_cp_cb,
310 			.disable = unicast_client_cp_cb,
311 			.metadata = unicast_client_cp_cb,
312 			.release = unicast_client_cp_cb,
313 		};
314 		int err;
315 
316 		err = bt_bap_unicast_client_register_cb(&unicast_client_cb);
317 		__ASSERT_NO_MSG(err == 0 || err == -EEXIST);
318 	}
319 }
320 
bt_cap_stream_ops_register(struct bt_cap_stream * stream,struct bt_bap_stream_ops * ops)321 void bt_cap_stream_ops_register(struct bt_cap_stream *stream,
322 				struct bt_bap_stream_ops *ops)
323 {
324 	stream->ops = ops;
325 
326 	/* CAP basically just forwards the BAP callbacks after doing what it (CAP) needs to do,
327 	 * so we can just always register the BAP callbacks here
328 	 *
329 	 * It is, however, only the CAP Initiator Unicast that depend on the callbacks being set in
330 	 * order to work, so for the CAP Initiator Unicast we need an additional register to ensure
331 	 * correctness.
332 	 */
333 
334 	bt_cap_stream_ops_register_bap(stream);
335 }
336 
337 #if defined(CONFIG_BT_AUDIO_TX)
bt_cap_stream_send(struct bt_cap_stream * stream,struct net_buf * buf,uint16_t seq_num)338 int bt_cap_stream_send(struct bt_cap_stream *stream, struct net_buf *buf, uint16_t seq_num)
339 {
340 	CHECKIF(stream == NULL) {
341 		LOG_DBG("stream is NULL");
342 
343 		return -EINVAL;
344 	}
345 
346 	return bt_bap_stream_send(&stream->bap_stream, buf, seq_num);
347 }
348 
bt_cap_stream_send_ts(struct bt_cap_stream * stream,struct net_buf * buf,uint16_t seq_num,uint32_t ts)349 int bt_cap_stream_send_ts(struct bt_cap_stream *stream, struct net_buf *buf, uint16_t seq_num,
350 			  uint32_t ts)
351 {
352 	CHECKIF(stream == NULL) {
353 		LOG_DBG("stream is NULL");
354 
355 		return -EINVAL;
356 	}
357 
358 	return bt_bap_stream_send_ts(&stream->bap_stream, buf, seq_num, ts);
359 }
360 
bt_cap_stream_get_tx_sync(struct bt_cap_stream * stream,struct bt_iso_tx_info * info)361 int bt_cap_stream_get_tx_sync(struct bt_cap_stream *stream, struct bt_iso_tx_info *info)
362 {
363 	CHECKIF(stream == NULL) {
364 		LOG_DBG("stream is NULL");
365 
366 		return -EINVAL;
367 	}
368 
369 	return bt_bap_stream_get_tx_sync(&stream->bap_stream, info);
370 }
371 #endif /* CONFIG_BT_AUDIO_TX */
372