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_BAP_CONN_PARAM_RELAXED,
603 				&peer.conn);
604 	if (err != 0) {
605 		LOG_WRN("Create conn to failed: %d, restarting scan", err);
606 		start_scan();
607 	}
608 
609 	return false; /* Stop parsing */
610 }
611 
scan_recv_cb(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)612 static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf)
613 {
614 	if (peer.conn != NULL) {
615 		/* Already connected */
616 		return;
617 	}
618 
619 	/* Check for connectable, extended advertising */
620 	if (((info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0) &&
621 	    ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE)) != 0) {
622 		/* Check for TMAS support in advertising data */
623 		bt_data_parse(buf, check_audio_support_and_connect_cb, (void *)info->addr);
624 	}
625 }
626 
scan_and_connect(void)627 static int scan_and_connect(void)
628 {
629 	int err;
630 
631 	start_scan();
632 
633 	err = k_sem_take(&sem_state_change, K_FOREVER);
634 	if (err != 0) {
635 		LOG_ERR("Failed to take sem_state_change: %d", err);
636 		return err;
637 	}
638 
639 	return 0;
640 }
641 
exchange_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_exchange_params * params)642 static void exchange_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
643 {
644 	if (err == BT_ATT_ERR_SUCCESS) {
645 		LOG_INF("MTU exchange done");
646 		k_sem_give(&sem_proc);
647 	} else {
648 		LOG_ERR("MTU exchange failed: err %u", err);
649 	}
650 }
651 
exchange_mtu(void)652 static int exchange_mtu(void)
653 {
654 	int err;
655 
656 	if (!IS_ENABLED(CONFIG_BT_GATT_AUTO_UPDATE_MTU)) {
657 		static struct bt_gatt_exchange_params exchange_params = {
658 			.func = exchange_cb,
659 		};
660 
661 		LOG_INF("Exchanging MTU");
662 
663 		k_sem_reset(&sem_proc);
664 
665 		err = bt_gatt_exchange_mtu(peer.conn, &exchange_params);
666 		if (err != 0) {
667 			LOG_ERR("Failed to exchange MTU: %d", err);
668 		}
669 
670 		err = k_sem_take(&sem_proc, SEM_TIMEOUT);
671 		if (err != 0) {
672 			LOG_ERR("Timeout on MTU exchange request: %d", err);
673 			return err;
674 		}
675 	}
676 
677 	LOG_INF("Waiting for MTU exchange");
678 	err = k_sem_take(&sem_mtu_exchanged, SEM_TIMEOUT);
679 	if (err != 0) {
680 		LOG_ERR("Timeout on MTU exchange: %d", err);
681 		return err;
682 	}
683 
684 	return 0;
685 }
686 
update_security(void)687 static int update_security(void)
688 {
689 	int err;
690 
691 	err = bt_conn_set_security(peer.conn, BT_SECURITY_L2);
692 	if (err != 0) {
693 		LOG_ERR("Failed to set security: %d", err);
694 		return err;
695 	}
696 
697 	LOG_INF("Waiting for security change");
698 	err = k_sem_take(&sem_security_changed, SEM_TIMEOUT);
699 	if (err != 0) {
700 		LOG_ERR("Timeout on security: %d", err);
701 		return err;
702 	}
703 
704 	return 0;
705 }
706 
init_cap_initiator(void)707 static int init_cap_initiator(void)
708 {
709 	static struct bt_bap_unicast_client_cb unicast_client_cbs = {
710 		.discover = discover_cb,
711 		.pac_record = pac_record_cb,
712 		.endpoint = endpoint_cb,
713 	};
714 	static struct bt_cap_initiator_cb cap_cb = {
715 		.unicast_discovery_complete = cap_discovery_complete_cb,
716 		.unicast_start_complete = unicast_start_complete_cb,
717 	};
718 	static struct bt_gatt_cb gatt_callbacks = {
719 		.att_mtu_updated = att_mtu_updated_cb,
720 	};
721 	static struct bt_le_scan_cb scan_callbacks = {
722 		.recv = scan_recv_cb,
723 	};
724 	int err;
725 
726 	err = bt_cap_initiator_register_cb(&cap_cb);
727 	if (err != 0) {
728 		LOG_ERR("Failed to register CAP callbacks: %d", err);
729 
730 		return err;
731 	}
732 
733 	err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
734 	if (err != 0) {
735 		LOG_ERR("Failed to register BAP unicast client callbacks: %d", err);
736 
737 		return err;
738 	}
739 
740 	bt_gatt_cb_register(&gatt_callbacks);
741 	bt_le_scan_cb_register(&scan_callbacks);
742 
743 	k_sem_init(&peer.source_stream_sem, 0, 1);
744 	k_sem_init(&peer.sink_stream_sem, 0, 1);
745 
746 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK)) {
747 		cap_initiator_tx_init();
748 	}
749 
750 	return 0;
751 }
752 
reset_cap_initiator(void)753 static int reset_cap_initiator(void)
754 {
755 	int err;
756 
757 	LOG_INF("Resetting");
758 
759 	if (peer.conn != NULL) {
760 		err = bt_conn_disconnect(peer.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
761 		if (err != 0) {
762 			return err;
763 		}
764 
765 		err = k_sem_take(&sem_state_change, K_FOREVER);
766 		if (err != 0) {
767 			LOG_ERR("Timeout on disconnect: %d", err);
768 			return err;
769 		}
770 	}
771 
772 	if (peer.source_stream.bap_stream.ep != NULL) {
773 		err = k_sem_take(&peer.source_stream_sem, SEM_TIMEOUT);
774 		if (err != 0) {
775 			LOG_ERR("Timeout on source_stream_sem: %d", err);
776 			return err;
777 		}
778 	}
779 
780 	if (peer.sink_stream.bap_stream.ep != NULL) {
781 		err = k_sem_take(&peer.sink_stream_sem, SEM_TIMEOUT);
782 		if (err != 0) {
783 			LOG_ERR("Timeout on sink_stream_sem: %d", err);
784 			return err;
785 		}
786 	}
787 
788 	if (unicast_group != NULL) {
789 		int err;
790 
791 		err = unicast_group_delete();
792 		if (err != 0) {
793 			return err;
794 		}
795 
796 		return err;
797 	}
798 
799 	peer.source_ep = NULL;
800 	peer.sink_ep = NULL;
801 	k_sem_reset(&sem_proc);
802 	k_sem_reset(&sem_state_change);
803 	k_sem_reset(&sem_mtu_exchanged);
804 
805 	return 0;
806 }
807 
cap_initiator_unicast(void)808 int cap_initiator_unicast(void)
809 {
810 	int err;
811 
812 	err = init_cap_initiator();
813 	if (err != 0) {
814 		return err;
815 	}
816 
817 	LOG_INF("CAP initiator unicast initialized");
818 
819 	while (true) {
820 		err = reset_cap_initiator();
821 		if (err != 0) {
822 			LOG_ERR("Failed to reset");
823 
824 			return err;
825 		}
826 
827 		/* Start scanning for and connecting to CAP Acceptors. CAP Acceptors are identified
828 		 * by their advertising data
829 		 */
830 		err = scan_and_connect();
831 		if (err != 0) {
832 			continue;
833 		}
834 
835 		/* BAP mandates support for an MTU of at least 65 octets. Because of that, we
836 		 * should always exchange the MTU before accessing BAP related services to ensure
837 		 * correctness
838 		 */
839 		err = exchange_mtu();
840 		if (err != 0) {
841 			continue;
842 		}
843 
844 		/* LE Audio services require encryption with LE Secure Connections, so we increase
845 		 * security before attempting to do any LE Audio operations
846 		 */
847 		err = update_security();
848 		if (err != 0) {
849 			continue;
850 		}
851 
852 		/* All remote CAP Acceptors shall have the Common Audio Service (CAS) so we start by
853 		 * discovering that on the remote device to determine if they are really CAP
854 		 * Acceptors. If they are only a BAP Unicast Server we ignore them.
855 		 */
856 		err = discover_cas();
857 		if (err != 0) {
858 			continue;
859 		}
860 
861 		/* Discover sink ASEs and capabilities. This may not result in any endpoints if they
862 		 * remote device is only a source (e.g. a microphone)
863 		 */
864 		err = discover_sinks();
865 		if (err != 0) {
866 			continue;
867 		}
868 
869 		/* Discover source ASEs and capabilities. This may not result in any endpoints if
870 		 * they remote device is only a sink (e.g. a speaker)
871 		 */
872 		err = discover_sources();
873 		if (err != 0) {
874 			continue;
875 		}
876 
877 		/* Create a unicast group (Connected Isochronous Group (CIG)) based on what we have
878 		 * found on the remote device
879 		 */
880 		err = unicast_group_create();
881 		if (err != 0) {
882 			continue;
883 		}
884 
885 		/* Execute the start operation which will take one or more streams into the
886 		 * streaming state
887 		 */
888 		err = unicast_audio_start();
889 		if (err != 0) {
890 			continue;
891 		}
892 
893 		/* Reset if disconnected */
894 		err = k_sem_take(&sem_state_change, K_FOREVER);
895 		if (err != 0) {
896 			LOG_ERR("Failed to take sem_state_change: err %d", err);
897 
898 			return err;
899 		}
900 	}
901 
902 	return 0;
903 }
904