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