1 /** @file
2  *  @brief Bluetooth Common Audio Profile (CAP) Acceptor unicast.
3  *
4  *  Copyright (c) 2021-2024 Nordic Semiconductor ASA
5  *  Copyright (c) 2023 NXP
6  *
7  *  SPDX-License-Identifier: Apache-2.0
8  */
9 
10 #include <autoconf.h>
11 #include <errno.h>
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #include <zephyr/bluetooth/audio/audio.h>
17 #include <zephyr/bluetooth/audio/bap.h>
18 #include <zephyr/bluetooth/audio/cap.h>
19 #include <zephyr/bluetooth/audio/lc3.h>
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/conn.h>
22 #include <zephyr/bluetooth/gap.h>
23 #include <zephyr/bluetooth/hci_types.h>
24 #include <zephyr/bluetooth/iso.h>
25 #include <zephyr/kernel.h>
26 #include <zephyr/kernel/thread_stack.h>
27 #include <zephyr/logging/log.h>
28 #include <zephyr/logging/log_core.h>
29 #include <zephyr/net_buf.h>
30 #include <zephyr/sys/util.h>
31 #include <zephyr/sys/util_macro.h>
32 
33 #include "cap_acceptor.h"
34 
35 LOG_MODULE_REGISTER(cap_acceptor_unicast, LOG_LEVEL_INF);
36 
37 #define PREF_PHY           BT_GAP_LE_PHY_2M
38 #define MIN_PD             20000U
39 #define MAX_PD             40000U
40 #define UNFRAMED_SUPPORTED true
41 #define LATENCY            20U
42 #define RTN                2U
43 
44 static const struct bt_bap_qos_cfg_pref qos_pref = BT_BAP_QOS_CFG_PREF(
45 	UNFRAMED_SUPPORTED, PREF_PHY, RTN, LATENCY, MIN_PD, MAX_PD, MIN_PD, MAX_PD);
46 uint64_t total_unicast_rx_iso_packet_count; /* This value is exposed to test code */
47 uint64_t total_unicast_tx_iso_packet_count; /* This value is exposed to test code */
48 
log_codec_cfg_cb(struct bt_data * data,void * user_data)49 static bool log_codec_cfg_cb(struct bt_data *data, void *user_data)
50 {
51 	const char *str = (const char *)user_data;
52 
53 	LOG_DBG("\t%s: type 0x%02x value_len %u", str, data->type, data->data_len);
54 	LOG_HEXDUMP_DBG(data->data, data->data_len, "\t\tdata");
55 
56 	return true;
57 }
58 
log_codec_cfg(const struct bt_audio_codec_cfg * codec_cfg)59 static void log_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg)
60 {
61 	LOG_INF("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u", codec_cfg->id, codec_cfg->cid,
62 		codec_cfg->vid, codec_cfg->data_len);
63 
64 	if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
65 		enum bt_audio_location chan_allocation;
66 		int ret;
67 
68 		/* LC3 uses the generic LTV format - other codecs might do as well */
69 
70 		bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, log_codec_cfg_cb, "data");
71 
72 		ret = bt_audio_codec_cfg_get_freq(codec_cfg);
73 		if (ret > 0) {
74 			LOG_INF("\tFrequency: %d Hz", bt_audio_codec_cfg_freq_to_freq_hz(ret));
75 		}
76 
77 		ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg);
78 		if (ret > 0) {
79 			LOG_INF("\tFrame Duration: %d us",
80 				bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret));
81 		}
82 
83 		if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, true) ==
84 		    0) {
85 			LOG_INF("\tChannel allocation: 0x%08X", chan_allocation);
86 		}
87 
88 		ret = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg);
89 		if (ret > 0) {
90 			LOG_INF("\tOctets per frame: %d", ret);
91 		}
92 
93 		LOG_INF("\tFrames per SDU: %d",
94 			bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true));
95 	} else {
96 		LOG_HEXDUMP_DBG(codec_cfg->data, codec_cfg->data_len, "data");
97 	}
98 
99 	bt_audio_data_parse(codec_cfg->meta, codec_cfg->meta_len, log_codec_cfg_cb, "meta");
100 }
101 
log_qos(const struct bt_bap_qos_cfg * qos)102 static void log_qos(const struct bt_bap_qos_cfg *qos)
103 {
104 	LOG_INF("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u rtn %u latency %u pd %u",
105 		qos->interval, qos->framing, qos->phy, qos->sdu, qos->rtn, qos->latency, qos->pd);
106 }
107 
unicast_server_config_cb(struct bt_conn * conn,const struct bt_bap_ep * ep,enum bt_audio_dir dir,const struct bt_audio_codec_cfg * codec_cfg,struct bt_bap_stream ** bap_stream,struct bt_bap_qos_cfg_pref * const pref,struct bt_bap_ascs_rsp * rsp)108 static int unicast_server_config_cb(struct bt_conn *conn, const struct bt_bap_ep *ep,
109 				    enum bt_audio_dir dir,
110 				    const struct bt_audio_codec_cfg *codec_cfg,
111 				    struct bt_bap_stream **bap_stream,
112 				    struct bt_bap_qos_cfg_pref *const pref,
113 				    struct bt_bap_ascs_rsp *rsp)
114 {
115 	struct bt_cap_stream *cap_stream;
116 
117 	LOG_INF("ASE Codec Config: conn %p ep %p dir %u", (void *)conn, (void *)ep, dir);
118 
119 	log_codec_cfg(codec_cfg);
120 
121 	cap_stream = stream_alloc(dir);
122 	if (cap_stream == NULL) {
123 		LOG_WRN("No streams available");
124 		*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM, BT_BAP_ASCS_REASON_NONE);
125 
126 		return -ENOMEM;
127 	}
128 
129 	*bap_stream = &cap_stream->bap_stream;
130 
131 	LOG_INF("ASE Codec Config bap_stream %p", *bap_stream);
132 
133 	*pref = qos_pref;
134 
135 	return 0;
136 }
137 
unicast_server_reconfig_cb(struct bt_bap_stream * bap_stream,enum bt_audio_dir dir,const struct bt_audio_codec_cfg * codec_cfg,struct bt_bap_qos_cfg_pref * const pref,struct bt_bap_ascs_rsp * rsp)138 static int unicast_server_reconfig_cb(struct bt_bap_stream *bap_stream, enum bt_audio_dir dir,
139 				      const struct bt_audio_codec_cfg *codec_cfg,
140 				      struct bt_bap_qos_cfg_pref *const pref,
141 				      struct bt_bap_ascs_rsp *rsp)
142 {
143 	LOG_INF("ASE Codec Reconfig: bap_stream %p", bap_stream);
144 	log_codec_cfg(codec_cfg);
145 	*pref = qos_pref;
146 
147 	return 0;
148 }
149 
unicast_server_qos_cb(struct bt_bap_stream * bap_stream,const struct bt_bap_qos_cfg * qos,struct bt_bap_ascs_rsp * rsp)150 static int unicast_server_qos_cb(struct bt_bap_stream *bap_stream, const struct bt_bap_qos_cfg *qos,
151 				 struct bt_bap_ascs_rsp *rsp)
152 {
153 	LOG_INF("QoS: bap_stream %p qos %p", bap_stream, qos);
154 
155 	log_qos(qos);
156 
157 	return 0;
158 }
159 
unicast_server_enable_cb(struct bt_bap_stream * bap_stream,const uint8_t meta[],size_t meta_len,struct bt_bap_ascs_rsp * rsp)160 static int unicast_server_enable_cb(struct bt_bap_stream *bap_stream, const uint8_t meta[],
161 				    size_t meta_len, struct bt_bap_ascs_rsp *rsp)
162 {
163 	LOG_INF("Enable: bap_stream %p meta_len %zu", bap_stream, meta_len);
164 
165 	return 0;
166 }
167 
unicast_server_start_cb(struct bt_bap_stream * bap_stream,struct bt_bap_ascs_rsp * rsp)168 static int unicast_server_start_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp)
169 {
170 	LOG_INF("Start: bap_stream %p", bap_stream);
171 
172 	return 0;
173 }
174 
175 struct data_func_param {
176 	struct bt_bap_ascs_rsp *rsp;
177 	bool stream_context_present;
178 };
179 
data_func_cb(struct bt_data * data,void * user_data)180 static bool data_func_cb(struct bt_data *data, void *user_data)
181 {
182 	struct data_func_param *func_param = (struct data_func_param *)user_data;
183 
184 	if (data->type == BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT) {
185 		func_param->stream_context_present = true;
186 	}
187 
188 	return true;
189 }
190 
unicast_server_metadata_cb(struct bt_bap_stream * bap_stream,const uint8_t meta[],size_t meta_len,struct bt_bap_ascs_rsp * rsp)191 static int unicast_server_metadata_cb(struct bt_bap_stream *bap_stream, const uint8_t meta[],
192 				      size_t meta_len, struct bt_bap_ascs_rsp *rsp)
193 {
194 	struct data_func_param func_param = {
195 		.rsp = rsp,
196 		.stream_context_present = false,
197 	};
198 	int err;
199 
200 	LOG_INF("Metadata: bap_stream %p meta_len %zu", bap_stream, meta_len);
201 
202 	err = bt_audio_data_parse(meta, meta_len, data_func_cb, &func_param);
203 	if (err != 0) {
204 		return err;
205 	}
206 
207 	if (!func_param.stream_context_present) {
208 		LOG_ERR("Stream audio context not present");
209 		*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED,
210 				       BT_BAP_ASCS_REASON_NONE);
211 
212 		return -EINVAL;
213 	}
214 
215 	return 0;
216 }
217 
unicast_server_disable_cb(struct bt_bap_stream * bap_stream,struct bt_bap_ascs_rsp * rsp)218 static int unicast_server_disable_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp)
219 {
220 	LOG_INF("Disable: bap_stream %p", bap_stream);
221 
222 	return 0;
223 }
224 
unicast_server_stop_cb(struct bt_bap_stream * bap_stream,struct bt_bap_ascs_rsp * rsp)225 static int unicast_server_stop_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp)
226 {
227 	LOG_INF("Stop: bap_stream %p", bap_stream);
228 
229 	return 0;
230 }
231 
unicast_server_release_cb(struct bt_bap_stream * bap_stream,struct bt_bap_ascs_rsp * rsp)232 static int unicast_server_release_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp)
233 {
234 	LOG_INF("Release: bap_stream %p", bap_stream);
235 
236 	return 0;
237 }
238 
239 static const struct bt_bap_unicast_server_cb unicast_server_cb = {
240 	.config = unicast_server_config_cb,
241 	.reconfig = unicast_server_reconfig_cb,
242 	.qos = unicast_server_qos_cb,
243 	.enable = unicast_server_enable_cb,
244 	.start = unicast_server_start_cb,
245 	.metadata = unicast_server_metadata_cb,
246 	.disable = unicast_server_disable_cb,
247 	.stop = unicast_server_stop_cb,
248 	.release = unicast_server_release_cb,
249 };
250 
unicast_stream_configured_cb(struct bt_bap_stream * bap_stream,const struct bt_bap_qos_cfg_pref * pref)251 static void unicast_stream_configured_cb(struct bt_bap_stream *bap_stream,
252 					 const struct bt_bap_qos_cfg_pref *pref)
253 {
254 	LOG_INF("Configured bap_stream %p", bap_stream);
255 
256 	/* TODO: The preference should be used/taken into account when
257 	 * setting the QoS
258 	 */
259 
260 	LOG_INF("Local preferences: unframed %s, phy %u, rtn %u, latency %u, pd_min %u, pd_max "
261 		"%u, pref_pd_min %u, pref_pd_max %u",
262 		pref->unframed_supported ? "supported" : "not supported", pref->phy, pref->rtn,
263 		pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max);
264 }
265 
unicast_stream_qos_set_cb(struct bt_bap_stream * bap_stream)266 static void unicast_stream_qos_set_cb(struct bt_bap_stream *bap_stream)
267 {
268 	LOG_INF("QoS set bap_stream %p", bap_stream);
269 }
270 
unicast_stream_enabled_cb(struct bt_bap_stream * bap_stream)271 static void unicast_stream_enabled_cb(struct bt_bap_stream *bap_stream)
272 {
273 	struct bt_bap_ep_info ep_info;
274 	int err;
275 
276 	LOG_INF("Enabled bap_stream %p", bap_stream);
277 
278 	err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
279 	if (err != 0) {
280 		LOG_ERR("Failed to get ep info: %d", err);
281 
282 		return;
283 	}
284 
285 	if (ep_info.dir == BT_AUDIO_DIR_SINK) {
286 		/* Automatically do the receiver start ready operation */
287 		err = bt_bap_stream_start(bap_stream);
288 		if (err != 0) {
289 			LOG_ERR("Failed to start: %d", err);
290 
291 			return;
292 		}
293 	}
294 }
295 
unicast_stream_started_cb(struct bt_bap_stream * bap_stream)296 static void unicast_stream_started_cb(struct bt_bap_stream *bap_stream)
297 {
298 	LOG_INF("Started bap_stream %p", bap_stream);
299 	total_unicast_rx_iso_packet_count = 0U;
300 }
301 
unicast_stream_metadata_updated_cb(struct bt_bap_stream * bap_stream)302 static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream)
303 {
304 	LOG_INF("Metadata updated bap_stream %p", bap_stream);
305 }
306 
unicast_stream_disabled_cb(struct bt_bap_stream * bap_stream)307 static void unicast_stream_disabled_cb(struct bt_bap_stream *bap_stream)
308 {
309 	LOG_INF("Disabled bap_stream %p", bap_stream);
310 }
311 
unicast_stream_stopped_cb(struct bt_bap_stream * bap_stream,uint8_t reason)312 static void unicast_stream_stopped_cb(struct bt_bap_stream *bap_stream, uint8_t reason)
313 {
314 	LOG_INF("Stopped bap_stream %p with reason 0x%02X", bap_stream, reason);
315 }
316 
unicast_stream_released_cb(struct bt_bap_stream * bap_stream)317 static void unicast_stream_released_cb(struct bt_bap_stream *bap_stream)
318 {
319 	struct bt_cap_stream *cap_stream =
320 		CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream);
321 
322 	LOG_INF("Released bap_stream %p", bap_stream);
323 
324 	stream_released(cap_stream);
325 }
326 
unicast_stream_recv_cb(struct bt_bap_stream * bap_stream,const struct bt_iso_recv_info * info,struct net_buf * buf)327 static void unicast_stream_recv_cb(struct bt_bap_stream *bap_stream,
328 				   const struct bt_iso_recv_info *info, struct net_buf *buf)
329 {
330 	/* Triggered every time we receive an HCI data packet from the controller.
331 	 * A call to this does not indicate valid data
332 	 * (see the `info->flags` for which flags to check),
333 	 */
334 
335 	if ((total_unicast_rx_iso_packet_count % 100U) == 0U) {
336 		LOG_INF("Received %llu HCI ISO data packets", total_unicast_rx_iso_packet_count);
337 	}
338 
339 	total_unicast_rx_iso_packet_count++;
340 }
341 
unicast_stream_sent_cb(struct bt_bap_stream * stream)342 static void unicast_stream_sent_cb(struct bt_bap_stream *stream)
343 {
344 	/* Triggered every time we have sent an HCI data packet to the controller */
345 
346 	if ((total_unicast_tx_iso_packet_count % 100U) == 0U) {
347 		LOG_INF("Sent %llu HCI ISO data packets", total_unicast_tx_iso_packet_count);
348 	}
349 
350 	total_unicast_tx_iso_packet_count++;
351 }
352 
tx_thread_func(void * arg1,void * arg2,void * arg3)353 static void tx_thread_func(void *arg1, void *arg2, void *arg3)
354 {
355 	NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT,
356 				  BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
357 				  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
358 	static uint8_t data[CONFIG_BT_ISO_TX_MTU];
359 	struct peer_config *peer = arg1;
360 	struct bt_cap_stream *cap_stream = &peer->source_stream;
361 	struct bt_bap_stream *bap_stream = &cap_stream->bap_stream;
362 
363 	for (size_t i = 0U; i < ARRAY_SIZE(data); i++) {
364 		data[i] = (uint8_t)i;
365 	}
366 
367 	while (true) {
368 		/* No-op if stream is not configured */
369 		if (bap_stream->ep != NULL) {
370 			struct bt_bap_ep_info ep_info;
371 			int err;
372 
373 			err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
374 			if (err == 0) {
375 				if (ep_info.state == BT_BAP_EP_STATE_STREAMING) {
376 					struct net_buf *buf;
377 
378 					buf = net_buf_alloc(&tx_pool, K_FOREVER);
379 					net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
380 
381 					net_buf_add_mem(buf, data, bap_stream->qos->sdu);
382 
383 					err = bt_cap_stream_send(cap_stream, buf, peer->tx_seq_num);
384 					if (err == 0) {
385 						peer->tx_seq_num++;
386 						continue; /* Attempt to send again ASAP */
387 					} else {
388 						LOG_ERR("Unable to send: %d", err);
389 						net_buf_unref(buf);
390 					}
391 				}
392 			}
393 		}
394 
395 		/* In case of any errors, retry with a delay */
396 		k_sleep(K_MSEC(100));
397 	}
398 }
399 
init_cap_acceptor_unicast(struct peer_config * peer)400 int init_cap_acceptor_unicast(struct peer_config *peer)
401 {
402 	static struct bt_bap_stream_ops unicast_stream_ops = {
403 		.configured = unicast_stream_configured_cb,
404 		.qos_set = unicast_stream_qos_set_cb,
405 		.enabled = unicast_stream_enabled_cb,
406 		.started = unicast_stream_started_cb,
407 		.metadata_updated = unicast_stream_metadata_updated_cb,
408 		.disabled = unicast_stream_disabled_cb,
409 		.stopped = unicast_stream_stopped_cb,
410 		.released = unicast_stream_released_cb,
411 		.recv = unicast_stream_recv_cb,
412 		.sent = unicast_stream_sent_cb,
413 	};
414 	static bool cbs_registered;
415 
416 	if (!cbs_registered) {
417 		int err;
418 		struct bt_bap_unicast_server_register_param param = {
419 			CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT,
420 			CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT
421 		};
422 
423 		err = bt_bap_unicast_server_register(&param);
424 		if (err != 0) {
425 			LOG_ERR("Failed to register BAP unicast server: %d", err);
426 
427 			return -ENOEXEC;
428 		}
429 
430 		err = bt_bap_unicast_server_register_cb(&unicast_server_cb);
431 		if (err != 0) {
432 			LOG_ERR("Failed to register BAP unicast server callbacks: %d", err);
433 
434 			return -ENOEXEC;
435 		}
436 
437 		cbs_registered = true;
438 	}
439 
440 	bt_cap_stream_ops_register(&peer->source_stream, &unicast_stream_ops);
441 	bt_cap_stream_ops_register(&peer->sink_stream, &unicast_stream_ops);
442 
443 	if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SRC)) {
444 		static bool thread_started;
445 
446 		if (!thread_started) {
447 			static K_KERNEL_STACK_DEFINE(tx_thread_stack, 1024);
448 			const int tx_thread_prio = K_PRIO_PREEMPT(5);
449 			static struct k_thread tx_thread;
450 
451 			k_thread_create(&tx_thread, tx_thread_stack,
452 					K_KERNEL_STACK_SIZEOF(tx_thread_stack), tx_thread_func,
453 					peer, NULL, NULL, tx_thread_prio, 0, K_NO_WAIT);
454 			k_thread_name_set(&tx_thread, "TX thread");
455 			thread_started = true;
456 		}
457 	}
458 
459 	return 0;
460 }
461