1 /*
2  * Copyright (c) 2022-2024 Nordic Semiconductor ASA
3  * Copyright 2023 NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <zephyr/autoconf.h>
12 #include <zephyr/bluetooth/audio/audio.h>
13 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
14 #include <zephyr/bluetooth/audio/cap.h>
15 #include <zephyr/bluetooth/audio/bap.h>
16 #include <zephyr/bluetooth/audio/csip.h>
17 #include <zephyr/bluetooth/bluetooth.h>
18 #include <zephyr/bluetooth/conn.h>
19 #include <zephyr/bluetooth/hci_types.h>
20 #include <zephyr/bluetooth/iso.h>
21 #include <zephyr/kernel.h>
22 #include <zephyr/net_buf.h>
23 #include <zephyr/sys/printk.h>
24 #include <zephyr/sys/util.h>
25 #include <zephyr/sys/util_macro.h>
26 #include <zephyr/types.h>
27 
28 #if defined(CONFIG_BT_CAP_INITIATOR)
29 
30 static struct k_work_delayable audio_send_work;
31 
32 static struct bt_cap_stream unicast_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT +
33 					    CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
34 static struct bt_bap_ep *unicast_sink_eps[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
35 static struct bt_bap_ep *unicast_source_eps[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
36 
37 NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT,
38 			  CONFIG_BT_ISO_TX_MTU + BT_ISO_CHAN_SEND_RESERVE, 8, NULL);
39 
40 static K_SEM_DEFINE(sem_cas_discovery, 0, 1);
41 static K_SEM_DEFINE(sem_discover_sink, 0, 1);
42 static K_SEM_DEFINE(sem_discover_source, 0, 1);
43 static K_SEM_DEFINE(sem_audio_start, 0, 1);
44 
unicast_stream_configured(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg_pref * pref)45 static void unicast_stream_configured(struct bt_bap_stream *stream,
46 				      const struct bt_bap_qos_cfg_pref *pref)
47 {
48 	printk("Configured stream %p\n", stream);
49 
50 	/* TODO: The preference should be used/taken into account when
51 	 * setting the QoS
52 	 */
53 }
54 
unicast_stream_qos_set(struct bt_bap_stream * stream)55 static void unicast_stream_qos_set(struct bt_bap_stream *stream)
56 {
57 	printk("QoS set stream %p\n", stream);
58 }
59 
unicast_stream_enabled(struct bt_bap_stream * stream)60 static void unicast_stream_enabled(struct bt_bap_stream *stream)
61 {
62 	printk("Enabled stream %p\n", stream);
63 }
64 
unicast_stream_started(struct bt_bap_stream * stream)65 static void unicast_stream_started(struct bt_bap_stream *stream)
66 {
67 	printk("Started stream %p\n", stream);
68 
69 	k_sem_give(&sem_audio_start);
70 }
71 
unicast_stream_metadata_updated(struct bt_bap_stream * stream)72 static void unicast_stream_metadata_updated(struct bt_bap_stream *stream)
73 {
74 	printk("Metadata updated stream %p\n", stream);
75 }
76 
unicast_stream_disabled(struct bt_bap_stream * stream)77 static void unicast_stream_disabled(struct bt_bap_stream *stream)
78 {
79 	printk("Disabled stream %p\n", stream);
80 }
81 
unicast_stream_stopped(struct bt_bap_stream * stream,uint8_t reason)82 static void unicast_stream_stopped(struct bt_bap_stream *stream, uint8_t reason)
83 {
84 	printk("Stopped stream %p with reason 0x%02X\n", stream, reason);
85 
86 	/* Stop send timer */
87 	k_work_cancel_delayable(&audio_send_work);
88 }
89 
unicast_stream_released(struct bt_bap_stream * stream)90 static void unicast_stream_released(struct bt_bap_stream *stream)
91 {
92 	printk("Released stream %p\n", stream);
93 }
94 
95 static struct bt_bap_stream_ops unicast_stream_ops = {
96 	.configured = unicast_stream_configured,
97 	.qos_set = unicast_stream_qos_set,
98 	.enabled = unicast_stream_enabled,
99 	.started = unicast_stream_started,
100 	.metadata_updated = unicast_stream_metadata_updated,
101 	.disabled = unicast_stream_disabled,
102 	.stopped = unicast_stream_stopped,
103 	.released = unicast_stream_released,
104 };
105 
106 static struct bt_bap_lc3_preset unicast_preset_48_2_1 =
107 	BT_BAP_LC3_UNICAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT,
108 					 BT_AUDIO_CONTEXT_TYPE_MEDIA);
109 
cap_discovery_complete_cb(struct bt_conn * conn,int err,const struct bt_csip_set_coordinator_set_member * member,const struct bt_csip_set_coordinator_csis_inst * csis_inst)110 static void cap_discovery_complete_cb(struct bt_conn *conn, int err,
111 				      const struct bt_csip_set_coordinator_set_member *member,
112 				      const struct bt_csip_set_coordinator_csis_inst *csis_inst)
113 {
114 	if (err != 0) {
115 		printk("Failed to discover CAS: %d", err);
116 		return;
117 	}
118 
119 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER)) {
120 		if (csis_inst == NULL) {
121 			printk("Failed to discover CAS CSIS");
122 			return;
123 		}
124 
125 		printk("Found CAS with CSIS %p\n", csis_inst);
126 	} else {
127 		printk("Found CAS\n");
128 	}
129 
130 	k_sem_give(&sem_cas_discovery);
131 }
132 
unicast_start_complete_cb(int err,struct bt_conn * conn)133 static void unicast_start_complete_cb(int err, struct bt_conn *conn)
134 {
135 	if (err != 0) {
136 		printk("Failed to start (failing conn %p): %d", conn, err);
137 		return;
138 	}
139 
140 	k_sem_give(&sem_audio_start);
141 }
142 
unicast_update_complete_cb(int err,struct bt_conn * conn)143 static void unicast_update_complete_cb(int err, struct bt_conn *conn)
144 {
145 	if (err != 0) {
146 		printk("Failed to update (failing conn %p): %d", conn, err);
147 		return;
148 	}
149 }
150 
unicast_stop_complete_cb(int err,struct bt_conn * conn)151 static void unicast_stop_complete_cb(int err, struct bt_conn *conn)
152 {
153 	if (err != 0) {
154 		printk("Failed to stop (failing conn %p): %d", conn, err);
155 		return;
156 	}
157 }
158 
159 static struct bt_cap_initiator_cb cap_cb = {
160 	.unicast_discovery_complete = cap_discovery_complete_cb,
161 	.unicast_start_complete = unicast_start_complete_cb,
162 	.unicast_update_complete = unicast_update_complete_cb,
163 	.unicast_stop_complete = unicast_stop_complete_cb,
164 };
165 
discover_cas(struct bt_conn * conn)166 static int discover_cas(struct bt_conn *conn)
167 {
168 	int err;
169 
170 	err = bt_cap_initiator_unicast_discover(conn);
171 	if (err != 0) {
172 		printk("Failed to discover CAS: %d\n", err);
173 		return err;
174 	}
175 
176 	err = k_sem_take(&sem_cas_discovery, K_FOREVER);
177 	if (err != 0) {
178 		printk("failed to take sem_cas_discovery (err %d)\n", err);
179 		return err;
180 	}
181 
182 	return err;
183 }
184 
print_hex(const uint8_t * ptr,size_t len)185 static void print_hex(const uint8_t *ptr, size_t len)
186 {
187 	while (len-- != 0) {
188 		printk("%02x", *ptr++);
189 	}
190 }
191 
print_cb(struct bt_data * data,void * user_data)192 static bool print_cb(struct bt_data *data, void *user_data)
193 {
194 	const char *str = (const char *)user_data;
195 
196 	printk("%s: type 0x%02x value_len %u\n", str, data->type, data->data_len);
197 	print_hex(data->data, data->data_len);
198 	printk("\n");
199 
200 	return true;
201 }
202 
print_remote_codec(const struct bt_audio_codec_cap * codec_cap,enum bt_audio_dir dir)203 static void print_remote_codec(const struct bt_audio_codec_cap *codec_cap, enum bt_audio_dir dir)
204 {
205 	printk("codec id 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid,
206 	       codec_cap->vid, codec_cap->data_len);
207 
208 	if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) {
209 		bt_audio_data_parse(codec_cap->data, codec_cap->data_len, print_cb, "data");
210 	} else { /* If not LC3, we cannot assume it's LTV */
211 		printk("data: ");
212 		print_hex(codec_cap->data, codec_cap->data_len);
213 		printk("\n");
214 	}
215 
216 	bt_audio_data_parse(codec_cap->meta, codec_cap->meta_len, print_cb, "meta");
217 }
218 
add_remote_sink(struct bt_bap_ep * ep)219 static void add_remote_sink(struct bt_bap_ep *ep)
220 {
221 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_sink_eps); i++) {
222 		if (unicast_sink_eps[i] == NULL) {
223 			printk("Sink #%zu: ep %p\n", i, ep);
224 			unicast_sink_eps[i] = ep;
225 			return;
226 		}
227 	}
228 }
229 
add_remote_source(struct bt_bap_ep * ep)230 static void add_remote_source(struct bt_bap_ep *ep)
231 {
232 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_source_eps); i++) {
233 		if (unicast_source_eps[i] == NULL) {
234 			printk("Source #%zu: ep %p\n", i, ep);
235 			unicast_source_eps[i] = ep;
236 			return;
237 		}
238 	}
239 }
240 
discover_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)241 static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
242 {
243 	if (err != 0) {
244 		printk("Discovery failed: %d\n", err);
245 		return;
246 	}
247 
248 	if (dir == BT_AUDIO_DIR_SINK) {
249 		printk("Sink discover complete\n");
250 		k_sem_give(&sem_discover_sink);
251 	} else if (dir == BT_AUDIO_DIR_SOURCE) {
252 		printk("Discover sources complete: err %d\n", err);
253 		k_sem_give(&sem_discover_source);
254 	}
255 }
256 
pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_audio_codec_cap * codec_cap)257 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir,
258 			  const struct bt_audio_codec_cap *codec_cap)
259 {
260 	print_remote_codec(codec_cap, dir);
261 }
262 
endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)263 static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
264 {
265 	if (dir == BT_AUDIO_DIR_SOURCE) {
266 		add_remote_source(ep);
267 	} else if (dir == BT_AUDIO_DIR_SINK) {
268 		add_remote_sink(ep);
269 	}
270 }
271 
discover_sinks(struct bt_conn * conn)272 static int discover_sinks(struct bt_conn *conn)
273 {
274 	int err;
275 
276 	err = bt_bap_unicast_client_discover(conn, BT_AUDIO_DIR_SINK);
277 	if (err != 0) {
278 		printk("Failed to discover sink: %d\n", err);
279 		return err;
280 	}
281 
282 	err = k_sem_take(&sem_discover_sink, K_FOREVER);
283 	if (err != 0) {
284 		printk("failed to take sem_discover_sink (err %d)\n", err);
285 		return err;
286 	}
287 
288 	return err;
289 }
290 
discover_sources(struct bt_conn * conn)291 static int discover_sources(struct bt_conn *conn)
292 {
293 	int err;
294 
295 	err = bt_bap_unicast_client_discover(conn, BT_AUDIO_DIR_SOURCE);
296 	if (err != 0) {
297 		printk("Failed to discover sources: %d\n", err);
298 		return err;
299 	}
300 
301 	err = k_sem_take(&sem_discover_source, K_FOREVER);
302 	if (err != 0) {
303 		printk("failed to take sem_discover_source (err %d)\n", err);
304 		return err;
305 	}
306 
307 	return 0;
308 }
309 
310 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
311 	.discover = discover_cb,
312 	.pac_record = pac_record_cb,
313 	.endpoint = endpoint_cb,
314 };
315 
unicast_group_create(struct bt_bap_unicast_group ** out_unicast_group)316 static int unicast_group_create(struct bt_bap_unicast_group **out_unicast_group)
317 {
318 	int err = 0;
319 	struct bt_bap_unicast_group_stream_param group_stream_params;
320 	struct bt_bap_unicast_group_stream_pair_param pair_params;
321 	struct bt_bap_unicast_group_param group_param;
322 
323 	group_stream_params.qos = &unicast_preset_48_2_1.qos;
324 	group_stream_params.stream = &unicast_streams[0].bap_stream;
325 	pair_params.tx_param = &group_stream_params;
326 	pair_params.rx_param = NULL;
327 
328 	group_param.packing = BT_ISO_PACKING_SEQUENTIAL;
329 	group_param.params_count = 1;
330 	group_param.params = &pair_params;
331 
332 	err = bt_bap_unicast_group_create(&group_param, out_unicast_group);
333 	if (err != 0) {
334 		printk("Failed to create group: %d\n", err);
335 		return err;
336 	}
337 	printk("Created group\n");
338 
339 	return err;
340 }
341 
unicast_audio_start(struct bt_conn * conn)342 static int unicast_audio_start(struct bt_conn *conn)
343 {
344 	int err = 0;
345 	struct bt_cap_unicast_audio_start_stream_param stream_param;
346 	struct bt_cap_unicast_audio_start_param param;
347 
348 	param.type = BT_CAP_SET_TYPE_AD_HOC;
349 	param.count = 1u;
350 	param.stream_params = &stream_param;
351 
352 	stream_param.member.member = conn;
353 	stream_param.stream = &unicast_streams[0];
354 	stream_param.ep = unicast_sink_eps[0];
355 	stream_param.codec_cfg = &unicast_preset_48_2_1.codec_cfg;
356 
357 	err = bt_cap_initiator_unicast_audio_start(&param);
358 	if (err != 0) {
359 		printk("Failed to start unicast audio: %d\n", err);
360 		return err;
361 	}
362 
363 	return err;
364 }
365 
366 /**
367  * @brief Send audio data on timeout
368  *
369  * This will send an amount of data equal to the configured QoS SDU.
370  * The data is just mock data, and does not actually represent any audio.
371 
372  *
373  * @param work Pointer to the work structure
374  */
audio_timer_timeout(struct k_work * work)375 static void audio_timer_timeout(struct k_work *work)
376 {
377 	static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU];
378 	static bool data_initialized;
379 	struct net_buf *buf;
380 	struct net_buf *buf_to_send;
381 	int ret;
382 	static size_t len_to_send;
383 	struct bt_bap_stream *stream = &unicast_streams[0].bap_stream;
384 
385 	len_to_send = unicast_preset_48_2_1.qos.sdu;
386 
387 	if (!data_initialized) {
388 		/* TODO: Actually encode some audio data */
389 		for (size_t i = 0; i < ARRAY_SIZE(buf_data); i++) {
390 			buf_data[i] = (uint8_t)i;
391 		}
392 
393 		data_initialized = true;
394 	}
395 
396 	buf = net_buf_alloc(&tx_pool, K_NO_WAIT);
397 	if (buf != NULL) {
398 		net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
399 		net_buf_add_mem(buf, buf_data, len_to_send);
400 		buf_to_send = buf;
401 
402 		ret = bt_bap_stream_send(stream, buf_to_send, 0);
403 		if (ret < 0) {
404 			printk("Failed to send audio data on streams: (%d)\n", ret);
405 			net_buf_unref(buf_to_send);
406 		} else {
407 			printk("Sending mock data with len %zu\n", len_to_send);
408 		}
409 	} else {
410 		printk("Failed to allocate TX buffer\n");
411 		/* Retry later */
412 	}
413 
414 	k_work_schedule(&audio_send_work, K_MSEC(1000));
415 }
416 
cap_initiator_init(void)417 int cap_initiator_init(void)
418 {
419 	int err = 0;
420 
421 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT)) {
422 		err = bt_cap_initiator_register_cb(&cap_cb);
423 		if (err != 0) {
424 			printk("Failed to register CAP callbacks (err %d)\n", err);
425 			return err;
426 		}
427 
428 		err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
429 		if (err != 0) {
430 			printk("Failed to register BAP unicast client callbacks (err %d)\n", err);
431 			return err;
432 		}
433 
434 		for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) {
435 			bt_cap_stream_ops_register(&unicast_streams[i],
436 						   &unicast_stream_ops);
437 		}
438 		k_work_init_delayable(&audio_send_work, audio_timer_timeout);
439 	}
440 
441 	return 0;
442 }
443 
cap_initiator_setup(struct bt_conn * conn)444 int cap_initiator_setup(struct bt_conn *conn)
445 {
446 	int err = 0;
447 	struct bt_bap_unicast_group *unicast_group;
448 
449 	k_sem_reset(&sem_cas_discovery);
450 	k_sem_reset(&sem_discover_sink);
451 	k_sem_reset(&sem_discover_source);
452 	k_sem_reset(&sem_audio_start);
453 
454 	err = discover_cas(conn);
455 	if (err != 0) {
456 		return err;
457 	}
458 
459 	err = discover_sinks(conn);
460 	if (err != 0) {
461 		return err;
462 	}
463 
464 	err = discover_sources(conn);
465 	if (err != 0) {
466 		return err;
467 	}
468 
469 	err = unicast_group_create(&unicast_group);
470 	if (err != 0) {
471 		return err;
472 	}
473 
474 	err = unicast_audio_start(conn);
475 	if (err != 0) {
476 		return err;
477 	}
478 
479 	k_sem_take(&sem_audio_start, K_FOREVER);
480 
481 	k_work_schedule(&audio_send_work, K_MSEC(0));
482 
483 	return err;
484 }
485 
486 #endif /* CONFIG_BT_CAP_INITIATOR */
487