1 /*
2 * Copyright (c) 2022 Trackunit Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*************************************************************************************************/
8 /* Dependencies */
9 /*************************************************************************************************/
10 #include <zephyr/ztest.h>
11 #include <zephyr/kernel.h>
12 #include <string.h>
13
14 #include <zephyr/modem/cmux.h>
15 #include <modem_backend_mock.h>
16
17 /*************************************************************************************************/
18 /* Definitions */
19 /*************************************************************************************************/
20 #define EVENT_CMUX_CONNECTED BIT(0)
21 #define EVENT_CMUX_DLCI1_OPEN BIT(1)
22 #define EVENT_CMUX_DLCI2_OPEN BIT(2)
23 #define EVENT_CMUX_DLCI1_RECEIVE_READY BIT(3)
24 #define EVENT_CMUX_DLCI1_TRANSMIT_IDLE BIT(4)
25 #define EVENT_CMUX_DLCI2_RECEIVE_READY BIT(5)
26 #define EVENT_CMUX_DLCI2_TRANSMIT_IDLE BIT(6)
27 #define EVENT_CMUX_DLCI1_CLOSED BIT(7)
28 #define EVENT_CMUX_DLCI2_CLOSED BIT(8)
29 #define EVENT_CMUX_DISCONNECTED BIT(9)
30
31 /*************************************************************************************************/
32 /* Instances */
33 /*************************************************************************************************/
34 static struct modem_cmux cmux;
35 static uint8_t cmux_receive_buf[127];
36 static uint8_t cmux_transmit_buf[149];
37 static struct modem_cmux_dlci dlci1;
38 static struct modem_cmux_dlci dlci2;
39 static struct modem_pipe *dlci1_pipe;
40 static struct modem_pipe *dlci2_pipe;
41
42 static struct k_event cmux_event;
43
44 static struct modem_backend_mock bus_mock;
45 static uint8_t bus_mock_rx_buf[4096];
46 static uint8_t bus_mock_tx_buf[4096];
47 static struct modem_pipe *bus_mock_pipe;
48
49 static uint8_t dlci1_receive_buf[127];
50 static uint8_t dlci2_receive_buf[127];
51
52 static uint8_t buffer1[4096];
53 static uint8_t buffer2[4096];
54
55 /*************************************************************************************************/
56 /* Callbacks */
57 /*************************************************************************************************/
test_modem_dlci1_pipe_callback(struct modem_pipe * pipe,enum modem_pipe_event event,void * user_data)58 static void test_modem_dlci1_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_event event,
59 void *user_data)
60 {
61 switch (event) {
62 case MODEM_PIPE_EVENT_OPENED:
63 k_event_post(&cmux_event, EVENT_CMUX_DLCI1_OPEN);
64 break;
65
66 case MODEM_PIPE_EVENT_RECEIVE_READY:
67 k_event_post(&cmux_event, EVENT_CMUX_DLCI1_RECEIVE_READY);
68 break;
69
70 case MODEM_PIPE_EVENT_TRANSMIT_IDLE:
71 k_event_post(&cmux_event, EVENT_CMUX_DLCI1_TRANSMIT_IDLE);
72 break;
73
74 case MODEM_PIPE_EVENT_CLOSED:
75 k_event_post(&cmux_event, EVENT_CMUX_DLCI1_CLOSED);
76 break;
77
78 default:
79 break;
80 }
81 }
82
test_modem_dlci2_pipe_callback(struct modem_pipe * pipe,enum modem_pipe_event event,void * user_data)83 static void test_modem_dlci2_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_event event,
84 void *user_data)
85 {
86 switch (event) {
87 case MODEM_PIPE_EVENT_OPENED:
88 k_event_post(&cmux_event, EVENT_CMUX_DLCI2_OPEN);
89 break;
90
91 case MODEM_PIPE_EVENT_RECEIVE_READY:
92 k_event_post(&cmux_event, EVENT_CMUX_DLCI2_RECEIVE_READY);
93 break;
94
95 case MODEM_PIPE_EVENT_TRANSMIT_IDLE:
96 k_event_post(&cmux_event, EVENT_CMUX_DLCI2_TRANSMIT_IDLE);
97 break;
98
99 case MODEM_PIPE_EVENT_CLOSED:
100 k_event_post(&cmux_event, EVENT_CMUX_DLCI2_CLOSED);
101 break;
102
103 default:
104 break;
105 }
106 }
107
108 /*************************************************************************************************/
109 /* CMUX frames */
110 /*************************************************************************************************/
111 static uint8_t cmux_frame_control_sabm_cmd[] = {0xF9, 0x03, 0x3F, 0x01, 0x1C, 0xF9};
112 static uint8_t cmux_frame_control_sabm_ack[] = {0xF9, 0x03, 0x73, 0x01, 0xD7, 0xF9};
113 static uint8_t cmux_frame_control_cld_cmd[] = {0xF9, 0x03, 0xEF, 0x05, 0xC3, 0x01, 0xF2, 0xF9};
114 static uint8_t cmux_frame_control_cld_ack[] = {0xF9, 0x03, 0xEF, 0x05, 0xC1, 0x01, 0xF2, 0xF9};
115 static uint8_t cmux_frame_dlci1_sabm_cmd[] = {0xF9, 0x07, 0x3F, 0x01, 0xDE, 0xF9};
116 static uint8_t cmux_frame_dlci1_sabm_ack[] = {0xF9, 0x07, 0x73, 0x01, 0x15, 0xF9};
117 static uint8_t cmux_frame_dlci1_disc_cmd[] = {0xF9, 0x07, 0x53, 0x01, 0x3F, 0xF9};
118 static uint8_t cmux_frame_dlci1_ua_ack[] = {0xF9, 0x07, 0x73, 0x01, 0x15, 0xF9};
119 static uint8_t cmux_frame_dlci2_sabm_cmd[] = {0xF9, 0x0B, 0x3F, 0x01, 0x59, 0xF9};
120 static uint8_t cmux_frame_dlci2_sabm_ack[] = {0xF9, 0x0B, 0x73, 0x01, 0x92, 0xF9};
121 static uint8_t cmux_frame_dlci2_disc_cmd[] = {0xF9, 0x0B, 0x53, 0x01, 0xB8, 0xF9};
122 static uint8_t cmux_frame_dlci2_ua_ack[] = {0xF9, 0x0B, 0x73, 0x01, 0x92, 0xF9};
123 static uint8_t cmux_frame_control_msc_cmd[] = {0xF9, 0x01, 0xFF, 0x0B, 0xE3,
124 0x07, 0x0B, 0x09, 0x01, 0x6C, 0xF9};
125
126 static uint8_t cmux_frame_control_msc_ack[] = {0xF9, 0x01, 0xFF, 0x0B, 0xE1,
127 0x07, 0x0B, 0x09, 0x01, 0x6C, 0xF9};
128
129 static uint8_t cmux_frame_control_fcon_cmd[] = {0xF9, 0x01, 0xFF, 0x05, 0xA3, 0x01, 0x86, 0xF9};
130 static uint8_t cmux_frame_control_fcon_ack[] = {0xF9, 0x01, 0xFF, 0x05, 0xA1, 0x01, 0x86, 0xF9};
131 static uint8_t cmux_frame_control_fcoff_cmd[] = {0xF9, 0x01, 0xFF, 0x05, 0x63, 0x01, 0x86, 0xF9};
132 static uint8_t cmux_frame_control_fcoff_ack[] = {0xF9, 0x01, 0xFF, 0x05, 0x61, 0x01, 0x86, 0xF9};
133
134 /*************************************************************************************************/
135 /* DLCI2 AT CMUX frames */
136 /*************************************************************************************************/
137 static uint8_t cmux_frame_dlci2_at_cgdcont[] = {
138 0xF9, 0x0B, 0xEF, 0x43, 0x41, 0x54, 0x2B, 0x43, 0x47, 0x44, 0x43, 0x4F, 0x4E,
139 0x54, 0x3D, 0x31, 0x2C, 0x22, 0x49, 0x50, 0x22, 0x2C, 0x22, 0x74, 0x72, 0x61,
140 0x63, 0x6B, 0x75, 0x6E, 0x69, 0x74, 0x2E, 0x6D, 0x32, 0x6D, 0x22, 0x23, 0xF9};
141
142 static uint8_t cmux_frame_data_dlci2_at_cgdcont[] = {
143 0x41, 0x54, 0x2B, 0x43, 0x47, 0x44, 0x43, 0x4F, 0x4E, 0x54, 0x3D,
144 0x31, 0x2C, 0x22, 0x49, 0x50, 0x22, 0x2C, 0x22, 0x74, 0x72, 0x61,
145 0x63, 0x6B, 0x75, 0x6E, 0x69, 0x74, 0x2E, 0x6D, 0x32, 0x6D, 0x22};
146
147 static uint8_t cmux_frame_dlci2_at_newline[] = {0xF9, 0x0B, 0xEF, 0x05, 0x0D, 0x0A, 0xB7, 0xF9};
148
149 static uint8_t cmux_frame_data_dlci2_at_newline[] = {0x0D, 0x0A};
150
151 /*************************************************************************************************/
152 /* DLCI2 AT CMUX error frames */
153 /*************************************************************************************************/
154 static uint8_t cmux_frame_dlci2_at_cgdcont_invalid_length[] = {
155 0xF9, 0x0B, 0xEF, 0xFE, 0x41, 0x54, 0x2B, 0x43, 0x47, 0x44, 0x43, 0x4F, 0x4E,
156 0x54, 0x3D, 0x31, 0x2C, 0x22, 0x49, 0x50, 0x22, 0x2C, 0x22, 0x74, 0x72, 0x61,
157 0x63, 0x6B, 0x75, 0x6E, 0x69, 0x74, 0x2E, 0x6D, 0x32, 0x6D, 0x22, 0x23, 0xF9};
158
159 /*************************************************************************************************/
160 /* DLCI1 AT CMUX frames */
161 /*************************************************************************************************/
162 static uint8_t cmux_frame_dlci1_at_at[] = {0xF9, 0x07, 0xEF, 0x05, 0x41, 0x54, 0x30, 0xF9};
163
164 static uint8_t cmux_frame_data_dlci1_at_at[] = {0x41, 0x54};
165
166 static uint8_t cmux_frame_dlci1_at_newline[] = {0xF9, 0x07, 0xEF, 0x05, 0x0D, 0x0A, 0x30, 0xF9};
167
168 static uint8_t cmux_frame_data_dlci1_at_newline[] = {0x0D, 0x0A};
169
170 /*************************************************************************************************/
171 /* DLCI1 AT CMUX Desync frames */
172 /*************************************************************************************************/
173 static uint8_t cmux_frame_dlci1_at_at_desync[] = {0x41, 0x54, 0x30, 0xF9};
174
175 /*************************************************************************************************/
176 /* DLCI2 PPP CMUX frames */
177 /*************************************************************************************************/
178 static uint8_t cmux_frame_dlci2_ppp_52[] = {
179 0xF9, 0x0B, 0xEF, 0x69, 0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x21, 0x7D, 0x20, 0x7D,
180 0x20, 0x7D, 0x38, 0x7D, 0x22, 0x7D, 0x26, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20,
181 0x7D, 0x23, 0x7D, 0x24, 0xC0, 0x23, 0x7D, 0x25, 0x7D, 0x26, 0x53, 0x96, 0x7D, 0x38, 0xAA,
182 0x7D, 0x27, 0x7D, 0x22, 0x7D, 0x28, 0x7D, 0x22, 0xD5, 0xA8, 0x7E, 0xF6, 0xF9};
183
184 static uint8_t cmux_frame_data_dlci2_ppp_52[] = {
185 0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x21, 0x7D, 0x20, 0x7D, 0x20, 0x7D,
186 0x38, 0x7D, 0x22, 0x7D, 0x26, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20,
187 0x7D, 0x23, 0x7D, 0x24, 0xC0, 0x23, 0x7D, 0x25, 0x7D, 0x26, 0x53, 0x96, 0x7D,
188 0x38, 0xAA, 0x7D, 0x27, 0x7D, 0x22, 0x7D, 0x28, 0x7D, 0x22, 0xD5, 0xA8, 0x7E};
189
190 static uint8_t cmux_frame_dlci2_ppp_18[] = {0xF9, 0x0B, 0xEF, 0x25, 0x7E, 0xFF, 0x7D, 0x23,
191 0xC0, 0x21, 0x7D, 0x22, 0x7D, 0x21, 0x7D, 0x20,
192 0x7D, 0x24, 0x7D, 0x3C, 0x90, 0x7E, 0x8F, 0xF9};
193
194 static uint8_t cmux_frame_data_dlci2_ppp_18[] = {0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21,
195 0x7D, 0x22, 0x7D, 0x21, 0x7D, 0x20,
196 0x7D, 0x24, 0x7D, 0x3C, 0x90, 0x7E};
197
198 const static struct modem_backend_mock_transaction transaction_control_cld = {
199 .get = cmux_frame_control_cld_cmd,
200 .get_size = sizeof(cmux_frame_control_cld_cmd),
201 .put = cmux_frame_control_cld_ack,
202 .put_size = sizeof(cmux_frame_control_cld_ack)
203 };
204
205 const static struct modem_backend_mock_transaction transaction_control_sabm = {
206 .get = cmux_frame_control_sabm_cmd,
207 .get_size = sizeof(cmux_frame_control_sabm_cmd),
208 .put = cmux_frame_control_sabm_ack,
209 .put_size = sizeof(cmux_frame_control_sabm_ack)
210 };
211
212 const static struct modem_backend_mock_transaction transaction_dlci1_disc = {
213 .get = cmux_frame_dlci1_disc_cmd,
214 .get_size = sizeof(cmux_frame_dlci1_disc_cmd),
215 .put = cmux_frame_dlci1_ua_ack,
216 .put_size = sizeof(cmux_frame_dlci1_ua_ack)
217 };
218
219 const static struct modem_backend_mock_transaction transaction_dlci2_disc = {
220 .get = cmux_frame_dlci2_disc_cmd,
221 .get_size = sizeof(cmux_frame_dlci2_disc_cmd),
222 .put = cmux_frame_dlci2_ua_ack,
223 .put_size = sizeof(cmux_frame_dlci2_ua_ack)
224 };
225
226 const static struct modem_backend_mock_transaction transaction_dlci1_sabm = {
227 .get = cmux_frame_dlci1_sabm_cmd,
228 .get_size = sizeof(cmux_frame_dlci1_sabm_cmd),
229 .put = cmux_frame_dlci1_ua_ack,
230 .put_size = sizeof(cmux_frame_dlci1_ua_ack)
231 };
232
233 const static struct modem_backend_mock_transaction transaction_dlci2_sabm = {
234 .get = cmux_frame_dlci2_sabm_cmd,
235 .get_size = sizeof(cmux_frame_dlci2_sabm_cmd),
236 .put = cmux_frame_dlci2_ua_ack,
237 .put_size = sizeof(cmux_frame_dlci2_ua_ack)
238 };
239
test_modem_cmux_callback(struct modem_cmux * cmux,enum modem_cmux_event event,void * user_data)240 static void test_modem_cmux_callback(struct modem_cmux *cmux, enum modem_cmux_event event,
241 void *user_data)
242 {
243 if (event == MODEM_CMUX_EVENT_CONNECTED) {
244 k_event_post(&cmux_event, EVENT_CMUX_CONNECTED);
245 return;
246 }
247
248 if (event == MODEM_CMUX_EVENT_DISCONNECTED) {
249 k_event_post(&cmux_event, EVENT_CMUX_DISCONNECTED);
250 return;
251 }
252 }
253
test_modem_cmux_setup(void)254 static void *test_modem_cmux_setup(void)
255 {
256 uint32_t events;
257
258 struct modem_cmux_dlci_config dlci1_config = {
259 .dlci_address = 1,
260 .receive_buf = dlci1_receive_buf,
261 .receive_buf_size = sizeof(dlci1_receive_buf),
262 };
263
264 struct modem_cmux_dlci_config dlci2_config = {
265 .dlci_address = 2,
266 .receive_buf = dlci2_receive_buf,
267 .receive_buf_size = sizeof(dlci2_receive_buf),
268 };
269
270 k_event_init(&cmux_event);
271
272 struct modem_cmux_config cmux_config = {
273 .callback = test_modem_cmux_callback,
274 .user_data = NULL,
275 .receive_buf = cmux_receive_buf,
276 .receive_buf_size = sizeof(cmux_receive_buf),
277 .transmit_buf = cmux_transmit_buf,
278 .transmit_buf_size = ARRAY_SIZE(cmux_transmit_buf),
279 };
280
281 modem_cmux_init(&cmux, &cmux_config);
282 dlci1_pipe = modem_cmux_dlci_init(&cmux, &dlci1, &dlci1_config);
283 dlci2_pipe = modem_cmux_dlci_init(&cmux, &dlci2, &dlci2_config);
284
285 const struct modem_backend_mock_config bus_mock_config = {
286 .rx_buf = bus_mock_rx_buf,
287 .rx_buf_size = sizeof(bus_mock_rx_buf),
288 .tx_buf = bus_mock_tx_buf,
289 .tx_buf_size = sizeof(bus_mock_tx_buf),
290 .limit = 32,
291 };
292
293 bus_mock_pipe = modem_backend_mock_init(&bus_mock, &bus_mock_config);
294 __ASSERT_NO_MSG(modem_pipe_open(bus_mock_pipe, K_SECONDS(10)) == 0);
295
296 /* Connect CMUX */
297 __ASSERT_NO_MSG(modem_cmux_attach(&cmux, bus_mock_pipe) == 0);
298 modem_backend_mock_prime(&bus_mock, &transaction_control_sabm);
299 __ASSERT_NO_MSG(modem_cmux_connect_async(&cmux) == 0);
300 events = k_event_wait(&cmux_event, EVENT_CMUX_CONNECTED, false, K_MSEC(100));
301 __ASSERT_NO_MSG(events == EVENT_CMUX_CONNECTED);
302
303 /* Open DLCI channels */
304 modem_pipe_attach(dlci1_pipe, test_modem_dlci1_pipe_callback, NULL);
305 modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm);
306 __ASSERT_NO_MSG(modem_pipe_open_async(dlci1_pipe) == 0);
307 events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI1_OPEN, false, K_MSEC(100));
308 __ASSERT_NO_MSG((events & EVENT_CMUX_DLCI1_OPEN));
309
310 modem_pipe_attach(dlci2_pipe, test_modem_dlci2_pipe_callback, NULL);
311 modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm);
312 __ASSERT_NO_MSG(modem_pipe_open_async(dlci2_pipe) == 0);
313 events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI2_OPEN, false, K_MSEC(100));
314 __ASSERT_NO_MSG((events & EVENT_CMUX_DLCI2_OPEN));
315
316 return NULL;
317 }
318
test_modem_cmux_before(void * f)319 static void test_modem_cmux_before(void *f)
320 {
321 /* Reset events */
322 k_event_clear(&cmux_event, UINT32_MAX);
323
324 /* Reset mock pipes */
325 modem_backend_mock_reset(&bus_mock);
326 }
327
ZTEST(modem_cmux,test_modem_cmux_receive_dlci2_at)328 ZTEST(modem_cmux, test_modem_cmux_receive_dlci2_at)
329 {
330 int ret;
331 uint32_t events;
332
333 modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_cgdcont,
334 sizeof(cmux_frame_dlci2_at_cgdcont));
335
336 modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_newline,
337 sizeof(cmux_frame_dlci2_at_newline));
338
339 k_msleep(100);
340
341 events = k_event_test(&cmux_event, EVENT_CMUX_DLCI2_RECEIVE_READY);
342 zassert_equal(events, EVENT_CMUX_DLCI2_RECEIVE_READY,
343 "Receive ready event not received for DLCI2 pipe");
344
345 ret = modem_pipe_receive(dlci2_pipe, buffer2, sizeof(buffer2));
346 zassert_true(ret == (sizeof(cmux_frame_data_dlci2_at_cgdcont) +
347 sizeof(cmux_frame_data_dlci2_at_newline)),
348 "Incorrect number of bytes received");
349
350 zassert_true(memcmp(buffer2, cmux_frame_data_dlci2_at_cgdcont,
351 sizeof(cmux_frame_data_dlci2_at_cgdcont)) == 0,
352 "Incorrect data received");
353
354 zassert_true(memcmp(&buffer2[sizeof(cmux_frame_data_dlci2_at_cgdcont)],
355 cmux_frame_data_dlci2_at_newline,
356 sizeof(cmux_frame_data_dlci2_at_newline)) == 0,
357 "Incorrect data received");
358 }
359
ZTEST(modem_cmux,test_modem_cmux_receive_dlci1_at)360 ZTEST(modem_cmux, test_modem_cmux_receive_dlci1_at)
361 {
362 int ret;
363 uint32_t events;
364
365 modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_at, sizeof(cmux_frame_dlci1_at_at));
366 modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_newline,
367 sizeof(cmux_frame_dlci1_at_newline));
368
369 k_msleep(100);
370
371 events = k_event_test(&cmux_event, EVENT_CMUX_DLCI1_RECEIVE_READY);
372 zassert_equal(events, EVENT_CMUX_DLCI1_RECEIVE_READY,
373 "Receive ready event not received for DLCI1 pipe");
374
375 ret = modem_pipe_receive(dlci1_pipe, buffer1, sizeof(buffer1));
376 zassert_true(ret == (sizeof(cmux_frame_data_dlci1_at_at) +
377 sizeof(cmux_frame_data_dlci1_at_newline)),
378 "Incorrect number of bytes received");
379
380 zassert_true(memcmp(buffer1, cmux_frame_data_dlci1_at_at,
381 sizeof(cmux_frame_data_dlci1_at_at)) == 0,
382 "Incorrect data received");
383
384 zassert_true(memcmp(&buffer1[sizeof(cmux_frame_data_dlci1_at_at)],
385 cmux_frame_data_dlci1_at_newline,
386 sizeof(cmux_frame_data_dlci1_at_newline)) == 0,
387 "Incorrect data received");
388 }
389
ZTEST(modem_cmux,test_modem_cmux_receive_dlci2_ppp)390 ZTEST(modem_cmux, test_modem_cmux_receive_dlci2_ppp)
391 {
392 int ret;
393 uint32_t events;
394
395 modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_ppp_52, sizeof(cmux_frame_dlci2_ppp_52));
396 modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_ppp_18, sizeof(cmux_frame_dlci2_ppp_18));
397
398 k_msleep(100);
399
400 events = k_event_test(&cmux_event, EVENT_CMUX_DLCI2_RECEIVE_READY);
401 zassert_equal(events, EVENT_CMUX_DLCI2_RECEIVE_READY,
402 "Receive ready event not received for DLCI2 pipe");
403
404 ret = modem_pipe_receive(dlci2_pipe, buffer2, sizeof(buffer2));
405 zassert_true(ret == (sizeof(cmux_frame_data_dlci2_ppp_52) +
406 sizeof(cmux_frame_data_dlci2_ppp_18)),
407 "Incorrect number of bytes received");
408
409 zassert_true(memcmp(buffer2, cmux_frame_data_dlci2_ppp_52,
410 sizeof(cmux_frame_data_dlci2_ppp_52)) == 0,
411 "Incorrect data received");
412
413 zassert_true(memcmp(&buffer2[sizeof(cmux_frame_data_dlci2_ppp_52)],
414 cmux_frame_data_dlci2_ppp_18,
415 sizeof(cmux_frame_data_dlci2_ppp_18)) == 0,
416 "Incorrect data received");
417 }
418
ZTEST(modem_cmux,test_modem_cmux_transmit_dlci2_ppp)419 ZTEST(modem_cmux, test_modem_cmux_transmit_dlci2_ppp)
420 {
421 int ret;
422 uint32_t events;
423
424 ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_dlci2_ppp_52,
425 sizeof(cmux_frame_data_dlci2_ppp_52));
426 zassert_true(ret == sizeof(cmux_frame_data_dlci2_ppp_52), "Failed to send DLCI2 PPP 52");
427
428 events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI2_TRANSMIT_IDLE, false, K_MSEC(200));
429 zassert_equal(events, EVENT_CMUX_DLCI2_TRANSMIT_IDLE,
430 "Transmit idle event not received for DLCI2 pipe");
431
432 k_event_clear(&cmux_event, EVENT_CMUX_DLCI2_TRANSMIT_IDLE);
433
434 ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_dlci2_ppp_18,
435 sizeof(cmux_frame_data_dlci2_ppp_18));
436 zassert_true(ret == sizeof(cmux_frame_data_dlci2_ppp_18), "Failed to send DLCI2 PPP 18");
437
438 events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI2_TRANSMIT_IDLE, false, K_MSEC(200));
439 zassert_equal(events, EVENT_CMUX_DLCI2_TRANSMIT_IDLE,
440 "Transmit idle event not received for DLCI2 pipe");
441
442 ret = modem_backend_mock_get(&bus_mock, buffer2, sizeof(buffer2));
443 zassert_true(ret == (sizeof(cmux_frame_dlci2_ppp_52) + sizeof(cmux_frame_dlci2_ppp_18)),
444 "Incorrect number of bytes transmitted");
445 }
446
ZTEST(modem_cmux,test_modem_cmux_resync)447 ZTEST(modem_cmux, test_modem_cmux_resync)
448 {
449 int ret;
450
451 modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_at_desync,
452 sizeof(cmux_frame_dlci1_at_at_desync));
453 modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_at, sizeof(cmux_frame_dlci1_at_at));
454 modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_newline,
455 sizeof(cmux_frame_dlci1_at_newline));
456
457 k_msleep(100);
458
459 ret = modem_pipe_receive(dlci1_pipe, buffer1, sizeof(buffer1));
460
461 zassert_true(ret == (sizeof(cmux_frame_data_dlci1_at_at) +
462 sizeof(cmux_frame_data_dlci1_at_newline)),
463 "Incorrect number of bytes received");
464
465 zassert_true(memcmp(buffer1, cmux_frame_data_dlci1_at_at,
466 sizeof(cmux_frame_data_dlci1_at_at)) == 0,
467 "Incorrect data received");
468
469 zassert_true(memcmp(&buffer1[sizeof(cmux_frame_data_dlci1_at_at)],
470 cmux_frame_data_dlci1_at_newline,
471 sizeof(cmux_frame_data_dlci1_at_newline)) == 0,
472 "Incorrect data received");
473 }
474
ZTEST(modem_cmux,test_modem_cmux_flow_control_dlci2)475 ZTEST(modem_cmux, test_modem_cmux_flow_control_dlci2)
476 {
477 int ret;
478
479 modem_backend_mock_put(&bus_mock, cmux_frame_control_fcoff_cmd,
480 sizeof(cmux_frame_control_fcoff_cmd));
481
482 k_msleep(100);
483
484 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
485 zassert_true(ret == sizeof(cmux_frame_control_fcoff_ack),
486 "Incorrect number of bytes received");
487
488 zassert_true(memcmp(buffer1, cmux_frame_control_fcoff_ack,
489 sizeof(cmux_frame_control_fcoff_ack)) == 0,
490 "Incorrect data received");
491
492 ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_dlci2_ppp_52,
493 sizeof(cmux_frame_data_dlci2_ppp_52));
494
495 zassert_true(ret == 0, "Failed to block transmit while flow control is off");
496
497 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
498 zassert_true(ret == 0, "FCOFF failed to prevent transmission of data");
499 modem_backend_mock_put(&bus_mock, cmux_frame_control_fcon_cmd,
500 sizeof(cmux_frame_control_fcon_cmd));
501
502 k_msleep(100);
503
504 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
505 zassert_true(ret == sizeof(cmux_frame_control_fcon_ack),
506 "Incorrect number of bytes received");
507
508 zassert_true(memcmp(buffer1, cmux_frame_control_fcon_ack,
509 sizeof(cmux_frame_control_fcon_ack)) == 0,
510 "Incorrect data received");
511
512 ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_dlci2_ppp_52,
513 sizeof(cmux_frame_data_dlci2_ppp_52));
514
515 zassert_true(ret == sizeof(cmux_frame_data_dlci2_ppp_52),
516 "Transmit failed after flow control is enabled");
517
518 k_msleep(100);
519
520 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
521 zassert_true(ret == sizeof(cmux_frame_dlci2_ppp_52),
522 "Transmit failed after flow control is enabled");
523
524 zassert_true(memcmp(buffer1, cmux_frame_dlci2_ppp_52,
525 sizeof(cmux_frame_dlci2_ppp_52)) == 0,
526 "Incorrect data received");
527 }
528
ZTEST(modem_cmux,test_modem_cmux_msc_cmd_ack)529 ZTEST(modem_cmux, test_modem_cmux_msc_cmd_ack)
530 {
531 int ret;
532
533 modem_backend_mock_put(&bus_mock, cmux_frame_control_msc_cmd,
534 sizeof(cmux_frame_control_msc_cmd));
535
536 k_msleep(100);
537
538 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
539 zassert_true(ret == sizeof(cmux_frame_control_msc_ack),
540 "Incorrect number of bytes received");
541
542 zassert_true(memcmp(buffer1, cmux_frame_control_msc_ack,
543 sizeof(cmux_frame_control_msc_ack)) == 0,
544 "Incorrect MSC ACK received");
545 }
546
ZTEST(modem_cmux,test_modem_cmux_dlci1_close_open)547 ZTEST(modem_cmux, test_modem_cmux_dlci1_close_open)
548 {
549 int ret;
550 uint32_t events;
551
552 /* Close DLCI1 */
553 zassert_true(modem_pipe_close_async(dlci1_pipe) == 0, "Failed to close DLCI1 pipe");
554
555 k_msleep(100);
556
557 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
558 zassert_true(ret == sizeof(cmux_frame_dlci1_disc_cmd),
559 "Incorrect number of bytes received for DLCI1 close cmd");
560
561 zassert_true(memcmp(buffer1, cmux_frame_dlci1_disc_cmd,
562 sizeof(cmux_frame_dlci1_disc_cmd)) == 0,
563 "Incorrect DLCI1 close cmd received");
564
565 modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_ua_ack,
566 sizeof(cmux_frame_dlci1_ua_ack));
567
568 events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_CLOSED),
569 false, K_MSEC(100));
570
571 zassert_true((events & EVENT_CMUX_DLCI1_CLOSED),
572 "DLCI1 not closed as expected");
573
574 /* Wait for potential T1 timeout */
575 k_msleep(500);
576
577 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
578 zassert_true(ret == 0, "Received unexpected data");
579
580 /* Open DLCI1 */
581 zassert_true(modem_pipe_open_async(dlci1_pipe) == 0, "Failed to open DLCI1 pipe");
582
583 k_msleep(100);
584
585 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
586 zassert_true(ret == sizeof(cmux_frame_dlci1_sabm_cmd),
587 "Incorrect number of bytes received for DLCI1 open cmd");
588
589 zassert_true(memcmp(buffer1, cmux_frame_dlci1_sabm_cmd,
590 sizeof(cmux_frame_dlci1_sabm_cmd)) == 0,
591 "Incorrect DLCI1 open cmd received");
592
593 modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_sabm_ack,
594 sizeof(cmux_frame_dlci1_sabm_ack));
595
596 events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_OPEN),
597 false, K_MSEC(100));
598
599 zassert_true((events & EVENT_CMUX_DLCI1_OPEN),
600 "DLCI1 not opened as expected");
601
602 /* Wait for potential T1 timeout */
603 k_msleep(500);
604
605 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
606 zassert_true(ret == 0, "Received unexpected data");
607 }
608
ZTEST(modem_cmux,test_modem_cmux_disconnect_connect)609 ZTEST(modem_cmux, test_modem_cmux_disconnect_connect)
610 {
611 uint32_t events;
612 int ret;
613
614 /* Disconnect CMUX */
615 zassert_true(modem_pipe_close_async(dlci1_pipe) == 0, "Failed to close DLCI1");
616 zassert_true(modem_pipe_close_async(dlci2_pipe) == 0, "Failed to close DLCI2");
617
618 modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_ua_ack,
619 sizeof(cmux_frame_dlci1_ua_ack));
620
621 modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_ua_ack,
622 sizeof(cmux_frame_dlci2_ua_ack));
623
624 events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_CLOSED | EVENT_CMUX_DLCI2_CLOSED),
625 false, K_MSEC(100));
626
627 zassert_true((events & EVENT_CMUX_DLCI1_CLOSED), "Failed to close DLCI1");
628 zassert_true((events & EVENT_CMUX_DLCI2_CLOSED), "Failed to close DLCI2");
629
630 /* Discard CMUX DLCI DISC commands */
631 modem_backend_mock_reset(&bus_mock);
632 zassert_true(modem_cmux_disconnect_async(&cmux) == 0, "Failed to disconnect CMUX");
633
634 k_msleep(100);
635
636 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
637
638 zassert_true(ret == sizeof(cmux_frame_control_cld_cmd),
639 "Incorrect number of bytes received for CLD cmd");
640
641 zassert_true(memcmp(buffer1, cmux_frame_control_cld_cmd,
642 sizeof(cmux_frame_control_cld_cmd)) == 0,
643 "Incorrect DLC cmd received");
644
645 modem_backend_mock_put(&bus_mock, cmux_frame_control_cld_ack,
646 sizeof(cmux_frame_control_cld_ack));
647
648 events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(100));
649 zassert_true((events & EVENT_CMUX_DISCONNECTED), "Failed to disconnect CMUX");
650
651 /* Wait for potential T1 timeout */
652 k_msleep(500);
653
654 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
655 zassert_true(ret == 0, "Received unexpected data");
656
657 /* Reconnect CMUX */
658 zassert_true(modem_cmux_connect_async(&cmux) == 0, "Failed to connect CMUX");
659
660 k_msleep(100);
661
662 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
663 zassert_true(ret == sizeof(cmux_frame_control_sabm_cmd),
664 "Incorrect number of bytes received for SABM cmd");
665
666 zassert_true(memcmp(buffer1, cmux_frame_control_sabm_cmd,
667 sizeof(cmux_frame_control_sabm_cmd)) == 0,
668 "Incorrect SABM cmd received");
669
670 modem_backend_mock_put(&bus_mock, cmux_frame_control_sabm_ack,
671 sizeof(cmux_frame_control_sabm_ack));
672
673 events = k_event_wait_all(&cmux_event, (EVENT_CMUX_CONNECTED), false, K_MSEC(100));
674 zassert_true((events & EVENT_CMUX_CONNECTED), "Failed to connect CMUX");
675
676 /* Wait for potential T1 timeout */
677 k_msleep(500);
678
679 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
680 zassert_true(ret == 0, "Received unexpected data");
681
682 /* Open DLCI1 */
683 zassert_true(modem_pipe_open_async(dlci1_pipe) == 0, "Failed to open DLCI1 pipe");
684
685 k_msleep(100);
686
687 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
688 zassert_true(ret == sizeof(cmux_frame_dlci1_sabm_cmd),
689 "Incorrect number of bytes received for DLCI1 open cmd");
690
691 zassert_true(memcmp(buffer1, cmux_frame_dlci1_sabm_cmd,
692 sizeof(cmux_frame_dlci1_sabm_cmd)) == 0,
693 "Incorrect DLCI1 open cmd received");
694
695 modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_sabm_ack,
696 sizeof(cmux_frame_dlci1_sabm_ack));
697
698 events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_OPEN),
699 false, K_MSEC(100));
700
701 zassert_true((events & EVENT_CMUX_DLCI1_OPEN),
702 "DLCI1 not opened as expected");
703
704 /* Wait for potential T1 timeout */
705 k_msleep(500);
706
707 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
708 zassert_true(ret == 0, "Received unexpected data");
709
710 /* Open DLCI2 */
711 zassert_true(modem_pipe_open_async(dlci2_pipe) == 0, "Failed to open DLCI2 pipe");
712
713 k_msleep(100);
714
715 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
716 zassert_true(ret == sizeof(cmux_frame_dlci2_sabm_cmd),
717 "Incorrect number of bytes received for DLCI1 open cmd");
718
719 zassert_true(memcmp(buffer1, cmux_frame_dlci2_sabm_cmd,
720 sizeof(cmux_frame_dlci2_sabm_cmd)) == 0,
721 "Incorrect DLCI1 open cmd received");
722
723 modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_sabm_ack,
724 sizeof(cmux_frame_dlci2_sabm_ack));
725
726 events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI2_OPEN),
727 false, K_MSEC(100));
728
729 zassert_true((events & EVENT_CMUX_DLCI2_OPEN),
730 "DLCI1 not opened as expected");
731
732 /* Wait for potential T1 timeout */
733 k_msleep(500);
734
735 ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
736 zassert_true(ret == 0, "Received unexpected data");
737 }
738
ZTEST(modem_cmux,test_modem_cmux_disconnect_connect_sync)739 ZTEST(modem_cmux, test_modem_cmux_disconnect_connect_sync)
740 {
741 modem_backend_mock_prime(&bus_mock, &transaction_dlci1_disc);
742 zassert_true(modem_pipe_close(dlci1_pipe, K_SECONDS(10)) == 0, "Failed to close DLCI1");
743 modem_backend_mock_prime(&bus_mock, &transaction_dlci2_disc);
744 zassert_true(modem_pipe_close(dlci2_pipe, K_SECONDS(10)) == 0, "Failed to close DLCI2");
745 modem_backend_mock_prime(&bus_mock, &transaction_control_cld);
746 zassert_true(modem_cmux_disconnect(&cmux) == 0, "Failed to disconnect CMUX");
747 zassert_true(modem_cmux_disconnect(&cmux) == -EALREADY,
748 "Should already be disconnected");
749
750 modem_backend_mock_prime(&bus_mock, &transaction_control_sabm);
751 zassert_true(modem_cmux_connect(&cmux) == 0, "Failed to connect CMUX");
752 zassert_true(modem_cmux_connect(&cmux) == -EALREADY,
753 "Should already be connected");
754
755 modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm);
756 zassert_true(modem_pipe_open(dlci1_pipe, K_SECONDS(10)) == 0,
757 "Failed to open DLCI1 pipe");
758 modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm);
759 zassert_true(modem_pipe_open(dlci2_pipe, K_SECONDS(10)) == 0,
760 "Failed to open DLCI2 pipe");
761 }
762
ZTEST(modem_cmux,test_modem_cmux_dlci_close_open_sync)763 ZTEST(modem_cmux, test_modem_cmux_dlci_close_open_sync)
764 {
765 modem_backend_mock_prime(&bus_mock, &transaction_dlci1_disc);
766 zassert_true(modem_pipe_close(dlci1_pipe, K_SECONDS(10)) == 0, "Failed to close DLCI1");
767 modem_backend_mock_prime(&bus_mock, &transaction_dlci2_disc);
768 zassert_true(modem_pipe_close(dlci2_pipe, K_SECONDS(10)) == 0, "Failed to close DLCI2");
769 modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm);
770 zassert_true(modem_pipe_open(dlci1_pipe, K_SECONDS(10)) == 0,
771 "Failed to open DLCI1 pipe");
772 modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm);
773 zassert_true(modem_pipe_open(dlci2_pipe, K_SECONDS(10)) == 0,
774 "Failed to open DLCI2 pipe");
775 }
776
ZTEST(modem_cmux,test_modem_cmux_prevent_work_while_released)777 ZTEST(modem_cmux, test_modem_cmux_prevent_work_while_released)
778 {
779 const uint8_t transmit[2];
780 uint8_t receive[2];
781
782 /* Disconnect CMUX */
783 modem_backend_mock_prime(&bus_mock, &transaction_control_cld);
784 zassert_ok(modem_cmux_disconnect(&cmux));
785
786 /* Start work to connect CMUX and open DLCI channels */
787 zassert_ok(modem_cmux_connect_async(&cmux));
788 zassert_ok(modem_pipe_open_async(dlci1_pipe));
789 zassert_ok(modem_pipe_open_async(dlci2_pipe));
790
791 /* Wait for and validate CMUX is sending requests */
792 k_msleep(500);
793 zassert_true(modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1)) > 0);
794
795 /* Release CMUX and validate no more requests are sent */
796 modem_cmux_release(&cmux);
797 modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
798 k_msleep(500);
799 zassert_true(modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1)) == 0);
800
801 /* Validate no new requests can be submitted */
802 modem_cmux_connect(&cmux);
803 modem_cmux_disconnect(&cmux);
804 modem_pipe_open(dlci1_pipe, K_SECONDS(10));
805 modem_pipe_open(dlci2_pipe, K_SECONDS(10));
806 modem_pipe_transmit(dlci1_pipe, transmit, sizeof(transmit));
807 modem_pipe_transmit(dlci2_pipe, transmit, sizeof(transmit));
808 modem_pipe_receive(dlci1_pipe, receive, sizeof(receive));
809 modem_pipe_receive(dlci2_pipe, receive, sizeof(receive));
810 modem_pipe_close(dlci1_pipe, K_SECONDS(10));
811 modem_pipe_close(dlci2_pipe, K_SECONDS(10));
812 k_msleep(500);
813 zassert_true(modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1)) == 0);
814
815 /* Restore CMUX */
816 zassert_ok(modem_cmux_attach(&cmux, bus_mock_pipe));
817 modem_backend_mock_prime(&bus_mock, &transaction_control_sabm);
818 zassert_ok(modem_cmux_connect(&cmux));
819 modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm);
820 zassert_ok(modem_pipe_open(dlci1_pipe, K_SECONDS(10)));
821 modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm);
822 zassert_ok(modem_pipe_open(dlci2_pipe, K_SECONDS(10)));
823 }
824
ZTEST(modem_cmux,test_modem_drop_frames_with_invalid_length)825 ZTEST(modem_cmux, test_modem_drop_frames_with_invalid_length)
826 {
827 int ret;
828 uint32_t events;
829
830 modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_cgdcont_invalid_length,
831 sizeof(cmux_frame_dlci2_at_cgdcont_invalid_length));
832
833 k_msleep(100);
834
835 events = k_event_test(&cmux_event, EVENT_CMUX_DLCI2_RECEIVE_READY);
836
837 zassert_false(events & EVENT_CMUX_DLCI2_RECEIVE_READY,
838 "Receive event should not have been received for DLCI2 pipe");
839
840 modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_cgdcont,
841 sizeof(cmux_frame_dlci2_at_cgdcont));
842
843 modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_newline,
844 sizeof(cmux_frame_dlci2_at_newline));
845
846 k_msleep(100);
847
848 events = k_event_test(&cmux_event, EVENT_CMUX_DLCI2_RECEIVE_READY);
849 zassert_equal(events, EVENT_CMUX_DLCI2_RECEIVE_READY,
850 "Receive ready event not received for DLCI2 pipe");
851
852 ret = modem_pipe_receive(dlci2_pipe, buffer2, sizeof(buffer2));
853 zassert_true(ret == (sizeof(cmux_frame_data_dlci2_at_cgdcont) +
854 sizeof(cmux_frame_data_dlci2_at_newline)),
855 "Incorrect number of bytes received");
856
857 zassert_true(memcmp(buffer2, cmux_frame_data_dlci2_at_cgdcont,
858 sizeof(cmux_frame_data_dlci2_at_cgdcont)) == 0,
859 "Incorrect data received");
860
861 zassert_true(memcmp(&buffer2[sizeof(cmux_frame_data_dlci2_at_cgdcont)],
862 cmux_frame_data_dlci2_at_newline,
863 sizeof(cmux_frame_data_dlci2_at_newline)) == 0,
864 "Incorrect data received");
865 }
866
867 ZTEST_SUITE(modem_cmux, NULL, test_modem_cmux_setup, test_modem_cmux_before, NULL, NULL);
868