1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <autoconf.h>
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 
12 #include <zephyr/bluetooth/addr.h>
13 #include <zephyr/bluetooth/att.h>
14 #include <zephyr/bluetooth/audio/audio.h>
15 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
16 #include <zephyr/bluetooth/audio/cap.h>
17 #include <zephyr/bluetooth/audio/bap.h>
18 #include <zephyr/bluetooth/audio/csip.h>
19 #include <zephyr/bluetooth/bluetooth.h>
20 #include <zephyr/bluetooth/conn.h>
21 #include <zephyr/bluetooth/gap.h>
22 #include <zephyr/bluetooth/gatt.h>
23 #include <zephyr/bluetooth/hci.h>
24 #include <zephyr/bluetooth/hci_types.h>
25 #include <zephyr/bluetooth/iso.h>
26 #include <zephyr/bluetooth/uuid.h>
27 #include <zephyr/kernel.h>
28 #include <zephyr/kernel/thread_stack.h>
29 #include <zephyr/logging/log.h>
30 #include <zephyr/logging/log_core.h>
31 #include <zephyr/net_buf.h>
32 #include <zephyr/sys/byteorder.h>
33 #include <zephyr/sys/util.h>
34 #include <zephyr/sys/util_macro.h>
35 
36 #include "cap_initiator.h"
37 
38 LOG_MODULE_REGISTER(cap_initiator_unicast, LOG_LEVEL_INF);
39 
40 #define SEM_TIMEOUT K_SECONDS(5)
41 
42 /* We use the same config for both sink and source streams
43  * For simplicity we use the mandatory configuration 16_2_1
44  */
45 static struct bt_bap_lc3_preset unicast_preset_16_2_1 = BT_BAP_LC3_UNICAST_PRESET_16_2_1(
46 	BT_AUDIO_LOCATION_MONO_AUDIO, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
47 static struct bt_bap_unicast_group *unicast_group;
48 uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */
49 uint64_t total_unicast_tx_iso_packet_count; /* This value is exposed to test code */
50 
51 /** Struct to contain information for a specific peer (CAP) device */
52 struct peer_config {
53 	/** Stream for the source endpoint */
54 	struct bt_cap_stream source_stream;
55 	/** Stream for the sink endpoint */
56 	struct bt_cap_stream sink_stream;
57 	/** Semaphore to help wait for a release operation if the source stream is not idle */
58 	struct k_sem source_stream_sem;
59 	/** Semaphore to help wait for a release operation if the sink stream is not idle */
60 	struct k_sem sink_stream_sem;
61 	/** Reference to the endpoint for the source stream */
62 	struct bt_bap_ep *source_ep;
63 	/** Reference to the endpoint for the sink stream */
64 	struct bt_bap_ep *sink_ep;
65 	/** ACL connection object for the peer device */
66 	struct bt_conn *conn;
67 	/** Current sequence number for TX */
68 	uint16_t tx_seq_num;
69 };
70 
71 /* TODO: Expand to multiple ACL connections */
72 static struct peer_config peer;
73 
74 static K_SEM_DEFINE(sem_proc, 0, 1);
75 static K_SEM_DEFINE(sem_state_change, 0, 1);
76 static K_SEM_DEFINE(sem_mtu_exchanged, 0, 1);
77 static K_SEM_DEFINE(sem_security_changed, 0, 1);
78 
is_tx_stream(struct bt_bap_stream * stream)79 static bool is_tx_stream(struct bt_bap_stream *stream)
80 {
81 	struct bt_bap_ep_info ep_info;
82 	int err;
83 
84 	err = bt_bap_ep_get_info(stream->ep, &ep_info);
85 	if (err != 0) {
86 		LOG_ERR("Failed to get ep info: %d", err);
87 
88 		return false;
89 	}
90 
91 	return ep_info.dir == BT_AUDIO_DIR_SINK;
92 }
93 
unicast_stream_configured_cb(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg_pref * pref)94 static void unicast_stream_configured_cb(struct bt_bap_stream *stream,
95 					 const struct bt_bap_qos_cfg_pref *pref)
96 {
97 	LOG_INF("Configured stream %p", stream);
98 
99 	/* TODO: The preference should be used/taken into account when
100 	 * setting the QoS
101 	 */
102 
103 	LOG_INF("Remote preferences: unframed %s, phy %u, rtn %u, latency %u, pd_min %u, pd_max "
104 		"%u, pref_pd_min %u, pref_pd_max %u",
105 		pref->unframed_supported ? "supported" : "not supported", pref->phy, pref->rtn,
106 		pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max);
107 }
108 
unicast_stream_qos_set_cb(struct bt_bap_stream * stream)109 static void unicast_stream_qos_set_cb(struct bt_bap_stream *stream)
110 {
111 	LOG_INF("QoS set stream %p", stream);
112 }
113 
unicast_stream_enabled_cb(struct bt_bap_stream * stream)114 static void unicast_stream_enabled_cb(struct bt_bap_stream *stream)
115 {
116 	LOG_INF("Enabled stream %p", stream);
117 }
118 
unicast_stream_started_cb(struct bt_bap_stream * stream)119 static void unicast_stream_started_cb(struct bt_bap_stream *stream)
120 {
121 	LOG_INF("Started stream %p", stream);
122 	total_rx_iso_packet_count = 0U;
123 	total_unicast_tx_iso_packet_count = 0U;
124 
125 	if (is_tx_stream(stream)) {
126 		struct bt_cap_stream *cap_stream =
127 			CONTAINER_OF(stream, struct bt_cap_stream, bap_stream);
128 		int err;
129 
130 		err = cap_initiator_tx_register_stream(cap_stream);
131 		if (err != 0) {
132 			LOG_ERR("Failed to register %p for TX: %d", stream, err);
133 		}
134 	}
135 }
136 
unicast_stream_metadata_updated_cb(struct bt_bap_stream * stream)137 static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *stream)
138 {
139 	LOG_INF("Metadata updated stream %p", stream);
140 }
141 
unicast_stream_disabled_cb(struct bt_bap_stream * stream)142 static void unicast_stream_disabled_cb(struct bt_bap_stream *stream)
143 {
144 	LOG_INF("Disabled stream %p", stream);
145 }
146 
unicast_stream_stopped_cb(struct bt_bap_stream * stream,uint8_t reason)147 static void unicast_stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
148 {
149 	LOG_INF("Stopped stream %p with reason 0x%02X", stream, reason);
150 
151 	if (is_tx_stream(stream)) {
152 		struct bt_cap_stream *cap_stream =
153 			CONTAINER_OF(stream, struct bt_cap_stream, bap_stream);
154 		int err;
155 
156 		err = cap_initiator_tx_unregister_stream(cap_stream);
157 		if (err != 0) {
158 			LOG_ERR("Failed to unregister %p for TX: %d", stream, err);
159 		}
160 	}
161 }
162 
unicast_stream_released_cb(struct bt_bap_stream * stream)163 static void unicast_stream_released_cb(struct bt_bap_stream *stream)
164 {
165 	LOG_INF("Released stream %p", stream);
166 
167 	if (stream == &peer.source_stream.bap_stream) {
168 		k_sem_give(&peer.source_stream_sem);
169 	} else if (stream == &peer.sink_stream.bap_stream) {
170 		k_sem_give(&peer.sink_stream_sem);
171 	}
172 }
173 
unicast_stream_recv_cb(struct bt_bap_stream * stream,const struct bt_iso_recv_info * info,struct net_buf * buf)174 static void unicast_stream_recv_cb(struct bt_bap_stream *stream,
175 				   const struct bt_iso_recv_info *info, struct net_buf *buf)
176 {
177 	/* Triggered every time we receive an HCI data packet from the controller.
178 	 * A call to this does not indicate valid data
179 	 * (see the `info->flags` for which flags to check),
180 	 */
181 
182 	if ((total_rx_iso_packet_count % 100U) == 0U) {
183 		LOG_INF("Received %llu HCI ISO data packets", total_rx_iso_packet_count);
184 	}
185 
186 	total_rx_iso_packet_count++;
187 }
188 
unicast_stream_sent_cb(struct bt_bap_stream * stream)189 static void unicast_stream_sent_cb(struct bt_bap_stream *stream)
190 {
191 	/* Triggered every time we have sent an HCI data packet to the controller */
192 
193 	if ((total_unicast_tx_iso_packet_count % 100U) == 0U) {
194 		LOG_INF("Sent %llu HCI ISO data packets", total_unicast_tx_iso_packet_count);
195 	}
196 
197 	total_unicast_tx_iso_packet_count++;
198 }
199 
200 static struct bt_bap_stream_ops unicast_stream_ops = {
201 	.configured = unicast_stream_configured_cb,
202 	.qos_set = unicast_stream_qos_set_cb,
203 	.enabled = unicast_stream_enabled_cb,
204 	.started = unicast_stream_started_cb,
205 	.metadata_updated = unicast_stream_metadata_updated_cb,
206 	.disabled = unicast_stream_disabled_cb,
207 	.stopped = unicast_stream_stopped_cb,
208 	.released = unicast_stream_released_cb,
209 	.recv = unicast_stream_recv_cb,
210 	.sent = unicast_stream_sent_cb,
211 };
212 
log_codec_cb(struct bt_data * data,void * user_data)213 static bool log_codec_cb(struct bt_data *data, void *user_data)
214 {
215 	const char *str = (const char *)user_data;
216 
217 	LOG_DBG("\t%s: type 0x%02x value_len %u", str, data->type, data->data_len);
218 	LOG_HEXDUMP_DBG(data->data, data->data_len, "\t\tdata");
219 
220 	return true;
221 }
222 
log_codec(const struct bt_audio_codec_cap * codec_cap,enum bt_audio_dir dir)223 static void log_codec(const struct bt_audio_codec_cap *codec_cap, enum bt_audio_dir dir)
224 {
225 	LOG_INF("codec id 0x%02x cid 0x%04x vid 0x%04x count %u", codec_cap->id, codec_cap->cid,
226 		codec_cap->vid, codec_cap->data_len);
227 
228 	if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) {
229 		bt_audio_data_parse(codec_cap->data, codec_cap->data_len, log_codec_cb, "data");
230 	} else { /* If not LC3, we cannot assume it's LTV */
231 		LOG_HEXDUMP_DBG(codec_cap->data, codec_cap->data_len, "data");
232 	}
233 
234 	bt_audio_data_parse(codec_cap->meta, codec_cap->meta_len, log_codec_cb, "meta");
235 }
236 
add_remote_sink(struct bt_bap_ep * ep)237 static void add_remote_sink(struct bt_bap_ep *ep)
238 {
239 	if (peer.sink_ep == NULL) {
240 		LOG_INF("Sink ep: %p", (void *)ep);
241 		peer.sink_ep = ep;
242 		return;
243 	}
244 }
245 
add_remote_source(struct bt_bap_ep * ep)246 static void add_remote_source(struct bt_bap_ep *ep)
247 {
248 	if (peer.source_ep == NULL) {
249 		LOG_INF("Source ep: %p", (void *)ep);
250 		peer.source_ep = ep;
251 		return;
252 	}
253 }
254 
discover_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)255 static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
256 {
257 	if (dir == BT_AUDIO_DIR_SINK) {
258 		if (err != 0) {
259 			LOG_ERR("Discovery sinks failed: %d", err);
260 		} else {
261 			LOG_INF("Discover sinks complete");
262 		}
263 	} else if (dir == BT_AUDIO_DIR_SOURCE) {
264 		if (err != 0) {
265 			LOG_ERR("Discovery sources failed: %d", err);
266 		} else {
267 			LOG_INF("Discover sources complete");
268 		}
269 	}
270 
271 	k_sem_give(&sem_proc);
272 }
273 
pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_audio_codec_cap * codec_cap)274 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir,
275 			  const struct bt_audio_codec_cap *codec_cap)
276 {
277 	log_codec(codec_cap, dir);
278 }
279 
endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)280 static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
281 {
282 	if (dir == BT_AUDIO_DIR_SOURCE) {
283 		add_remote_source(ep);
284 	} else if (dir == BT_AUDIO_DIR_SINK) {
285 		add_remote_sink(ep);
286 	}
287 }
288 
discover_sinks(void)289 static int discover_sinks(void)
290 {
291 	int err;
292 
293 	LOG_INF("Discovering sink ASEs");
294 	k_sem_reset(&sem_proc);
295 
296 	bt_cap_stream_ops_register(&peer.sink_stream, &unicast_stream_ops);
297 
298 	err = bt_bap_unicast_client_discover(peer.conn, BT_AUDIO_DIR_SINK);
299 	if (err != 0) {
300 		LOG_ERR("Failed to discover sink: %d", err);
301 		return err;
302 	}
303 
304 	err = k_sem_take(&sem_proc, SEM_TIMEOUT);
305 	if (err != 0) {
306 		LOG_ERR("Timeout on sinks discover: %d", err);
307 		return err;
308 	}
309 
310 	return err;
311 }
312 
discover_sources(void)313 static int discover_sources(void)
314 {
315 	int err;
316 
317 	LOG_INF("Discovering source ASEs");
318 	k_sem_reset(&sem_proc);
319 
320 	bt_cap_stream_ops_register(&peer.source_stream, &unicast_stream_ops);
321 
322 	err = bt_bap_unicast_client_discover(peer.conn, BT_AUDIO_DIR_SOURCE);
323 	if (err != 0) {
324 		LOG_ERR("Failed to discover sources: %d", err);
325 		return err;
326 	}
327 
328 	err = k_sem_take(&sem_proc, SEM_TIMEOUT);
329 	if (err != 0) {
330 		LOG_ERR("Timeout on sources discover: %d", err);
331 		return err;
332 	}
333 
334 	return 0;
335 }
336 
unicast_group_create(void)337 static int unicast_group_create(void)
338 {
339 	struct bt_bap_unicast_group_stream_param source_stream_param = {
340 		.qos = &unicast_preset_16_2_1.qos,
341 		.stream = &peer.source_stream.bap_stream,
342 	};
343 	struct bt_bap_unicast_group_stream_param sink_stream_param = {
344 		.qos = &unicast_preset_16_2_1.qos,
345 		.stream = &peer.sink_stream.bap_stream,
346 	};
347 	struct bt_bap_unicast_group_stream_pair_param pair_params = {0};
348 	struct bt_bap_unicast_group_param group_param = {0};
349 	int err;
350 
351 	if (peer.source_ep != NULL) {
352 		pair_params.rx_param = &source_stream_param;
353 	}
354 
355 	if (peer.sink_ep != NULL) {
356 		pair_params.tx_param = &sink_stream_param;
357 	}
358 
359 	group_param.params_count = 1U;
360 	group_param.params = &pair_params;
361 
362 	err = bt_bap_unicast_group_create(&group_param, &unicast_group);
363 	if (err != 0) {
364 		LOG_ERR("Failed to create group: %d", err);
365 		return err;
366 	}
367 
368 	LOG_INF("Created group");
369 
370 	return err;
371 }
372 
unicast_group_delete(void)373 static int unicast_group_delete(void)
374 {
375 	int err;
376 
377 	err = bt_bap_unicast_group_delete(unicast_group);
378 	if (err != 0) {
379 		LOG_ERR("Failed to delete group: %d", err);
380 		return err;
381 	}
382 	unicast_group = NULL;
383 
384 	LOG_INF("Deleted group");
385 
386 	return err;
387 }
388 
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)389 static void cap_discovery_complete_cb(struct bt_conn *conn, int err,
390 				      const struct bt_csip_set_coordinator_set_member *member,
391 				      const struct bt_csip_set_coordinator_csis_inst *csis_inst)
392 {
393 	if (err != 0) {
394 		LOG_ERR("CAS discovery completed with error: %d", err);
395 
396 		return;
397 	}
398 
399 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER) && csis_inst != NULL) {
400 		LOG_INF("Found CAS with CSIS %p", csis_inst);
401 		/* TODO: Do set member discovery */
402 	} else {
403 		LOG_INF("Found CAS");
404 	}
405 
406 	k_sem_give(&sem_proc);
407 }
408 
unicast_start_complete_cb(int err,struct bt_conn * conn)409 static void unicast_start_complete_cb(int err, struct bt_conn *conn)
410 {
411 	if (err != 0) {
412 		LOG_ERR("Failed to start (failing conn %p): %d", (void *)conn, err);
413 		return;
414 	}
415 
416 	k_sem_give(&sem_proc);
417 }
418 
discover_cas(void)419 static int discover_cas(void)
420 {
421 	int err;
422 
423 	LOG_INF("Discovering CAS");
424 	k_sem_reset(&sem_proc);
425 
426 	err = bt_cap_initiator_unicast_discover(peer.conn);
427 	if (err != 0) {
428 		LOG_ERR("Failed to discover CAS: %d", err);
429 		return err;
430 	}
431 
432 	err = k_sem_take(&sem_proc, SEM_TIMEOUT);
433 	if (err != 0) {
434 		LOG_ERR("Timeout on CAS discover: %d", err);
435 		return err;
436 	}
437 
438 	return err;
439 }
440 
unicast_audio_start(void)441 static int unicast_audio_start(void)
442 {
443 	/* TODO: Expand to start multiple streams on multiple CAP acceptors */
444 	struct bt_cap_unicast_audio_start_stream_param stream_param[2] = {0};
445 	struct bt_cap_unicast_audio_start_param param = {0};
446 	int err;
447 
448 	LOG_INF("Starting streams");
449 
450 	if (peer.sink_ep != NULL) {
451 		stream_param[param.count].member.member = peer.conn;
452 		stream_param[param.count].stream = &peer.sink_stream;
453 		stream_param[param.count].ep = peer.sink_ep;
454 		stream_param[param.count].codec_cfg = &unicast_preset_16_2_1.codec_cfg;
455 		param.count++;
456 	}
457 
458 	if (peer.source_ep != NULL) {
459 		stream_param[param.count].member.member = peer.conn;
460 		stream_param[param.count].stream = &peer.source_stream;
461 		stream_param[param.count].ep = peer.source_ep;
462 		stream_param[param.count].codec_cfg = &unicast_preset_16_2_1.codec_cfg;
463 		param.count++;
464 	}
465 
466 	param.type = BT_CAP_SET_TYPE_AD_HOC;
467 	param.stream_params = stream_param;
468 
469 	err = bt_cap_initiator_unicast_audio_start(&param);
470 	if (err != 0) {
471 		LOG_ERR("Failed to start unicast audio: %d", err);
472 		return err;
473 	}
474 
475 	return err;
476 }
477 
att_mtu_updated_cb(struct bt_conn * conn,uint16_t tx,uint16_t rx)478 static void att_mtu_updated_cb(struct bt_conn *conn, uint16_t tx, uint16_t rx)
479 {
480 	LOG_INF("MTU exchanged: %u/%u", tx, rx);
481 	k_sem_give(&sem_mtu_exchanged);
482 }
483 
start_scan(void)484 static void start_scan(void)
485 {
486 	int err;
487 
488 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
489 	if (err != 0) {
490 		LOG_ERR("Scanning failed to start: %d", err);
491 		return;
492 	}
493 
494 	LOG_INF("Scanning successfully started");
495 }
496 
connected_cb(struct bt_conn * conn,uint8_t err)497 static void connected_cb(struct bt_conn *conn, uint8_t err)
498 {
499 	char addr[BT_ADDR_LE_STR_LEN];
500 
501 	(void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
502 
503 	if (err != 0) {
504 		LOG_ERR("Failed to connect to %s: %u", addr, err);
505 
506 		bt_conn_unref(peer.conn);
507 		peer.conn = NULL;
508 
509 		start_scan();
510 		return;
511 	}
512 
513 	if (conn != peer.conn) {
514 		return;
515 	}
516 
517 	LOG_INF("Connected: %s", addr);
518 	k_sem_give(&sem_state_change);
519 }
520 
disconnected_cb(struct bt_conn * conn,uint8_t reason)521 static void disconnected_cb(struct bt_conn *conn, uint8_t reason)
522 {
523 	char addr[BT_ADDR_LE_STR_LEN];
524 
525 	if (conn != peer.conn) {
526 		return;
527 	}
528 
529 	(void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
530 
531 	LOG_INF("Disconnected: %s, reason 0x%02x %s", addr, reason, bt_hci_err_to_str(reason));
532 
533 	bt_conn_unref(peer.conn);
534 	peer.conn = NULL;
535 
536 	k_sem_give(&sem_state_change);
537 }
538 
security_changed_cb(struct bt_conn * conn,bt_security_t level,enum bt_security_err sec_err)539 static void security_changed_cb(struct bt_conn *conn, bt_security_t level,
540 				enum bt_security_err sec_err)
541 {
542 	if (sec_err == 0) {
543 		LOG_INF("Security changed: %u", level);
544 		k_sem_give(&sem_security_changed);
545 	} else {
546 		LOG_ERR("Failed to set security level: %s(%d)",
547 			bt_security_err_to_str(sec_err), sec_err);
548 
549 		if (sec_err == BT_SECURITY_ERR_PIN_OR_KEY_MISSING) {
550 			int err;
551 
552 			LOG_INF("Removing old key");
553 			err = bt_unpair(BT_ID_DEFAULT, bt_conn_get_dst(conn));
554 			if (err != 0) {
555 				LOG_ERR("Failed to remove old key: %d", err);
556 			}
557 		}
558 	}
559 }
560 
561 BT_CONN_CB_DEFINE(conn_callbacks) = {
562 	.connected = connected_cb,
563 	.disconnected = disconnected_cb,
564 	.security_changed = security_changed_cb,
565 };
566 
check_audio_support_and_connect_cb(struct bt_data * data,void * user_data)567 static bool check_audio_support_and_connect_cb(struct bt_data *data, void *user_data)
568 {
569 	char addr_str[BT_ADDR_LE_STR_LEN];
570 	bt_addr_le_t *addr = user_data;
571 	const struct bt_uuid *uuid;
572 	uint16_t uuid_val;
573 	int err;
574 
575 	LOG_DBG("[AD]: %u data_len %u", data->type, data->data_len);
576 
577 	if (data->type != BT_DATA_SVC_DATA16) {
578 		return true; /* Continue parsing to next AD data type */
579 	}
580 
581 	if (data->data_len < sizeof(uuid_val)) {
582 		LOG_DBG("AD invalid size %u", data->data_len);
583 		return true; /* Continue parsing to next AD data type */
584 	}
585 
586 	/* We are looking for the CAS service data */
587 	uuid_val = sys_get_le16(data->data);
588 	uuid = BT_UUID_DECLARE_16(uuid_val);
589 	if (bt_uuid_cmp(uuid, BT_UUID_CAS) != 0) {
590 		return true; /* Continue parsing to next AD data type */
591 	}
592 
593 	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
594 	LOG_INF("Attempt to connect to %s", addr_str);
595 
596 	err = bt_le_scan_stop();
597 	if (err != 0) {
598 		LOG_ERR("Failed to stop scan: %d", err);
599 		return false;
600 	}
601 
602 	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &peer.conn);
603 	if (err != 0) {
604 		LOG_WRN("Create conn to failed: %d, restarting scan", err);
605 		start_scan();
606 	}
607 
608 	return false; /* Stop parsing */
609 }
610 
scan_recv_cb(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)611 static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf)
612 {
613 	if (peer.conn != NULL) {
614 		/* Already connected */
615 		return;
616 	}
617 
618 	/* Check for connectable, extended advertising */
619 	if (((info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0) &&
620 	    ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE)) != 0) {
621 		/* Check for TMAS support in advertising data */
622 		bt_data_parse(buf, check_audio_support_and_connect_cb, (void *)info->addr);
623 	}
624 }
625 
scan_and_connect(void)626 static int scan_and_connect(void)
627 {
628 	int err;
629 
630 	start_scan();
631 
632 	err = k_sem_take(&sem_state_change, K_FOREVER);
633 	if (err != 0) {
634 		LOG_ERR("Failed to take sem_state_change: %d", err);
635 		return err;
636 	}
637 
638 	return 0;
639 }
640 
exchange_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_exchange_params * params)641 static void exchange_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
642 {
643 	if (err == BT_ATT_ERR_SUCCESS) {
644 		LOG_INF("MTU exchange done");
645 		k_sem_give(&sem_proc);
646 	} else {
647 		LOG_ERR("MTU exchange failed: err %u", err);
648 	}
649 }
650 
exchange_mtu(void)651 static int exchange_mtu(void)
652 {
653 	int err;
654 
655 	if (!IS_ENABLED(CONFIG_BT_GATT_AUTO_UPDATE_MTU)) {
656 		static struct bt_gatt_exchange_params exchange_params = {
657 			.func = exchange_cb,
658 		};
659 
660 		LOG_INF("Exchanging MTU");
661 
662 		k_sem_reset(&sem_proc);
663 
664 		err = bt_gatt_exchange_mtu(peer.conn, &exchange_params);
665 		if (err != 0) {
666 			LOG_ERR("Failed to exchange MTU: %d", err);
667 		}
668 
669 		err = k_sem_take(&sem_proc, SEM_TIMEOUT);
670 		if (err != 0) {
671 			LOG_ERR("Timeout on MTU exchange request: %d", err);
672 			return err;
673 		}
674 	}
675 
676 	LOG_INF("Waiting for MTU exchange");
677 	err = k_sem_take(&sem_mtu_exchanged, SEM_TIMEOUT);
678 	if (err != 0) {
679 		LOG_ERR("Timeout on MTU exchange: %d", err);
680 		return err;
681 	}
682 
683 	return 0;
684 }
685 
update_security(void)686 static int update_security(void)
687 {
688 	int err;
689 
690 	err = bt_conn_set_security(peer.conn, BT_SECURITY_L2);
691 	if (err != 0) {
692 		LOG_ERR("Failed to set security: %d", err);
693 		return err;
694 	}
695 
696 	LOG_INF("Waiting for security change");
697 	err = k_sem_take(&sem_security_changed, SEM_TIMEOUT);
698 	if (err != 0) {
699 		LOG_ERR("Timeout on security: %d", err);
700 		return err;
701 	}
702 
703 	return 0;
704 }
705 
init_cap_initiator(void)706 static int init_cap_initiator(void)
707 {
708 	static struct bt_bap_unicast_client_cb unicast_client_cbs = {
709 		.discover = discover_cb,
710 		.pac_record = pac_record_cb,
711 		.endpoint = endpoint_cb,
712 	};
713 	static struct bt_cap_initiator_cb cap_cb = {
714 		.unicast_discovery_complete = cap_discovery_complete_cb,
715 		.unicast_start_complete = unicast_start_complete_cb,
716 	};
717 	static struct bt_gatt_cb gatt_callbacks = {
718 		.att_mtu_updated = att_mtu_updated_cb,
719 	};
720 	static struct bt_le_scan_cb scan_callbacks = {
721 		.recv = scan_recv_cb,
722 	};
723 	int err;
724 
725 	err = bt_cap_initiator_register_cb(&cap_cb);
726 	if (err != 0) {
727 		LOG_ERR("Failed to register CAP callbacks: %d", err);
728 
729 		return err;
730 	}
731 
732 	err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
733 	if (err != 0) {
734 		LOG_ERR("Failed to register BAP unicast client callbacks: %d", err);
735 
736 		return err;
737 	}
738 
739 	bt_gatt_cb_register(&gatt_callbacks);
740 	bt_le_scan_cb_register(&scan_callbacks);
741 
742 	k_sem_init(&peer.source_stream_sem, 0, 1);
743 	k_sem_init(&peer.sink_stream_sem, 0, 1);
744 
745 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK)) {
746 		cap_initiator_tx_init();
747 	}
748 
749 	return 0;
750 }
751 
reset_cap_initiator(void)752 static int reset_cap_initiator(void)
753 {
754 	int err;
755 
756 	LOG_INF("Resetting");
757 
758 	if (peer.conn != NULL) {
759 		err = bt_conn_disconnect(peer.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
760 		if (err != 0) {
761 			return err;
762 		}
763 
764 		err = k_sem_take(&sem_state_change, K_FOREVER);
765 		if (err != 0) {
766 			LOG_ERR("Timeout on disconnect: %d", err);
767 			return err;
768 		}
769 	}
770 
771 	if (peer.source_stream.bap_stream.ep != NULL) {
772 		err = k_sem_take(&peer.source_stream_sem, SEM_TIMEOUT);
773 		if (err != 0) {
774 			LOG_ERR("Timeout on source_stream_sem: %d", err);
775 			return err;
776 		}
777 	}
778 
779 	if (peer.sink_stream.bap_stream.ep != NULL) {
780 		err = k_sem_take(&peer.sink_stream_sem, SEM_TIMEOUT);
781 		if (err != 0) {
782 			LOG_ERR("Timeout on sink_stream_sem: %d", err);
783 			return err;
784 		}
785 	}
786 
787 	if (unicast_group != NULL) {
788 		int err;
789 
790 		err = unicast_group_delete();
791 		if (err != 0) {
792 			return err;
793 		}
794 
795 		return err;
796 	}
797 
798 	peer.source_ep = NULL;
799 	peer.sink_ep = NULL;
800 	k_sem_reset(&sem_proc);
801 	k_sem_reset(&sem_state_change);
802 	k_sem_reset(&sem_mtu_exchanged);
803 
804 	return 0;
805 }
806 
cap_initiator_unicast(void)807 int cap_initiator_unicast(void)
808 {
809 	int err;
810 
811 	err = init_cap_initiator();
812 	if (err != 0) {
813 		return err;
814 	}
815 
816 	LOG_INF("CAP initiator unicast initialized");
817 
818 	while (true) {
819 		err = reset_cap_initiator();
820 		if (err != 0) {
821 			LOG_ERR("Failed to reset");
822 
823 			return err;
824 		}
825 
826 		/* Start scanning for and connecting to CAP Acceptors. CAP Acceptors are identified
827 		 * by their advertising data
828 		 */
829 		err = scan_and_connect();
830 		if (err != 0) {
831 			continue;
832 		}
833 
834 		/* BAP mandates support for an MTU of at least 65 octets. Because of that, we
835 		 * should always exchange the MTU before accessing BAP related services to ensure
836 		 * correctness
837 		 */
838 		err = exchange_mtu();
839 		if (err != 0) {
840 			continue;
841 		}
842 
843 		/* LE Audio services require encryption with LE Secure Connections, so we increase
844 		 * security before attempting to do any LE Audio operations
845 		 */
846 		err = update_security();
847 		if (err != 0) {
848 			continue;
849 		}
850 
851 		/* All remote CAP Acceptors shall have the Common Audio Service (CAS) so we start by
852 		 * discovering that on the remote device to determine if they are really CAP
853 		 * Acceptors. If they are only a BAP Unicast Server we ignore them.
854 		 */
855 		err = discover_cas();
856 		if (err != 0) {
857 			continue;
858 		}
859 
860 		/* Discover sink ASEs and capabilities. This may not result in any endpoints if they
861 		 * remote device is only a source (e.g. a microphone)
862 		 */
863 		err = discover_sinks();
864 		if (err != 0) {
865 			continue;
866 		}
867 
868 		/* Discover source ASEs and capabilities. This may not result in any endpoints if
869 		 * they remote device is only a sink (e.g. a speaker)
870 		 */
871 		err = discover_sources();
872 		if (err != 0) {
873 			continue;
874 		}
875 
876 		/* Create a unicast group (Connected Isochronous Group (CIG)) based on what we have
877 		 * found on the remote device
878 		 */
879 		err = unicast_group_create();
880 		if (err != 0) {
881 			continue;
882 		}
883 
884 		/* Execute the start operation which will take one or more streams into the
885 		 * streaming state
886 		 */
887 		err = unicast_audio_start();
888 		if (err != 0) {
889 			continue;
890 		}
891 
892 		/* Reset if disconnected */
893 		err = k_sem_take(&sem_state_change, K_FOREVER);
894 		if (err != 0) {
895 			LOG_ERR("Failed to take sem_state_change: err %d", err);
896 
897 			return err;
898 		}
899 	}
900 
901 	return 0;
902 }
903