1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2023 Codecoup
5 * Copyright (c) 2024 Demant A/S
6 * Copyright (c) 2024 Nordic Semiconductor ASA
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #include <errno.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <zephyr/fff.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/bluetooth/audio/audio.h>
17 #include <zephyr/bluetooth/audio/bap.h>
18 #include <zephyr/bluetooth/audio/pacs.h>
19 #include <zephyr/bluetooth/conn.h>
20 #include <zephyr/bluetooth/hci_types.h>
21 #include <zephyr/bluetooth/gatt.h>
22 #include <zephyr/bluetooth/uuid.h>
23 #include <zephyr/sys/util_macro.h>
24
25 #include "assert.h"
26 #include "ascs_internal.h"
27 #include "bap_unicast_server.h"
28 #include "bap_unicast_server_expects.h"
29 #include "bap_stream.h"
30 #include "bap_stream_expects.h"
31 #include "conn.h"
32 #include "gatt.h"
33 #include "gatt_expects.h"
34 #include "iso.h"
35 #include "mock_kernel.h"
36 #include "pacs.h"
37
38 #include "test_common.h"
39 #include "ztest_assert.h"
40
41 DEFINE_FFF_GLOBALS;
42
mock_init_rule_before(const struct ztest_unit_test * test,void * fixture)43 static void mock_init_rule_before(const struct ztest_unit_test *test, void *fixture)
44 {
45 test_mocks_init();
46 }
47
mock_destroy_rule_after(const struct ztest_unit_test * test,void * fixture)48 static void mock_destroy_rule_after(const struct ztest_unit_test *test, void *fixture)
49 {
50 test_mocks_cleanup();
51 }
52
53 ZTEST_RULE(mock_rule, mock_init_rule_before, mock_destroy_rule_after);
54
55 struct ascs_test_suite_fixture {
56 const struct bt_gatt_attr *ase_cp;
57 struct bt_bap_stream stream;
58 struct bt_conn conn;
59 struct {
60 uint8_t id;
61 const struct bt_gatt_attr *attr;
62 } ase_snk, ase_src;
63 };
64
ascs_test_suite_fixture_init(struct ascs_test_suite_fixture * fixture)65 static void ascs_test_suite_fixture_init(struct ascs_test_suite_fixture *fixture)
66 {
67 struct bt_bap_unicast_server_register_param param = {
68 CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT,
69 CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT
70 };
71 int err;
72
73 memset(fixture, 0, sizeof(*fixture));
74
75 err = bt_bap_unicast_server_register(¶m);
76 zassert_equal(err, 0, "Unexpected err response %d", err);
77
78 fixture->ase_cp = test_ase_control_point_get();
79
80 test_conn_init(&fixture->conn);
81
82 test_ase_snk_get(CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT, &fixture->ase_snk.attr);
83 if (fixture->ase_snk.attr != NULL) {
84 fixture->ase_snk.id = test_ase_id_get(fixture->ase_snk.attr);
85 }
86
87 test_ase_src_get(CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT, &fixture->ase_src.attr);
88 if (fixture->ase_src.attr != NULL) {
89 fixture->ase_src.id = test_ase_id_get(fixture->ase_src.attr);
90 }
91 }
92
ascs_test_suite_setup(void)93 static void *ascs_test_suite_setup(void)
94 {
95 struct ascs_test_suite_fixture *fixture;
96
97 fixture = malloc(sizeof(*fixture));
98 zassert_not_null(fixture);
99
100 return fixture;
101 }
102
ascs_test_suite_before(void * f)103 static void ascs_test_suite_before(void *f)
104 {
105 memset(f, 0, sizeof(struct ascs_test_suite_fixture));
106 ascs_test_suite_fixture_init(f);
107 }
108
ascs_test_suite_teardown(void * f)109 static void ascs_test_suite_teardown(void *f)
110 {
111 free(f);
112 }
113
ascs_test_suite_after(void * f)114 static void ascs_test_suite_after(void *f)
115 {
116 int err;
117
118 /* If any of these fails, it's a fatal error for any tests running afterwards */
119 err = bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb);
120 zassert_true(err == 0 || err == -EALREADY, "Unexpected err response %d", err);
121
122 /* Sleep to trigger any pending state changes from unregister_cb */
123 k_sleep(K_SECONDS(1));
124
125 err = bt_bap_unicast_server_unregister();
126 zassert_equal(err, 0, "Unexpected err response %d", err);
127 }
128
129 ZTEST_SUITE(ascs_test_suite, NULL, ascs_test_suite_setup, ascs_test_suite_before,
130 ascs_test_suite_after, ascs_test_suite_teardown);
131
ZTEST_F(ascs_test_suite,test_has_sink_ase_chrc)132 ZTEST_F(ascs_test_suite, test_has_sink_ase_chrc)
133 {
134 Z_TEST_SKIP_IFNDEF(CONFIG_BT_ASCS_ASE_SNK);
135
136 zassert_not_null(fixture->ase_snk.attr);
137 }
138
ZTEST_F(ascs_test_suite,test_has_source_ase_chrc)139 ZTEST_F(ascs_test_suite, test_has_source_ase_chrc)
140 {
141 Z_TEST_SKIP_IFNDEF(CONFIG_BT_ASCS_ASE_SRC);
142
143 zassert_not_null(fixture->ase_src.attr);
144 }
145
ZTEST_F(ascs_test_suite,test_has_control_point_chrc)146 ZTEST_F(ascs_test_suite, test_has_control_point_chrc)
147 {
148 zassert_not_null(fixture->ase_cp);
149 }
150
ZTEST_F(ascs_test_suite,test_sink_ase_read_state_idle)151 ZTEST_F(ascs_test_suite, test_sink_ase_read_state_idle)
152 {
153 const struct bt_gatt_attr *ase = fixture->ase_snk.attr;
154 struct bt_conn *conn = &fixture->conn;
155 struct test_ase_chrc_value_hdr hdr = { 0xff };
156 ssize_t ret;
157
158 Z_TEST_SKIP_IFNDEF(CONFIG_BT_ASCS_ASE_SNK);
159 zexpect_not_null(fixture->ase_snk.attr);
160
161 ret = ase->read(conn, ase, &hdr, sizeof(hdr), 0);
162 zassert_false(ret < 0, "attr->read returned unexpected (err 0x%02x)", BT_GATT_ERR(ret));
163 zassert_equal(0x00, hdr.ase_state, "unexpected ASE_State 0x%02x", hdr.ase_state);
164 }
165
ZTEST_F(ascs_test_suite,test_release_ase_on_callback_unregister)166 ZTEST_F(ascs_test_suite, test_release_ase_on_callback_unregister)
167 {
168 const struct test_ase_chrc_value_hdr *hdr;
169 const struct bt_gatt_attr *ase;
170 struct bt_bap_stream *stream = &fixture->stream;
171 struct bt_conn *conn = &fixture->conn;
172 struct bt_gatt_notify_params *notify_params;
173 uint8_t ase_id;
174 int err;
175
176 if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
177 ase = fixture->ase_snk.attr;
178 ase_id = fixture->ase_snk.id;
179 } else {
180 ase = fixture->ase_src.attr;
181 ase_id = fixture->ase_src.id;
182 }
183
184 zexpect_not_null(ase);
185 zexpect_true(ase_id != 0x00);
186
187 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
188 zassert_equal(err, 0, "unexpected err response %d", err);
189
190 /* Set ASE to non-idle state */
191 test_ase_control_client_config_codec(conn, ase_id, stream);
192
193 /* Reset mock, as we expect ASE notification to be sent */
194 bt_gatt_notify_cb_reset();
195
196 /* Unregister the callbacks - whis will clean up the ASCS */
197 bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb);
198
199 /* Expected to notify the upper layers */
200 expect_bt_bap_unicast_server_cb_release_called_once(stream);
201 expect_bt_bap_stream_ops_released_called_once(stream);
202
203 /* Expected to notify the client */
204 expect_bt_gatt_notify_cb_called_once(conn, ase->uuid, ase, EMPTY, sizeof(*hdr));
205
206 notify_params = mock_bt_gatt_notify_cb_fake.arg1_val;
207 hdr = (void *)notify_params->data;
208 zassert_equal(0x00, hdr->ase_state, "unexpected ASE_State 0x%02x", hdr->ase_state);
209 }
210
ZTEST_F(ascs_test_suite,test_abort_client_operation_if_callback_not_registered)211 ZTEST_F(ascs_test_suite, test_abort_client_operation_if_callback_not_registered)
212 {
213 const struct test_ase_cp_chrc_value_param *param;
214 const struct test_ase_cp_chrc_value_hdr *hdr;
215 const struct bt_gatt_attr *ase_cp = fixture->ase_cp;
216 struct bt_bap_stream *stream = &fixture->stream;
217 struct bt_conn *conn = &fixture->conn;
218 struct bt_gatt_notify_params *notify_params;
219 uint8_t ase_id;
220
221 if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
222 ase_id = fixture->ase_snk.id;
223 } else {
224 ase_id = fixture->ase_src.id;
225 }
226
227 zexpect_not_null(ase_cp);
228 zexpect_true(ase_id != 0x00);
229
230 /* Set ASE to non-idle state */
231 test_ase_control_client_config_codec(conn, ase_id, stream);
232
233 /* Expected ASE Control Point notification with Unspecified Error was sent */
234 expect_bt_gatt_notify_cb_called_once(conn, BT_UUID_ASCS_ASE_CP, ase_cp,
235 EMPTY, TEST_ASE_CP_CHRC_VALUE_SIZE(1));
236
237 notify_params = mock_bt_gatt_notify_cb_fake.arg1_val;
238 hdr = (void *)notify_params->data;
239 zassert_equal(0x01, hdr->opcode, "unexpected Opcode 0x%02x", hdr->opcode);
240 zassert_equal(0x01, hdr->number_of_ases, "unexpected Number_of_ASEs 0x%02x",
241 hdr->number_of_ases);
242 param = (void *)hdr->params;
243 zassert_equal(ase_id, param->ase_id, "unexpected ASE_ID 0x%02x", param->ase_id);
244 /* Expect Unspecified Error */
245 zassert_equal(0x0E, param->response_code, "unexpected Response_Code 0x%02x",
246 param->response_code);
247 zassert_equal(0x00, param->reason, "unexpected Reason 0x%02x", param->reason);
248 }
249
ZTEST_F(ascs_test_suite,test_release_ase_on_acl_disconnection)250 ZTEST_F(ascs_test_suite, test_release_ase_on_acl_disconnection)
251 {
252 struct bt_bap_stream *stream = &fixture->stream;
253 struct bt_conn *conn = &fixture->conn;
254 const struct bt_gatt_attr *ase;
255 struct bt_iso_chan *chan;
256 uint8_t ase_id;
257 int err;
258
259 if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
260 ase = fixture->ase_snk.attr;
261 ase_id = fixture->ase_snk.id;
262 } else {
263 ase = fixture->ase_src.attr;
264 ase_id = fixture->ase_src.id;
265 }
266
267 zexpect_not_null(ase);
268 zexpect_true(ase_id != 0x00);
269
270 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
271 zassert_equal(err, 0, "unexpected err response %d", err);
272
273 /* Set ASE to non-idle state */
274 test_preamble_state_streaming(conn, ase_id, stream, &chan,
275 !IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK));
276
277 /* Mock ACL disconnection */
278 mock_bt_conn_disconnected(conn, BT_HCI_ERR_CONN_TIMEOUT);
279
280 /* Expected to notify the upper layers */
281 expect_bt_bap_stream_ops_released_called_once(stream);
282
283 /* Mock CIS disconnection */
284 mock_bt_iso_disconnected(chan, BT_HCI_ERR_CONN_TIMEOUT);
285 }
286
ZTEST_F(ascs_test_suite,test_release_ase_pair_on_acl_disconnection)287 ZTEST_F(ascs_test_suite, test_release_ase_pair_on_acl_disconnection)
288 {
289 const struct bt_gatt_attr *ase_snk, *ase_src;
290 struct bt_bap_stream snk_stream, src_stream;
291 struct bt_conn *conn = &fixture->conn;
292 uint8_t ase_snk_id, ase_src_id;
293 struct bt_iso_chan *chan;
294 int err;
295
296 if (CONFIG_BT_ASCS_MAX_ACTIVE_ASES < 2) {
297 ztest_test_skip();
298 }
299
300 Z_TEST_SKIP_IFNDEF(CONFIG_BT_ASCS_ASE_SNK);
301 memset(&snk_stream, 0, sizeof(snk_stream));
302 ase_snk = fixture->ase_snk.attr;
303 zexpect_not_null(ase_snk);
304 ase_snk_id = fixture->ase_snk.id;
305 zexpect_true(ase_snk_id != 0x00);
306
307 Z_TEST_SKIP_IFNDEF(CONFIG_BT_ASCS_ASE_SRC);
308 memset(&src_stream, 0, sizeof(src_stream));
309 ase_src = fixture->ase_src.attr;
310 zexpect_not_null(ase_src);
311 ase_src_id = fixture->ase_src.id;
312 zexpect_true(ase_src_id != 0x00);
313
314 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
315 zassert_equal(err, 0, "unexpected err response %d", err);
316
317 test_ase_control_client_config_codec(conn, ase_snk_id, &snk_stream);
318 test_ase_control_client_config_qos(conn, ase_snk_id);
319 test_ase_control_client_enable(conn, ase_snk_id);
320
321 test_ase_control_client_config_codec(conn, ase_src_id, &src_stream);
322 test_ase_control_client_config_qos(conn, ase_src_id);
323 test_ase_control_client_enable(conn, ase_src_id);
324
325 err = mock_bt_iso_accept(conn, 0x01, 0x01, &chan);
326 zassert_equal(0, err, "Failed to connect iso: err %d", err);
327
328 test_ase_control_client_receiver_start_ready(conn, ase_src_id);
329
330 err = bt_bap_stream_start(&snk_stream);
331 zassert_equal(0, err, "bt_bap_stream_start err %d", err);
332
333 test_mocks_reset();
334
335 /* Mock ACL disconnection */
336 mock_bt_conn_disconnected(conn, BT_HCI_ERR_CONN_TIMEOUT);
337
338 /* Expected to notify the upper layers */
339 const struct bt_bap_stream *streams[2] = { &snk_stream, &src_stream };
340
341 expect_bt_bap_stream_ops_released_called(streams, 2);
342
343 /* Mock CIS disconnection */
344 mock_bt_iso_disconnected(chan, BT_HCI_ERR_CONN_TIMEOUT);
345 }
346
ZTEST_F(ascs_test_suite,test_recv_in_streaming_state)347 ZTEST_F(ascs_test_suite, test_recv_in_streaming_state)
348 {
349 struct bt_bap_stream *stream = &fixture->stream;
350 struct bt_conn *conn = &fixture->conn;
351 uint8_t ase_id = fixture->ase_snk.id;
352 struct bt_iso_recv_info info = {
353 .seq_num = 1,
354 .flags = BT_ISO_FLAGS_VALID,
355 };
356 struct bt_iso_chan *chan;
357 struct net_buf buf;
358 int err;
359
360 Z_TEST_SKIP_IFNDEF(CONFIG_BT_ASCS_ASE_SNK);
361
362 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
363 zassert_equal(err, 0, "unexpected err response %d", err);
364
365 test_preamble_state_streaming(conn, ase_id, stream, &chan, false);
366
367 chan->ops->recv(chan, &info, &buf);
368
369 /* Verification */
370 expect_bt_bap_stream_ops_recv_called_once(stream, &info, &buf);
371 }
372
ZTEST_F(ascs_test_suite,test_recv_in_enabling_state)373 ZTEST_F(ascs_test_suite, test_recv_in_enabling_state)
374 {
375 struct bt_bap_stream *stream = &fixture->stream;
376 struct bt_conn *conn = &fixture->conn;
377 uint8_t ase_id = fixture->ase_snk.id;
378 struct bt_iso_recv_info info = {
379 .seq_num = 1,
380 .flags = BT_ISO_FLAGS_VALID,
381 };
382 struct bt_iso_chan *chan;
383 struct net_buf buf;
384 int err;
385
386 Z_TEST_SKIP_IFNDEF(CONFIG_BT_ASCS_ASE_SNK);
387
388 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
389 zassert_equal(err, 0, "unexpected err response %d", err);
390
391 test_preamble_state_enabling(conn, ase_id, stream);
392
393 err = mock_bt_iso_accept(conn, 0x01, 0x01, &chan);
394 zassert_equal(0, err, "Failed to connect iso: err %d", err);
395
396 test_mocks_reset();
397
398 chan->ops->recv(chan, &info, &buf);
399
400 /* Verification */
401 expect_bt_bap_stream_ops_recv_not_called();
402 }
403
ZTEST_F(ascs_test_suite,test_cis_link_loss_in_streaming_state)404 ZTEST_F(ascs_test_suite, test_cis_link_loss_in_streaming_state)
405 {
406 struct bt_bap_stream *stream = &fixture->stream;
407 struct bt_conn *conn = &fixture->conn;
408 const struct bt_gatt_attr *ase;
409 struct bt_iso_chan *chan;
410 uint8_t ase_id;
411 int err;
412
413 if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
414 ase = fixture->ase_snk.attr;
415 ase_id = fixture->ase_snk.id;
416 } else {
417 ase = fixture->ase_src.attr;
418 ase_id = fixture->ase_src.id;
419 }
420 zexpect_not_null(ase);
421 zexpect_true(ase_id != 0x00);
422
423 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
424 zassert_equal(err, 0, "unexpected err response %d", err);
425
426 test_preamble_state_streaming(conn, ase_id, stream, &chan,
427 !IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK));
428
429 /* Mock CIS disconnection */
430 mock_bt_iso_disconnected(chan, BT_HCI_ERR_CONN_TIMEOUT);
431
432 /* Expected to notify the upper layers */
433 expect_bt_bap_stream_ops_qos_set_called_once(stream);
434 expect_bt_bap_stream_ops_disabled_called_once(stream);
435 expect_bt_bap_stream_ops_released_not_called();
436 expect_bt_bap_stream_ops_disconnected_called_once(stream);
437 }
438
test_cis_link_loss_in_disabling_state(struct ascs_test_suite_fixture * fixture,bool streaming)439 static void test_cis_link_loss_in_disabling_state(struct ascs_test_suite_fixture *fixture,
440 bool streaming)
441 {
442 struct bt_bap_stream *stream = &fixture->stream;
443 struct bt_conn *conn = &fixture->conn;
444 const struct bt_gatt_attr *ase;
445 struct bt_iso_chan *chan;
446 uint8_t ase_id;
447 int err;
448
449 Z_TEST_SKIP_IFNDEF(CONFIG_BT_ASCS_ASE_SRC);
450
451 ase = fixture->ase_src.attr;
452 ase_id = fixture->ase_src.id;
453 zexpect_not_null(ase);
454 zexpect_true(ase_id != 0x00);
455
456 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
457 zassert_equal(err, 0, "unexpected err response %d", err);
458
459 test_preamble_state_enabling(conn, ase_id, stream);
460 err = mock_bt_iso_accept(conn, 0x01, 0x01, &chan);
461 zassert_equal(0, err, "Failed to connect iso: err %d", err);
462
463 if (streaming) {
464 test_ase_control_client_receiver_start_ready(conn, ase_id);
465 }
466
467 test_ase_control_client_disable(conn, ase_id);
468
469 expect_bt_bap_stream_ops_disabled_called_once(stream);
470
471 test_mocks_reset();
472
473 /* Mock CIS disconnection */
474 mock_bt_iso_disconnected(chan, BT_HCI_ERR_CONN_TIMEOUT);
475
476 /* Expected to notify the upper layers */
477 expect_bt_bap_stream_ops_qos_set_called_once(stream);
478 expect_bt_bap_stream_ops_disabled_not_called();
479 expect_bt_bap_stream_ops_released_not_called();
480 expect_bt_bap_stream_ops_disconnected_called_once(stream);
481 }
482
ZTEST_F(ascs_test_suite,test_cis_link_loss_in_disabling_state_v1)483 ZTEST_F(ascs_test_suite, test_cis_link_loss_in_disabling_state_v1)
484 {
485 /* Enabling -> Streaming -> Disabling */
486 test_cis_link_loss_in_disabling_state(fixture, true);
487 }
488
ZTEST_F(ascs_test_suite,test_cis_link_loss_in_disabling_state_v2)489 ZTEST_F(ascs_test_suite, test_cis_link_loss_in_disabling_state_v2)
490 {
491 /* Enabling -> Disabling */
492 test_cis_link_loss_in_disabling_state(fixture, false);
493 }
494
ZTEST_F(ascs_test_suite,test_cis_link_loss_in_enabling_state)495 ZTEST_F(ascs_test_suite, test_cis_link_loss_in_enabling_state)
496 {
497 struct bt_bap_stream *stream = &fixture->stream;
498 struct bt_conn *conn = &fixture->conn;
499 const struct bt_gatt_attr *ase;
500 struct bt_iso_chan *chan;
501 uint8_t ase_id;
502 int err;
503
504 if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
505 ase = fixture->ase_snk.attr;
506 ase_id = fixture->ase_snk.id;
507 } else {
508 ase = fixture->ase_src.attr;
509 ase_id = fixture->ase_src.id;
510 }
511 zexpect_not_null(ase);
512 zexpect_true(ase_id != 0x00);
513
514 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
515 zassert_equal(err, 0, "unexpected err response %d", err);
516
517 test_preamble_state_enabling(conn, ase_id, stream);
518 err = mock_bt_iso_accept(conn, 0x01, 0x01, &chan);
519 zassert_equal(0, err, "Failed to connect iso: err %d", err);
520
521 /* Mock CIS disconnection */
522 mock_bt_iso_disconnected(chan, BT_HCI_ERR_CONN_TIMEOUT);
523
524 /* Expected no change in ASE state */
525 expect_bt_bap_stream_ops_qos_set_not_called();
526 expect_bt_bap_stream_ops_released_not_called();
527 expect_bt_bap_stream_ops_disconnected_called_once(stream);
528
529 err = bt_bap_stream_disable(stream);
530 zassert_equal(0, err, "Failed to disable stream: err %d", err);
531
532 if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
533 expect_bt_bap_stream_ops_qos_set_called_once(stream);
534 expect_bt_bap_stream_ops_disabled_called_once(stream);
535 } else {
536 /* Server-initiated disable operation that shall not cause transition to QoS */
537 expect_bt_bap_stream_ops_qos_set_not_called();
538 }
539 }
540
ZTEST_F(ascs_test_suite,test_cis_link_loss_in_enabling_state_client_retries)541 ZTEST_F(ascs_test_suite, test_cis_link_loss_in_enabling_state_client_retries)
542 {
543 struct bt_bap_stream *stream = &fixture->stream;
544 struct bt_conn *conn = &fixture->conn;
545 const struct bt_gatt_attr *ase;
546 struct bt_iso_chan *chan;
547 uint8_t ase_id;
548 int err;
549
550 if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
551 ase = fixture->ase_snk.attr;
552 ase_id = fixture->ase_snk.id;
553 } else {
554 ase = fixture->ase_src.attr;
555 ase_id = fixture->ase_src.id;
556 }
557 zexpect_not_null(ase);
558 zexpect_true(ase_id != 0x00);
559
560 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
561 zassert_equal(err, 0, "unexpected err response %d", err);
562
563 test_preamble_state_enabling(conn, ase_id, stream);
564 err = mock_bt_iso_accept(conn, 0x01, 0x01, &chan);
565 zassert_equal(0, err, "Failed to connect iso: err %d", err);
566 expect_bt_bap_stream_ops_connected_called_once(stream);
567
568 /* Mock CIS disconnection */
569 mock_bt_iso_disconnected(chan, BT_HCI_ERR_CONN_FAIL_TO_ESTAB);
570
571 /* Expected to not notify the upper layers */
572 expect_bt_bap_stream_ops_qos_set_not_called();
573 expect_bt_bap_stream_ops_released_not_called();
574 expect_bt_bap_stream_ops_disconnected_called_once(stream);
575
576 /* Client retries to establish CIS */
577 err = mock_bt_iso_accept(conn, 0x01, 0x01, &chan);
578 zassert_equal(0, err, "Failed to connect iso: err %d", err);
579 if (!IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
580 test_ase_control_client_receiver_start_ready(conn, ase_id);
581 } else {
582 err = bt_bap_stream_start(stream);
583 zassert_equal(0, err, "bt_bap_stream_start err %d", err);
584 }
585
586 expect_bt_bap_stream_ops_connected_called_twice(stream);
587 expect_bt_bap_stream_ops_started_called_once(stream);
588 }
589
590 static struct bt_bap_stream *stream_allocated;
591 static const struct bt_bap_qos_cfg_pref qos_pref =
592 BT_BAP_QOS_CFG_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000);
593
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)594 static int unicast_server_cb_config_custom_fake(struct bt_conn *conn, const struct bt_bap_ep *ep,
595 enum bt_audio_dir dir,
596 const struct bt_audio_codec_cfg *codec_cfg,
597 struct bt_bap_stream **stream,
598 struct bt_bap_qos_cfg_pref *const pref,
599 struct bt_bap_ascs_rsp *rsp)
600 {
601 *stream = stream_allocated;
602 *pref = qos_pref;
603 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
604
605 bt_bap_stream_cb_register(*stream, &mock_bap_stream_ops);
606
607 return 0;
608 }
609
ZTEST_F(ascs_test_suite,test_ase_state_notification_retry)610 ZTEST_F(ascs_test_suite, test_ase_state_notification_retry)
611 {
612 struct bt_bap_stream *stream = &fixture->stream;
613 struct bt_conn *conn = &fixture->conn;
614 const struct bt_gatt_attr *ase, *cp;
615 struct bt_conn_info info;
616 uint8_t ase_id;
617 int err;
618
619 if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
620 ase = fixture->ase_snk.attr;
621 ase_id = fixture->ase_snk.id;
622 } else {
623 ase = fixture->ase_src.attr;
624 ase_id = fixture->ase_src.id;
625 }
626
627 zexpect_not_null(ase);
628 zassert_not_equal(ase_id, 0x00);
629
630 cp = test_ase_control_point_get();
631 zexpect_not_null(cp);
632
633 err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
634 zassert_equal(err, 0, "unexpected err response %d", err);
635
636 stream_allocated = stream;
637 mock_bap_unicast_server_cb_config_fake.custom_fake = unicast_server_cb_config_custom_fake;
638
639 /* Mock out of buffers case */
640 mock_bt_gatt_notify_cb_fake.return_val = -ENOMEM;
641
642 const uint8_t buf[] = {
643 0x01, /* Opcode = Config Codec */
644 0x01, /* Number_of_ASEs */
645 ase_id, /* ASE_ID[0] */
646 0x01, /* Target_Latency[0] = Target low latency */
647 0x02, /* Target_PHY[0] = LE 2M PHY */
648 0x06, /* Codec_ID[0].Coding_Format = LC3 */
649 0x00, 0x00, /* Codec_ID[0].Company_ID */
650 0x00, 0x00, /* Codec_ID[0].Vendor_Specific_Codec_ID */
651 0x00, /* Codec_Specific_Configuration_Length[0] */
652 };
653
654 cp->write(conn, cp, (void *)buf, sizeof(buf), 0, 0);
655
656 /* Verification */
657 expect_bt_bap_stream_ops_configured_not_called();
658
659 mock_bt_gatt_notify_cb_fake.return_val = 0;
660
661 err = bt_conn_get_info(conn, &info);
662 zassert_equal(err, 0);
663
664 /* Wait for ASE state notification retry */
665 k_sleep(K_MSEC(BT_CONN_INTERVAL_TO_MS(info.le.interval)));
666
667 expect_bt_bap_stream_ops_configured_called_once(stream, EMPTY);
668 }
669