1 /*
2 * Copyright (c) 2020 Demant
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/types.h>
8 #include <zephyr/ztest.h>
9
10 #define ULL_LLCP_UNITTEST
11
12 #include <zephyr/bluetooth/hci.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <zephyr/sys/slist.h>
15 #include <zephyr/sys/util.h>
16 #include "hal/ccm.h"
17
18 #include "util/util.h"
19 #include "util/mem.h"
20 #include "util/memq.h"
21 #include "util/dbuf.h"
22
23 #include "pdu_df.h"
24 #include "lll/pdu_vendor.h"
25 #include "pdu.h"
26 #include "ll.h"
27 #include "ll_settings.h"
28
29 #include "lll.h"
30 #include "lll/lll_df_types.h"
31 #include "lll_conn.h"
32 #include "lll_conn_iso.h"
33
34 #include "ull_tx_queue.h"
35
36 #include "isoal.h"
37 #include "ull_iso_types.h"
38 #include "ull_conn_iso_types.h"
39 #include "ull_conn_types.h"
40 #include "ull_llcp.h"
41 #include "ull_conn_internal.h"
42 #include "ull_llcp_internal.h"
43
44 #include "helper_pdu.h"
45 #include "helper_util.h"
46
47 static struct ll_conn conn;
48
chmu_setup(void * data)49 static void chmu_setup(void *data)
50 {
51 test_setup(&conn);
52 }
53
is_instant_reached(struct ll_conn * conn,uint16_t instant)54 static bool is_instant_reached(struct ll_conn *conn, uint16_t instant)
55 {
56 return ((event_counter(conn) - instant) & 0xFFFF) <= 0x7FFF;
57 }
58
ZTEST(chmu,test_channel_map_update_central_loc)59 ZTEST(chmu, test_channel_map_update_central_loc)
60 {
61 uint8_t chm[5] = { 0x00, 0x04, 0x05, 0x06, 0x00 };
62 uint8_t initial_chm[5];
63 uint8_t err;
64 struct node_tx *tx;
65 struct pdu_data *pdu;
66 uint16_t instant;
67 struct pdu_data_llctrl_chan_map_ind chmu_ind = {
68 .instant = 6,
69 .chm = { 0x00, 0x04, 0x05, 0x06, 0x00 },
70 };
71
72 /* Store initial channel map */
73 memcpy(initial_chm, conn.lll.data_chan_map, sizeof(conn.lll.data_chan_map));
74
75 /* Role */
76 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
77
78 /* Connect */
79 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
80
81 err = ull_cp_chan_map_update(&conn, chm);
82 zassert_equal(err, BT_HCI_ERR_SUCCESS);
83
84 /* Prepare */
85 event_prepare(&conn);
86
87 /* Tx Queue should have one LL Control PDU */
88 lt_rx(LL_CHAN_MAP_UPDATE_IND, &conn, &tx, &chmu_ind);
89 lt_rx_q_is_empty(&conn);
90
91 /* Done */
92 event_done(&conn);
93
94 /* Save Instant */
95 pdu = (struct pdu_data *)tx->pdu;
96 instant = sys_le16_to_cpu(pdu->llctrl.chan_map_ind.instant);
97
98 /* Release Tx */
99 ull_cp_release_tx(&conn, tx);
100
101 /* spin conn events */
102 while (!is_instant_reached(&conn, instant)) {
103 /* Prepare */
104 event_prepare(&conn);
105
106 /* Tx Queue should NOT have a LL Control PDU */
107 lt_rx_q_is_empty(&conn);
108
109 /* Done */
110 event_done(&conn);
111
112 /* There should NOT be a host notification */
113 ut_rx_q_is_empty();
114
115 /* check if still using initial channel map */
116 zassert_mem_equal(conn.lll.data_chan_map, initial_chm,
117 sizeof(conn.lll.data_chan_map),
118 "Channel map invalid");
119 }
120
121 /* Prepare */
122 event_prepare(&conn);
123
124 /* Tx Queue should NOT have a LL Control PDU */
125 lt_rx_q_is_empty(&conn);
126
127 /* Done */
128 event_done(&conn);
129
130 /* There should be no host notification */
131 ut_rx_q_is_empty();
132
133 /* at this point new channel map shall be in use */
134 zassert_mem_equal(conn.lll.data_chan_map, chm, sizeof(conn.lll.data_chan_map),
135 "Channel map invalid");
136
137 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
138 "Free CTX buffers %d", llcp_ctx_buffers_free());
139 }
140
ZTEST(chmu,test_channel_map_update_central_invalid)141 ZTEST(chmu, test_channel_map_update_central_invalid)
142 {
143 uint8_t chm[5] = { 0x00, 0x04, 0x05, 0x06, 0x00 };
144 uint8_t err;
145 struct node_tx *tx;
146 struct pdu_data_llctrl_unknown_rsp unknown_rsp = {
147 .type = PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND
148 };
149 struct pdu_data_llctrl_chan_map_ind chmu_ind = {
150 .instant = 6,
151 .chm = { 0x00, 0x04, 0x05, 0x06, 0x00 },
152 };
153
154 /* Role */
155 test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
156
157 /* Connect */
158 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
159
160 err = ull_cp_chan_map_update(&conn, chm);
161 zassert_equal(err, BT_HCI_ERR_SUCCESS);
162
163 /* Prepare */
164 event_prepare(&conn);
165
166 /* Tx Queue should have one LL Control PDU */
167 lt_rx(LL_CHAN_MAP_UPDATE_IND, &conn, &tx, &chmu_ind);
168 lt_rx_q_is_empty(&conn);
169
170 /* Done */
171 event_done(&conn);
172
173 /* Release Tx */
174 ull_cp_release_tx(&conn, tx);
175
176 /* Prepare */
177 event_prepare(&conn);
178
179 /* Tx Queue should NOT have a LL Control PDU */
180 lt_rx_q_is_empty(&conn);
181
182 /* Done */
183 event_done(&conn);
184
185 /* There should NOT be a host notification */
186 ut_rx_q_is_empty();
187
188
189 /* Prepare */
190 event_prepare(&conn);
191
192 /* Tx Queue should NOT have a LL Control PDU */
193 lt_rx_q_is_empty(&conn);
194
195 /* Inject invalid 'RSP' */
196 lt_tx(LL_UNKNOWN_RSP, &conn, &unknown_rsp);
197
198 /* Done */
199 event_done(&conn);
200
201 /* Tx Queue should NOT have a LL Control PDU */
202 lt_rx_q_is_empty(&conn);
203
204 /* Termination 'triggered' */
205 zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
206 "Terminate reason %d", conn.llcp_terminate.reason_final);
207
208 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
209 "Free CTX buffers %d", llcp_ctx_buffers_free());
210 }
211
ZTEST(chmu,test_channel_map_update_periph_rem)212 ZTEST(chmu, test_channel_map_update_periph_rem)
213 {
214 uint8_t chm[5] = { 0x00, 0x04, 0x05, 0x06, 0x00 };
215 uint8_t initial_chm[5];
216 struct pdu_data_llctrl_chan_map_ind chmu_ind = {
217 .instant = 6,
218 .chm = { 0x00, 0x04, 0x05, 0x06, 0x00 },
219 };
220 uint16_t instant = 6;
221
222 /* Store initial channel map */
223 memcpy(initial_chm, conn.lll.data_chan_map, sizeof(conn.lll.data_chan_map));
224
225 /* Role */
226 test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
227
228 /* Connect */
229 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
230
231 /* Prepare */
232 event_prepare(&conn);
233
234 /* Tx Queue should NOT have a LL Control PDU */
235 lt_rx_q_is_empty(&conn);
236
237 /* RX */
238 lt_tx(LL_CHAN_MAP_UPDATE_IND, &conn, &chmu_ind);
239
240 /* Done */
241 event_done(&conn);
242
243 /* spin conn events */
244 while (!is_instant_reached(&conn, instant)) {
245 /* Prepare */
246 event_prepare(&conn);
247
248 /* Tx Queue should NOT have a LL Control PDU */
249 lt_rx_q_is_empty(&conn);
250
251 /* Done */
252 event_done(&conn);
253
254 /* There should NOT be a host notification */
255 ut_rx_q_is_empty();
256
257 /* check if using old channel map */
258 zassert_mem_equal(conn.lll.data_chan_map, initial_chm,
259 sizeof(conn.lll.data_chan_map),
260 "Channel map invalid");
261 }
262
263 /* Prepare */
264 event_prepare(&conn);
265
266 /* Tx Queue should NOT have a LL Control PDU */
267 lt_rx_q_is_empty(&conn);
268
269 /* Done */
270 event_done(&conn);
271
272 /* There should be no host notification */
273 ut_rx_q_is_empty();
274
275 /* at this point new channel map shall be in use */
276 zassert_mem_equal(conn.lll.data_chan_map, chm, sizeof(conn.lll.data_chan_map),
277 "Channel map invalid");
278
279 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
280 "Free CTX buffers %d", llcp_ctx_buffers_free());
281 }
282
ZTEST(chmu,test_channel_map_update_periph_invalid)283 ZTEST(chmu, test_channel_map_update_periph_invalid)
284 {
285 struct pdu_data_llctrl_chan_map_ind chmu_ind = {
286 .instant = 6,
287 .chm = { 0x00, 0x04, 0x05, 0x06, 0x00 },
288 };
289 struct pdu_data_llctrl_unknown_rsp unknown_rsp = {
290 .type = PDU_DATA_LLCTRL_TYPE_UNUSED
291 };
292
293 /* Role */
294 test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
295
296 /* Connect */
297 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
298
299 /* Prepare */
300 event_prepare(&conn);
301
302 /* Tx Queue should NOT have a LL Control PDU */
303 lt_rx_q_is_empty(&conn);
304
305 /* RX */
306 lt_tx(LL_CHAN_MAP_UPDATE_IND, &conn, &chmu_ind);
307
308 /* Done */
309 event_done(&conn);
310
311 /* There should not be a host notifications */
312 ut_rx_q_is_empty();
313
314 /* Prepare */
315 event_prepare(&conn);
316 /* Done */
317 event_done(&conn);
318
319 /* Prepare */
320 event_prepare(&conn);
321
322 /* Tx Queue should NOT have a LL Control PDU */
323 lt_rx_q_is_empty(&conn);
324
325 /* Inject invalid 'RSP' */
326 lt_tx(LL_UNKNOWN_RSP, &conn, &unknown_rsp);
327
328 /* Done */
329 event_done(&conn);
330
331 /* Tx Queue should NOT have a LL Control PDU */
332 lt_rx_q_is_empty(&conn);
333
334 /* Termination 'triggered' */
335 zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
336 "Terminate reason %d", conn.llcp_terminate.reason_final);
337
338 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
339 "Free CTX buffers %d", llcp_ctx_buffers_free());
340 }
341
ZTEST(chmu,test_channel_map_update_periph_loc)342 ZTEST(chmu, test_channel_map_update_periph_loc)
343 {
344 uint8_t err;
345 uint8_t chm[5] = { 0x00, 0x06, 0x06, 0x06, 0x00 };
346
347 /* Role */
348 test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
349
350 /* Connect */
351 ull_cp_state_set(&conn, ULL_CP_CONNECTED);
352
353 err = ull_cp_chan_map_update(&conn, chm);
354 zassert_equal(err, BT_HCI_ERR_CMD_DISALLOWED);
355
356 zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(),
357 "Free CTX buffers %d", llcp_ctx_buffers_free());
358 }
359
360 ZTEST_SUITE(chmu, NULL, NULL, chmu_setup, NULL, NULL);
361