1 /*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <stddef.h>
9 #include <zephyr/ztest.h>
10
11 #include <zephyr/bluetooth/bluetooth.h>
12 #include <zephyr/bluetooth/hci.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <host/hci_core.h>
15
16 #include "util/util.h"
17 #include "util/memq.h"
18 #include "util/mem.h"
19 #include "util/dbuf.h"
20
21 #include "pdu_df.h"
22 #include "lll/pdu_vendor.h"
23 #include "pdu.h"
24
25 #include "hal/ccm.h"
26
27 #include "lll.h"
28 #include "lll/lll_adv_types.h"
29 #include "lll_adv.h"
30 #include "lll/lll_adv_pdu.h"
31 #include "lll/lll_adv_internal.h"
32 #include "lll_adv_sync.h"
33 #include "lll/lll_df_types.h"
34
35 #include "ull_adv_types.h"
36 #include "ull_adv_internal.h"
37
38 #include "ll.h"
39 #include "common.h"
40
41 #define TEST_ADV_SET_HANDLE 0
42 #define TEST_CTE_COUNT 3
43 #define TEST_PER_ADV_CHAIN_LENGTH 5
44 #define TEST_PER_ADV_CHAIN_INCREASED_LENGTH 7
45 #define TEST_PER_ADV_CHAIN_DECREASED_LENGTH (TEST_CTE_COUNT - 1)
46 #define TEST_PER_ADV_SINGLE_PDU 1
47 #define TEST_CTE_SINGLE 1
48 /* It does not matter for purpose of this tests what is the type or length of CTE used. */
49 #define TEST_CTE_TYPE BT_HCI_LE_AOD_CTE_2US
50
ZTEST(test_add_cte_to_per_adv_chain,test_remove_cte_from_chain_extended_to_tx_all_cte)51 ZTEST(test_add_cte_to_per_adv_chain, test_remove_cte_from_chain_extended_to_tx_all_cte)
52 {
53 struct ll_adv_set *adv;
54 uint8_t handle;
55 int err;
56
57 /* Setup for test */
58 adv = common_create_adv_set(TEST_ADV_SET_HANDLE);
59 common_prepare_df_cfg(adv, TEST_CTE_COUNT);
60 common_create_per_adv_chain(adv, TEST_PER_ADV_SINGLE_PDU);
61
62 handle = ull_adv_handle_get(adv);
63
64 ll_df_set_cl_cte_tx_enable(handle, true);
65
66 err = ll_df_set_cl_cte_tx_enable(handle, false);
67 zassert_equal(err, 0,
68 "Unexpected error while disabling CTE for periodic advertising chain, err: %d",
69 err);
70 /* Validate result */
71 common_validate_per_adv_chain(adv, TEST_PER_ADV_SINGLE_PDU);
72
73 common_teardown(adv);
74 }
75
ZTEST(test_add_cte_to_per_adv_chain,test_remove_cte_from_chain_where_each_pdu_includes_cte)76 ZTEST(test_add_cte_to_per_adv_chain, test_remove_cte_from_chain_where_each_pdu_includes_cte)
77 {
78 struct ll_adv_set *adv;
79 uint8_t handle;
80 int err;
81
82 /* Setup for test */
83 adv = common_create_adv_set(TEST_ADV_SET_HANDLE);
84 /* Use the same number for PDUs in a chain as for CTE request */
85 common_prepare_df_cfg(adv, TEST_CTE_COUNT);
86 common_create_per_adv_chain(adv, TEST_CTE_COUNT);
87
88 handle = ull_adv_handle_get(adv);
89
90 err = ll_df_set_cl_cte_tx_enable(handle, true);
91 zassert_equal(err, 0,
92 "Unexpected error while enabling CTE for periodic advertising chain, err: %d",
93 err);
94
95 err = ll_df_set_cl_cte_tx_enable(handle, false);
96 zassert_equal(err, 0,
97 "Unexpected error while disabling CTE for periodic advertising chain, err: %d",
98 err);
99 /* Validate result */
100 common_validate_per_adv_chain(adv, TEST_CTE_COUNT);
101
102 common_teardown(adv);
103 }
104
ZTEST(test_add_cte_to_per_adv_chain,test_remove_cte_from_chain_with_more_pdu_than_cte)105 ZTEST(test_add_cte_to_per_adv_chain, test_remove_cte_from_chain_with_more_pdu_than_cte)
106 {
107 struct ll_adv_set *adv;
108 uint8_t handle;
109 int err;
110
111 /* Setup for test */
112 adv = common_create_adv_set(TEST_ADV_SET_HANDLE);
113 /* Use the same number for PDUs in a chain as for CTE request */
114 common_prepare_df_cfg(adv, TEST_CTE_COUNT);
115 common_create_per_adv_chain(adv, TEST_PER_ADV_CHAIN_LENGTH);
116
117 handle = ull_adv_handle_get(adv);
118
119 ll_df_set_cl_cte_tx_enable(handle, true);
120
121 err = ll_df_set_cl_cte_tx_enable(handle, false);
122 zassert_equal(err, 0,
123 "Unexpected error while disabling CTE for periodic advertising chain, err: %d",
124 err);
125 /* Validate result */
126 common_validate_per_adv_chain(adv, TEST_PER_ADV_CHAIN_LENGTH);
127
128 common_teardown(adv);
129 }
130
ZTEST(test_add_cte_to_per_adv_chain,test_remove_cte_from_single_pdu_chain)131 ZTEST(test_add_cte_to_per_adv_chain, test_remove_cte_from_single_pdu_chain)
132 {
133 struct ll_adv_set *adv;
134 uint8_t handle;
135 int err;
136
137 /* Setup for test */
138 adv = common_create_adv_set(TEST_ADV_SET_HANDLE);
139 /* Use the same number for PDUs in a chain as for CTE request */
140 common_prepare_df_cfg(adv, TEST_CTE_SINGLE);
141 common_create_per_adv_chain(adv, TEST_PER_ADV_SINGLE_PDU);
142
143 handle = ull_adv_handle_get(adv);
144
145 ll_df_set_cl_cte_tx_enable(handle, true);
146
147 err = ll_df_set_cl_cte_tx_enable(handle, false);
148 zassert_equal(err, 0,
149 "Unexpected error while disabling CTE for periodic advertising chain, err: %d",
150 err);
151 /* Validate result */
152 common_validate_per_adv_chain(adv, TEST_PER_ADV_SINGLE_PDU);
153
154 common_teardown(adv);
155 }
156
remove_cte_from_chain_after_enqueue_to_lll(uint8_t cte_count,uint8_t init_chain_length,uint8_t expected_mem_pdu_used_count_for_enable,uint8_t expected_mem_pdu_used_count_for_disable,uint8_t expected_pdu_in_chain_after_cte_disable,uint8_t updated_chain_length,uint8_t expected_end_fifo_free_pdu_count,bool new_chain_before_cte_disable)157 static void remove_cte_from_chain_after_enqueue_to_lll(
158 uint8_t cte_count, uint8_t init_chain_length,
159 uint8_t expected_mem_pdu_used_count_for_enable,
160 uint8_t expected_mem_pdu_used_count_for_disable,
161 uint8_t expected_pdu_in_chain_after_cte_disable, uint8_t updated_chain_length,
162 uint8_t expected_end_fifo_free_pdu_count, bool new_chain_before_cte_disable)
163 {
164 uint32_t pdu_mem_cnt_expected, pdu_mem_cnt;
165 struct pdu_adv *pdu_prev, *pdu_new;
166 struct ll_adv_set *adv;
167 uint32_t pdu_fifo_cnt;
168 uint8_t handle;
169 uint8_t upd;
170 int err;
171
172 pdu_mem_cnt_expected = lll_adv_pdu_mem_free_count_get();
173
174 /* Setup for test */
175 adv = common_create_adv_set(TEST_ADV_SET_HANDLE);
176 /* Use smaller number of CTE for request than number of PDUs in an initial chain.
177 * In such situation chain should not be extended and PDUs pool should be not affected.
178 */
179 common_prepare_df_cfg(adv, cte_count);
180 common_create_per_adv_chain(adv, init_chain_length);
181
182 handle = ull_adv_handle_get(adv);
183
184 err = ll_df_set_cl_cte_tx_enable(handle, true);
185 zassert_equal(err, 0,
186 "Unexpected error while enabling CTE for periodic advertising chain, err: %d",
187 err);
188
189 /* Swap PDU double buffer and get new latest PDU data */
190 pdu_new = lll_adv_sync_data_latest_get(adv->lll.sync, NULL, &upd);
191 zassert_not_equal(pdu_new, NULL,
192 "Unexpected value of new PDU pointer after PDU double buffer swap");
193
194 pdu_prev = lll_adv_sync_data_peek(adv->lll.sync, NULL);
195 zassert_equal(pdu_prev, pdu_new,
196 "Unexpected value of previous PDU pointer after PDU double buffer swap");
197
198 /* Free PDUs fifo should hold single PDU released during double buffer swap. The PDU
199 * was allocated during advertising set creation.
200 */
201 pdu_fifo_cnt = lll_adv_free_pdu_fifo_count_get();
202 zassert_equal(pdu_fifo_cnt, TEST_PER_ADV_SINGLE_PDU,
203 "Unexpected number of free PDUs in a fifo: %d", pdu_fifo_cnt);
204
205 /* Expected free PDUs count is decreased by:
206 * - single PDU allocated during advertising set creation,
207 * - number of PDUs allocated for per. adv. chain to Tx CTE
208 */
209 pdu_mem_cnt_expected -= expected_mem_pdu_used_count_for_enable;
210 pdu_mem_cnt = lll_adv_pdu_mem_free_count_get();
211 zassert_equal(pdu_mem_cnt, pdu_mem_cnt_expected,
212 "Unexpected amount of free PDUs memory: %d, expected %d", pdu_mem_cnt,
213 pdu_mem_cnt_expected);
214
215 if (new_chain_before_cte_disable) {
216 common_create_per_adv_chain(adv, updated_chain_length);
217 }
218
219 err = ll_df_set_cl_cte_tx_enable(handle, false);
220 zassert_equal(err, 0,
221 "Unexpected error while disabling CTE for periodic advertising chain, err: %d",
222 err);
223 /* Validate result */
224 common_validate_per_adv_chain(adv, expected_pdu_in_chain_after_cte_disable);
225
226 /* Swap PDU double buffer to check correctness of release former PDUs */
227 pdu_new = lll_adv_sync_data_latest_get(adv->lll.sync, NULL, &upd);
228 zassert_not_equal(pdu_new, NULL,
229 "Unexpected value of PDU pointer after PDU double buffer swap");
230
231 /* Validate number of released PDUs */
232
233 /* Number of free PDUs in a fifo is a number of released PDUs from former periodic
234 * advertising chain. One free PDU that had been in a fifo was used for allocation of
235 * the new PDU without CTE.
236 */
237 pdu_fifo_cnt = lll_adv_free_pdu_fifo_count_get();
238 zassert_equal(pdu_fifo_cnt, expected_end_fifo_free_pdu_count,
239 "Unexpected number of free PDUs in a fifo: %d", pdu_fifo_cnt);
240
241 /* Number of free PDUs in memory pool may decreased. Single PDU for AUX_SYNC_IND was
242 * acquired from free PDUs fifo. The memory pool will decrease by number of non empty PDUs
243 * in a chain subtracted by 1 (PDU taken from free PDUs fifo).
244 */
245 pdu_mem_cnt_expected -= expected_mem_pdu_used_count_for_disable;
246
247 pdu_mem_cnt = lll_adv_pdu_mem_free_count_get();
248 zassert_equal(pdu_mem_cnt, pdu_mem_cnt_expected,
249 "Unexpected amount of free PDUs memory: %d, expected %d", pdu_mem_cnt,
250 pdu_mem_cnt_expected);
251
252 common_teardown(adv);
253 }
254
ZTEST(test_add_cte_to_per_adv_chain,test_remove_cte_from_chain_extended_to_tx_all_cte_after_enqueue_to_lll)255 ZTEST(test_add_cte_to_per_adv_chain,
256 test_remove_cte_from_chain_extended_to_tx_all_cte_after_enqueue_to_lll)
257 {
258 uint8_t cte_count = TEST_CTE_COUNT;
259 uint8_t init_chain_length = TEST_PER_ADV_SINGLE_PDU;
260 uint8_t expected_mem_pdu_used_count_for_enable = TEST_CTE_COUNT + TEST_PER_ADV_SINGLE_PDU;
261 uint8_t expected_mem_pdu_used_count_for_disable = 0;
262 uint8_t expected_pdu_in_chain_after_cte_disable = TEST_PER_ADV_SINGLE_PDU;
263 uint8_t updated_chain_length = 0;
264 uint8_t expected_end_fifo_free_pdu_count = TEST_CTE_COUNT;
265 bool new_chain_before_cte_disable = false;
266
267 remove_cte_from_chain_after_enqueue_to_lll(
268 cte_count, init_chain_length, expected_mem_pdu_used_count_for_enable,
269 expected_mem_pdu_used_count_for_disable, expected_pdu_in_chain_after_cte_disable,
270 updated_chain_length, expected_end_fifo_free_pdu_count,
271 new_chain_before_cte_disable);
272 }
273
ZTEST(test_add_cte_to_per_adv_chain,test_remove_cte_from_chain_with_more_pdu_than_cte_after_enqueue_to_lll)274 ZTEST(test_add_cte_to_per_adv_chain,
275 test_remove_cte_from_chain_with_more_pdu_than_cte_after_enqueue_to_lll)
276 {
277 uint8_t cte_count = TEST_CTE_COUNT;
278 uint8_t init_chain_length = TEST_PER_ADV_CHAIN_LENGTH;
279 uint8_t expected_mem_pdu_used_count_for_enable =
280 TEST_PER_ADV_CHAIN_LENGTH + TEST_PER_ADV_SINGLE_PDU;
281 uint8_t expected_mem_pdu_used_count_for_disable =
282 TEST_PER_ADV_CHAIN_LENGTH - TEST_PER_ADV_SINGLE_PDU;
283 uint8_t expected_pdu_in_chain_after_cte_disable = TEST_PER_ADV_CHAIN_LENGTH;
284 uint8_t updated_chain_length = 0;
285 uint8_t expected_end_fifo_free_pdu_count = TEST_PER_ADV_CHAIN_LENGTH;
286 bool new_chain_before_cte_disable = false;
287
288 remove_cte_from_chain_after_enqueue_to_lll(
289 cte_count, init_chain_length, expected_mem_pdu_used_count_for_enable,
290 expected_mem_pdu_used_count_for_disable, expected_pdu_in_chain_after_cte_disable,
291 updated_chain_length, expected_end_fifo_free_pdu_count,
292 new_chain_before_cte_disable);
293 }
294
ZTEST(test_add_cte_to_per_adv_chain,test_remove_cte_from_chain_length_increased_after_enqueue_to_lll)295 ZTEST(test_add_cte_to_per_adv_chain,
296 test_remove_cte_from_chain_length_increased_after_enqueue_to_lll)
297 {
298 uint8_t cte_count = TEST_CTE_COUNT;
299 uint8_t init_chain_length = TEST_PER_ADV_CHAIN_LENGTH;
300 uint8_t expected_mem_pdu_used_count_for_enable =
301 TEST_PER_ADV_CHAIN_LENGTH + TEST_PER_ADV_SINGLE_PDU;
302 uint8_t expected_mem_pdu_used_count_for_disable =
303 TEST_PER_ADV_CHAIN_INCREASED_LENGTH - TEST_PER_ADV_SINGLE_PDU;
304 uint8_t expected_pdu_in_chain_after_cte_disable = TEST_PER_ADV_CHAIN_INCREASED_LENGTH;
305 uint8_t updated_chain_length = TEST_PER_ADV_CHAIN_INCREASED_LENGTH;
306 uint8_t expected_end_fifo_free_pdu_count = TEST_PER_ADV_CHAIN_LENGTH;
307 bool new_chain_before_cte_disable = true;
308
309 remove_cte_from_chain_after_enqueue_to_lll(
310 cte_count, init_chain_length, expected_mem_pdu_used_count_for_enable,
311 expected_mem_pdu_used_count_for_disable, expected_pdu_in_chain_after_cte_disable,
312 updated_chain_length, expected_end_fifo_free_pdu_count,
313 new_chain_before_cte_disable);
314 }
315
ZTEST(test_add_cte_to_per_adv_chain,test_remove_cte_from_chain_length_decreased_after_enqueue_to_lll)316 ZTEST(test_add_cte_to_per_adv_chain,
317 test_remove_cte_from_chain_length_decreased_after_enqueue_to_lll)
318 {
319 uint8_t cte_count = TEST_CTE_COUNT;
320 uint8_t init_chain_length = TEST_PER_ADV_CHAIN_LENGTH;
321 uint8_t expected_mem_pdu_used_count_for_enable =
322 TEST_PER_ADV_CHAIN_LENGTH + TEST_PER_ADV_SINGLE_PDU;
323 uint8_t expected_mem_pdu_used_count_for_disable =
324 TEST_PER_ADV_CHAIN_DECREASED_LENGTH - TEST_PER_ADV_SINGLE_PDU;
325 uint8_t expected_pdu_in_chain_after_cte_disable = TEST_PER_ADV_CHAIN_DECREASED_LENGTH;
326 uint8_t updated_chain_length = TEST_PER_ADV_CHAIN_DECREASED_LENGTH;
327 uint8_t expected_end_fifo_free_pdu_count = TEST_PER_ADV_CHAIN_LENGTH;
328 bool new_chain_before_cte_disable = true;
329
330 remove_cte_from_chain_after_enqueue_to_lll(
331 cte_count, init_chain_length, expected_mem_pdu_used_count_for_enable,
332 expected_mem_pdu_used_count_for_disable, expected_pdu_in_chain_after_cte_disable,
333 updated_chain_length, expected_end_fifo_free_pdu_count,
334 new_chain_before_cte_disable);
335 }
336
337 ZTEST_SUITE(test_remove_cte_from_per_adv_chain, NULL, NULL, NULL, NULL, NULL);
338