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