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