1 /*
2 * Copyright (c) 2022 Demant
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/types.h>
8 #include <zephyr/ztest.h>
9
10 #include <zephyr/bluetooth/hci.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <zephyr/sys/slist.h>
13 #include <zephyr/sys/util.h>
14 #include "hal/ccm.h"
15
16 #include "util/util.h"
17 #include "util/mem.h"
18 #include "util/memq.h"
19 #include "util/dbuf.h"
20
21 #include "pdu_df.h"
22 #include "lll/pdu_vendor.h"
23 #include "pdu.h"
24 #include "ll.h"
25 #include "ll_feat.h"
26 #include "ll_settings.h"
27
28 #include "lll.h"
29 #include "lll/lll_df_types.h"
30 #include "lll_conn.h"
31 #include "lll_conn_iso.h"
32
33 #include "ull_tx_queue.h"
34
35 #include "isoal.h"
36 #include "ull_iso_types.h"
37 #include "ull_conn_iso_types.h"
38 #include "ull_conn_types.h"
39 #include "ull_llcp.h"
40 #include "ull_conn_internal.h"
41 #include "ull_llcp_internal.h"
42 #include "ull_llcp_features.h"
43
44 #include "helper_pdu.h"
45 #include "helper_util.h"
46
47 static struct ll_conn conn;
48
sca_setup(void * data)49 static void sca_setup(void *data)
50 {
51 test_setup(&conn);
52 }
53
54 /* +-----+ +-------+ +-----+
55 * | UT | | LL_A | | LT |
56 * +-----+ +-------+ +-----+
57 * | | |
58 * | Start | |
59 * | SCA Update Proc. | |
60 * |--------------------------->| |
61 * | | |
62 * | | LL_CLOCK_ACCURACY_REQ |
63 * | |------------------------------->|
64 * | | |
65 * | | LL_CLOCK_ACCURACY_RSP |
66 * | |<-------------------------------|
67 * | | |
68 * | Start | |
69 * | SCA UPdate Proc. | |
70 * |--------------------------->| |
71 * | | |
72 * | | LL_CLOCK_ACCURACY_REQ |
73 * | |------------------------------->|
74 * | | |
75 * | | LL_UNKNOWN_RSP |
76 * | |<-------------------------------|
77 * | | |
78 */
ZTEST(sca_central,test_sca_central_loc)79 ZTEST(sca_central, test_sca_central_loc)
80 {
81 uint8_t err;
82 struct node_tx *tx;
83 struct node_rx_pdu *ntf;
84 struct node_rx_sca scau = { .status = BT_HCI_ERR_SUCCESS, .sca = 2 };
85 struct pdu_data_llctrl_clock_accuracy_req local_sca_req = { };
86 struct pdu_data_llctrl_clock_accuracy_rsp remote_sca_rsp = { .sca = 2 };
87 struct pdu_data_llctrl_unknown_rsp unknown_rsp = {
88 .type = PDU_DATA_LLCTRL_TYPE_CLOCK_ACCURACY_REQ
89 };
90
91 /* Role */
92 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
93
94 /* Connect */
95 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
96
97 /* Initiate an SCA Procedure */
98 err = ull_cp_req_peer_sca(&conn);
99 zassert_equal(err, BT_HCI_ERR_SUCCESS);
100
101 /* Confirm SCA Update is indicated as supported */
102 zassert_equal(feature_sca(&conn), true, "SCA Update Feature masked out");
103
104 /* Prepare */
105 event_prepare(&conn);
106
107 /* Tx Queue should have one LL Control PDU */
108 lt_rx(LL_CLOCK_ACCURACY_REQ, &conn, &tx, &local_sca_req);
109 lt_rx_q_is_empty(&conn);
110
111 /* Rx */
112 lt_tx(LL_CLOCK_ACCURACY_RSP, &conn, &remote_sca_rsp);
113
114 /* Done */
115 event_done(&conn);
116
117 /* Release tx node */
118 ull_cp_release_tx(&conn, tx);
119
120 /* Termination not 'triggered' */
121 zassert_equal(conn.llcp_terminate.reason_final, 0,
122 "Terminate reason %d", conn.llcp_terminate.reason_final);
123
124 /* There should be one notification due to Peer SCA Request */
125 ut_rx_node(NODE_PEER_SCA_UPDATE, &ntf, &scau);
126 ut_rx_q_is_empty();
127
128 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
129 "Free CTX buffers %d", llcp_ctx_buffers_free());
130
131 /* Initiate another SCA Procedure */
132 err = ull_cp_req_peer_sca(&conn);
133 zassert_equal(err, BT_HCI_ERR_SUCCESS);
134
135 /* Prepare */
136 event_prepare(&conn);
137
138 /* Tx Queue should have one LL Control PDU */
139 lt_rx(LL_CLOCK_ACCURACY_REQ, &conn, &tx, &local_sca_req);
140 lt_rx_q_is_empty(&conn);
141
142 /* Rx */
143 lt_tx(LL_UNKNOWN_RSP, &conn, &unknown_rsp);
144
145 /* Done */
146 event_done(&conn);
147
148 /* Release tx node */
149 ull_cp_release_tx(&conn, tx);
150
151 /* Confirm SCA Update is now indicated as NOT supported */
152 zassert_equal(feature_sca(&conn), false, "SCA Update Feature masked in");
153
154 /* Termination not 'triggered' */
155 zassert_equal(conn.llcp_terminate.reason_final, 0,
156 "Terminate reason %d", conn.llcp_terminate.reason_final);
157
158 scau.status = BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
159 scau.sca = 0;
160
161 /* There should be one notification due to Peer SCA Request */
162 ut_rx_node(NODE_PEER_SCA_UPDATE, &ntf, &scau);
163 ut_rx_q_is_empty();
164
165 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
166 "Free CTX buffers %d", llcp_ctx_buffers_free());
167
168 }
169
170 /* +-----+ +-------+ +-----+
171 * | UT | | LL_A | | LT |
172 * +-----+ +-------+ +-----+
173 * | | |
174 * | Start | |
175 * | SCA Update Proc. | |
176 * |--------------------------->| |
177 * | | |
178 * | | LL_CLOCK_ACCURACY_REQ |
179 * | |------------------------->|
180 * | | |
181 * | | LL_<INVALID>_RSP |
182 * | |<-------------------------|
183 * | | |
184 * ~~~~~~~~~~~~~~~~~ TERMINATE CONNECTION ~~~~~~~~~~~~~~
185 * | | |
186 */
ZTEST(sca_central,test_sca_central_loc_invalid_rsp)187 ZTEST(sca_central, test_sca_central_loc_invalid_rsp)
188 {
189 uint8_t err;
190 struct node_tx *tx;
191
192 struct pdu_data_llctrl_reject_ind reject_ind = {
193 .error_code = BT_HCI_ERR_LL_PROC_COLLISION
194 };
195 struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
196 .reject_opcode = PDU_DATA_LLCTRL_TYPE_CLOCK_ACCURACY_REQ,
197 .error_code = BT_HCI_ERR_LL_PROC_COLLISION
198 };
199 struct pdu_data_llctrl_clock_accuracy_req local_sca_req = {};
200
201 /* Role */
202 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
203
204 /* Connect */
205 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
206
207 /* Initiate an SCA Procedure */
208 err = ull_cp_req_peer_sca(&conn);
209 zassert_equal(err, BT_HCI_ERR_SUCCESS);
210
211 /* Prepare */
212 event_prepare(&conn);
213
214 /* Tx Queue should have one LL Control PDU */
215 lt_rx(LL_CLOCK_ACCURACY_REQ, &conn, &tx, &local_sca_req);
216 lt_rx_q_is_empty(&conn);
217
218 /* Rx */
219 lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind);
220
221 /* Done */
222 event_done(&conn);
223
224 /* Release tx node */
225 ull_cp_release_tx(&conn, tx);
226
227 /* Termination 'triggered' */
228 zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
229 "Terminate reason %d", conn.llcp_terminate.reason_final);
230
231 /* Clear termination flag for subsequent test cycle */
232 conn.llcp_terminate.reason_final = 0;
233
234 /* There should not be a host notifications */
235 ut_rx_q_is_empty();
236
237 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
238 "Free CTX buffers %d", llcp_ctx_buffers_free());
239
240 /* Initiate another SCA Procedure */
241 err = ull_cp_req_peer_sca(&conn);
242 zassert_equal(err, BT_HCI_ERR_SUCCESS);
243
244 /* Prepare */
245 event_prepare(&conn);
246
247 /* Tx Queue should have one LL Control PDU */
248 lt_rx(LL_CLOCK_ACCURACY_REQ, &conn, &tx, &local_sca_req);
249 lt_rx_q_is_empty(&conn);
250
251 /* Rx */
252 lt_tx(LL_REJECT_IND, &conn, &reject_ind);
253
254 /* Done */
255 event_done(&conn);
256
257 /* Release tx node */
258 ull_cp_release_tx(&conn, tx);
259
260 /* Termination 'triggered' */
261 zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
262 "Terminate reason %d", conn.llcp_terminate.reason_final);
263
264 /* There should not be a host notifications */
265 ut_rx_q_is_empty();
266
267 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
268 "Free CTX buffers %d", llcp_ctx_buffers_free());
269
270 }
271
272 /* +-----+ +-------+ +-----+
273 * | UT | | LL_A | | LT |
274 * +-----+ +-------+ +-----+
275 * | | |
276 * | Start | |
277 * | SCA Update Proc. | |
278 * |--------------------------->| |
279 * | | |
280 * | | LL_CLOCK_ACCURACY_REQ |
281 * | |------------------------->|
282 * | | |
283 * | | LL_<INVALID>_RSP |
284 * | |<-------------------------|
285 * | | |
286 * ~~~~~~~~~~~~~~~~~ TERMINATE CONNECTION ~~~~~~~~~~~~~~
287 * | | |
288 */
ZTEST(sca_periph,test_sca_peripheral_loc_invalid_rsp)289 ZTEST(sca_periph, test_sca_peripheral_loc_invalid_rsp)
290 {
291 uint8_t err;
292 struct node_tx *tx;
293
294 struct pdu_data_llctrl_reject_ind reject_ind = {
295 .error_code = BT_HCI_ERR_LL_PROC_COLLISION
296 };
297 struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
298 .reject_opcode = PDU_DATA_LLCTRL_TYPE_CLOCK_ACCURACY_REQ,
299 .error_code = BT_HCI_ERR_LL_PROC_COLLISION
300 };
301 struct pdu_data_llctrl_clock_accuracy_req local_sca_req = {};
302
303 /* Role */
304 test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
305
306 /* Connect */
307 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
308
309 /* Initiate an SCA Procedure */
310 err = ull_cp_req_peer_sca(&conn);
311 zassert_equal(err, BT_HCI_ERR_SUCCESS);
312
313 /* Prepare */
314 event_prepare(&conn);
315
316 /* Tx Queue should have one LL Control PDU */
317 lt_rx(LL_CLOCK_ACCURACY_REQ, &conn, &tx, &local_sca_req);
318 lt_rx_q_is_empty(&conn);
319
320 /* Rx */
321 lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind);
322
323 /* Done */
324 event_done(&conn);
325
326 /* Release tx node */
327 ull_cp_release_tx(&conn, tx);
328
329 /* Termination 'triggered' */
330 zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
331 "Terminate reason %d", conn.llcp_terminate.reason_final);
332
333 /* Clear termination flag for subsequent test cycle */
334 conn.llcp_terminate.reason_final = 0;
335
336 /* There should not be a host notifications */
337 ut_rx_q_is_empty();
338
339 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
340 "Free CTX buffers %d", llcp_ctx_buffers_free());
341
342 /* Initiate another SCA Procedure */
343 err = ull_cp_req_peer_sca(&conn);
344 zassert_equal(err, BT_HCI_ERR_SUCCESS);
345
346 /* Prepare */
347 event_prepare(&conn);
348
349 /* Tx Queue should have one LL Control PDU */
350 lt_rx(LL_CLOCK_ACCURACY_REQ, &conn, &tx, &local_sca_req);
351 lt_rx_q_is_empty(&conn);
352
353 /* Rx */
354 lt_tx(LL_REJECT_IND, &conn, &reject_ind);
355
356 /* Done */
357 event_done(&conn);
358
359 /* Release tx node */
360 ull_cp_release_tx(&conn, tx);
361
362 /* Termination 'triggered' */
363 zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
364 "Terminate reason %d", conn.llcp_terminate.reason_final);
365
366 /* There should not be a host notifications */
367 ut_rx_q_is_empty();
368
369 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
370 "Free CTX buffers %d", llcp_ctx_buffers_free());
371
372 }
373
374 /* +-----+ +-------+ +-----+
375 * | UT | | LL_A | | LT |
376 * +-----+ +-------+ +-----+
377 * | | |
378 * | Start | |
379 * | SCA Update Proc. | |
380 * |--------------------------->| |
381 * | | |
382 * | | LL_CLOCK_ACCURACY_REQ |
383 * | |------------------------->|
384 * | | |
385 * | | LL_CLOCK_ACCURACY_RSP |
386 * | |<-------------------------|
387 * | | |
388 * | | |
389 */
ZTEST(sca_periph,test_ping_periph_loc)390 ZTEST(sca_periph, test_ping_periph_loc)
391 {
392 uint8_t err;
393 struct node_tx *tx;
394 struct node_rx_pdu *ntf;
395 struct node_rx_sca scau = { .status = BT_HCI_ERR_SUCCESS, .sca = 2 };
396 struct pdu_data_llctrl_clock_accuracy_req local_sca_req = { };
397 struct pdu_data_llctrl_clock_accuracy_rsp remote_sca_rsp = { .sca = 2 };
398
399 /* Role */
400 test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
401
402 /* Connect */
403 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
404
405 /* Initiate an SCA Procedure */
406 err = ull_cp_req_peer_sca(&conn);
407 zassert_equal(err, BT_HCI_ERR_SUCCESS);
408
409 /* Prepare */
410 event_prepare(&conn);
411
412 /* Tx Queue should have one LL Control PDU */
413 lt_rx(LL_CLOCK_ACCURACY_REQ, &conn, &tx, &local_sca_req);
414 lt_rx_q_is_empty(&conn);
415
416 /* Rx */
417 lt_tx(LL_CLOCK_ACCURACY_RSP, &conn, &remote_sca_rsp);
418
419 /* Done */
420 event_done(&conn);
421
422 /* Release tx node */
423 ull_cp_release_tx(&conn, tx);
424
425 /* Termination not 'triggered' */
426 zassert_equal(conn.llcp_terminate.reason_final, 0,
427 "Terminate reason %d", conn.llcp_terminate.reason_final);
428
429 /* There should be one notification due to Peer SCA Request */
430 ut_rx_node(NODE_PEER_SCA_UPDATE, &ntf, &scau);
431 ut_rx_q_is_empty();
432
433 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
434 "Free CTX buffers %d", llcp_ctx_buffers_free());
435 }
436
437 /* +-----+ +-------+ +-----+
438 * | UT | | LL_A | | LT |
439 * +-----+ +-------+ +-----+
440 * | | |
441 * | | LL_CLOCK_ACCURACY_REQ |
442 * | |------------------------->|
443 * | | |
444 * | | LL_CLOCK_ACCURACY_RSP |
445 * | |<-------------------------|
446 * | | |
447 * | | |
448 */
ZTEST(sca_central,test_ping_central_rem)449 ZTEST(sca_central, test_ping_central_rem)
450 {
451 struct node_tx *tx;
452
453 struct pdu_data_llctrl_clock_accuracy_req local_sca_req = { };
454
455 struct pdu_data_llctrl_clock_accuracy_rsp remote_sca_rsp = { };
456
457 /* Role */
458 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
459
460 /* Connect */
461 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
462
463 /* Prepare */
464 event_prepare(&conn);
465
466 /* Tx */
467 lt_tx(LL_CLOCK_ACCURACY_REQ, &conn, &local_sca_req);
468
469 /* Done */
470 event_done(&conn);
471
472 /* Prepare */
473 event_prepare(&conn);
474
475 /* Tx Queue should have one LL Control PDU */
476 lt_rx(LL_CLOCK_ACCURACY_RSP, &conn, &tx, &remote_sca_rsp);
477 lt_rx_q_is_empty(&conn);
478
479 event_tx_ack(&conn, tx);
480
481 /* Done */
482 event_done(&conn);
483
484 /* Release tx node */
485 ull_cp_release_tx(&conn, tx);
486
487 /* There should not be a host notifications */
488 ut_rx_q_is_empty();
489
490 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
491 "Free CTX buffers %d", llcp_ctx_buffers_free());
492 }
493
494 /* +-----+ +-------+ +-----+
495 * | UT | | LL_A | | LT |
496 * +-----+ +-------+ +-----+
497 * | | |
498 * | | LL_CLOCK_ACCURACY_REQ |
499 * | |------------------------->|
500 * | | |
501 * | | LL_CLOCK_ACCURACY_RSP |
502 * | |<-------------------------|
503 * | | |
504 * | | |
505 */
ZTEST(sca_periph,test_ping_periph_rem)506 ZTEST(sca_periph, test_ping_periph_rem)
507 {
508 struct node_tx *tx;
509
510 struct pdu_data_llctrl_clock_accuracy_req local_sca_req = { };
511
512 struct pdu_data_llctrl_clock_accuracy_rsp remote_sca_rsp = { };
513
514 /* Role */
515 test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
516
517 /* Connect */
518 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
519
520 /* Prepare */
521 event_prepare(&conn);
522
523 /* Tx */
524 lt_tx(LL_CLOCK_ACCURACY_REQ, &conn, &local_sca_req);
525
526 /* Done */
527 event_done(&conn);
528
529 /* Prepare */
530 event_prepare(&conn);
531
532 /* Tx Queue should have one LL Control PDU */
533 lt_rx(LL_CLOCK_ACCURACY_RSP, &conn, &tx, &remote_sca_rsp);
534 lt_rx_q_is_empty(&conn);
535
536 event_tx_ack(&conn, tx);
537
538 /* Done */
539 event_done(&conn);
540
541 /* Release tx node */
542 ull_cp_release_tx(&conn, tx);
543
544 /* There should not be a host notifications */
545 ut_rx_q_is_empty();
546
547 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
548 "Free CTX buffers %d", llcp_ctx_buffers_free());
549 }
550
551 ZTEST_SUITE(sca_central, NULL, NULL, sca_setup, NULL, NULL);
552 ZTEST_SUITE(sca_periph, NULL, NULL, sca_setup, NULL, NULL);
553