1 /* btp_cap.c - Bluetooth CAP Tester */
2 
3 /*
4  * Copyright (c) 2023 Codecoup
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 #include <errno.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include <zephyr/autoconf.h>
14 #include <zephyr/bluetooth/addr.h>
15 #include <zephyr/bluetooth/audio/audio.h>
16 #include <zephyr/bluetooth/audio/bap.h>
17 #include <zephyr/bluetooth/audio/cap.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/iso.h>
23 #include <zephyr/bluetooth/uuid.h>
24 #include <zephyr/kernel.h>
25 #include <zephyr/logging/log.h>
26 #include <zephyr/net_buf.h>
27 #include <zephyr/sys/byteorder.h>
28 #include <zephyr/sys/util.h>
29 #include <zephyr/sys/util_macro.h>
30 
31 #include "btp/btp.h"
32 #include "btp_bap_audio_stream.h"
33 #include "bap_endpoint.h"
34 
35 #include "btp_bap_unicast.h"
36 #include "btp_bap_broadcast.h"
37 
38 #define LOG_MODULE_NAME bttester_cap
39 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
40 
41 static struct btp_bap_unicast_group *u_group;
42 
43 static K_SEM_DEFINE(source_stopped_sem, 0U, CONFIG_BT_BAP_BROADCAST_SRC_COUNT);
44 
45 struct cap_initiator_broadcast_params {
46 	struct bt_cap_initiator_broadcast_subgroup_param
47 		cap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
48 	struct bt_cap_initiator_broadcast_stream_param
49 		cap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT]
50 				 [CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
51 };
52 
53 static struct cap_initiator_broadcast_params
54 	cap_broadcast_params[CONFIG_BT_BAP_BROADCAST_SRC_COUNT];
55 
56 
57 extern struct bt_csip_set_coordinator_set_member *btp_csip_set_members[CONFIG_BT_MAX_CONN];
58 
stream_unicast_to_bap(struct btp_bap_unicast_stream * stream)59 static struct bt_bap_stream *stream_unicast_to_bap(struct btp_bap_unicast_stream *stream)
60 {
61 	return &stream->audio_stream.cap_stream.bap_stream;
62 }
63 
stream_unicast_to_cap(struct btp_bap_unicast_stream * stream)64 static struct bt_cap_stream *stream_unicast_to_cap(struct btp_bap_unicast_stream *stream)
65 {
66 	return &stream->audio_stream.cap_stream;
67 }
68 
stream_broadcast_to_cap(struct btp_bap_broadcast_stream * stream)69 static struct bt_cap_stream *stream_broadcast_to_cap(struct btp_bap_broadcast_stream *stream)
70 {
71 	return &stream->audio_stream.cap_stream;
72 }
73 
btp_send_discovery_completed_ev(struct bt_conn * conn,uint8_t status)74 static void btp_send_discovery_completed_ev(struct bt_conn *conn, uint8_t status)
75 {
76 	struct btp_cap_discovery_completed_ev ev;
77 
78 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
79 	ev.status = status;
80 
81 	tester_event(BTP_SERVICE_ID_CAP, BTP_CAP_EV_DISCOVERY_COMPLETED, &ev, sizeof(ev));
82 }
83 
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)84 static void cap_discovery_complete_cb(struct bt_conn *conn, int err,
85 				      const struct bt_csip_set_coordinator_set_member *member,
86 				      const struct bt_csip_set_coordinator_csis_inst *csis_inst)
87 {
88 	LOG_DBG("");
89 
90 	if (err != 0) {
91 		LOG_DBG("Failed to discover CAS: %d", err);
92 		btp_send_discovery_completed_ev(conn, BTP_CAP_DISCOVERY_STATUS_FAILED);
93 
94 		return;
95 	}
96 
97 	if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER)) {
98 		if (csis_inst == NULL) {
99 			LOG_DBG("Failed to discover CAS CSIS");
100 			btp_send_discovery_completed_ev(conn, BTP_CAP_DISCOVERY_STATUS_FAILED);
101 
102 			return;
103 		}
104 
105 		LOG_DBG("Found CAS with CSIS %p", csis_inst);
106 	} else {
107 		LOG_DBG("Found CAS");
108 	}
109 
110 	btp_send_discovery_completed_ev(conn, BTP_CAP_DISCOVERY_STATUS_SUCCESS);
111 }
112 
btp_send_cap_unicast_start_completed_ev(uint8_t cig_id,uint8_t status)113 static void btp_send_cap_unicast_start_completed_ev(uint8_t cig_id, uint8_t status)
114 {
115 	struct btp_cap_unicast_start_completed_ev ev;
116 
117 	ev.cig_id = cig_id;
118 	ev.status = status;
119 
120 	tester_event(BTP_SERVICE_ID_CAP, BTP_CAP_EV_UNICAST_START_COMPLETED, &ev, sizeof(ev));
121 }
122 
btp_send_cap_unicast_stop_completed_ev(uint8_t cig_id,uint8_t status)123 static void btp_send_cap_unicast_stop_completed_ev(uint8_t cig_id, uint8_t status)
124 {
125 	struct btp_cap_unicast_stop_completed_ev ev;
126 
127 	ev.cig_id = cig_id;
128 	ev.status = status;
129 
130 	tester_event(BTP_SERVICE_ID_CAP, BTP_CAP_EV_UNICAST_STOP_COMPLETED, &ev, sizeof(ev));
131 }
132 
unicast_start_complete_cb(int err,struct bt_conn * conn)133 static void unicast_start_complete_cb(int err, struct bt_conn *conn)
134 {
135 	LOG_DBG("");
136 
137 	if (err != 0) {
138 		LOG_DBG("Failed to unicast-start, err %d", err);
139 		btp_send_cap_unicast_start_completed_ev(u_group->cig_id,
140 							BTP_CAP_UNICAST_START_STATUS_FAILED);
141 
142 		return;
143 	}
144 
145 	btp_send_cap_unicast_start_completed_ev(u_group->cig_id,
146 						BTP_CAP_UNICAST_START_STATUS_SUCCESS);
147 }
148 
unicast_update_complete_cb(int err,struct bt_conn * conn)149 static void unicast_update_complete_cb(int err, struct bt_conn *conn)
150 {
151 	LOG_DBG("");
152 
153 	if (err != 0) {
154 		LOG_DBG("Failed to unicast-update, err %d", err);
155 	}
156 }
157 
unicast_stop_complete_cb(int err,struct bt_conn * conn)158 static void unicast_stop_complete_cb(int err, struct bt_conn *conn)
159 {
160 	LOG_DBG("");
161 
162 	if (err != 0) {
163 		LOG_DBG("Failed to unicast-stop, err %d", err);
164 		btp_send_cap_unicast_stop_completed_ev(u_group->cig_id,
165 						       BTP_CAP_UNICAST_START_STATUS_FAILED);
166 
167 		return;
168 	}
169 
170 	btp_send_cap_unicast_stop_completed_ev(u_group->cig_id,
171 					       BTP_CAP_UNICAST_START_STATUS_SUCCESS);
172 }
173 
broadcast_stopped_cb(struct bt_cap_broadcast_source * source,uint8_t reason)174 static void broadcast_stopped_cb(struct bt_cap_broadcast_source *source, uint8_t reason)
175 {
176 	LOG_DBG("");
177 
178 	k_sem_give(&source_stopped_sem);
179 }
180 
181 static struct bt_cap_initiator_cb cap_cb = {
182 	.unicast_discovery_complete = cap_discovery_complete_cb,
183 	.unicast_start_complete = unicast_start_complete_cb,
184 	.unicast_update_complete = unicast_update_complete_cb,
185 	.unicast_stop_complete = unicast_stop_complete_cb,
186 	.broadcast_stopped = broadcast_stopped_cb,
187 };
188 
btp_cap_supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)189 static uint8_t btp_cap_supported_commands(const void *cmd, uint16_t cmd_len,
190 					  void *rsp, uint16_t *rsp_len)
191 {
192 	struct btp_cap_read_supported_commands_rp *rp = rsp;
193 
194 	*rsp_len = tester_supported_commands(BTP_SERVICE_ID_CAP, rp->data);
195 	*rsp_len += sizeof(*rp);
196 
197 	return BTP_STATUS_SUCCESS;
198 }
199 
btp_cap_discover(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)200 static uint8_t btp_cap_discover(const void *cmd, uint16_t cmd_len,
201 				void *rsp, uint16_t *rsp_len)
202 {
203 	const struct btp_cap_discover_cmd *cp = cmd;
204 	struct bt_conn *conn;
205 	int err;
206 
207 	LOG_DBG("");
208 
209 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
210 	if (!conn) {
211 		LOG_ERR("Unknown connection");
212 		return BTP_STATUS_FAILED;
213 	}
214 
215 	err = bt_cap_initiator_unicast_discover(conn);
216 	if (err != 0) {
217 		LOG_DBG("Failed to discover remote ASEs: %d", err);
218 		bt_conn_unref(conn);
219 
220 		return BTP_STATUS_FAILED;
221 	}
222 
223 	bt_conn_unref(conn);
224 
225 	return BTP_STATUS_SUCCESS;
226 }
227 
cap_unicast_setup_ase(struct bt_conn * conn,uint8_t ase_id,uint8_t cis_id,uint8_t cig_id,struct bt_audio_codec_cfg * codec_cfg,struct bt_bap_qos_cfg * qos)228 static int cap_unicast_setup_ase(struct bt_conn *conn, uint8_t ase_id, uint8_t cis_id,
229 				 uint8_t cig_id, struct bt_audio_codec_cfg *codec_cfg,
230 				 struct bt_bap_qos_cfg *qos)
231 {
232 	struct btp_bap_unicast_group *group;
233 	struct btp_bap_unicast_stream *u_stream;
234 	struct bt_bap_stream *stream;
235 	struct btp_bap_unicast_connection *u_conn = btp_bap_unicast_conn_get(bt_conn_index(conn));
236 
237 	u_stream = btp_bap_unicast_stream_find(u_conn, ase_id);
238 	if (u_stream == NULL) {
239 		/* Configure a new u_stream */
240 		u_stream = btp_bap_unicast_stream_alloc(u_conn);
241 		if (u_stream == NULL) {
242 			LOG_DBG("No streams available");
243 
244 			return -ENOMEM;
245 		}
246 	}
247 
248 	stream = stream_unicast_to_bap(u_stream);
249 	bt_cap_stream_ops_register(&u_stream->audio_stream.cap_stream, stream->ops);
250 
251 	u_stream->conn_id = bt_conn_index(conn);
252 	u_stream->ase_id = ase_id;
253 	u_stream->cig_id = cig_id;
254 	u_stream->cis_id = cis_id;
255 	memcpy(&u_stream->codec_cfg, codec_cfg, sizeof(*codec_cfg));
256 
257 	group = btp_bap_unicast_group_find(cig_id);
258 	if (group == NULL) {
259 		return -EINVAL;
260 	}
261 
262 	memcpy(&group->qos[cis_id], qos, sizeof(*qos));
263 
264 	return 0;
265 }
266 
btp_cap_unicast_setup_ase(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)267 static uint8_t btp_cap_unicast_setup_ase(const void *cmd, uint16_t cmd_len,
268 					 void *rsp, uint16_t *rsp_len)
269 {
270 	const struct btp_cap_unicast_setup_ase_cmd *cp = cmd;
271 	struct bt_audio_codec_cfg codec_cfg;
272 	struct bt_bap_qos_cfg qos;
273 	struct bt_conn *conn;
274 	const uint8_t *ltv_ptr;
275 	int err;
276 
277 	LOG_DBG("");
278 
279 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
280 	if (!conn) {
281 		LOG_ERR("Unknown connection");
282 
283 		return BTP_STATUS_FAILED;
284 	}
285 
286 	memset(&qos, 0, sizeof(qos));
287 	qos.phy = BT_BAP_QOS_CFG_2M;
288 	qos.framing = cp->framing;
289 	qos.rtn = cp->retransmission_num;
290 	qos.sdu = sys_le16_to_cpu(cp->max_sdu);
291 	qos.latency = sys_le16_to_cpu(cp->max_transport_latency);
292 	qos.interval = sys_get_le24(cp->sdu_interval);
293 	qos.pd = sys_get_le24(cp->presentation_delay);
294 
295 	memset(&codec_cfg, 0, sizeof(codec_cfg));
296 	codec_cfg.target_latency = BT_AUDIO_CODEC_CFG_TARGET_LATENCY_BALANCED;
297 	codec_cfg.target_phy = BT_AUDIO_CODEC_CFG_TARGET_PHY_2M;
298 	codec_cfg.id = cp->coding_format;
299 	codec_cfg.vid = cp->vid;
300 	codec_cfg.cid = cp->cid;
301 
302 	ltv_ptr = cp->ltvs;
303 	if (cp->cc_ltvs_len != 0) {
304 		codec_cfg.data_len = cp->cc_ltvs_len;
305 		memcpy(codec_cfg.data, ltv_ptr, cp->cc_ltvs_len);
306 		ltv_ptr += cp->cc_ltvs_len;
307 	}
308 
309 	if (cp->metadata_ltvs_len != 0) {
310 		codec_cfg.meta_len = cp->metadata_ltvs_len;
311 		memcpy(codec_cfg.meta, ltv_ptr, cp->metadata_ltvs_len);
312 	}
313 
314 	err = cap_unicast_setup_ase(conn, cp->ase_id, cp->cis_id, cp->cig_id, &codec_cfg, &qos);
315 	bt_conn_unref(conn);
316 
317 	return BTP_STATUS_VAL(err);
318 }
319 
btp_cap_unicast_audio_start(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)320 static uint8_t btp_cap_unicast_audio_start(const void *cmd, uint16_t cmd_len,
321 					   void *rsp, uint16_t *rsp_len)
322 {
323 	int err;
324 	size_t stream_count = 0;
325 	const struct btp_cap_unicast_audio_start_cmd *cp = cmd;
326 	struct bt_cap_unicast_audio_start_param start_param;
327 	struct bt_cap_unicast_audio_start_stream_param stream_params[
328 		ARRAY_SIZE(btp_csip_set_members) * BTP_BAP_UNICAST_MAX_STREAMS_COUNT];
329 
330 	LOG_DBG("");
331 
332 	err = btp_bap_unicast_group_create(cp->cig_id, &u_group);
333 	if (err != 0) {
334 		LOG_ERR("Failed to create unicast group");
335 
336 		return BTP_STATUS_FAILED;
337 	}
338 
339 	for (size_t conn_index = 0; conn_index < ARRAY_SIZE(btp_csip_set_members); conn_index++) {
340 		struct btp_bap_unicast_connection *u_conn = btp_bap_unicast_conn_get(conn_index);
341 
342 		if (u_conn->end_points_count == 0) {
343 			/* Connection not initialized */
344 			continue;
345 		}
346 
347 		for (size_t i = 0; i < ARRAY_SIZE(u_conn->streams); i++) {
348 			struct bt_cap_unicast_audio_start_stream_param *stream_param;
349 			struct btp_bap_unicast_stream *u_stream = &u_conn->streams[i];
350 
351 			if (!u_stream->in_use || u_stream->cig_id != cp->cig_id) {
352 				continue;
353 			}
354 
355 			stream_param = &stream_params[stream_count++];
356 			stream_param->stream = stream_unicast_to_cap(u_stream);
357 			stream_param->codec_cfg = &u_stream->codec_cfg;
358 			stream_param->member.member = bt_conn_lookup_addr_le(BT_ID_DEFAULT,
359 									     &u_conn->address);
360 			stream_param->ep = btp_bap_unicast_end_point_find(u_conn, u_stream->ase_id);
361 		}
362 	}
363 
364 	start_param.type = cp->set_type;
365 	start_param.count = stream_count;
366 	start_param.stream_params = stream_params;
367 
368 	err = bt_cap_initiator_unicast_audio_start(&start_param);
369 	if (err != 0) {
370 		LOG_ERR("Failed to start unicast audio: %d", err);
371 
372 		return BTP_STATUS_FAILED;
373 	}
374 
375 	return BTP_STATUS_SUCCESS;
376 }
377 
btp_cap_unicast_audio_update(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)378 static uint8_t btp_cap_unicast_audio_update(const void *cmd, uint16_t cmd_len,
379 					    void *rsp, uint16_t *rsp_len)
380 {
381 	int err;
382 	const uint8_t *data_ptr;
383 	const struct btp_cap_unicast_audio_update_cmd *cp = cmd;
384 	struct bt_cap_unicast_audio_update_stream_param
385 		stream_params[ARRAY_SIZE(btp_csip_set_members) * BTP_BAP_UNICAST_MAX_STREAMS_COUNT];
386 	struct bt_cap_unicast_audio_update_param param = {0};
387 
388 	LOG_DBG("");
389 
390 	if (cp->stream_count == 0) {
391 		return BTP_STATUS_FAILED;
392 	}
393 
394 	data_ptr = cp->update_data;
395 	for (size_t i = 0; i < cp->stream_count; i++) {
396 		struct btp_bap_unicast_connection *u_conn;
397 		struct btp_bap_unicast_stream *u_stream;
398 		struct bt_conn *conn;
399 		struct btp_cap_unicast_audio_update_data *update_data =
400 			(struct btp_cap_unicast_audio_update_data *)data_ptr;
401 		struct bt_cap_unicast_audio_update_stream_param *stream_param = &stream_params[i];
402 
403 		conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &update_data->address);
404 		if (!conn) {
405 			LOG_ERR("Unknown connection");
406 
407 			return BTP_STATUS_FAILED;
408 		}
409 
410 		u_conn = btp_bap_unicast_conn_get(bt_conn_index(conn));
411 		bt_conn_unref(conn);
412 		if (u_conn->end_points_count == 0) {
413 			/* Connection not initialized */
414 
415 			return BTP_STATUS_FAILED;
416 		}
417 
418 		u_stream = btp_bap_unicast_stream_find(u_conn, update_data->ase_id);
419 		if (u_stream == NULL) {
420 			return BTP_STATUS_FAILED;
421 		}
422 
423 		stream_param->stream = &u_stream->audio_stream.cap_stream;
424 		stream_param->meta_len = update_data->metadata_ltvs_len;
425 		stream_param->meta = update_data->metadata_ltvs;
426 
427 		data_ptr = ((uint8_t *)update_data) + stream_param->meta_len +
428 			   sizeof(struct btp_cap_unicast_audio_update_data);
429 	}
430 
431 	param.count = cp->stream_count;
432 	param.stream_params = stream_params;
433 	param.type = BT_CAP_SET_TYPE_AD_HOC;
434 
435 	err = bt_cap_initiator_unicast_audio_update(&param);
436 	if (err != 0) {
437 		LOG_ERR("Failed to start unicast audio: %d", err);
438 
439 		return BTP_STATUS_FAILED;
440 	}
441 
442 	return BTP_STATUS_SUCCESS;
443 }
444 
btp_cap_unicast_audio_stop(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)445 static uint8_t btp_cap_unicast_audio_stop(const void *cmd, uint16_t cmd_len,
446 					  void *rsp, uint16_t *rsp_len)
447 {
448 	struct bt_cap_stream
449 		*streams[ARRAY_SIZE(btp_csip_set_members) * BTP_BAP_UNICAST_MAX_STREAMS_COUNT];
450 	struct bt_cap_unicast_audio_stop_param param = {0};
451 	int err;
452 	const struct btp_cap_unicast_audio_stop_cmd *cp = cmd;
453 	size_t stream_cnt = 0U;
454 
455 	LOG_DBG("");
456 
457 	/* Get generate the same stream list as used by btp_cap_unicast_audio_start */
458 	for (size_t conn_index = 0; conn_index < ARRAY_SIZE(btp_csip_set_members); conn_index++) {
459 		struct btp_bap_unicast_connection *u_conn = btp_bap_unicast_conn_get(conn_index);
460 
461 		if (u_conn->end_points_count == 0) {
462 			/* Connection not initialized */
463 			continue;
464 		}
465 
466 		for (size_t i = 0; i < ARRAY_SIZE(u_conn->streams); i++) {
467 			struct btp_bap_unicast_stream *u_stream = &u_conn->streams[i];
468 
469 			if (!u_stream->in_use || u_stream->cig_id != cp->cig_id) {
470 				continue;
471 			}
472 
473 			streams[stream_cnt++] = stream_unicast_to_cap(u_stream);
474 		}
475 	}
476 
477 	param.streams = streams;
478 	param.count = stream_cnt;
479 	param.type = BT_CAP_SET_TYPE_AD_HOC;
480 	param.release = (cp->flags & BTP_CAP_UNICAST_AUDIO_STOP_FLAG_RELEASE) != 0;
481 
482 	err = bt_cap_initiator_unicast_audio_stop(&param);
483 	if (err != 0) {
484 		LOG_ERR("Failed to start unicast audio: %d", err);
485 
486 		return BTP_STATUS_FAILED;
487 	}
488 
489 	return BTP_STATUS_SUCCESS;
490 }
491 
btp_cap_broadcast_source_setup_stream(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)492 static uint8_t btp_cap_broadcast_source_setup_stream(const void *cmd, uint16_t cmd_len,
493 						     void *rsp, uint16_t *rsp_len)
494 {
495 	const uint8_t *ltv_ptr;
496 	struct btp_bap_broadcast_stream *stream;
497 	const struct btp_cap_broadcast_source_setup_stream_cmd *cp = cmd;
498 	struct btp_bap_broadcast_local_source *source =
499 		btp_bap_broadcast_local_source_from_src_id_get(cp->source_id);
500 
501 	if (source == NULL) {
502 		return BTP_STATUS_FAILED;
503 	}
504 
505 	struct bt_audio_codec_cfg *codec_cfg;
506 
507 	stream = btp_bap_broadcast_stream_alloc(source);
508 	if (stream == NULL) {
509 		return BTP_STATUS_FAILED;
510 	}
511 
512 	stream->subgroup_id = cp->subgroup_id;
513 	codec_cfg = &stream->codec_cfg;
514 	memset(codec_cfg, 0, sizeof(*codec_cfg));
515 	codec_cfg->id = cp->coding_format;
516 	codec_cfg->vid = cp->vid;
517 	codec_cfg->cid = cp->cid;
518 
519 	ltv_ptr = cp->ltvs;
520 	if (cp->cc_ltvs_len != 0) {
521 		codec_cfg->data_len = cp->cc_ltvs_len;
522 		memcpy(codec_cfg->data, ltv_ptr, cp->cc_ltvs_len);
523 		ltv_ptr += cp->cc_ltvs_len;
524 	}
525 
526 	if (cp->metadata_ltvs_len != 0) {
527 		codec_cfg->meta_len = cp->metadata_ltvs_len;
528 		memcpy(codec_cfg->meta, ltv_ptr, cp->metadata_ltvs_len);
529 	}
530 
531 	return BTP_STATUS_SUCCESS;
532 }
533 
btp_cap_broadcast_source_setup_subgroup(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)534 static uint8_t btp_cap_broadcast_source_setup_subgroup(const void *cmd, uint16_t cmd_len,
535 						       void *rsp, uint16_t *rsp_len)
536 {
537 	const uint8_t *ltv_ptr;
538 	struct bt_audio_codec_cfg *codec_cfg;
539 	const struct btp_cap_broadcast_source_setup_subgroup_cmd *cp = cmd;
540 	struct btp_bap_broadcast_local_source *source =
541 		btp_bap_broadcast_local_source_from_src_id_get(cp->source_id);
542 
543 	if (source == NULL) {
544 		return BTP_STATUS_FAILED;
545 	}
546 
547 	if (cp->subgroup_id >= ARRAY_SIZE(cap_broadcast_params[0].cap_subgroup_params)) {
548 		return BTP_STATUS_FAILED;
549 	}
550 
551 	uint8_t idx = btp_bap_broadcast_local_source_idx_get(source);
552 
553 	if (idx >= ARRAY_SIZE(cap_broadcast_params)) {
554 		return BTP_STATUS_FAILED;
555 	}
556 
557 	struct bt_cap_initiator_broadcast_subgroup_param *subgroup_param =
558 		&cap_broadcast_params[idx].cap_subgroup_params[cp->subgroup_id];
559 
560 	subgroup_param->codec_cfg = &source->subgroup_codec_cfg[cp->subgroup_id];
561 
562 	codec_cfg = subgroup_param->codec_cfg;
563 
564 	memset(codec_cfg, 0, sizeof(*codec_cfg));
565 	codec_cfg->id = cp->coding_format;
566 	codec_cfg->vid = cp->vid;
567 	codec_cfg->cid = cp->cid;
568 
569 	ltv_ptr = cp->ltvs;
570 	if (cp->cc_ltvs_len != 0) {
571 		codec_cfg->data_len = cp->cc_ltvs_len;
572 		memcpy(codec_cfg->data, ltv_ptr, cp->cc_ltvs_len);
573 		ltv_ptr += cp->cc_ltvs_len;
574 	}
575 
576 	if (cp->metadata_ltvs_len != 0) {
577 		codec_cfg->meta_len = cp->metadata_ltvs_len;
578 		memcpy(codec_cfg->meta, ltv_ptr, cp->metadata_ltvs_len);
579 	}
580 
581 	return BTP_STATUS_SUCCESS;
582 }
583 
cap_broadcast_source_adv_setup(struct btp_bap_broadcast_local_source * source,uint32_t * gap_settings)584 static int cap_broadcast_source_adv_setup(struct btp_bap_broadcast_local_source *source,
585 					  uint32_t *gap_settings)
586 {
587 	int err;
588 
589 	NET_BUF_SIMPLE_DEFINE(base_buf, 128);
590 
591 	/* Broadcast Audio Streaming Endpoint advertising data */
592 	struct bt_data per_ad;
593 
594 	/* A more specialized adv instance may already have been created by another btp module */
595 	if (source->ext_adv == NULL) {
596 		struct bt_le_adv_param param = *BT_LE_EXT_ADV_NCONN;
597 		struct bt_data base_ad[2];
598 
599 		NET_BUF_SIMPLE_DEFINE(ad_buf, BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE);
600 		*gap_settings = BIT(BTP_GAP_SETTINGS_DISCOVERABLE) |
601 				BIT(BTP_GAP_SETTINGS_EXTENDED_ADVERTISING);
602 		/* Setup extended advertising data */
603 		net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL);
604 		net_buf_simple_add_le24(&ad_buf, source->broadcast_id);
605 		base_ad[0].type = BT_DATA_SVC_DATA16;
606 		base_ad[0].data_len = ad_buf.len;
607 		base_ad[0].data = ad_buf.data;
608 		base_ad[1].type = BT_DATA_NAME_COMPLETE;
609 		base_ad[1].data_len = sizeof(CONFIG_BT_DEVICE_NAME) - 1;
610 		base_ad[1].data = CONFIG_BT_DEVICE_NAME;
611 
612 		err = tester_gap_create_adv_instance(&param, BTP_GAP_ADDR_TYPE_IDENTITY,
613 						     base_ad, 2, NULL, 0, gap_settings,
614 						     &source->ext_adv);
615 		if (err != 0) {
616 			LOG_DBG("Failed to create extended advertising instance: %d", err);
617 			return -EINVAL;
618 		}
619 	}
620 
621 	err = tester_gap_padv_configure(source->ext_adv,
622 					BT_LE_PER_ADV_PARAM(BT_GAP_PER_ADV_FAST_INT_MIN_2,
623 							    BT_GAP_PER_ADV_FAST_INT_MAX_2,
624 							    BT_LE_PER_ADV_OPT_NONE));
625 	if (err != 0) {
626 		LOG_DBG("Failed to configure periodic advertising: %d", err);
627 
628 		return -EINVAL;
629 	}
630 
631 	err = bt_cap_initiator_broadcast_get_base(source->cap_broadcast, &base_buf);
632 	if (err != 0) {
633 		LOG_DBG("Failed to get encoded BASE: %d\n", err);
634 
635 		return -EINVAL;
636 	}
637 
638 	per_ad.type = BT_DATA_SVC_DATA16;
639 	per_ad.data_len = base_buf.len;
640 	per_ad.data = base_buf.data;
641 	err = tester_gap_padv_set_data(source->ext_adv, &per_ad, 1);
642 	if (err != 0) {
643 		return -EINVAL;
644 	}
645 
646 	return 0;
647 }
648 
btp_cap_broadcast_source_setup(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)649 static uint8_t btp_cap_broadcast_source_setup(const void *cmd, uint16_t cmd_len,
650 					      void *rsp, uint16_t *rsp_len)
651 {
652 	int err;
653 	uint32_t gap_settings;
654 	static struct bt_cap_initiator_broadcast_create_param create_param;
655 	const struct btp_cap_broadcast_source_setup_cmd *cp = cmd;
656 	struct btp_cap_broadcast_source_setup_rp *rp = rsp;
657 	struct btp_bap_broadcast_local_source *source =
658 		btp_bap_broadcast_local_source_from_src_id_get(cp->source_id);
659 
660 	if (source == NULL) {
661 		return BTP_STATUS_FAILED;
662 	}
663 
664 	struct cap_initiator_broadcast_params *cap_params =
665 		&cap_broadcast_params[cp->source_id];
666 
667 	struct bt_bap_qos_cfg *qos = &source->qos;
668 
669 	LOG_DBG("");
670 
671 	memset(&create_param, 0, sizeof(create_param));
672 
673 	for (size_t i = 0; i < ARRAY_SIZE(source->streams); i++) {
674 		struct btp_bap_broadcast_stream *stream = &source->streams[i];
675 		struct bt_cap_initiator_broadcast_stream_param *stream_param;
676 		uint8_t bis_id;
677 
678 		if (!stream->in_use) {
679 			/* No more streams set up */
680 			break;
681 		}
682 
683 		bis_id = cap_params->cap_subgroup_params[stream->subgroup_id].stream_count++;
684 		stream_param = &cap_params->cap_stream_params[stream->subgroup_id][bis_id];
685 
686 		stream_param->stream = stream_broadcast_to_cap(stream);
687 
688 		if (cp->flags & BTP_CAP_BROADCAST_SOURCE_SETUP_FLAG_SUBGROUP_CODEC) {
689 			stream_param->data_len = 0;
690 			stream_param->data = NULL;
691 		} else {
692 			stream_param->data_len = stream->codec_cfg.data_len;
693 			stream_param->data = stream->codec_cfg.data;
694 		}
695 	}
696 
697 	for (size_t i = 0; i < ARRAY_SIZE(cap_params->cap_subgroup_params); i++) {
698 		if (cap_params->cap_subgroup_params[i].stream_count == 0) {
699 			/* No gaps allowed */
700 			break;
701 		}
702 
703 		cap_params->cap_subgroup_params[i].stream_params = cap_params->cap_stream_params[i];
704 		create_param.subgroup_count++;
705 	}
706 
707 	if (create_param.subgroup_count == 0) {
708 		return BTP_STATUS_FAILED;
709 	}
710 
711 	memset(qos, 0, sizeof(*qos));
712 	qos->phy = BT_BAP_QOS_CFG_2M;
713 	qos->framing = cp->framing;
714 	qos->rtn = cp->retransmission_num;
715 	qos->sdu = sys_le16_to_cpu(cp->max_sdu);
716 	qos->latency = sys_le16_to_cpu(cp->max_transport_latency);
717 	qos->interval = sys_get_le24(cp->sdu_interval);
718 	qos->pd = sys_get_le24(cp->presentation_delay);
719 
720 	create_param.subgroup_params = cap_params->cap_subgroup_params;
721 	create_param.qos = qos;
722 	create_param.packing = BT_ISO_PACKING_SEQUENTIAL;
723 	create_param.encryption = cp->flags & BTP_CAP_BROADCAST_SOURCE_SETUP_FLAG_ENCRYPTION;
724 	memcpy(create_param.broadcast_code, cp->broadcast_code, sizeof(cp->broadcast_code));
725 
726 	err = bt_cap_initiator_broadcast_audio_create(&create_param, &source->cap_broadcast);
727 	memset(&cap_params->cap_subgroup_params, 0, sizeof(cap_params->cap_subgroup_params));
728 	memset(&create_param, 0, sizeof(create_param));
729 	if (err != 0) {
730 		LOG_ERR("Failed to create audio source: %d", err);
731 
732 		return BTP_STATUS_FAILED;
733 	}
734 
735 	err = cap_broadcast_source_adv_setup(source, &gap_settings);
736 	if (err != 0) {
737 		return BTP_STATUS_FAILED;
738 	}
739 
740 	rp->gap_settings = gap_settings;
741 	sys_put_le24(source->broadcast_id, rp->broadcast_id);
742 	*rsp_len = sizeof(*rp);
743 
744 	return BTP_STATUS_SUCCESS;
745 }
746 
btp_cap_broadcast_source_release(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)747 static uint8_t btp_cap_broadcast_source_release(const void *cmd, uint16_t cmd_len,
748 						void *rsp, uint16_t *rsp_len)
749 {
750 	int err;
751 	const struct btp_cap_broadcast_source_release_cmd *cp = cmd;
752 	struct btp_bap_broadcast_local_source *source =
753 		btp_bap_broadcast_local_source_from_src_id_get(cp->source_id);
754 
755 	LOG_DBG("");
756 
757 	/* If no source has been created yet, there is nothing to release */
758 	if (source == NULL || source->cap_broadcast == NULL) {
759 		return BTP_STATUS_SUCCESS;
760 	}
761 
762 	err = bt_cap_initiator_broadcast_audio_delete(source->cap_broadcast);
763 	if (err != 0) {
764 		LOG_DBG("Unable to delete broadcast source: %d", err);
765 
766 		return BTP_STATUS_FAILED;
767 	}
768 
769 	memset(source, 0, sizeof(*source));
770 
771 	return BTP_STATUS_SUCCESS;
772 }
773 
btp_cap_broadcast_adv_start(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)774 static uint8_t btp_cap_broadcast_adv_start(const void *cmd, uint16_t cmd_len,
775 					   void *rsp, uint16_t *rsp_len)
776 {
777 	int err;
778 	const struct btp_cap_broadcast_adv_start_cmd *cp = cmd;
779 	struct btp_bap_broadcast_local_source *source =
780 		btp_bap_broadcast_local_source_from_src_id_get(cp->source_id);
781 
782 	if (source == NULL) {
783 		return BTP_STATUS_FAILED;
784 	}
785 
786 	if (source->ext_adv == NULL) {
787 		return BTP_STATUS_FAILED;
788 	}
789 
790 	err = tester_gap_start_ext_adv(source->ext_adv);
791 	if (err != 0) {
792 		return BTP_STATUS_FAILED;
793 	}
794 
795 	err = tester_gap_padv_start(source->ext_adv);
796 	if (err != 0) {
797 		LOG_DBG("Unable to start periodic advertising: %d", err);
798 
799 		return BTP_STATUS_FAILED;
800 	}
801 
802 	return BTP_STATUS_SUCCESS;
803 }
804 
btp_cap_broadcast_adv_stop(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)805 static uint8_t btp_cap_broadcast_adv_stop(const void *cmd, uint16_t cmd_len,
806 					  void *rsp, uint16_t *rsp_len)
807 {
808 	int err;
809 	const struct btp_cap_broadcast_adv_stop_cmd *cp = cmd;
810 
811 	LOG_DBG("");
812 
813 	struct btp_bap_broadcast_local_source *source =
814 		btp_bap_broadcast_local_source_from_src_id_get(cp->source_id);
815 
816 	if (source == NULL) {
817 		return BTP_STATUS_FAILED;
818 	}
819 
820 	err = tester_gap_padv_stop(source->ext_adv);
821 	if (err == -ESRCH) {
822 		/* Ext adv hasn't been created yet */
823 		return BTP_STATUS_SUCCESS;
824 	} else if (err != 0) {
825 		LOG_DBG("Failed to stop periodic adv, err: %d", err);
826 		return BTP_STATUS_FAILED;
827 	}
828 
829 	err = tester_gap_stop_ext_adv(source->ext_adv);
830 
831 	return BTP_STATUS_VAL(err);
832 }
833 
btp_cap_broadcast_source_start(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)834 static uint8_t btp_cap_broadcast_source_start(const void *cmd, uint16_t cmd_len,
835 					      void *rsp, uint16_t *rsp_len)
836 {
837 	int err;
838 	const struct btp_cap_broadcast_source_start_cmd *cp = cmd;
839 	struct btp_bap_broadcast_local_source *source =
840 		btp_bap_broadcast_local_source_from_src_id_get(cp->source_id);
841 
842 	if (source == NULL) {
843 		return BTP_STATUS_FAILED;
844 	}
845 
846 	LOG_DBG("");
847 
848 	if (source->ext_adv == NULL) {
849 		return BTP_STATUS_FAILED;
850 	}
851 
852 	err = bt_cap_initiator_broadcast_audio_start(source->cap_broadcast, source->ext_adv);
853 	if (err != 0) {
854 		LOG_ERR("Failed to start audio source: %d", err);
855 
856 		return BTP_STATUS_FAILED;
857 	}
858 
859 	return BTP_STATUS_SUCCESS;
860 }
861 
btp_cap_broadcast_source_stop(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)862 static uint8_t btp_cap_broadcast_source_stop(const void *cmd, uint16_t cmd_len,
863 					     void *rsp, uint16_t *rsp_len)
864 {
865 	int err;
866 	const struct btp_cap_broadcast_source_stop_cmd *cp = cmd;
867 	struct btp_bap_broadcast_local_source *source =
868 		btp_bap_broadcast_local_source_from_src_id_get(cp->source_id);
869 
870 	/* If no source has been started yet, there is nothing to stop */
871 	if (source == NULL || source->cap_broadcast == NULL) {
872 		return BTP_STATUS_SUCCESS;
873 	}
874 
875 	err = bt_cap_initiator_broadcast_audio_stop(source->cap_broadcast);
876 	if (err != 0) {
877 		LOG_ERR("Failed to stop audio source: %d", err);
878 
879 		return BTP_STATUS_FAILED;
880 	}
881 
882 	/* Make sure source is stopped before proceeding */
883 	err = k_sem_take(&source_stopped_sem, K_SECONDS(1));
884 	if (err) {
885 		LOG_ERR("Semaphore timed out: %d", err);
886 
887 		return BTP_STATUS_FAILED;
888 	}
889 
890 	return BTP_STATUS_SUCCESS;
891 }
892 
btp_cap_broadcast_source_update(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)893 static uint8_t btp_cap_broadcast_source_update(const void *cmd, uint16_t cmd_len,
894 					       void *rsp, uint16_t *rsp_len)
895 {
896 	int err;
897 	struct bt_data per_ad;
898 	const struct btp_cap_broadcast_source_update_cmd *cp = cmd;
899 	struct btp_bap_broadcast_local_source *source =
900 		btp_bap_broadcast_local_source_from_src_id_get(cp->source_id);
901 
902 	if (source == NULL) {
903 		return BTP_STATUS_FAILED;
904 	}
905 
906 	NET_BUF_SIMPLE_DEFINE(base_buf, 128);
907 
908 	LOG_DBG("");
909 
910 	if (cp->metadata_ltvs_len == 0) {
911 		return BTP_STATUS_FAILED;
912 	}
913 
914 	err = bt_cap_initiator_broadcast_audio_update(source->cap_broadcast, cp->metadata_ltvs,
915 						      cp->metadata_ltvs_len);
916 	if (err != 0) {
917 		LOG_ERR("Failed to update audio source: %d", err);
918 
919 		return BTP_STATUS_FAILED;
920 	}
921 
922 	err = bt_cap_initiator_broadcast_get_base(source->cap_broadcast, &base_buf);
923 	if (err != 0) {
924 		LOG_DBG("Failed to get encoded BASE: %d\n", err);
925 
926 		return -EINVAL;
927 	}
928 
929 	per_ad.type = BT_DATA_SVC_DATA16;
930 	per_ad.data_len = base_buf.len;
931 	per_ad.data = base_buf.data;
932 	err = tester_gap_padv_set_data(source->ext_adv, &per_ad, 1);
933 	if (err != 0) {
934 		return -EINVAL;
935 	}
936 
937 	return BTP_STATUS_SUCCESS;
938 }
939 
940 static const struct btp_handler cap_handlers[] = {
941 	{
942 		.opcode = BTP_CAP_READ_SUPPORTED_COMMANDS,
943 		.index = BTP_INDEX_NONE,
944 		.expect_len = 0,
945 		.func = btp_cap_supported_commands
946 	},
947 	{
948 		.opcode = BTP_CAP_DISCOVER,
949 		.expect_len = sizeof(struct btp_cap_discover_cmd),
950 		.func = btp_cap_discover
951 	},
952 	{
953 		.opcode = BTP_CAP_UNICAST_SETUP_ASE,
954 		.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
955 		.func = btp_cap_unicast_setup_ase
956 	},
957 	{
958 		.opcode = BTP_CAP_UNICAST_AUDIO_START,
959 		.expect_len = sizeof(struct btp_cap_unicast_audio_start_cmd),
960 		.func = btp_cap_unicast_audio_start
961 	},
962 	{
963 		.opcode = BTP_CAP_UNICAST_AUDIO_UPDATE,
964 		.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
965 		.func = btp_cap_unicast_audio_update
966 	},
967 	{
968 		.opcode = BTP_CAP_UNICAST_AUDIO_STOP,
969 		.expect_len = sizeof(struct btp_cap_unicast_audio_stop_cmd),
970 		.func = btp_cap_unicast_audio_stop
971 	},
972 	{
973 		.opcode = BTP_CAP_BROADCAST_SOURCE_SETUP_STREAM,
974 		.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
975 		.func = btp_cap_broadcast_source_setup_stream
976 	},
977 	{
978 		.opcode = BTP_CAP_BROADCAST_SOURCE_SETUP_SUBGROUP,
979 		.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
980 		.func = btp_cap_broadcast_source_setup_subgroup
981 	},
982 	{
983 		.opcode = BTP_CAP_BROADCAST_SOURCE_SETUP,
984 		.expect_len = sizeof(struct btp_cap_broadcast_source_setup_cmd),
985 		.func = btp_cap_broadcast_source_setup
986 	},
987 	{
988 		.opcode = BTP_CAP_BROADCAST_SOURCE_RELEASE,
989 		.expect_len = sizeof(struct btp_cap_broadcast_source_release_cmd),
990 		.func = btp_cap_broadcast_source_release
991 	},
992 	{
993 		.opcode = BTP_CAP_BROADCAST_ADV_START,
994 		.expect_len = sizeof(struct btp_cap_broadcast_adv_start_cmd),
995 		.func = btp_cap_broadcast_adv_start
996 	},
997 	{
998 		.opcode = BTP_CAP_BROADCAST_ADV_STOP,
999 		.expect_len = sizeof(struct btp_cap_broadcast_adv_stop_cmd),
1000 		.func = btp_cap_broadcast_adv_stop
1001 	},
1002 	{
1003 		.opcode = BTP_CAP_BROADCAST_SOURCE_START,
1004 		.expect_len = sizeof(struct btp_cap_broadcast_source_start_cmd),
1005 		.func = btp_cap_broadcast_source_start
1006 	},
1007 	{
1008 		.opcode = BTP_CAP_BROADCAST_SOURCE_STOP,
1009 		.expect_len = sizeof(struct btp_cap_broadcast_source_stop_cmd),
1010 		.func = btp_cap_broadcast_source_stop
1011 	},
1012 	{
1013 		.opcode = BTP_CAP_BROADCAST_SOURCE_UPDATE,
1014 		.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
1015 		.func = btp_cap_broadcast_source_update
1016 	},
1017 };
1018 
tester_init_cap(void)1019 uint8_t tester_init_cap(void)
1020 {
1021 	int err;
1022 
1023 	err = bt_cap_initiator_register_cb(&cap_cb);
1024 	if (err != 0) {
1025 		LOG_DBG("Failed to register CAP callbacks (err %d)", err);
1026 		return err;
1027 	}
1028 
1029 	tester_register_command_handlers(BTP_SERVICE_ID_CAP, cap_handlers,
1030 					 ARRAY_SIZE(cap_handlers));
1031 
1032 	return BTP_STATUS_SUCCESS;
1033 }
1034 
tester_unregister_cap(void)1035 uint8_t tester_unregister_cap(void)
1036 {
1037 	return BTP_STATUS_SUCCESS;
1038 }
1039