1 /* btp_bap_unicast.c - Bluetooth BAP Tester */
2 
3 /*
4  * Copyright (c) 2023 Codecoup
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <stddef.h>
10 #include <errno.h>
11 
12 #include <zephyr/bluetooth/iso.h>
13 #include <zephyr/types.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/sys/ring_buffer.h>
16 #include <zephyr/bluetooth/audio/audio.h>
17 #include <zephyr/bluetooth/hci_types.h>
18 #include <hci_core.h>
19 
20 #include "bap_endpoint.h"
21 #include <zephyr/logging/log.h>
22 #include <zephyr/sys/byteorder.h>
23 #define LOG_MODULE_NAME bttester_bap_unicast
24 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
25 #include "btp/btp.h"
26 #include "btp_bap_audio_stream.h"
27 #include "btp_bap_unicast.h"
28 
29 static struct bt_bap_qos_cfg_pref qos_pref =
30 	BT_BAP_QOS_CFG_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 10000, 40000, 10000, 40000);
31 
32 static struct btp_bap_unicast_connection connections[CONFIG_BT_MAX_CONN];
33 static struct btp_bap_unicast_group cigs[CONFIG_BT_ISO_MAX_CIG];
34 
stream_bap_to_unicast(struct bt_bap_stream * stream)35 static inline struct btp_bap_unicast_stream *stream_bap_to_unicast(struct bt_bap_stream *stream)
36 {
37 	return CONTAINER_OF(CONTAINER_OF(CONTAINER_OF(stream, struct bt_cap_stream, bap_stream),
38 		struct btp_bap_audio_stream, cap_stream),
39 		struct btp_bap_unicast_stream, audio_stream);
40 }
41 
stream_unicast_to_bap(struct btp_bap_unicast_stream * stream)42 static inline struct bt_bap_stream *stream_unicast_to_bap(struct btp_bap_unicast_stream *stream)
43 {
44 	return &stream->audio_stream.cap_stream.bap_stream;
45 }
46 
print_cb(struct bt_data * data,void * user_data)47 static bool print_cb(struct bt_data *data, void *user_data)
48 {
49 	const char *str = (const char *)user_data;
50 
51 	LOG_DBG("%s: type 0x%02x value_len %u", str, data->type, data->data_len);
52 	LOG_HEXDUMP_DBG(data->data, data->data_len, "");
53 
54 	return true;
55 }
56 
print_codec_cfg(const struct bt_audio_codec_cfg * codec_cfg)57 static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg)
58 {
59 	LOG_DBG("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u", codec_cfg->id, codec_cfg->cid,
60 		codec_cfg->vid, codec_cfg->data_len);
61 
62 	if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
63 		enum bt_audio_location chan_allocation;
64 		int ret;
65 
66 		/* LC3 uses the generic LTV format - other codecs might do as well */
67 
68 		bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, print_cb, "data");
69 
70 		ret = bt_audio_codec_cfg_get_freq(codec_cfg);
71 		if (ret > 0) {
72 			LOG_DBG("  Frequency: %d Hz", bt_audio_codec_cfg_freq_to_freq_hz(ret));
73 		}
74 
75 		ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg);
76 		if (ret > 0) {
77 			LOG_DBG("  Frame Duration: %d us",
78 				bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret));
79 		}
80 
81 		ret = bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, false);
82 		if (ret == 0) {
83 			LOG_DBG("  Channel allocation: 0x%x", chan_allocation);
84 		}
85 
86 		LOG_DBG("  Octets per frame: %d (negative means value not pressent)",
87 			bt_audio_codec_cfg_get_octets_per_frame(codec_cfg));
88 		LOG_DBG("  Frames per SDU: %d",
89 			bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true));
90 	} else {
91 		LOG_HEXDUMP_DBG(codec_cfg->data, codec_cfg->data_len, "data");
92 	}
93 
94 	bt_audio_data_parse(codec_cfg->meta, codec_cfg->meta_len, print_cb, "meta");
95 }
96 
print_codec_cap(const struct bt_audio_codec_cap * codec_cap)97 static void print_codec_cap(const struct bt_audio_codec_cap *codec_cap)
98 {
99 	LOG_DBG("codec_cap 0x%02x cid 0x%04x vid 0x%04x count %zu", codec_cap->id, codec_cap->cid,
100 		codec_cap->vid, codec_cap->data_len);
101 
102 	if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) {
103 		bt_audio_data_parse(codec_cap->data, codec_cap->data_len, print_cb, "data");
104 	} else {
105 		LOG_HEXDUMP_DBG(codec_cap->data, codec_cap->data_len, "data");
106 	}
107 
108 	bt_audio_data_parse(codec_cap->meta, codec_cap->meta_len, print_cb, "meta");
109 }
110 
btp_bap_unicast_stream_free(struct btp_bap_unicast_stream * stream)111 void btp_bap_unicast_stream_free(struct btp_bap_unicast_stream *stream)
112 {
113 	(void)memset(stream, 0, sizeof(*stream));
114 }
115 
btp_bap_unicast_stream_find(struct btp_bap_unicast_connection * conn,uint8_t ase_id)116 struct btp_bap_unicast_stream *btp_bap_unicast_stream_find(
117 	struct btp_bap_unicast_connection *conn, uint8_t ase_id)
118 {
119 	for (size_t i = 0; i < ARRAY_SIZE(conn->streams); i++) {
120 		struct bt_bap_stream *stream = stream_unicast_to_bap(&conn->streams[i]);
121 		struct bt_bap_ep_info info;
122 
123 		if (stream->ep == NULL) {
124 			continue;
125 		}
126 
127 		(void)bt_bap_ep_get_info(stream->ep, &info);
128 		if (info.id == ase_id) {
129 			return &conn->streams[i];
130 		}
131 	}
132 
133 	return NULL;
134 }
135 
btp_bap_unicast_end_point_find(struct btp_bap_unicast_connection * conn,uint8_t ase_id)136 struct bt_bap_ep *btp_bap_unicast_end_point_find(struct btp_bap_unicast_connection *conn,
137 						 uint8_t ase_id)
138 {
139 	for (size_t i = 0; i < ARRAY_SIZE(conn->end_points); i++) {
140 		struct bt_bap_ep_info info;
141 		struct bt_bap_ep *ep = conn->end_points[i];
142 
143 		if (ep == NULL) {
144 			continue;
145 		}
146 
147 		(void)bt_bap_ep_get_info(ep, &info);
148 		if (info.id == ase_id) {
149 			return ep;
150 		}
151 	}
152 
153 	return NULL;
154 }
155 
btp_send_ascs_ase_state_changed_ev(struct bt_conn * conn,uint8_t ase_id,uint8_t state)156 static void btp_send_ascs_ase_state_changed_ev(struct bt_conn *conn, uint8_t ase_id, uint8_t state)
157 {
158 	struct btp_ascs_ase_state_changed_ev ev;
159 
160 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
161 	ev.ase_id = ase_id;
162 	ev.state = state;
163 
164 	tester_event(BTP_SERVICE_ID_ASCS, BTP_ASCS_EV_ASE_STATE_CHANGED, &ev, sizeof(ev));
165 }
166 
btp_send_ascs_operation_completed_ev(struct bt_conn * conn,uint8_t ase_id,uint8_t opcode,uint8_t status)167 static void btp_send_ascs_operation_completed_ev(struct bt_conn *conn, uint8_t ase_id,
168 						 uint8_t opcode, uint8_t status)
169 {
170 	struct btp_ascs_operation_completed_ev ev;
171 
172 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
173 	ev.ase_id = ase_id;
174 	ev.opcode = opcode;
175 	ev.status = status;
176 	ev.flags = 0;
177 
178 	tester_event(BTP_SERVICE_ID_ASCS, BTP_ASCS_EV_OPERATION_COMPLETED, &ev, sizeof(ev));
179 }
180 
181 struct search_type_param {
182 	uint8_t type;
183 	const uint8_t *data;
184 };
185 
data_type_search_cb(struct bt_data * data,void * user_data)186 static bool data_type_search_cb(struct bt_data *data, void *user_data)
187 {
188 	struct search_type_param *param = (struct search_type_param *)user_data;
189 
190 	if (param->type == data->type) {
191 		param->data = data->data;
192 
193 		return false;
194 	}
195 
196 	return true;
197 }
198 
codec_cap_get_val(const struct bt_audio_codec_cap * codec_cap,uint8_t type,const uint8_t ** data)199 static bool codec_cap_get_val(const struct bt_audio_codec_cap *codec_cap, uint8_t type,
200 			      const uint8_t **data)
201 {
202 	struct search_type_param param = {
203 		.type = type,
204 		.data = NULL,
205 	};
206 	int err;
207 
208 	err = bt_audio_data_parse(codec_cap->data, codec_cap->data_len, data_type_search_cb,
209 				  &param);
210 	if (err != 0 && err != -ECANCELED) {
211 		LOG_DBG("Could not parse the data: %d", err);
212 
213 		return false;
214 	}
215 
216 	if (param.data == NULL) {
217 		LOG_DBG("Could not find the type %u", type);
218 
219 		return false;
220 	}
221 
222 	*data = param.data;
223 
224 	return true;
225 }
226 
btp_send_pac_codec_found_ev(struct bt_conn * conn,const struct bt_audio_codec_cap * codec_cap,enum bt_audio_dir dir)227 static void btp_send_pac_codec_found_ev(struct bt_conn *conn,
228 					const struct bt_audio_codec_cap *codec_cap,
229 					enum bt_audio_dir dir)
230 {
231 	struct btp_bap_codec_cap_found_ev ev;
232 	const uint8_t *data;
233 
234 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
235 
236 	ev.dir = dir;
237 	ev.coding_format = codec_cap->id;
238 
239 	if (codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_CAP_TYPE_FREQ, &data)) {
240 		memcpy(&ev.frequencies, data, sizeof(ev.frequencies));
241 	}
242 
243 	if (codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_CAP_TYPE_DURATION, &data)) {
244 		memcpy(&ev.frame_durations, data, sizeof(ev.frame_durations));
245 	}
246 
247 	if (codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_CAP_TYPE_FRAME_LEN, &data)) {
248 		memcpy(&ev.octets_per_frame, data, sizeof(ev.octets_per_frame));
249 	}
250 
251 	if (codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_CAP_TYPE_CHAN_COUNT, &data)) {
252 		memcpy(&ev.channel_counts, data, sizeof(ev.channel_counts));
253 	}
254 
255 	tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_CODEC_CAP_FOUND, &ev, sizeof(ev));
256 }
257 
btp_send_ase_found_ev(struct bt_conn * conn,struct bt_bap_ep * ep)258 static void btp_send_ase_found_ev(struct bt_conn *conn, struct bt_bap_ep *ep)
259 {
260 	struct bt_bap_ep_info info;
261 	struct btp_ascs_ase_found_ev ev;
262 
263 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
264 
265 	(void)bt_bap_ep_get_info(ep, &info);
266 	ev.ase_id = info.id;
267 	ev.dir = info.dir;
268 
269 	tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_ASE_FOUND, &ev, sizeof(ev));
270 }
271 
print_qos(const struct bt_bap_qos_cfg * qos)272 static inline void print_qos(const struct bt_bap_qos_cfg *qos)
273 {
274 	LOG_DBG("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u rtn %u latency %u pd %u",
275 		qos->interval, qos->framing, qos->phy, qos->sdu, qos->rtn, qos->latency, qos->pd);
276 }
277 
validate_codec_parameters(const struct bt_audio_codec_cfg * codec_cfg)278 static int validate_codec_parameters(const struct bt_audio_codec_cfg *codec_cfg)
279 {
280 	int frames_per_sdu;
281 	int octets_per_frame;
282 	int chan_allocation_err;
283 	enum bt_audio_location chan_allocation;
284 	int ret;
285 
286 	chan_allocation_err =
287 		bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, false);
288 	octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg);
289 	frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true);
290 
291 	ret = bt_audio_codec_cfg_get_freq(codec_cfg);
292 	if (ret < 0) {
293 		LOG_DBG("Error: Invalid codec frequency: %d", ret);
294 		return -EINVAL;
295 	}
296 
297 	ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg);
298 	if (ret < 0) {
299 		LOG_DBG("Error: Invalid frame duration: %d", ret);
300 		return -EINVAL;
301 	}
302 
303 	if (octets_per_frame < 0) {
304 		LOG_DBG("Error: Invalid octets per frame.");
305 		return -EINVAL;
306 	}
307 
308 	if (frames_per_sdu < 0) {
309 		/* The absence of the Codec_Frame_Blocks_Per_SDU LTV structure shall be
310 		 * interpreted as equivalent to a Codec_Frame_Blocks_Per_SDU value of 0x01
311 		 */
312 		LOG_DBG("Codec_Frame_Blocks_Per_SDU LTV structure not defined.");
313 	}
314 
315 	if (chan_allocation_err < 0) {
316 		/* The absence of the Audio_Channel_Allocation LTV structure shall be
317 		 * interpreted as a single channel with no specified Audio Location.
318 		 */
319 		LOG_DBG("Audio_Channel_Allocation LTV structure not defined.");
320 	}
321 
322 	return 0;
323 }
324 
lc3_config(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 ** stream,struct bt_bap_qos_cfg_pref * const pref,struct bt_bap_ascs_rsp * rsp)325 static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir,
326 		      const struct bt_audio_codec_cfg *codec_cfg, struct bt_bap_stream **stream,
327 		      struct bt_bap_qos_cfg_pref *const pref, struct bt_bap_ascs_rsp *rsp)
328 {
329 	struct bt_bap_ep_info info;
330 	struct btp_bap_unicast_connection *u_conn;
331 	struct btp_bap_unicast_stream *u_stream;
332 
333 	LOG_DBG("ASE Codec Config: ep %p dir %u", ep, dir);
334 
335 	print_codec_cfg(codec_cfg);
336 	(void)bt_bap_ep_get_info(ep, &info);
337 
338 	if (validate_codec_parameters(codec_cfg)) {
339 		*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_REJECTED,
340 				       BT_BAP_ASCS_REASON_CODEC_DATA);
341 
342 		btp_send_ascs_operation_completed_ev(conn, info.id, BT_ASCS_CONFIG_OP,
343 						     BTP_ASCS_STATUS_FAILED);
344 
345 		return -ENOTSUP;
346 	}
347 
348 	u_conn = &connections[bt_conn_index(conn)];
349 	u_stream = btp_bap_unicast_stream_alloc(u_conn);
350 	if (u_stream == NULL) {
351 		LOG_DBG("No free stream available");
352 		*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM, BT_BAP_ASCS_REASON_NONE);
353 
354 		btp_send_ascs_operation_completed_ev(conn, info.id, BT_ASCS_CONFIG_OP,
355 						     BTP_ASCS_STATUS_FAILED);
356 
357 		return -ENOMEM;
358 	}
359 
360 	*stream = stream_unicast_to_bap(u_stream);
361 	LOG_DBG("ASE Codec Config stream %p", *stream);
362 
363 	if (dir == BT_AUDIO_DIR_SOURCE) {
364 		u_conn->configured_source_stream_count++;
365 	} else {
366 		u_conn->configured_sink_stream_count++;
367 	}
368 
369 	*pref = qos_pref;
370 
371 	return 0;
372 }
373 
lc3_reconfig(struct bt_bap_stream * 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)374 static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir,
375 			const struct bt_audio_codec_cfg *codec_cfg,
376 			struct bt_bap_qos_cfg_pref *const pref, struct bt_bap_ascs_rsp *rsp)
377 {
378 	LOG_DBG("ASE Codec Reconfig: stream %p", stream);
379 
380 	print_codec_cfg(codec_cfg);
381 
382 	return 0;
383 }
384 
lc3_qos(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg * qos,struct bt_bap_ascs_rsp * rsp)385 static int lc3_qos(struct bt_bap_stream *stream, const struct bt_bap_qos_cfg *qos,
386 		   struct bt_bap_ascs_rsp *rsp)
387 {
388 	LOG_DBG("QoS: stream %p qos %p", stream, qos);
389 
390 	print_qos(qos);
391 
392 	return 0;
393 }
394 
valid_metadata_type(uint8_t type,uint8_t len,const uint8_t * data)395 static bool valid_metadata_type(uint8_t type, uint8_t len, const uint8_t *data)
396 {
397 	/* PTS checks if we are able to reject unsupported metadata type or RFU vale.
398 	 * The only RFU value PTS seems to check for now is the streaming context.
399 	 */
400 	if (!BT_AUDIO_METADATA_TYPE_IS_KNOWN(type)) {
401 		return false;
402 	}
403 
404 	if (type == BT_AUDIO_METADATA_TYPE_PREF_CONTEXT ||
405 	    type == BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT) {
406 		/* PTS wants us to reject the parameter if reserved bits are set */
407 		if ((sys_get_le16(data) & ~(uint16_t)(BT_AUDIO_CONTEXT_TYPE_ANY)) > 0) {
408 			return false;
409 		}
410 	}
411 
412 	return true;
413 }
414 
data_func_cb(struct bt_data * data,void * user_data)415 static bool data_func_cb(struct bt_data *data, void *user_data)
416 {
417 	struct bt_bap_ascs_rsp *rsp = (struct bt_bap_ascs_rsp *)user_data;
418 
419 	if (!valid_metadata_type(data->type, data->data_len, data->data)) {
420 		LOG_DBG("Invalid metadata type %u or length %u", data->type, data->data_len);
421 		*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED, data->type);
422 		return false;
423 	}
424 
425 	return true;
426 }
427 
lc3_enable(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len,struct bt_bap_ascs_rsp * rsp)428 static int lc3_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len,
429 		      struct bt_bap_ascs_rsp *rsp)
430 {
431 	int err;
432 	struct bt_bap_ep_info info;
433 
434 	LOG_DBG("Metadata: stream %p meta_len %zu", stream, meta_len);
435 
436 	err = bt_audio_data_parse(meta, meta_len, data_func_cb, rsp);
437 	if (err != 0) {
438 		(void)bt_bap_ep_get_info(stream->ep, &info);
439 		btp_send_ascs_operation_completed_ev(stream->conn, info.id,
440 						     BT_ASCS_ENABLE_OP, BTP_ASCS_STATUS_FAILED);
441 	}
442 
443 	return err;
444 }
445 
lc3_start(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)446 static int lc3_start(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
447 {
448 	LOG_DBG("Start: stream %p", stream);
449 
450 	return 0;
451 }
452 
lc3_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len,struct bt_bap_ascs_rsp * rsp)453 static int lc3_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len,
454 			struct bt_bap_ascs_rsp *rsp)
455 {
456 	int err;
457 	struct bt_bap_ep_info info;
458 
459 	LOG_DBG("Metadata: stream %p meta_count %zu", stream, meta_len);
460 
461 	err = bt_audio_data_parse(meta, meta_len, data_func_cb, rsp);
462 	if (err != 0) {
463 		(void)bt_bap_ep_get_info(stream->ep, &info);
464 		btp_send_ascs_operation_completed_ev(stream->conn, info.id,
465 						     BT_ASCS_METADATA_OP, BTP_ASCS_STATUS_FAILED);
466 	}
467 
468 	return err;
469 }
470 
lc3_disable(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)471 static int lc3_disable(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
472 {
473 	LOG_DBG("Disable: stream %p", stream);
474 
475 	return 0;
476 }
477 
lc3_stop(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)478 static int lc3_stop(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
479 {
480 	LOG_DBG("Stop: stream %p", stream);
481 
482 	return 0;
483 }
484 
lc3_release(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)485 static int lc3_release(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
486 {
487 	LOG_DBG("Release: stream %p", stream);
488 
489 	return 0;
490 }
491 
492 static const struct bt_bap_unicast_server_cb unicast_server_cb = {
493 	.config = lc3_config,
494 	.reconfig = lc3_reconfig,
495 	.qos = lc3_qos,
496 	.enable = lc3_enable,
497 	.start = lc3_start,
498 	.metadata = lc3_metadata,
499 	.disable = lc3_disable,
500 	.stop = lc3_stop,
501 	.release = lc3_release,
502 };
503 
stream_configured(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg_pref * pref)504 static void stream_configured(struct bt_bap_stream *stream, const struct bt_bap_qos_cfg_pref *pref)
505 {
506 	struct bt_bap_ep_info info;
507 	struct btp_bap_unicast_connection *u_conn;
508 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
509 
510 	(void)bt_bap_ep_get_info(stream->ep, &info);
511 	LOG_DBG("Configured stream %p, ep %u, dir %u", stream, info.id, info.dir);
512 
513 	u_stream->conn_id = bt_conn_index(stream->conn);
514 	u_conn = &connections[u_stream->conn_id];
515 	u_stream->ase_id = info.id;
516 
517 	btp_send_ascs_operation_completed_ev(stream->conn, u_stream->ase_id,
518 					     BT_ASCS_CONFIG_OP, BTP_ASCS_STATUS_SUCCESS);
519 }
520 
stream_qos_set(struct bt_bap_stream * stream)521 static void stream_qos_set(struct bt_bap_stream *stream)
522 {
523 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
524 
525 	LOG_DBG("QoS set stream %p", stream);
526 	btp_send_ascs_operation_completed_ev(stream->conn, u_stream->ase_id,
527 					     BT_ASCS_QOS_OP, BTP_ASCS_STATUS_SUCCESS);
528 }
529 
stream_enabled(struct bt_bap_stream * stream)530 static void stream_enabled(struct bt_bap_stream *stream)
531 {
532 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
533 	struct bt_bap_ep_info info;
534 	struct bt_conn_info conn_info;
535 	int err;
536 
537 	LOG_DBG("Enabled stream %p", stream);
538 
539 	(void)bt_bap_ep_get_info(stream->ep, &info);
540 	(void)bt_conn_get_info(stream->conn, &conn_info);
541 	if (conn_info.role == BT_HCI_ROLE_PERIPHERAL && info.dir == BT_AUDIO_DIR_SINK) {
542 		/* Automatically do the receiver start ready operation */
543 		err = bt_bap_stream_start(stream);
544 		if (err != 0) {
545 			LOG_DBG("Failed to start stream %p", stream);
546 			btp_send_ascs_operation_completed_ev(stream->conn, u_stream->ase_id,
547 							     BT_ASCS_ENABLE_OP,
548 							     BTP_ASCS_STATUS_FAILED);
549 
550 			return;
551 		}
552 	}
553 
554 	btp_send_ascs_operation_completed_ev(stream->conn, u_stream->ase_id,
555 					     BT_ASCS_ENABLE_OP, BTP_ASCS_STATUS_SUCCESS);
556 }
557 
stream_metadata_updated(struct bt_bap_stream * stream)558 static void stream_metadata_updated(struct bt_bap_stream *stream)
559 {
560 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
561 
562 	LOG_DBG("Metadata updated stream %p", stream);
563 	btp_send_ascs_operation_completed_ev(stream->conn, u_stream->ase_id,
564 					     BT_ASCS_METADATA_OP, BTP_ASCS_STATUS_SUCCESS);
565 }
566 
stream_disabled(struct bt_bap_stream * stream)567 static void stream_disabled(struct bt_bap_stream *stream)
568 {
569 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
570 
571 	LOG_DBG("Disabled stream %p", stream);
572 
573 	btp_send_ascs_operation_completed_ev(stream->conn, u_stream->ase_id,
574 					     BT_ASCS_DISABLE_OP, BTP_ASCS_STATUS_SUCCESS);
575 }
576 
stream_released(struct bt_bap_stream * stream)577 static void stream_released(struct bt_bap_stream *stream)
578 {
579 	uint8_t cig_id;
580 	struct bt_bap_ep_info info;
581 	struct btp_bap_unicast_connection *u_conn;
582 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
583 
584 	LOG_DBG("Released stream %p", stream);
585 
586 	u_conn = &connections[u_stream->conn_id];
587 
588 	if (stream->ep != NULL) {
589 		(void)bt_bap_ep_get_info(stream->ep, &info);
590 		if (info.dir == BT_AUDIO_DIR_SINK) {
591 			u_conn->configured_sink_stream_count--;
592 		} else {
593 			u_conn->configured_source_stream_count--;
594 		}
595 	}
596 
597 	cig_id = u_stream->cig_id;
598 	btp_bap_unicast_stream_free(u_stream);
599 
600 	if (cigs[cig_id].in_use == true &&
601 	    u_conn->configured_sink_stream_count == 0 &&
602 	    u_conn->configured_source_stream_count == 0) {
603 		struct btp_bap_unicast_group *u_cig = &cigs[cig_id];
604 
605 		/* The unicast group will be deleted only at release of the last stream */
606 		LOG_DBG("Deleting unicast group");
607 
608 		int err = bt_bap_unicast_group_delete(u_cig->cig);
609 
610 		if (err != 0) {
611 			LOG_DBG("Unable to delete unicast group: %d", err);
612 
613 			return;
614 		}
615 
616 		memset(u_cig, 0, sizeof(*u_cig));
617 	}
618 }
619 
stream_started(struct bt_bap_stream * stream)620 static void stream_started(struct bt_bap_stream *stream)
621 {
622 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
623 	struct bt_bap_ep_info info;
624 
625 	/* Callback called on transition to Streaming state */
626 
627 	LOG_DBG("Started stream %p", stream);
628 
629 	/* Start TX */
630 	if (btp_bap_audio_stream_can_send(&u_stream->audio_stream)) {
631 		int err;
632 
633 		err = btp_bap_audio_stream_tx_register(&u_stream->audio_stream);
634 		if (err != 0) {
635 			LOG_ERR("Failed to register stream: %d", err);
636 		}
637 	}
638 
639 	(void)bt_bap_ep_get_info(stream->ep, &info);
640 	btp_send_ascs_ase_state_changed_ev(stream->conn, u_stream->ase_id, info.state);
641 }
642 
stream_connected(struct bt_bap_stream * stream)643 static void stream_connected(struct bt_bap_stream *stream)
644 {
645 	struct bt_conn_info conn_info;
646 	struct bt_bap_ep_info ep_info;
647 	int err;
648 
649 	LOG_DBG("Connected stream %p", stream);
650 
651 	(void)bt_bap_ep_get_info(stream->ep, &ep_info);
652 	(void)bt_conn_get_info(stream->conn, &conn_info);
653 	if (conn_info.role == BT_HCI_ROLE_CENTRAL && ep_info.dir == BT_AUDIO_DIR_SOURCE) {
654 		/* Automatically do the receiver start ready operation for source ASEs as the client
655 		 */
656 		err = bt_bap_stream_start(stream);
657 		if (err != 0) {
658 			LOG_ERR("Failed to start stream %p", stream);
659 		}
660 	}
661 }
662 
stream_stopped(struct bt_bap_stream * stream,uint8_t reason)663 static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason)
664 {
665 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
666 
667 	LOG_DBG("Stopped stream %p with reason 0x%02X", stream, reason);
668 
669 	if (btp_bap_audio_stream_can_send(&u_stream->audio_stream)) {
670 		int err;
671 
672 		err = btp_bap_audio_stream_tx_unregister(&u_stream->audio_stream);
673 		if (err != 0) {
674 			LOG_ERR("Failed to unregister stream: %d", err);
675 		}
676 	}
677 
678 	btp_send_ascs_operation_completed_ev(stream->conn, u_stream->ase_id,
679 					     BT_ASCS_STOP_OP, BTP_STATUS_SUCCESS);
680 }
681 
send_stream_received_ev(struct bt_conn * conn,struct bt_bap_ep * ep,uint8_t data_len,uint8_t * data)682 static void send_stream_received_ev(struct bt_conn *conn, struct bt_bap_ep *ep,
683 				    uint8_t data_len, uint8_t *data)
684 {
685 	struct btp_bap_stream_received_ev *ev;
686 
687 	tester_rsp_buffer_lock();
688 	tester_rsp_buffer_allocate(sizeof(*ev) + data_len, (uint8_t **)&ev);
689 
690 	LOG_DBG("Stream received, ep %d, dir %d, len %d", ep->status.id, ep->dir,
691 		data_len);
692 
693 	bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn));
694 
695 	ev->ase_id = ep->status.id;
696 	ev->data_len = data_len;
697 	memcpy(ev->data, data, data_len);
698 
699 	tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_STREAM_RECEIVED, ev, sizeof(*ev) + data_len);
700 
701 	tester_rsp_buffer_free();
702 	tester_rsp_buffer_unlock();
703 }
704 
stream_recv(struct bt_bap_stream * stream,const struct bt_iso_recv_info * info,struct net_buf * buf)705 static void stream_recv(struct bt_bap_stream *stream,
706 			const struct bt_iso_recv_info *info,
707 			struct net_buf *buf)
708 {
709 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
710 
711 	if (u_stream->already_sent == false) {
712 		/* For now, send just a first packet, to limit the number
713 		 * of logs and not unnecessarily spam through btp.
714 		 */
715 		LOG_DBG("Incoming audio on stream %p len %u flags 0x%02X seq_num %u and ts %u",
716 			stream, buf->len, info->flags, info->seq_num, info->ts);
717 
718 		if ((info->flags & BT_ISO_FLAGS_VALID) == 0) {
719 			u_stream->already_sent = true;
720 			send_stream_received_ev(stream->conn, stream->ep, buf->len, buf->data);
721 		}
722 	}
723 }
724 
725 static struct bt_bap_stream_ops stream_ops = {
726 	.configured = stream_configured,
727 	.qos_set = stream_qos_set,
728 	.enabled = stream_enabled,
729 	.metadata_updated = stream_metadata_updated,
730 	.disabled = stream_disabled,
731 	.released = stream_released,
732 	.started = stream_started,
733 	.stopped = stream_stopped,
734 	.recv = stream_recv,
735 	.sent = btp_bap_audio_stream_sent_cb,
736 	.connected = stream_connected,
737 };
738 
btp_bap_unicast_stream_alloc(struct btp_bap_unicast_connection * conn)739 struct btp_bap_unicast_stream *btp_bap_unicast_stream_alloc(
740 	struct btp_bap_unicast_connection *conn)
741 {
742 	for (size_t i = 0; i < ARRAY_SIZE(conn->streams); i++) {
743 		struct btp_bap_unicast_stream *stream = &conn->streams[i];
744 
745 		if (stream->in_use == false) {
746 			bt_bap_stream_cb_register(stream_unicast_to_bap(stream), &stream_ops);
747 			stream->in_use = true;
748 
749 			return stream;
750 		}
751 	}
752 
753 	return NULL;
754 }
755 
unicast_client_location_cb(struct bt_conn * conn,enum bt_audio_dir dir,enum bt_audio_location loc)756 static void unicast_client_location_cb(struct bt_conn *conn,
757 				       enum bt_audio_dir dir,
758 				       enum bt_audio_location loc)
759 {
760 	LOG_DBG("dir %u loc %X", dir, loc);
761 }
762 
available_contexts_cb(struct bt_conn * conn,enum bt_audio_context snk_ctx,enum bt_audio_context src_ctx)763 static void available_contexts_cb(struct bt_conn *conn,
764 				  enum bt_audio_context snk_ctx,
765 				  enum bt_audio_context src_ctx)
766 {
767 	LOG_DBG("snk ctx %u src ctx %u", snk_ctx, src_ctx);
768 }
769 
config_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)770 static void config_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
771 		      enum bt_bap_ascs_reason reason)
772 {
773 	LOG_DBG("stream %p config operation rsp_code %u reason %u", stream, rsp_code, reason);
774 }
775 
qos_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)776 static void qos_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
777 		   enum bt_bap_ascs_reason reason)
778 {
779 	LOG_DBG("stream %p qos operation rsp_code %u reason %u", stream, rsp_code, reason);
780 }
781 
enable_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)782 static void enable_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
783 		      enum bt_bap_ascs_reason reason)
784 {
785 	LOG_DBG("stream %p enable operation rsp_code %u reason %u", stream, rsp_code, reason);
786 }
787 
start_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)788 static void start_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
789 		     enum bt_bap_ascs_reason reason)
790 {
791 	struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream);
792 
793 	/* Callback called on Receiver Start Ready notification from ASE Control Point */
794 
795 	LOG_DBG("stream %p start operation rsp_code %u reason %u", stream, rsp_code, reason);
796 	u_stream->already_sent = false;
797 
798 	btp_send_ascs_operation_completed_ev(stream->conn, u_stream->ase_id,
799 					     BT_ASCS_START_OP, BTP_STATUS_SUCCESS);
800 }
801 
stop_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)802 static void stop_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
803 		    enum bt_bap_ascs_reason reason)
804 {
805 	LOG_DBG("stream %p stop operation rsp_code %u reason %u", stream, rsp_code, reason);
806 }
807 
disable_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)808 static void disable_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
809 		       enum bt_bap_ascs_reason reason)
810 {
811 	LOG_DBG("stream %p disable operation rsp_code %u reason %u", stream, rsp_code, reason);
812 }
813 
metadata_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)814 static void metadata_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
815 			enum bt_bap_ascs_reason reason)
816 {
817 	LOG_DBG("stream %p metadata operation rsp_code %u reason %u", stream, rsp_code, reason);
818 }
819 
release_cb(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)820 static void release_cb(struct bt_bap_stream *stream, enum bt_bap_ascs_rsp_code rsp_code,
821 		       enum bt_bap_ascs_reason reason)
822 {
823 	LOG_DBG("stream %p release operation rsp_code %u reason %u", stream, rsp_code, reason);
824 }
825 
pac_record_cb(struct bt_conn * conn,enum bt_audio_dir dir,const struct bt_audio_codec_cap * codec_cap)826 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir,
827 			  const struct bt_audio_codec_cap *codec_cap)
828 {
829 	LOG_DBG("");
830 
831 	if (codec_cap != NULL) {
832 		LOG_DBG("Discovered codec capabilities %p", codec_cap);
833 		print_codec_cap(codec_cap);
834 		btp_send_pac_codec_found_ev(conn, codec_cap, dir);
835 	}
836 }
837 
btp_send_discovery_completed_ev(struct bt_conn * conn,uint8_t status)838 static void btp_send_discovery_completed_ev(struct bt_conn *conn, uint8_t status)
839 {
840 	struct btp_bap_discovery_completed_ev ev;
841 
842 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
843 	ev.status = status;
844 
845 	tester_event(BTP_SERVICE_ID_BAP, BTP_BAP_EV_DISCOVERY_COMPLETED, &ev, sizeof(ev));
846 }
847 
endpoint_cb(struct bt_conn * conn,enum bt_audio_dir dir,struct bt_bap_ep * ep)848 static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
849 {
850 	struct btp_bap_unicast_connection *u_conn;
851 
852 	LOG_DBG("");
853 
854 	if (ep != NULL) {
855 		LOG_DBG("Discovered ASE %p, id %u, dir 0x%02x", ep, ep->status.id, ep->dir);
856 
857 		u_conn = &connections[bt_conn_index(conn)];
858 
859 		if (u_conn->end_points_count >= CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT +
860 						    CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT) {
861 			LOG_DBG("Failed to cache ep %p due to configured limit: %zu", ep,
862 				u_conn->end_points_count);
863 
864 			btp_send_discovery_completed_ev(conn, BTP_BAP_DISCOVERY_STATUS_FAILED);
865 
866 			return;
867 		}
868 
869 		u_conn->end_points[u_conn->end_points_count++] = ep;
870 		btp_send_ase_found_ev(conn, ep);
871 
872 		return;
873 	}
874 }
875 
discover_cb(struct bt_conn * conn,int err,enum bt_audio_dir dir)876 static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
877 {
878 	LOG_DBG("");
879 
880 	if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
881 		LOG_DBG("Discover remote ASEs failed: %d", err);
882 		btp_send_discovery_completed_ev(conn, BTP_BAP_DISCOVERY_STATUS_FAILED);
883 		return;
884 	}
885 
886 	LOG_DBG("Discover complete");
887 
888 	if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
889 		LOG_DBG("Discover remote ASEs completed without finding any source ASEs");
890 	} else {
891 		LOG_DBG("Discover remote ASEs complete: err %d", err);
892 	}
893 
894 	if (dir == BT_AUDIO_DIR_SINK) {
895 		err = bt_bap_unicast_client_discover(conn, BT_AUDIO_DIR_SOURCE);
896 
897 		if (err != 0) {
898 			LOG_DBG("Failed to discover source ASEs: %d", err);
899 			btp_send_discovery_completed_ev(conn, BTP_BAP_DISCOVERY_STATUS_FAILED);
900 		}
901 
902 		return;
903 	}
904 
905 	btp_send_discovery_completed_ev(conn, BTP_BAP_DISCOVERY_STATUS_SUCCESS);
906 }
907 
908 static struct bt_bap_unicast_server_register_param param = {
909 	CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT,
910 	CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT
911 };
912 
913 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
914 	.location = unicast_client_location_cb,
915 	.available_contexts = available_contexts_cb,
916 	.config = config_cb,
917 	.qos = qos_cb,
918 	.enable = enable_cb,
919 	.start = start_cb,
920 	.stop = stop_cb,
921 	.disable = disable_cb,
922 	.metadata = metadata_cb,
923 	.release = release_cb,
924 	.pac_record = pac_record_cb,
925 	.endpoint = endpoint_cb,
926 	.discover = discover_cb,
927 };
928 
btp_bap_discover(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)929 uint8_t btp_bap_discover(const void *cmd, uint16_t cmd_len,
930 			 void *rsp, uint16_t *rsp_len)
931 {
932 	const struct btp_bap_discover_cmd *cp = cmd;
933 	struct bt_conn *conn;
934 	struct btp_bap_unicast_connection *u_conn;
935 	struct bt_conn_info conn_info;
936 	int err;
937 
938 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
939 	if (!conn) {
940 		LOG_ERR("Unknown connection");
941 		return BTP_STATUS_FAILED;
942 	}
943 
944 	u_conn = &connections[bt_conn_index(conn)];
945 	(void)bt_conn_get_info(conn, &conn_info);
946 
947 	if (u_conn->end_points_count > 0 || conn_info.role != BT_HCI_ROLE_CENTRAL) {
948 		bt_conn_unref(conn);
949 
950 		return BTP_STATUS_FAILED;
951 	}
952 
953 	err = bt_bap_unicast_client_discover(conn, BT_AUDIO_DIR_SINK);
954 	if (err != 0) {
955 		LOG_DBG("Failed to discover remote ASEs: %d", err);
956 		bt_conn_unref(conn);
957 
958 		return BTP_STATUS_FAILED;
959 	}
960 
961 	bt_conn_unref(conn);
962 
963 	return BTP_STATUS_SUCCESS;
964 }
965 
server_stream_config(struct bt_conn * conn,struct bt_bap_stream * stream,struct bt_audio_codec_cfg * codec_cfg,struct bt_bap_qos_cfg_pref * qos)966 static int server_stream_config(struct bt_conn *conn, struct bt_bap_stream *stream,
967 				struct bt_audio_codec_cfg *codec_cfg,
968 				struct bt_bap_qos_cfg_pref *qos)
969 {
970 	int err;
971 	struct bt_bap_ep_info info;
972 
973 	err = bt_bap_unicast_server_config_ase(conn, stream, codec_cfg, qos);
974 	if (err != 0) {
975 		return err;
976 	}
977 
978 	print_codec_cfg(codec_cfg);
979 	(void)bt_bap_ep_get_info(stream->ep, &info);
980 
981 	LOG_DBG("ASE Codec Config: ase_id %u dir %u", info.id, info.dir);
982 	LOG_DBG("ASE Codec Config stream %p", stream);
983 
984 	return 0;
985 }
986 
client_add_ase_to_cis(struct btp_bap_unicast_connection * u_conn,uint8_t ase_id,uint8_t cis_id,uint8_t cig_id)987 static uint8_t client_add_ase_to_cis(struct btp_bap_unicast_connection *u_conn, uint8_t ase_id,
988 				     uint8_t cis_id, uint8_t cig_id)
989 {
990 	struct btp_bap_unicast_stream *stream;
991 
992 	if (cig_id >= CONFIG_BT_ISO_MAX_CIG ||
993 	    cis_id >= CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT) {
994 		return -EINVAL;
995 	}
996 
997 	stream = btp_bap_unicast_stream_find(u_conn, ase_id);
998 	if (stream == NULL) {
999 		return -EINVAL;
1000 	}
1001 
1002 	LOG_DBG("Added ASE %u to CIS %u at CIG %u", ase_id, cis_id, cig_id);
1003 
1004 	stream->cig_id = cig_id;
1005 	stream->cis_id = cis_id;
1006 
1007 	return 0;
1008 }
1009 
client_unicast_group_param_set(struct btp_bap_unicast_connection * u_conn,uint8_t cig_id,struct bt_bap_unicast_group_stream_pair_param * pair_params,struct bt_bap_unicast_group_stream_param ** stream_param_ptr)1010 static int client_unicast_group_param_set(struct btp_bap_unicast_connection *u_conn, uint8_t cig_id,
1011 	struct bt_bap_unicast_group_stream_pair_param *pair_params,
1012 	struct bt_bap_unicast_group_stream_param **stream_param_ptr)
1013 {
1014 	struct bt_bap_unicast_group_stream_param *stream_params = *stream_param_ptr;
1015 
1016 	for (size_t i = 0; i < ARRAY_SIZE(u_conn->streams); i++) {
1017 		struct bt_bap_ep_info info;
1018 		struct bt_bap_ep *ep;
1019 		struct btp_bap_unicast_stream *u_stream = &u_conn->streams[i];
1020 		struct bt_bap_stream *stream = stream_unicast_to_bap(u_stream);
1021 
1022 		if (u_stream->in_use == false || u_stream->cig_id != cig_id) {
1023 			continue;
1024 		}
1025 
1026 		ep = btp_bap_unicast_end_point_find(u_conn, u_stream->ase_id);
1027 		if (ep == NULL) {
1028 			return -EINVAL;
1029 		}
1030 
1031 		stream_params->stream = stream;
1032 		stream_params->qos = &cigs[u_stream->cig_id].qos[u_stream->cis_id];
1033 
1034 		(void)bt_bap_ep_get_info(ep, &info);
1035 		if (info.dir == BT_AUDIO_DIR_SOURCE) {
1036 			if (pair_params[u_stream->cis_id].rx_param != NULL) {
1037 				return -EINVAL;
1038 			}
1039 
1040 			pair_params[u_stream->cis_id].rx_param = stream_params;
1041 		} else {
1042 			if (pair_params[u_stream->cis_id].tx_param != NULL) {
1043 				return -EINVAL;
1044 			}
1045 
1046 			pair_params[u_stream->cis_id].tx_param = stream_params;
1047 		}
1048 
1049 		stream_params++;
1050 	}
1051 
1052 	*stream_param_ptr = stream_params;
1053 
1054 	return 0;
1055 }
1056 
btp_bap_unicast_group_create(uint8_t cig_id,struct btp_bap_unicast_group ** out_unicast_group)1057 int btp_bap_unicast_group_create(uint8_t cig_id,
1058 					   struct btp_bap_unicast_group **out_unicast_group)
1059 {
1060 	int err;
1061 	struct bt_bap_unicast_group_stream_pair_param
1062 		pair_params[BTP_BAP_UNICAST_MAX_STREAMS_COUNT];
1063 	struct bt_bap_unicast_group_stream_param stream_params[BTP_BAP_UNICAST_MAX_STREAMS_COUNT];
1064 	struct bt_bap_unicast_group_stream_param *stream_param_ptr;
1065 	struct bt_bap_unicast_group_param param;
1066 	size_t cis_cnt = 0;
1067 
1068 	(void)memset(pair_params, 0, sizeof(pair_params));
1069 	(void)memset(stream_params, 0, sizeof(stream_params));
1070 	*out_unicast_group = NULL;
1071 
1072 	if (cig_id >= CONFIG_BT_ISO_MAX_CIG) {
1073 		return -EINVAL;
1074 	}
1075 
1076 	/* API does not allow to assign a CIG ID freely, so ensure we create groups
1077 	 * in the right order.
1078 	 */
1079 	for (uint8_t i = 0; i < cig_id; i++) {
1080 		if (cigs[i].in_use == false) {
1081 			return -EINVAL;
1082 		}
1083 	}
1084 
1085 	if (cigs[cig_id].in_use == true) {
1086 		struct btp_bap_unicast_group *u_cig = &cigs[cig_id];
1087 
1088 		err = bt_bap_unicast_group_delete(u_cig->cig);
1089 		if (err != 0) {
1090 			LOG_DBG("Failed to delete the unicast group, err %d", err);
1091 
1092 			return BTP_STATUS_FAILED;
1093 		}
1094 
1095 		memset(u_cig, 0, sizeof(*u_cig));
1096 	}
1097 
1098 	stream_param_ptr = stream_params;
1099 	for (size_t i = 0; i < CONFIG_BT_MAX_CONN; i++) {
1100 		struct btp_bap_unicast_connection *unicast_conn = &connections[i];
1101 
1102 		if (unicast_conn->end_points_count == 0) {
1103 			continue;
1104 		}
1105 
1106 		/* CISes have been assigned earlier to CIGs with client_add_ase_to_cis() */
1107 		err = client_unicast_group_param_set(unicast_conn, cig_id, pair_params,
1108 						     &stream_param_ptr);
1109 		if (err != 0) {
1110 			return err;
1111 		}
1112 	}
1113 
1114 	/* Count CISes to be established */
1115 	for (size_t count = ARRAY_SIZE(pair_params); count > 0; --count) {
1116 		size_t i = count - 1;
1117 
1118 		if (pair_params[i].tx_param != NULL || pair_params[i].rx_param != NULL) {
1119 			cis_cnt++;
1120 
1121 			continue;
1122 		}
1123 
1124 		if (cis_cnt > 0) {
1125 			/* No gaps allowed */
1126 			return -EINVAL;
1127 		}
1128 	}
1129 
1130 	param.params = pair_params;
1131 	param.params_count = cis_cnt;
1132 	param.packing = BT_ISO_PACKING_SEQUENTIAL;
1133 
1134 	LOG_DBG("Creating unicast group");
1135 	err = bt_bap_unicast_group_create(&param, &cigs[cig_id].cig);
1136 	if (err != 0) {
1137 		LOG_DBG("Could not create unicast group (err %d)", err);
1138 		return -EINVAL;
1139 	}
1140 
1141 	cigs[cig_id].in_use = true;
1142 	cigs[cig_id].cig_id = cig_id;
1143 	*out_unicast_group = &cigs[cig_id];
1144 
1145 	return 0;
1146 }
1147 
btp_bap_unicast_group_find(uint8_t cig_id)1148 struct btp_bap_unicast_group *btp_bap_unicast_group_find(uint8_t cig_id)
1149 {
1150 	if (cig_id >= CONFIG_BT_ISO_MAX_CIG) {
1151 		return NULL;
1152 	}
1153 
1154 	return &cigs[cig_id];
1155 }
1156 
client_configure_codec(struct btp_bap_unicast_connection * u_conn,struct bt_conn * conn,uint8_t ase_id,struct bt_audio_codec_cfg * codec_cfg)1157 static int client_configure_codec(struct btp_bap_unicast_connection *u_conn, struct bt_conn *conn,
1158 				  uint8_t ase_id, struct bt_audio_codec_cfg *codec_cfg)
1159 {
1160 	int err;
1161 	struct bt_bap_ep *ep;
1162 	struct btp_bap_unicast_stream *stream;
1163 
1164 	stream = btp_bap_unicast_stream_find(u_conn, ase_id);
1165 	if (stream == NULL) {
1166 		/* Configure a new stream */
1167 		stream = btp_bap_unicast_stream_alloc(u_conn);
1168 		if (stream == NULL) {
1169 			LOG_DBG("No streams available");
1170 
1171 			return -ENOMEM;
1172 		}
1173 
1174 		if (u_conn->end_points_count == 0) {
1175 			return -EINVAL;
1176 		}
1177 
1178 		ep = btp_bap_unicast_end_point_find(u_conn, ase_id);
1179 		if (ep == NULL) {
1180 			return -EINVAL;
1181 		}
1182 
1183 		memcpy(&stream->codec_cfg, codec_cfg, sizeof(*codec_cfg));
1184 		err = bt_bap_stream_config(conn, stream_unicast_to_bap(stream), ep,
1185 					   &stream->codec_cfg);
1186 	} else {
1187 		/* Reconfigure a stream */
1188 		memcpy(&stream->codec_cfg, codec_cfg, sizeof(*codec_cfg));
1189 		err = bt_bap_stream_reconfig(stream_unicast_to_bap(stream),
1190 					     &stream->codec_cfg);
1191 	}
1192 
1193 	return err;
1194 }
1195 
server_configure_codec(struct btp_bap_unicast_connection * u_conn,struct bt_conn * conn,uint8_t ase_id,struct bt_audio_codec_cfg * codec_cfg)1196 static int server_configure_codec(struct btp_bap_unicast_connection *u_conn, struct bt_conn *conn,
1197 				  uint8_t ase_id, struct bt_audio_codec_cfg *codec_cfg)
1198 {
1199 	struct btp_bap_unicast_stream *stream;
1200 	int err = 0;
1201 
1202 	stream = btp_bap_unicast_stream_find(u_conn, ase_id);
1203 	if (stream == NULL) {
1204 		/* Zephyr allocates ASE instances for remote clients dynamically.
1205 		 * To initiate Codec Config operation autonomously in server the role,
1206 		 * we have to initialize all ASEs with a smaller ID first.
1207 		 * Fortunately, the PTS has nothing against such behavior.
1208 		 */
1209 		for (uint8_t i = 1; i <= ase_id; i++) {
1210 			stream = btp_bap_unicast_stream_find(u_conn, i);
1211 			if (stream != NULL) {
1212 				continue;
1213 			}
1214 
1215 			/* Configure a new stream */
1216 			stream = btp_bap_unicast_stream_alloc(u_conn);
1217 			if (stream == NULL) {
1218 				LOG_DBG("No streams available");
1219 
1220 				return -ENOMEM;
1221 			}
1222 
1223 			memcpy(&stream->codec_cfg, codec_cfg, sizeof(*codec_cfg));
1224 			err = server_stream_config(conn, stream_unicast_to_bap(stream),
1225 						   &stream->codec_cfg, &qos_pref);
1226 		}
1227 	} else {
1228 		/* Reconfigure a stream */
1229 		memcpy(&stream->codec_cfg, codec_cfg, sizeof(*codec_cfg));
1230 		err = bt_bap_stream_reconfig(stream_unicast_to_bap(stream), &stream->codec_cfg);
1231 	}
1232 
1233 	return err;
1234 }
1235 
btp_ascs_configure_codec(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1236 uint8_t btp_ascs_configure_codec(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
1237 {
1238 	int err;
1239 	const struct btp_ascs_configure_codec_cmd *cp = cmd;
1240 	struct bt_conn *conn;
1241 	struct bt_conn_info conn_info;
1242 	struct btp_bap_unicast_connection *u_conn;
1243 	struct bt_audio_codec_cfg codec_cfg;
1244 
1245 	LOG_DBG("");
1246 
1247 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
1248 	if (!conn) {
1249 		LOG_ERR("Unknown connection");
1250 		return BTP_STATUS_FAILED;
1251 	}
1252 
1253 	u_conn = &connections[bt_conn_index(conn)];
1254 
1255 	(void)bt_conn_get_info(conn, &conn_info);
1256 
1257 	memset(&codec_cfg, 0, sizeof(codec_cfg));
1258 
1259 	codec_cfg.id = cp->coding_format;
1260 	codec_cfg.vid = cp->vid;
1261 	codec_cfg.cid = cp->cid;
1262 
1263 	if (cp->cc_ltvs_len != 0) {
1264 		codec_cfg.data_len = cp->cc_ltvs_len;
1265 		memcpy(codec_cfg.data, cp->cc_ltvs, cp->cc_ltvs_len);
1266 	}
1267 
1268 	if (conn_info.role == BT_HCI_ROLE_CENTRAL) {
1269 		err = client_configure_codec(u_conn, conn, cp->ase_id, &codec_cfg);
1270 	} else {
1271 		err = server_configure_codec(u_conn, conn, cp->ase_id, &codec_cfg);
1272 	}
1273 
1274 	bt_conn_unref(conn);
1275 
1276 	if (err) {
1277 		LOG_DBG("Failed to configure stream (err %d)", err);
1278 		return BTP_STATUS_FAILED;
1279 	}
1280 
1281 	return BTP_STATUS_SUCCESS;
1282 }
1283 
btp_ascs_preconfigure_qos(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1284 uint8_t btp_ascs_preconfigure_qos(const void *cmd, uint16_t cmd_len,
1285 				  void *rsp, uint16_t *rsp_len)
1286 {
1287 	const struct btp_ascs_preconfigure_qos_cmd *cp = cmd;
1288 	struct bt_bap_qos_cfg *qos;
1289 
1290 	LOG_DBG("");
1291 
1292 	qos = &cigs[cp->cig_id].qos[cp->cis_id];
1293 	memset(qos, 0, sizeof(*qos));
1294 
1295 	qos->phy = BT_BAP_QOS_CFG_2M;
1296 	qos->framing = cp->framing;
1297 	qos->rtn = cp->retransmission_num;
1298 	qos->sdu = sys_le16_to_cpu(cp->max_sdu);
1299 	qos->latency = sys_le16_to_cpu(cp->max_transport_latency);
1300 	qos->interval = sys_get_le24(cp->sdu_interval);
1301 	qos->pd = sys_get_le24(cp->presentation_delay);
1302 
1303 	return BTP_STATUS_SUCCESS;
1304 }
1305 
btp_ascs_configure_qos(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1306 uint8_t btp_ascs_configure_qos(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
1307 {
1308 	int err;
1309 	const struct btp_ascs_configure_qos_cmd *cp = cmd;
1310 	struct bt_conn_info conn_info;
1311 	struct bt_conn *conn;
1312 	struct btp_bap_unicast_group *out_unicast_group;
1313 
1314 	LOG_DBG("");
1315 
1316 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
1317 	if (!conn) {
1318 		LOG_ERR("Unknown connection");
1319 
1320 		return BTP_STATUS_FAILED;
1321 	}
1322 
1323 	(void)bt_conn_get_info(conn, &conn_info);
1324 	if (conn_info.role == BT_HCI_ROLE_PERIPHERAL) {
1325 		bt_conn_unref(conn);
1326 
1327 		return BTP_STATUS_FAILED;
1328 	}
1329 
1330 	if (cigs[cp->cig_id].in_use == false) {
1331 		err = btp_bap_unicast_group_create(cp->cig_id, &out_unicast_group);
1332 		if (err != 0) {
1333 			LOG_DBG("Unable to create unicast group, err %d", err);
1334 			bt_conn_unref(conn);
1335 
1336 			return BTP_STATUS_FAILED;
1337 		}
1338 	}
1339 
1340 	LOG_DBG("QoS configuring streams");
1341 	err = bt_bap_stream_qos(conn, cigs[cp->cig_id].cig);
1342 	bt_conn_unref(conn);
1343 
1344 	if (err != 0) {
1345 		LOG_DBG("Unable to QoS configure streams: %d", err);
1346 
1347 		return BTP_STATUS_FAILED;
1348 	}
1349 
1350 	return BTP_STATUS_SUCCESS;
1351 }
1352 
btp_ascs_enable(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1353 uint8_t btp_ascs_enable(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
1354 {
1355 	int err;
1356 	const struct btp_ascs_enable_cmd *cp = cmd;
1357 	struct btp_bap_unicast_connection *u_conn;
1358 	struct btp_bap_unicast_stream *stream;
1359 	struct bt_conn *conn;
1360 
1361 	LOG_DBG("");
1362 
1363 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
1364 	if (!conn) {
1365 		LOG_ERR("Unknown connection");
1366 		return BTP_STATUS_FAILED;
1367 	}
1368 
1369 	u_conn = &connections[bt_conn_index(conn)];
1370 	bt_conn_unref(conn);
1371 
1372 	stream = btp_bap_unicast_stream_find(u_conn, cp->ase_id);
1373 	if (stream == NULL) {
1374 		return BTP_STATUS_FAILED;
1375 	}
1376 
1377 	LOG_DBG("Enabling stream");
1378 	err = bt_bap_stream_enable(stream_unicast_to_bap(stream), NULL, 0);
1379 	if (err != 0) {
1380 		LOG_DBG("Could not enable stream: %d", err);
1381 		return BTP_STATUS_FAILED;
1382 	}
1383 
1384 	return BTP_STATUS_SUCCESS;
1385 }
1386 
btp_ascs_disable(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1387 uint8_t btp_ascs_disable(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
1388 {
1389 	int err;
1390 	const struct btp_ascs_disable_cmd *cp = cmd;
1391 	struct btp_bap_unicast_connection *u_conn;
1392 	struct btp_bap_unicast_stream *stream;
1393 	struct bt_conn *conn;
1394 
1395 	LOG_DBG("");
1396 
1397 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
1398 	if (!conn) {
1399 		LOG_ERR("Unknown connection");
1400 		return BTP_STATUS_FAILED;
1401 	}
1402 
1403 	u_conn = &connections[bt_conn_index(conn)];
1404 	bt_conn_unref(conn);
1405 
1406 	stream = btp_bap_unicast_stream_find(u_conn, cp->ase_id);
1407 	if (stream == NULL) {
1408 		return BTP_STATUS_FAILED;
1409 	}
1410 
1411 	LOG_DBG("Disabling stream");
1412 
1413 	err = bt_bap_stream_disable(stream_unicast_to_bap(stream));
1414 	if (err != 0) {
1415 		LOG_DBG("Could not disable stream: %d", err);
1416 		return BTP_STATUS_FAILED;
1417 	}
1418 
1419 	return BTP_STATUS_SUCCESS;
1420 }
1421 
btp_ascs_receiver_start_ready(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1422 uint8_t btp_ascs_receiver_start_ready(const void *cmd, uint16_t cmd_len,
1423 				      void *rsp, uint16_t *rsp_len)
1424 {
1425 	int err;
1426 	const struct btp_ascs_receiver_start_ready_cmd *cp = cmd;
1427 	struct btp_bap_unicast_connection *u_conn;
1428 	struct btp_bap_unicast_stream *stream;
1429 	struct bt_bap_stream *bap_stream;
1430 	struct bt_bap_ep_info info;
1431 	struct bt_conn *conn;
1432 
1433 	LOG_DBG("");
1434 
1435 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
1436 	if (!conn) {
1437 		LOG_ERR("Unknown connection");
1438 		return BTP_STATUS_FAILED;
1439 	}
1440 
1441 	u_conn = &connections[bt_conn_index(conn)];
1442 	bt_conn_unref(conn);
1443 
1444 	stream = btp_bap_unicast_stream_find(u_conn, cp->ase_id);
1445 	if (stream == NULL) {
1446 		return BTP_STATUS_FAILED;
1447 	}
1448 
1449 	bap_stream = stream_unicast_to_bap(stream);
1450 	(void)bt_bap_ep_get_info(bap_stream->ep, &info);
1451 	if (info.state == BT_BAP_EP_STATE_STREAMING) {
1452 		/* Already started */
1453 		return BTP_STATUS_SUCCESS;
1454 	}
1455 
1456 	LOG_DBG("Starting stream %p, ep %u, dir %u", bap_stream, cp->ase_id, info.dir);
1457 
1458 	while (true) {
1459 		err = bt_bap_stream_connect(bap_stream);
1460 		if (err == -EBUSY) {
1461 			/* TODO: How to determine if a controller is ready again after
1462 			 * bt_bap_stream_start? In AC 6(i) tests the PTS sends Receiver Start Ready
1463 			 * only after all CISes are established.
1464 			 */
1465 			k_sleep(K_MSEC(1000));
1466 			continue;
1467 		} else if (err != 0 && err != -EALREADY) {
1468 			LOG_DBG("Could not connect stream: %d", err);
1469 			return BTP_STATUS_FAILED;
1470 		}
1471 
1472 		break;
1473 	};
1474 
1475 	return BTP_STATUS_SUCCESS;
1476 }
1477 
btp_ascs_receiver_stop_ready(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1478 uint8_t btp_ascs_receiver_stop_ready(const void *cmd, uint16_t cmd_len,
1479 				     void *rsp, uint16_t *rsp_len)
1480 {
1481 	int err;
1482 	const struct btp_ascs_receiver_stop_ready_cmd *cp = cmd;
1483 	struct btp_bap_unicast_connection *u_conn;
1484 	struct btp_bap_unicast_stream *stream;
1485 	struct bt_conn *conn;
1486 
1487 	LOG_DBG("");
1488 
1489 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
1490 	if (!conn) {
1491 		LOG_ERR("Unknown connection");
1492 		return BTP_STATUS_FAILED;
1493 	}
1494 
1495 	u_conn = &connections[bt_conn_index(conn)];
1496 	bt_conn_unref(conn);
1497 
1498 	stream = btp_bap_unicast_stream_find(u_conn, cp->ase_id);
1499 	if (stream == NULL) {
1500 		return BTP_STATUS_FAILED;
1501 	}
1502 
1503 	LOG_DBG("Stopping stream");
1504 	err = bt_bap_stream_stop(stream_unicast_to_bap(stream));
1505 	if (err != 0) {
1506 		LOG_DBG("Could not stop stream: %d", err);
1507 		return BTP_STATUS_FAILED;
1508 	}
1509 
1510 	return BTP_STATUS_SUCCESS;
1511 }
1512 
btp_ascs_release(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1513 uint8_t btp_ascs_release(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
1514 {
1515 	int err;
1516 	const struct btp_ascs_release_cmd *cp = cmd;
1517 	struct btp_bap_unicast_connection *u_conn;
1518 	struct btp_bap_unicast_stream *stream;
1519 	struct bt_conn *conn;
1520 
1521 	LOG_DBG("");
1522 
1523 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
1524 	if (!conn) {
1525 		LOG_ERR("Unknown connection");
1526 		return BTP_STATUS_FAILED;
1527 	}
1528 
1529 	u_conn = &connections[bt_conn_index(conn)];
1530 	bt_conn_unref(conn);
1531 
1532 	stream = btp_bap_unicast_stream_find(u_conn, cp->ase_id);
1533 	if (stream == NULL) {
1534 		return BTP_STATUS_FAILED;
1535 	}
1536 
1537 	LOG_DBG("Releasing stream");
1538 	err = bt_bap_stream_release(stream_unicast_to_bap(stream));
1539 	if (err != 0) {
1540 		LOG_DBG("Unable to release stream, err %d", err);
1541 		return BTP_STATUS_FAILED;
1542 	}
1543 
1544 	return BTP_STATUS_SUCCESS;
1545 }
1546 
btp_ascs_update_metadata(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1547 uint8_t btp_ascs_update_metadata(const void *cmd, uint16_t cmd_len,
1548 				 void *rsp, uint16_t *rsp_len)
1549 {
1550 	const uint8_t meta[] = {
1551 		BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT,
1552 				    BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_ANY)),
1553 	};
1554 	const struct btp_ascs_update_metadata_cmd *cp = cmd;
1555 	struct btp_bap_unicast_connection *u_conn;
1556 	struct btp_bap_unicast_stream *stream;
1557 	struct bt_conn *conn;
1558 	int err;
1559 
1560 	LOG_DBG("");
1561 
1562 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
1563 	if (!conn) {
1564 		LOG_ERR("Unknown connection");
1565 		return BTP_STATUS_FAILED;
1566 	}
1567 
1568 	u_conn = &connections[bt_conn_index(conn)];
1569 	bt_conn_unref(conn);
1570 
1571 	stream = btp_bap_unicast_stream_find(u_conn, cp->ase_id);
1572 	if (stream == NULL) {
1573 		return BTP_STATUS_FAILED;
1574 	}
1575 
1576 	LOG_DBG("Updating stream metadata");
1577 	err = bt_bap_stream_metadata(stream_unicast_to_bap(stream), meta, ARRAY_SIZE(meta));
1578 	if (err != 0) {
1579 		LOG_DBG("Failed to update stream metadata, err %d", err);
1580 		return BTP_STATUS_FAILED;
1581 	}
1582 
1583 	return BTP_STATUS_SUCCESS;
1584 }
1585 
btp_ascs_add_ase_to_cis(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)1586 uint8_t btp_ascs_add_ase_to_cis(const void *cmd, uint16_t cmd_len,
1587 				void *rsp, uint16_t *rsp_len)
1588 {
1589 	int err;
1590 	struct bt_conn *conn;
1591 	struct btp_bap_unicast_connection *u_conn;
1592 	struct bt_conn_info conn_info;
1593 	const struct btp_ascs_add_ase_to_cis *cp = cmd;
1594 
1595 	LOG_DBG("");
1596 
1597 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
1598 	if (!conn) {
1599 		LOG_ERR("Unknown connection");
1600 
1601 		return BTP_STATUS_FAILED;
1602 	}
1603 
1604 	(void)bt_conn_get_info(conn, &conn_info);
1605 	if (conn_info.role == BT_HCI_ROLE_PERIPHERAL) {
1606 		bt_conn_unref(conn);
1607 
1608 		return BTP_STATUS_FAILED;
1609 	}
1610 
1611 	u_conn = &connections[bt_conn_index(conn)];
1612 	bt_conn_unref(conn);
1613 
1614 	err = client_add_ase_to_cis(u_conn, cp->ase_id, cp->cis_id, cp->cig_id);
1615 
1616 	return BTP_STATUS_VAL(err);
1617 }
1618 
btp_bap_unicast_conn_get(size_t conn_index)1619 struct btp_bap_unicast_connection *btp_bap_unicast_conn_get(size_t conn_index)
1620 {
1621 	return &connections[conn_index];
1622 }
1623 
connected(struct bt_conn * conn,uint8_t err)1624 static void connected(struct bt_conn *conn, uint8_t err)
1625 {
1626 	struct btp_bap_unicast_connection *u_conn;
1627 	char addr[BT_ADDR_LE_STR_LEN];
1628 
1629 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
1630 
1631 	if (err != 0) {
1632 		LOG_DBG("Failed to connect to %s (%u)", addr, err);
1633 		return;
1634 	}
1635 
1636 	LOG_DBG("Connected: %s", addr);
1637 
1638 	u_conn = &connections[bt_conn_index(conn)];
1639 	memset(u_conn, 0, sizeof(*u_conn));
1640 	bt_addr_le_copy(&u_conn->address, bt_conn_get_dst(conn));
1641 }
1642 
disconnected(struct bt_conn * conn,uint8_t reason)1643 static void disconnected(struct bt_conn *conn, uint8_t reason)
1644 {
1645 	char addr[BT_ADDR_LE_STR_LEN];
1646 
1647 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
1648 
1649 	LOG_DBG("Disconnected: %s (reason 0x%02x)", addr, reason);
1650 }
1651 
1652 static struct bt_conn_cb conn_callbacks = {
1653 	.connected = connected,
1654 	.disconnected = disconnected,
1655 };
1656 
1657 static bool unicast_inited;
1658 
btp_bap_unicast_init(void)1659 int btp_bap_unicast_init(void)
1660 {
1661 	int err;
1662 
1663 	if (unicast_inited) {
1664 		return 0;
1665 	}
1666 
1667 	(void)memset(connections, 0, sizeof(connections));
1668 
1669 	err = bt_bap_unicast_server_register(&param);
1670 	if (err != 0) {
1671 		LOG_DBG("Failed to register unicast server (err %d)\n", err);
1672 
1673 		return err;
1674 	}
1675 
1676 	err = bt_bap_unicast_server_register_cb(&unicast_server_cb);
1677 	if (err != 0) {
1678 		LOG_DBG("Failed to register client callbacks: %d", err);
1679 		return err;
1680 	}
1681 
1682 	err = bt_bap_unicast_client_register_cb(&unicast_client_cbs);
1683 	if (err != 0) {
1684 		LOG_DBG("Failed to register client callbacks: %d", err);
1685 		return err;
1686 	}
1687 
1688 	bt_conn_cb_register(&conn_callbacks);
1689 
1690 	unicast_inited = true;
1691 
1692 	return 0;
1693 }
1694