1 /*
2  * Copyright (c) 2023 Codecoup
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stdarg.h>
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <zephyr/bluetooth/att.h>
12 #include <zephyr/bluetooth/gap.h>
13 #include <zephyr/bluetooth/hci_types.h>
14 #include <zephyr/bluetooth/iso.h>
15 #include <zephyr/fff.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/types.h>
18 #include <zephyr/bluetooth/audio/audio.h>
19 #include <zephyr/bluetooth/audio/bap.h>
20 #include <zephyr/bluetooth/conn.h>
21 #include <zephyr/bluetooth/gatt.h>
22 #include <zephyr/bluetooth/uuid.h>
23 #include <zephyr/sys/util_macro.h>
24 #include <zephyr/syscalls/kernel.h>
25 #include <zephyr/ztest_assert.h>
26 #include <sys/types.h>
27 
28 #include "bap_unicast_server.h"
29 #include "bap_stream.h"
30 #include "conn.h"
31 #include "gatt.h"
32 #include "iso.h"
33 #include "mock_kernel.h"
34 #include "pacs.h"
35 
36 #include "test_common.h"
37 
test_mocks_init(void)38 void test_mocks_init(void)
39 {
40 	mock_bap_unicast_server_init();
41 	mock_bt_iso_init();
42 	mock_bt_pacs_init();
43 	mock_bap_stream_init();
44 	mock_bt_gatt_init();
45 }
46 
test_mocks_cleanup(void)47 void test_mocks_cleanup(void)
48 {
49 	mock_bap_unicast_server_cleanup();
50 	mock_bt_iso_cleanup();
51 	mock_bt_pacs_cleanup();
52 	mock_bap_stream_cleanup();
53 	mock_bt_gatt_cleanup();
54 }
55 
test_mocks_reset(void)56 void test_mocks_reset(void)
57 {
58 	test_mocks_cleanup();
59 	test_mocks_init();
60 }
61 
attr_found(const struct bt_gatt_attr * attr,uint16_t handle,void * user_data)62 static uint8_t attr_found(const struct bt_gatt_attr *attr, uint16_t handle, void *user_data)
63 {
64 	const struct bt_gatt_attr **result = user_data;
65 
66 	*result = attr;
67 
68 	return BT_GATT_ITER_STOP;
69 }
70 
test_conn_init(struct bt_conn * conn)71 void test_conn_init(struct bt_conn *conn)
72 {
73 	conn->index = 0;
74 	conn->info.type = BT_CONN_TYPE_LE;
75 	conn->info.role = BT_CONN_ROLE_PERIPHERAL;
76 	conn->info.state = BT_CONN_STATE_CONNECTED;
77 	conn->info.security.level = BT_SECURITY_L2;
78 	conn->info.security.enc_key_size = BT_ENC_KEY_SIZE_MAX;
79 	conn->info.security.flags = BT_SECURITY_FLAG_OOB | BT_SECURITY_FLAG_SC;
80 	conn->info.le.interval_us = BT_GAP_INIT_CONN_INT_MIN * BT_HCI_LE_INTERVAL_UNIT_US;
81 }
82 
test_ase_control_point_get(void)83 const struct bt_gatt_attr *test_ase_control_point_get(void)
84 {
85 	static const struct bt_gatt_attr *attr;
86 
87 	if (attr == NULL) {
88 		bt_gatt_foreach_attr_type(BT_ATT_FIRST_ATTRIBUTE_HANDLE,
89 					  BT_ATT_LAST_ATTRIBUTE_HANDLE,
90 					  BT_UUID_ASCS_ASE_CP, NULL, 1, attr_found, &attr);
91 	}
92 
93 	zassert_not_null(attr, "ASE Control Point not found");
94 
95 	return attr;
96 
97 }
98 
test_ase_get(const struct bt_uuid * uuid,int num_ase,...)99 uint8_t test_ase_get(const struct bt_uuid *uuid, int num_ase, ...)
100 {
101 	const struct bt_gatt_attr *attr = NULL;
102 	va_list attrs;
103 	uint8_t i;
104 
105 	va_start(attrs, num_ase);
106 
107 	for (i = 0; i < num_ase; i++) {
108 		const struct bt_gatt_attr *prev = attr;
109 
110 		bt_gatt_foreach_attr_type(BT_ATT_FIRST_ATTRIBUTE_HANDLE,
111 					  BT_ATT_LAST_ATTRIBUTE_HANDLE,
112 					  uuid, NULL, i + 1, attr_found, &attr);
113 
114 		/* Another attribute was not found */
115 		if (attr == prev) {
116 			break;
117 		}
118 
119 		*(va_arg(attrs, const struct bt_gatt_attr **)) = attr;
120 	}
121 
122 	va_end(attrs);
123 
124 	return i;
125 }
126 
test_ase_id_get(const struct bt_gatt_attr * ase)127 uint8_t test_ase_id_get(const struct bt_gatt_attr *ase)
128 {
129 	struct test_ase_chrc_value_hdr hdr = { 0 };
130 	ssize_t ret;
131 
132 	ret = ase->read(NULL, ase, &hdr, sizeof(hdr), 0);
133 	zassert_false(ret < 0, "ase->read returned unexpected (err 0x%02x)",
134 		      (uint8_t)BT_GATT_ERR(ret));
135 
136 	return hdr.ase_id;
137 }
138 
139 static struct bt_bap_stream *stream_allocated;
140 static const struct bt_bap_qos_cfg_pref qos_pref =
141 	BT_BAP_QOS_CFG_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000);
142 
unicast_server_cb_config_custom_fake(struct bt_conn * conn,const struct bt_bap_ep * ep,enum bt_audio_dir dir,const struct bt_audio_codec_cfg * codec_cfg,struct bt_bap_stream ** stream,struct bt_bap_qos_cfg_pref * const pref,struct bt_bap_ascs_rsp * rsp)143 static int unicast_server_cb_config_custom_fake(struct bt_conn *conn, const struct bt_bap_ep *ep,
144 						enum bt_audio_dir dir,
145 						const struct bt_audio_codec_cfg *codec_cfg,
146 						struct bt_bap_stream **stream,
147 						struct bt_bap_qos_cfg_pref *const pref,
148 						struct bt_bap_ascs_rsp *rsp)
149 {
150 	*stream = stream_allocated;
151 	*pref = qos_pref;
152 	*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
153 
154 	bt_bap_stream_cb_register(*stream, &mock_bap_stream_ops);
155 
156 	return 0;
157 }
158 
test_ase_control_client_config_codec(struct bt_conn * conn,uint8_t ase_id,struct bt_bap_stream * stream)159 void test_ase_control_client_config_codec(struct bt_conn *conn, uint8_t ase_id,
160 					  struct bt_bap_stream *stream)
161 {
162 	const struct bt_gatt_attr *attr = test_ase_control_point_get();
163 	const uint8_t buf[] = {
164 		0x01,           /* Opcode = Config Codec */
165 		0x01,           /* Number_of_ASEs */
166 		ase_id,         /* ASE_ID[0] */
167 		0x01,           /* Target_Latency[0] = Target low latency */
168 		0x02,           /* Target_PHY[0] = LE 2M PHY */
169 		0x06,           /* Codec_ID[0].Coding_Format = LC3 */
170 		0x00, 0x00,     /* Codec_ID[0].Company_ID */
171 		0x00, 0x00,     /* Codec_ID[0].Vendor_Specific_Codec_ID */
172 		0x00,           /* Codec_Specific_Configuration_Length[0] */
173 	};
174 
175 	ssize_t ret;
176 
177 	stream_allocated = stream;
178 	mock_bap_unicast_server_cb_config_fake.custom_fake = unicast_server_cb_config_custom_fake;
179 
180 	ret = attr->write(conn, attr, (void *)buf, sizeof(buf), 0, 0);
181 	zassert_false(ret < 0, "cp_attr->write returned unexpected (err 0x%02x)",
182 		      (uint8_t)BT_GATT_ERR(ret));
183 
184 	stream_allocated = NULL;
185 
186 	test_drain_syswq(); /* Ensure that state transitions are completed */
187 }
188 
test_ase_control_client_config_qos(struct bt_conn * conn,uint8_t ase_id)189 void test_ase_control_client_config_qos(struct bt_conn *conn, uint8_t ase_id)
190 {
191 	const struct bt_gatt_attr *attr = test_ase_control_point_get();
192 	const uint8_t buf[] = {
193 		0x02,                   /* Opcode = Config QoS */
194 		0x01,                   /* Number_of_ASEs */
195 		ase_id,                 /* ASE_ID[0] */
196 		0x01,                   /* CIG_ID[0] */
197 		0x01,                   /* CIS_ID[0] */
198 		0xFF, 0x00, 0x00,       /* SDU_Interval[0] */
199 		0x00,                   /* Framing[0] */
200 		0x02,                   /* PHY[0] */
201 		0x64, 0x00,             /* Max_SDU[0] */
202 		0x02,                   /* Retransmission_Number[0] */
203 		0x0A, 0x00,             /* Max_Transport_Latency[0] */
204 		0x40, 0x9C, 0x00,       /* Presentation_Delay[0] */
205 	};
206 	ssize_t ret;
207 
208 	ret = attr->write(conn, attr, (void *)buf, sizeof(buf), 0, 0);
209 	zassert_false(ret < 0, "attr->write returned unexpected (err 0x%02x)",
210 		      (uint8_t)BT_GATT_ERR(ret));
211 
212 	test_drain_syswq(); /* Ensure that state transitions are completed */
213 }
214 
test_ase_control_client_enable(struct bt_conn * conn,uint8_t ase_id)215 void test_ase_control_client_enable(struct bt_conn *conn, uint8_t ase_id)
216 {
217 	const struct bt_gatt_attr *attr = test_ase_control_point_get();
218 	const uint8_t buf[] = {
219 		0x03,                   /* Opcode = Enable */
220 		0x01,                   /* Number_of_ASEs */
221 		ase_id,                 /* ASE_ID[0] */
222 		0x00,                   /* Metadata_Length[0] */
223 	};
224 	ssize_t ret;
225 
226 	ret = attr->write(conn, attr, (void *)buf, sizeof(buf), 0, 0);
227 	zassert_false(ret < 0, "attr->write returned unexpected (err 0x%02x)",
228 		      (uint8_t)BT_GATT_ERR(ret));
229 
230 	test_drain_syswq(); /* Ensure that state transitions are completed */
231 }
232 
test_ase_control_client_disable(struct bt_conn * conn,uint8_t ase_id)233 void test_ase_control_client_disable(struct bt_conn *conn, uint8_t ase_id)
234 {
235 	const struct bt_gatt_attr *attr = test_ase_control_point_get();
236 	const uint8_t buf[] = {
237 		0x05,                   /* Opcode = Disable */
238 		0x01,                   /* Number_of_ASEs */
239 		ase_id,                 /* ASE_ID[0] */
240 	};
241 	ssize_t ret;
242 
243 	ret = attr->write(conn, attr, (void *)buf, sizeof(buf), 0, 0);
244 	zassert_false(ret < 0, "attr->write returned unexpected (err 0x%02x)",
245 		      (uint8_t)BT_GATT_ERR(ret));
246 
247 	test_drain_syswq(); /* Ensure that state transitions are completed */
248 }
249 
test_ase_control_client_release(struct bt_conn * conn,uint8_t ase_id)250 void test_ase_control_client_release(struct bt_conn *conn, uint8_t ase_id)
251 {
252 	const struct bt_gatt_attr *attr = test_ase_control_point_get();
253 	const uint8_t buf[] = {
254 		0x08,                   /* Opcode = Release */
255 		0x01,                   /* Number_of_ASEs */
256 		ase_id,                 /* ASE_ID[0] */
257 	};
258 	ssize_t ret;
259 
260 	ret = attr->write(conn, attr, (void *)buf, sizeof(buf), 0, 0);
261 	zassert_false(ret < 0, "attr->write returned unexpected (err 0x%02x)",
262 		      (uint8_t)BT_GATT_ERR(ret));
263 
264 	test_drain_syswq(); /* Ensure that state transitions are completed */
265 }
266 
test_ase_control_client_update_metadata(struct bt_conn * conn,uint8_t ase_id)267 void test_ase_control_client_update_metadata(struct bt_conn *conn, uint8_t ase_id)
268 {
269 	const struct bt_gatt_attr *attr = test_ase_control_point_get();
270 	const uint8_t buf[] = {
271 		0x07,                   /* Opcode = Update Metadata */
272 		0x01,                   /* Number_of_ASEs */
273 		ase_id,                 /* ASE_ID[0] */
274 		0x04,                   /* Metadata_Length[0] */
275 		0x03, 0x02, 0x04, 0x00, /* Metadata[0] = Streaming Context (Media) */
276 	};
277 	ssize_t ret;
278 
279 	ret = attr->write(conn, attr, (void *)buf, sizeof(buf), 0, 0);
280 	zassert_false(ret < 0, "attr->write returned unexpected (err 0x%02x)",
281 		      (uint8_t)BT_GATT_ERR(ret));
282 
283 	test_drain_syswq(); /* Ensure that state transitions are completed */
284 }
285 
test_ase_control_client_receiver_start_ready(struct bt_conn * conn,uint8_t ase_id)286 void test_ase_control_client_receiver_start_ready(struct bt_conn *conn, uint8_t ase_id)
287 {
288 	const struct bt_gatt_attr *attr = test_ase_control_point_get();
289 	const uint8_t buf[] = {
290 		0x04,                   /* Opcode = Receiver Start Ready */
291 		0x01,                   /* Number_of_ASEs */
292 		ase_id,                 /* ASE_ID[0] */
293 	};
294 	ssize_t ret;
295 
296 	ret = attr->write(conn, attr, (void *)buf, sizeof(buf), 0, 0);
297 	zassert_false(ret < 0, "attr->write returned unexpected (err 0x%02x)",
298 		      (uint8_t)BT_GATT_ERR(ret));
299 
300 	test_drain_syswq(); /* Ensure that state transitions are completed */
301 }
302 
test_ase_control_client_receiver_stop_ready(struct bt_conn * conn,uint8_t ase_id)303 void test_ase_control_client_receiver_stop_ready(struct bt_conn *conn, uint8_t ase_id)
304 {
305 	const struct bt_gatt_attr *attr = test_ase_control_point_get();
306 	const uint8_t buf[] = {
307 		0x06,                   /* Opcode = Receiver Stop Ready */
308 		0x01,                   /* Number_of_ASEs */
309 		ase_id,                 /* ASE_ID[0] */
310 	};
311 	ssize_t ret;
312 
313 	ret = attr->write(conn, attr, (void *)buf, sizeof(buf), 0, 0);
314 	zassert_false(ret < 0, "attr->write returned unexpected (err 0x%02x)",
315 		      (uint8_t)BT_GATT_ERR(ret));
316 
317 	test_drain_syswq(); /* Ensure that state transitions are completed */
318 }
319 
test_preamble_state_codec_configured(struct bt_conn * conn,uint8_t ase_id,struct bt_bap_stream * stream)320 void test_preamble_state_codec_configured(struct bt_conn *conn, uint8_t ase_id,
321 					  struct bt_bap_stream *stream)
322 {
323 	test_ase_control_client_config_codec(conn, ase_id, stream);
324 	test_mocks_reset();
325 }
326 
test_preamble_state_qos_configured(struct bt_conn * conn,uint8_t ase_id,struct bt_bap_stream * stream)327 void test_preamble_state_qos_configured(struct bt_conn *conn, uint8_t ase_id,
328 					struct bt_bap_stream *stream)
329 {
330 	test_ase_control_client_config_codec(conn, ase_id, stream);
331 	test_ase_control_client_config_qos(conn, ase_id);
332 	test_mocks_reset();
333 }
334 
test_preamble_state_enabling(struct bt_conn * conn,uint8_t ase_id,struct bt_bap_stream * stream)335 void test_preamble_state_enabling(struct bt_conn *conn, uint8_t ase_id,
336 				  struct bt_bap_stream *stream)
337 {
338 	test_ase_control_client_config_codec(conn, ase_id, stream);
339 	test_ase_control_client_config_qos(conn, ase_id);
340 	test_ase_control_client_enable(conn, ase_id);
341 	test_mocks_reset();
342 }
343 
test_preamble_state_streaming(struct bt_conn * conn,uint8_t ase_id,struct bt_bap_stream * stream,struct bt_iso_chan ** chan,bool source)344 void test_preamble_state_streaming(struct bt_conn *conn, uint8_t ase_id,
345 				   struct bt_bap_stream *stream, struct bt_iso_chan **chan,
346 				   bool source)
347 {
348 	int err;
349 
350 	test_ase_control_client_config_codec(conn, ase_id, stream);
351 	test_ase_control_client_config_qos(conn, ase_id);
352 	test_ase_control_client_enable(conn, ase_id);
353 
354 	err = mock_bt_iso_accept(conn, 0x01, 0x01, chan);
355 	zassert_equal(0, err, "Failed to connect iso: err %d", err);
356 
357 	if (source) {
358 		test_ase_control_client_receiver_start_ready(conn, ase_id);
359 	} else {
360 		err = bt_bap_stream_start(stream);
361 		zassert_equal(0, err, "bt_bap_stream_start err %d", err);
362 	}
363 
364 	test_drain_syswq(); /* Ensure that state transitions are completed */
365 
366 	test_mocks_reset();
367 }
368 
test_preamble_state_disabling(struct bt_conn * conn,uint8_t ase_id,struct bt_bap_stream * stream,struct bt_iso_chan ** chan)369 void test_preamble_state_disabling(struct bt_conn *conn, uint8_t ase_id,
370 				   struct bt_bap_stream *stream, struct bt_iso_chan **chan)
371 {
372 	int err;
373 
374 	test_ase_control_client_config_codec(conn, ase_id, stream);
375 	test_ase_control_client_config_qos(conn, ase_id);
376 	test_ase_control_client_enable(conn, ase_id);
377 
378 	err = mock_bt_iso_accept(conn, 0x01, 0x01, chan);
379 	zassert_equal(0, err, "Failed to connect iso: err %d", err);
380 
381 	test_ase_control_client_receiver_start_ready(conn, ase_id);
382 	test_ase_control_client_disable(conn, ase_id);
383 
384 	test_mocks_reset();
385 }
386 
test_preamble_state_releasing(struct bt_conn * conn,uint8_t ase_id,struct bt_bap_stream * stream,struct bt_iso_chan ** chan,bool source)387 void test_preamble_state_releasing(struct bt_conn *conn, uint8_t ase_id,
388 				   struct bt_bap_stream *stream, struct bt_iso_chan **chan,
389 				   bool source)
390 {
391 	test_preamble_state_streaming(conn, ase_id, stream, chan, source);
392 	test_ase_control_client_release(conn, ase_id);
393 
394 	/* Reset the mocks especially the function call count */
395 	mock_bap_unicast_server_cleanup();
396 	mock_bt_iso_cleanup();
397 	mock_bap_stream_cleanup();
398 	mock_bt_gatt_cleanup();
399 	mock_bap_unicast_server_init();
400 	mock_bt_iso_init();
401 	mock_bap_stream_init();
402 	mock_bt_gatt_init();
403 
404 	/* At this point, ISO is still connected, thus ASE is in releasing state */
405 }
406 
test_drain_syswq(void)407 void test_drain_syswq(void)
408 {
409 	const int err = k_work_queue_drain(&k_sys_work_q, false);
410 
411 	zassert_true(err >= 0, "Failed to drain system workqueue: %d", err);
412 }
413