1 /*
2 * Copyright (c) 2024 Demant
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/types.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/fff.h>
10
11 DEFINE_FFF_GLOBALS;
12
13 #include <zephyr/bluetooth/hci.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/slist.h>
16 #include <zephyr/sys/util.h>
17 #include "hal/ccm.h"
18
19 #include "util/util.h"
20 #include "util/mem.h"
21 #include "util/memq.h"
22 #include "util/mayfly.h"
23 #include "util/dbuf.h"
24
25 #include "pdu_df.h"
26 #include "lll/pdu_vendor.h"
27 #include "pdu.h"
28 #include "ll.h"
29 #include "ll_settings.h"
30 #include "ll_feat.h"
31
32 #include "lll.h"
33 #include "lll/lll_df_types.h"
34 #include "lll_conn.h"
35 #include "lll_conn_iso.h"
36 #include "lll/lll_adv_types.h"
37 #include "lll_adv.h"
38 #include "lll/lll_adv_pdu.h"
39 #include "lll_chan.h"
40 #include "lll_scan.h"
41 #include "lll_sync.h"
42 #include "lll_sync_iso.h"
43
44 #include "ull_adv_types.h"
45 #include "ull_scan_types.h"
46 #include "ull_sync_types.h"
47
48 #include "ull_tx_queue.h"
49
50 #include "isoal.h"
51 #include "ull_iso_types.h"
52 #include "ull_conn_iso_types.h"
53
54 #include "ull_conn_types.h"
55 #include "ull_llcp.h"
56 #include "ull_llcp_internal.h"
57 #include "ull_sync_internal.h"
58 #include "ull_internal.h"
59
60 #include "helper_pdu.h"
61 #include "helper_util.h"
62
63 static struct ll_conn conn;
64 static struct ll_sync_set *sync;
65 static struct ll_adv_sync_set *adv_sync;
66
periodic_sync_setup(void * data)67 static void periodic_sync_setup(void *data)
68 {
69 test_setup(&conn);
70 }
71
72 /* Custom fakes for this test suite */
73
74 /* uint32_t mayfly_enqueue(uint8_t caller_id, uint8_t callee_id,
75 * uint8_t chain, struct mayfly *m);
76 */
77 FAKE_VALUE_FUNC(uint32_t, mayfly_enqueue, uint8_t, uint8_t, uint8_t, struct mayfly *);
78
mayfly_enqueue_custom_fake(uint8_t caller_id,uint8_t callee_id,uint8_t chain,struct mayfly * m)79 uint32_t mayfly_enqueue_custom_fake(uint8_t caller_id, uint8_t callee_id,
80 uint8_t chain, struct mayfly *m)
81 {
82 /* Only proceed if it is the right mayfly enqueue used for getting the offset */
83 if (m->param == &conn && chain == 1U) {
84 /* Mock that mayfly has run and ull_lp_past_offset_calc_reply()
85 * is called with the found past offset
86 */
87 ull_lp_past_offset_calc_reply(&conn, 0, 0, 0);
88 }
89
90 return 0;
91 }
92
93 /* void ull_sync_transfer_received(struct ll_conn *conn, uint16_t service_data,
94 * struct pdu_adv_sync_info *si, uint16_t conn_event_count,
95 * uint16_t last_pa_event_counter, uint8_t sid,
96 * uint8_t addr_type, uint8_t sca, uint8_t phy,
97 * uint8_t *adv_addr, uint16_t sync_conn_event_count,
98 * uint8_t addr_resolved);
99 */
100 FAKE_VOID_FUNC(ull_sync_transfer_received, struct ll_conn *, uint16_t,
101 struct pdu_adv_sync_info *,
102 uint16_t,
103 uint16_t,
104 uint8_t,
105 uint8_t,
106 uint8_t,
107 uint8_t,
108 uint8_t *,
109 uint16_t,
110 uint8_t);
111
ull_sync_transfer_received_custom_fake(struct ll_conn * conn,uint16_t service_data,struct pdu_adv_sync_info * si,uint16_t conn_event_count,uint16_t last_pa_event_counter,uint8_t sid,uint8_t addr_type,uint8_t sca,uint8_t phy,uint8_t * adv_addr,uint16_t sync_conn_event_count,uint8_t addr_resolved)112 void ull_sync_transfer_received_custom_fake(struct ll_conn *conn, uint16_t service_data,
113 struct pdu_adv_sync_info *si, uint16_t conn_event_count,
114 uint16_t last_pa_event_counter, uint8_t sid,
115 uint8_t addr_type, uint8_t sca, uint8_t phy,
116 uint8_t *adv_addr, uint16_t sync_conn_event_count,
117 uint8_t addr_resolved)
118 {
119 }
120 /* +-----+ +-------+ +-----+
121 * | UT | | LL_A | | LT |
122 * +-----+ +-------+ +-----+
123 * | | |
124 * | Start | |
125 * | Periodic Adv. Sync Transfer| |
126 * | Proc. | |
127 * |--------------------------->| |
128 * | | |
129 * | | LL_PERIODIC_SYNC_IND|
130 * | |------------------> |
131 * | | 'll_ack'|
132 * | | |
133 * |Periodic Adv. Sync Transfer | |
134 * | Proc. Complete | |
135 * |<---------------------------| |
136 * | | |
137 */
ZTEST(periodic_sync_transfer,test_periodic_sync_transfer_loc)138 ZTEST(periodic_sync_transfer, test_periodic_sync_transfer_loc)
139 {
140 uint8_t err;
141 struct node_tx *tx;
142 struct proc_ctx *ctx;
143 uint16_t service_data = 0;
144
145 adv_sync = NULL;
146 sync = ull_sync_is_enabled_get(0);
147
148 struct pdu_data_llctrl_periodic_sync_ind local_periodic_sync_ind = {
149 .id = 0x00,
150 .conn_event_count = 0x00,
151 .last_pa_event_counter = 0x00,
152 .sid = 0x00,
153 .addr_type = 0x00,
154 .sca = 0x00,
155 .phy = 0x00,
156 .adv_addr = { 0, 0, 0, 0, 0, 0},
157 .sync_conn_event_count = 0
158 };
159
160 /* Reset and setup mayfly_enqueue_custom_fake */
161 RESET_FAKE(mayfly_enqueue);
162 mayfly_enqueue_fake .custom_fake = mayfly_enqueue_custom_fake;
163
164 /* Initialise sync_info */
165 memset(&local_periodic_sync_ind.sync_info, 0, sizeof(struct pdu_adv_sync_info));
166
167 /* Role */
168 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
169
170 /* Connect */
171 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
172 conn.llcp.fex.features_peer |= BIT64(BT_LE_FEAT_BIT_PAST_RECV);
173
174 /* Initiate a Periodic Adv. Sync Transfer Procedure */
175 err = ull_cp_periodic_sync(&conn, sync, adv_sync, service_data);
176 zassert_equal(err, BT_HCI_ERR_SUCCESS);
177
178 /* Connection event done with successful rx from peer */
179 ctx = llcp_lr_peek_proc(&conn, PROC_PERIODIC_SYNC);
180 if (ctx) {
181 ctx->data.periodic_sync.conn_start_to_actual_us = 0;
182 ctx->data.periodic_sync.conn_evt_trx = 1;
183 llcp_lp_past_conn_evt_done(&conn, ctx);
184 }
185
186 /* Prepare */
187 event_prepare(&conn);
188
189 /* Tx Queue should have one LL Control PDU */
190 lt_rx(LL_PERIODIC_SYNC_IND, &conn, &tx, &local_periodic_sync_ind);
191 lt_rx_q_is_empty(&conn);
192
193 /* TX Ack */
194 event_tx_ack(&conn, tx);
195
196 /* Done */
197 event_done(&conn);
198
199 /* Release tx node */
200 ull_cp_release_tx(&conn, tx);
201
202 /* There should be no host notifications */
203 ut_rx_q_is_empty();
204
205 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
206 "Free CTX buffers %d and ctx_buffers_cnt is %d", llcp_ctx_buffers_free(),
207 test_ctx_buffers_cnt());
208 }
209
ZTEST(periodic_sync_transfer,test_periodic_sync_transfer_loc_2)210 ZTEST(periodic_sync_transfer, test_periodic_sync_transfer_loc_2)
211 {
212 uint8_t err;
213 uint16_t service_data = 0;
214
215 sync = ull_sync_is_enabled_get(0);
216 adv_sync = NULL;
217
218 ull_cp_init();
219 ull_tx_q_init(&conn.tx_q);
220 ull_llcp_init(&conn);
221 conn.llcp.fex.features_peer |= BIT64(BT_LE_FEAT_BIT_PAST_RECV);
222
223 err = ull_cp_periodic_sync(&conn, sync, adv_sync, service_data);
224
225 for (int i = 0U; i < CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM; i++) {
226 zassert_equal(err, BT_HCI_ERR_SUCCESS);
227 err = ull_cp_periodic_sync(&conn, sync, adv_sync, service_data);
228 }
229
230 zassert_not_equal(err, BT_HCI_ERR_SUCCESS, NULL);
231
232 zassert_equal(llcp_ctx_buffers_free(),
233 test_ctx_buffers_cnt() - CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM,
234 "Free CTX buffers %d", llcp_ctx_buffers_free());
235 }
236
237 /* +-----+ +-------+ +-----+
238 * | UT | | LL_A | | LT |
239 * +-----+ +-------+ +-----+
240 * | | |
241 * | | LL_PERIODIC_SYNC_IND |
242 * | |<----------------------- |
243 * | | |
244 * | | |
245 * | | |
246 * | | |
247 */
ZTEST(periodic_sync_transfer,test_periodic_sync_transfer_rem)248 ZTEST(periodic_sync_transfer, test_periodic_sync_transfer_rem)
249 {
250 struct pdu_data_llctrl_periodic_sync_ind remote_periodic_sync_ind = {
251 .id = 0x01,
252 .conn_event_count = 0x00,
253 .last_pa_event_counter = 0x00,
254 .sid = 0x00,
255 .addr_type = 0x01,
256 .sca = 0x00,
257 .phy = 0x01,
258 .adv_addr = { 0, 0, 0, 0, 0, 0},
259 .sync_conn_event_count = 0
260 };
261
262 /* Reset and setup fake functions */
263 RESET_FAKE(ull_sync_transfer_received);
264 ull_sync_transfer_received_fake.custom_fake = ull_sync_transfer_received_custom_fake;
265
266 RESET_FAKE(mayfly_enqueue);
267 mayfly_enqueue_fake .custom_fake = mayfly_enqueue_custom_fake;
268
269 /* Initialise sync_info */
270 memset(&remote_periodic_sync_ind.sync_info, 0, sizeof(struct pdu_adv_sync_info));
271
272 /* Role */
273 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
274
275 /* Connect */
276 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
277 conn.llcp.fex.features_peer |= BIT64(BT_LE_FEAT_BIT_PAST_RECV);
278
279 /* Prepare */
280 event_prepare(&conn);
281
282 /* Rx */
283 lt_tx(LL_PERIODIC_SYNC_IND, &conn, &remote_periodic_sync_ind);
284
285 /* Done */
286 event_done(&conn);
287
288 /* Prepare */
289 event_prepare(&conn);
290
291 /* Tx Queue should have one LL Control PDU */
292 lt_rx_q_is_empty(&conn);
293
294 /* Done */
295 event_done(&conn);
296
297 /* There should not be a host notifications */
298 ut_rx_q_is_empty();
299
300 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
301 "Free CTX buffers %d and ctx_buffers_cnt is %d", llcp_ctx_buffers_free(),
302 test_ctx_buffers_cnt());
303
304
305 /* Verify that ull_sync_transfer_received was called,
306 * hence the phy invalidation mechanism works
307 */
308 zassert_equal(ull_sync_transfer_received_fake.call_count, 1,
309 "ull_sync_transfer_received_fake.call_count is %d and expected: %d",
310 ull_sync_transfer_received_fake.call_count, 1);
311 }
312
313 /* +-----+ +-------+ +-----+
314 * | UT | | LL_A | | LT |
315 * +-----+ +-------+ +-----+
316 * | | |
317 * | | LL_PERIODIC_SYNC_IND |
318 * | |<------------------------|
319 * | | |
320 * | | |
321 * | | |
322 * | | |
323 * | Start | |
324 * | Periodic Adv. Sync Transfer| |
325 * | Proc. | |
326 * |--------------------------->| |
327 * | | |
328 * | | |
329 * | | LL_PERIODIC_SYNC_IND |
330 * | |------------------------>|
331 * | | 'll_ack'|
332 * |Periodic Adv. Sync Transfer | |
333 * | Proc. Complete | |
334 * |<---------------------------| |
335 * | | |
336 */
ZTEST(periodic_sync_transfer,test_periodic_sync_transfer_rem_2)337 ZTEST(periodic_sync_transfer, test_periodic_sync_transfer_rem_2)
338 {
339 uint8_t err;
340 struct node_tx *tx;
341 uint16_t service_data = 0;
342 struct proc_ctx *ctx;
343
344 sync = ull_sync_is_enabled_get(0);
345 adv_sync = NULL;
346
347 struct pdu_data_llctrl_periodic_sync_ind local_periodic_sync_ind = {
348 .id = 0x00,
349 .conn_event_count = 0x01,
350 .last_pa_event_counter = 0x00,
351 .sid = 0x00,
352 .addr_type = 0x00,
353 .sca = 0x00,
354 .phy = 0x00,
355 .adv_addr = { 0, 0, 0, 0, 0, 0},
356 .sync_conn_event_count = 0x01
357 };
358
359 struct pdu_data_llctrl_periodic_sync_ind remote_periodic_sync_ind = {
360 .id = 0x01,
361 .conn_event_count = 0x00,
362 .last_pa_event_counter = 0x00,
363 .sid = 0x00,
364 .addr_type = 0x01,
365 .sca = 0x00,
366 .phy = 0x01,
367 .adv_addr = { 0, 0, 0, 0, 0, 0},
368 .sync_conn_event_count = 0
369 };
370
371 /* Reset and setup fake functions */
372 RESET_FAKE(ull_sync_transfer_received);
373 ull_sync_transfer_received_fake.custom_fake = ull_sync_transfer_received_custom_fake;
374
375 RESET_FAKE(mayfly_enqueue);
376 mayfly_enqueue_fake .custom_fake = mayfly_enqueue_custom_fake;
377
378 /* Initialise sync_info */
379 memset(&local_periodic_sync_ind.sync_info, 0, sizeof(struct pdu_adv_sync_info));
380 memset(&remote_periodic_sync_ind.sync_info, 0, sizeof(struct pdu_adv_sync_info));
381
382 /* Role */
383 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
384
385 /* Connect */
386 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
387 conn.llcp.fex.features_peer |= BIT64(BT_LE_FEAT_BIT_PAST_RECV);
388
389 /* Prepare */
390 event_prepare(&conn);
391
392 /* Rx */
393 lt_tx(LL_PERIODIC_SYNC_IND, &conn, &remote_periodic_sync_ind);
394
395 /* Done */
396 event_done(&conn);
397
398 /* Initiate a Periodic Adv. Sync Transfer Procedure */
399 err = ull_cp_periodic_sync(&conn, sync, adv_sync, service_data);
400 zassert_equal(err, BT_HCI_ERR_SUCCESS);
401
402 /* Connection event done with successful rx from peer */
403 ctx = llcp_lr_peek_proc(&conn, PROC_PERIODIC_SYNC);
404 if (ctx) {
405 ctx->data.periodic_sync.conn_start_to_actual_us = 0;
406 ctx->data.periodic_sync.conn_evt_trx = 1;
407 llcp_lp_past_conn_evt_done(&conn, ctx);
408 }
409
410 /* Prepare */
411 event_prepare(&conn);
412
413 /* Tx Queue should have one LL Control PDU */
414 lt_rx(LL_PERIODIC_SYNC_IND, &conn, &tx, &local_periodic_sync_ind);
415 lt_rx_q_is_empty(&conn);
416
417 /* TX Ack */
418 event_tx_ack(&conn, tx);
419
420 /* Done */
421 event_done(&conn);
422
423 /* Release tx node */
424 ull_cp_release_tx(&conn, tx);
425
426 /* There should be no host notifications */
427 ut_rx_q_is_empty();
428
429 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
430 "Free CTX buffers %d and ctx_buffers_cnt is %d", llcp_ctx_buffers_free(),
431 test_ctx_buffers_cnt());
432
433 /* Verify that ull_sync_transfer_received was called,
434 * hence the phy invalidation mechanism works
435 */
436 zassert_equal(ull_sync_transfer_received_fake.call_count, 1,
437 "ull_sync_transfer_received_fake.call_count is %d and expected: %d",
438 ull_sync_transfer_received_fake.call_count, 1);
439 }
440
441 /* +-----+ +-------+ +-----+
442 * | UT | | LL_A | | LT |
443 * +-----+ +-------+ +-----+
444 * | | |
445 * | Start | |
446 * | Periodic Adv. Sync Transfer| |
447 * | Proc. | |
448 * |--------------------------->| |
449 * | | |
450 * | | LL_PERIODIC_SYNC_IND|
451 * | |------------------> |
452 * | | 'll_ack'|
453 * | | |
454 * | | |
455 * | | |
456 * |Periodic Adv. Sync Transfer | |
457 * |Proc. Complete | |
458 * |<---------------------------| |
459 * | Start | |
460 * | Periodic Adv. Sync Transfer| |
461 * | Proc. | |
462 * |--------------------------->| |
463 * | | |
464 * | | |
465 * | | LL_PERIODIC_SYNC_IND|
466 * | |------------------> |
467 * |Periodic Adv. Sync Transfer | 'll_ack'|
468 * | Proc. Complete | |
469 * |<---------------------------| |
470 * | | |
471 */
ZTEST(periodic_sync_transfer,test_periodic_sync_transfer_loc_twice)472 ZTEST(periodic_sync_transfer, test_periodic_sync_transfer_loc_twice)
473 {
474 uint8_t err;
475 struct node_tx *tx;
476 uint16_t service_data = 0;
477 struct proc_ctx *ctx;
478
479 sync = ull_sync_is_enabled_get(0);
480 adv_sync = NULL;
481
482 struct pdu_data_llctrl_periodic_sync_ind local_periodic_sync_ind = {
483 .id = 0x00,
484 .conn_event_count = 0x00,
485 .last_pa_event_counter = 0x00,
486 .sid = 0x00,
487 .addr_type = 0x00,
488 .sca = 0x00,
489 .phy = 0x00,
490 .adv_addr = { 0, 0, 0, 0, 0, 0},
491 .sync_conn_event_count = 0
492 };
493
494 /* Reset and setup mayfly_enqueue_custom_fake */
495 RESET_FAKE(mayfly_enqueue);
496 mayfly_enqueue_fake .custom_fake = mayfly_enqueue_custom_fake;
497
498 /* Initialise sync_info */
499 memset(&local_periodic_sync_ind.sync_info, 0, sizeof(struct pdu_adv_sync_info));
500
501 /* Role */
502 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
503
504 /* Connect */
505 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
506 conn.llcp.fex.features_peer |= BIT64(BT_LE_FEAT_BIT_PAST_RECV);
507
508 /* Initiate a periodic_sync Procedure */
509 err = ull_cp_periodic_sync(&conn, sync, adv_sync, service_data);
510 zassert_equal(err, BT_HCI_ERR_SUCCESS);
511
512 /* Connection event done with successful rx from peer */
513 ctx = llcp_lr_peek_proc(&conn, PROC_PERIODIC_SYNC);
514 if (ctx) {
515 ctx->data.periodic_sync.conn_start_to_actual_us = 0;
516 ctx->data.periodic_sync.conn_evt_trx = 1;
517 llcp_lp_past_conn_evt_done(&conn, ctx);
518 }
519
520 /* Initiate a periodic_sync Procedure */
521 err = ull_cp_periodic_sync(&conn, sync, adv_sync, service_data);
522 zassert_equal(err, BT_HCI_ERR_SUCCESS);
523
524 /* Prepare */
525 event_prepare(&conn);
526
527 /* Tx Queue should have one LL Control PDU */
528 lt_rx(LL_PERIODIC_SYNC_IND, &conn, &tx, &local_periodic_sync_ind);
529 lt_rx_q_is_empty(&conn);
530
531 /* TX Ack */
532 event_tx_ack(&conn, tx);
533
534 /* Done */
535 event_done(&conn);
536
537 /* Increase connection event count */
538 local_periodic_sync_ind.conn_event_count++;
539 local_periodic_sync_ind.sync_conn_event_count++;
540
541 /* There should be no host notifications */
542 ut_rx_q_is_empty();
543
544 /* Connection event done with successful rx from peer */
545 ctx = llcp_lr_peek_proc(&conn, PROC_PERIODIC_SYNC);
546 if (ctx) {
547 ctx->data.periodic_sync.conn_start_to_actual_us = 0;
548 ctx->data.periodic_sync.conn_evt_trx = 1;
549 llcp_lp_past_conn_evt_done(&conn, ctx);
550 }
551
552 /* Prepare */
553 event_prepare(&conn);
554
555 /* Tx Queue should have one LL Control PDU */
556 lt_rx(LL_PERIODIC_SYNC_IND, &conn, &tx, &local_periodic_sync_ind);
557 lt_rx_q_is_empty(&conn);
558
559 /* TX Ack */
560 event_tx_ack(&conn, tx);
561
562 /* Done */
563 event_done(&conn);
564
565 /* Release tx node */
566 ull_cp_release_tx(&conn, tx);
567
568 /* There should be no host notifications */
569 ut_rx_q_is_empty();
570
571 /* Second attempt to run the periodic_sync completes immediately in idle state.
572 * The context is released just after that.
573 */
574 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
575 "Free CTX buffers %d and ctx_buffers_cnt is %d", llcp_ctx_buffers_free(),
576 test_ctx_buffers_cnt());
577 }
578
579 /*
580 * +-----+ +-------+ +-----+
581 * | UT | | LL_A | | LT |
582 * +-----+ +-------+ +-----+
583 * | | |
584 * | | LL_PERIODIC_SYNC_IND |
585 * | | (Invalid PHY) |
586 * | |<----------------------- |
587 * | | |
588 * | | |
589 * | | |
590 * | | |
591 */
ZTEST(periodic_sync_transfer,test_periodic_sync_transfer_invalid_phy)592 ZTEST(periodic_sync_transfer, test_periodic_sync_transfer_invalid_phy)
593 {
594 struct pdu_data_llctrl_periodic_sync_ind remote_periodic_sync_ind = {
595 .id = 0x01,
596 .conn_event_count = 0x00,
597 .last_pa_event_counter = 0x00,
598 .sid = 0x00,
599 .addr_type = 0x01,
600 .sca = 0x00,
601 .phy = 0x03,
602 .adv_addr = { 0, 0, 0, 0, 0, 0},
603 .sync_conn_event_count = 0
604 };
605
606 /* Reset and setup ull_sync_transfer_received fake */
607 RESET_FAKE(ull_sync_transfer_received);
608 ull_sync_transfer_received_fake.custom_fake = ull_sync_transfer_received_custom_fake;
609
610 RESET_FAKE(mayfly_enqueue);
611 mayfly_enqueue_fake .custom_fake = mayfly_enqueue_custom_fake;
612
613 /* Initialise sync_info */
614 memset(&remote_periodic_sync_ind.sync_info, 0, sizeof(struct pdu_adv_sync_info));
615
616 /* Role */
617 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
618
619 /* Connect */
620 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
621 conn.llcp.fex.features_peer |= BIT64(BT_LE_FEAT_BIT_PAST_RECV);
622
623 /* Prepare */
624 event_prepare(&conn);
625
626 /* Rx */
627 lt_tx(LL_PERIODIC_SYNC_IND, &conn, &remote_periodic_sync_ind);
628
629 /* Done */
630 event_done(&conn);
631
632 /* Prepare */
633 event_prepare(&conn);
634
635 /* Tx Queue should have one LL Control PDU */
636 lt_rx_q_is_empty(&conn);
637
638 /* Done */
639 event_done(&conn);
640
641 /* There should not be a host notifications */
642 ut_rx_q_is_empty();
643
644 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
645 "Free CTX buffers %d and ctx_buffers_cnt is %d", llcp_ctx_buffers_free(),
646 test_ctx_buffers_cnt());
647
648 /* Verify that ull_sync_transfer_received was not called,
649 * hence the phy invalidation mechanism works
650 */
651 zassert_equal(ull_sync_transfer_received_fake.call_count, 0,
652 "ull_sync_transfer_received_fake.call_count is %d and expected: %d",
653 ull_sync_transfer_received_fake.call_count, 0);
654 }
655
656 ZTEST_SUITE(periodic_sync_transfer, NULL, NULL, periodic_sync_setup, NULL, NULL);
657