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