blob: 0e84d5a627016655f94c091679a1b82311522803 [file] [log] [blame]
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +07001/*
2 * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
3 * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
Vadim Yanitskiy811638c2023-11-30 03:09:05 +070019#include <errno.h>
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +070020#include <stdio.h>
21#include <stdint.h>
22
23#include <osmocom/core/msgb.h>
24#include <osmocom/core/utils.h>
25#include <osmocom/core/soft_uart.h>
26
27static struct {
28 size_t data_len;
29 const uint8_t *data;
30} g_tx_cb_cfg;
31
32static void suart_rx_cb(void *priv, struct msgb *msg, unsigned int flags)
33{
34 fprintf(stdout, "%s(flags=%02x): %s\n",
35 __func__, flags, msgb_hexdump(msg));
36 msgb_free(msg);
37}
38
39static void suart_tx_cb(void *priv, struct msgb *msg)
40{
41 size_t n_bytes;
42
43 n_bytes = OSMO_MIN(g_tx_cb_cfg.data_len, msg->data_len);
44 if (g_tx_cb_cfg.data != NULL && n_bytes > 0)
45 memcpy(msgb_put(msg, n_bytes), g_tx_cb_cfg.data, n_bytes);
46
47 fprintf(stdout, "%s(len=%u/%u): %s\n",
48 __func__, msg->len, msg->data_len, msgb_hexdump(msg));
49}
50
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +070051static void suart_status_change_cb(void *priv, unsigned int status)
52{
53 fprintf(stdout, "%s(status=0x%08x)\n", __func__, status);
54}
55
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +070056static const struct osmo_soft_uart_cfg suart_test_default_cfg = {
57 .num_data_bits = 8,
58 .num_stop_bits = 1,
59 .parity_mode = OSMO_SUART_PARITY_NONE,
60 .rx_buf_size = 128,
61 .rx_cb = &suart_rx_cb,
62 .tx_cb = &suart_tx_cb,
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +070063 .status_change_cb = &suart_status_change_cb,
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +070064};
65
66static void test_rx_exec(struct osmo_soft_uart *suart,
67 const char *input)
68{
69 for (unsigned int i = 0; input[i] != '\0'; i++) {
70 ubit_t ubit;
71
72 switch (input[i]) {
73 case '0':
74 case '1':
75 ubit = input[i] - '0';
76 osmo_soft_uart_rx_ubits(suart, &ubit, 1);
77 break;
78 case 'F':
79 printf("%s() @ %u: flush the Rx buffer\n", __func__, i);
80 osmo_soft_uart_flush_rx(suart);
81 break;
82 case ' ': /* padding */
83 continue;
84 default:
85 printf("%s() @ %u: unknown opcode '%c'\n",
86 __func__, i, input[i]);
87 break;
88 }
89 }
90}
91
92static void test_rx(void)
93{
94 struct osmo_soft_uart_cfg cfg;
95 struct osmo_soft_uart *suart;
96
97 suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg);
98 OSMO_ASSERT(suart != NULL);
99
100 osmo_soft_uart_set_rx(suart, true);
101
102 printf("======== %s(): testing 8-N-1 (no data)\n", __func__);
103 test_rx_exec(suart, "F11111F11111F");
104
105 printf("======== %s(): testing 8-N-1 (fill up flush)\n", __func__);
106 cfg = suart_test_default_cfg;
107 cfg.rx_buf_size = 4;
108 osmo_soft_uart_configure(suart, &cfg);
109 test_rx_exec(suart, "11111" /* no data */
110 "0 01111011 1"
111 "0 10110101 1"
112 "0 01111101 1"
113 "0 11110111 1" /* filled up, expect flush */
114 "0 00000000 1"
115 "0 01010101 1"
116 "0 10101010 1"
117 "0 11111111 1" /* filled up, expect flush */
118 "F" /* flush! (for sanity) */
119 );
120
121 printf("======== %s(): testing 8-N-1 (HELLO)\n", __func__);
122 cfg = suart_test_default_cfg;
123 cfg.num_stop_bits = 1;
124 osmo_soft_uart_configure(suart, &cfg);
125 test_rx_exec(suart, "111111" /* no data */
126 "0 00010010 1F" /* 'H', flush! */
127 "0 10100010 1F" /* 'E', flush! */
128 "1111111111111" /* no data */
129 "0 00110010 1F" /* 'L', flush! */
130 "0 00110010 1F" /* 'L', flush! */
131 "1111111111111" /* no data */
132 "0 11110010 1F" /* 'O', flush! */
133 );
134
135 printf("======== %s(): testing 8-N-1 (framing errors)\n", __func__);
136 test_rx_exec(suart, "11111" /* no data */
137 "0 00000000 0" /* stop bit != 1, expect flush */
138 "0 01010101 0" /* stop bit != 1, expect flush */
139 "0 11111111 1" /* stop bit == 1, recovery */
140 "F" /* flush! */
141 );
142
143 printf("======== %s(): testing 8-N-2 (HELLO)\n", __func__);
144 cfg = suart_test_default_cfg;
145 cfg.num_stop_bits = 2;
146 osmo_soft_uart_configure(suart, &cfg);
147 test_rx_exec(suart, "11111111" /* no data */
148 "0 00010010 1F1F" /* 'H', flush! */
149 "0 10100010 1F1F" /* 'E', flush! */
150 "111111111111111" /* no data */
151 "0 00110010 1F1F" /* 'L', flush! */
152 "0 00110010 1F1F" /* 'L', flush! */
153 "111111111111111" /* no data */
154 "0 11110010 1F1F" /* 'O', flush! */
155 );
156
157 printf("======== %s(): testing 8-N-2 (framing errors)\n", __func__);
158 test_rx_exec(suart, "11111" /* no data */
159 "0 00000000 00" /* stop bit != 1, expect flush */
160 "0 01010101 01" /* stop bit != 1, expect flush */
161 "0 10101010 10" /* stop bit != 1, expect flush */
162 "0 11111111 11" /* stop bit == 1, recovery */
163 "F" /* flush! (for sanity) */
164 );
165
166
167 printf("======== %s(): testing 8-E-1 (invalid parity)\n", __func__);
168 cfg = suart_test_default_cfg;
169 cfg.parity_mode = OSMO_SUART_PARITY_EVEN;
170 osmo_soft_uart_configure(suart, &cfg);
171 test_rx_exec(suart, "1111111" /* no data */
172 "0 00000000 1 1" /* odd parity, expect flush */
173 "0 10000000 0 1" /* odd parity, expect flush */
174 "0 11111111 1 1" /* odd parity, expect flush */
175 "F" /* flush! (for sanity) */
176 );
177 printf("======== %s(): testing 8-E-1 (valid parity)\n", __func__);
178 test_rx_exec(suart, "1111111" /* no data */
179 "0 00000000 0 1"
180 "0 11111111 0 1"
181 "0 01010101 0 1"
182 "0 10101010 0 1"
183 "F" /* flush! */
184 "0 00000001 1 1"
185 "0 00000111 1 1"
186 "0 00011111 1 1"
187 "0 01111111 1 1"
188 "F" /* flush! */
189 );
190
191 printf("======== %s(): testing 8-O-1 (invalid parity)\n", __func__);
192 cfg = suart_test_default_cfg;
193 cfg.parity_mode = OSMO_SUART_PARITY_ODD;
194 osmo_soft_uart_configure(suart, &cfg);
195 test_rx_exec(suart,
196 "0 00000000 0 1" /* even parity, expect flush */
197 "0 10000000 1 1" /* even parity, expect flush */
198 "0 11111111 0 1" /* even parity, expect flush */
199 "F" /* flush! (for sanity) */
200 );
201 printf("======== %s(): testing 8-O-1 (valid parity)\n", __func__);
202 test_rx_exec(suart, "1111111" /* no data */
203 "0 00000000 1 1"
204 "0 11111111 1 1"
205 "0 01010101 1 1"
206 "0 10101010 1 1"
207 "F" /* flush! */
208 "0 00000001 0 1"
209 "0 00000111 0 1"
210 "0 00011111 0 1"
211 "0 01111111 0 1"
212 "F" /* flush! */
213 );
214
215 osmo_soft_uart_free(suart);
216}
217
218static void test_tx_rx_exec_one(struct osmo_soft_uart *suart,
219 size_t n_bits_total, size_t n_bits_frame)
220{
221 ubit_t tx_buf[n_bits_total];
222 ubit_t *ptr = &tx_buf[0];
223 int rc;
224
225 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[0], n_bits_total);
Vadim Yanitskiyffb8d5e2023-12-04 03:17:26 +0700226 OSMO_ASSERT(rc == n_bits_total);
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +0700227
228 rc = osmo_soft_uart_rx_ubits(suart, &tx_buf[0], n_bits_total);
229 OSMO_ASSERT(rc == 0);
230 osmo_soft_uart_flush_rx(suart);
231
232 printf("%s(n_bits_total=%zu):", __func__, n_bits_total);
233 while (n_bits_total > 0) {
234 size_t n_bits = OSMO_MIN(n_bits_frame, n_bits_total);
235 printf(" %s", osmo_ubit_dump(ptr, n_bits));
236 n_bits_total -= n_bits;
237 ptr += n_bits;
238 }
239 printf("\n");
240}
241
242static void test_tx_rx_exec(struct osmo_soft_uart *suart, size_t n_bits_frame)
243{
244 const uint8_t tx_data[][4] = {
245 { 0xde, 0xad, 0xbe, 0xef },
246 { 0x00, 0xaa, 0x55, 0xff },
247 { 0x01, 0x02, 0x04, 0x08 },
248 { 0x10, 0x20, 0x40, 0x80 },
249 };
250
251 for (size_t i = 0; i < ARRAY_SIZE(tx_data); i++) {
252 g_tx_cb_cfg.data_len = 4;
253 g_tx_cb_cfg.data = tx_data[i];
254 test_tx_rx_exec_one(suart, 4 * n_bits_frame, n_bits_frame);
255 }
256
257 g_tx_cb_cfg.data_len = 0;
258 g_tx_cb_cfg.data = NULL;
259 test_tx_rx_exec_one(suart, 4 * n_bits_frame, n_bits_frame);
260}
261
262static void test_tx_rx(void)
263{
264 struct osmo_soft_uart_cfg cfg;
265 struct osmo_soft_uart *suart;
Vadim Yanitskiy811638c2023-11-30 03:09:05 +0700266 int rc;
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +0700267
268 suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg);
269 OSMO_ASSERT(suart != NULL);
270
Vadim Yanitskiy811638c2023-11-30 03:09:05 +0700271 /* expect -EAGAIN when the transmitter is not enabled */
272 rc = osmo_soft_uart_tx_ubits(suart, NULL, 42);
273 OSMO_ASSERT(rc == -EAGAIN);
274 /* expect -EAGAIN when the receiver is not enabled */
275 rc = osmo_soft_uart_rx_ubits(suart, NULL, 42);
276 OSMO_ASSERT(rc == -EAGAIN);
277
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +0700278 osmo_soft_uart_set_tx(suart, true);
279 osmo_soft_uart_set_rx(suart, true);
280
281 printf("======== %s(): testing 8-N-1\n", __func__);
282 test_tx_rx_exec(suart, (1 + 8 + 1));
283
284 printf("======== %s(): testing 8-N-2\n", __func__);
285 cfg = suart_test_default_cfg;
286 cfg.num_stop_bits = 2;
287 osmo_soft_uart_configure(suart, &cfg);
288 test_tx_rx_exec(suart, (1 + 8 + 2));
289
290 printf("======== %s(): testing 8-E-1\n", __func__);
291 cfg = suart_test_default_cfg;
292 cfg.parity_mode = OSMO_SUART_PARITY_EVEN;
293 osmo_soft_uart_configure(suart, &cfg);
294 test_tx_rx_exec(suart, (1 + 8 + 1 + 1));
295
296 printf("======== %s(): testing 8-O-1\n", __func__);
297 cfg = suart_test_default_cfg;
298 cfg.parity_mode = OSMO_SUART_PARITY_ODD;
299 osmo_soft_uart_configure(suart, &cfg);
300 test_tx_rx_exec(suart, (1 + 8 + 1 + 1));
301
Vadim Yanitskiy0d78a002023-11-19 16:15:38 +0700302 printf("======== %s(): testing 8-M-1\n", __func__);
303 cfg = suart_test_default_cfg;
304 cfg.parity_mode = OSMO_SUART_PARITY_MARK;
305 osmo_soft_uart_configure(suart, &cfg);
306 test_tx_rx_exec(suart, (1 + 8 + 1 + 1));
307
308 printf("======== %s(): testing 8-S-1\n", __func__);
309 cfg = suart_test_default_cfg;
310 cfg.parity_mode = OSMO_SUART_PARITY_SPACE;
311 osmo_soft_uart_configure(suart, &cfg);
312 test_tx_rx_exec(suart, (1 + 8 + 1 + 1));
313
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +0700314 printf("======== %s(): testing 6-N-1\n", __func__);
315 cfg = suart_test_default_cfg;
316 cfg.num_data_bits = 6;
317 osmo_soft_uart_configure(suart, &cfg);
318 test_tx_rx_exec(suart, (1 + 6 + 1));
319
320 osmo_soft_uart_free(suart);
321}
322
Vadim Yanitskiydab66292023-11-20 23:47:18 +0700323static void test_tx_rx_pull_n(unsigned int n)
324{
325 struct osmo_soft_uart *suart;
326 ubit_t tx_buf[32];
327 int rc;
328
329 suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg);
330 OSMO_ASSERT(suart != NULL);
331
332 osmo_soft_uart_set_tx(suart, true);
333 osmo_soft_uart_set_rx(suart, true);
334
335 g_tx_cb_cfg.data = (void *)"\x55";
336 g_tx_cb_cfg.data_len = 1;
337
338 printf("======== %s(): pulling %lu bits (%u at a time)\n", __func__, sizeof(tx_buf), n);
339 for (unsigned int i = 0; i < sizeof(tx_buf); i += n) {
340 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[i], n);
Vadim Yanitskiyffb8d5e2023-12-04 03:17:26 +0700341 OSMO_ASSERT(rc == n);
Vadim Yanitskiydab66292023-11-20 23:47:18 +0700342 }
343 printf("%s\n", osmo_ubit_dump(&tx_buf[0], sizeof(tx_buf)));
344
345 printf("======== %s(): feeding %lu bits into the receiver\n", __func__, sizeof(tx_buf));
346 rc = osmo_soft_uart_rx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
347 OSMO_ASSERT(rc == 0);
348 osmo_soft_uart_flush_rx(suart);
349
350 osmo_soft_uart_free(suart);
351}
352
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +0700353static void test_modem_status(void)
354{
355 struct osmo_soft_uart *suart;
356 unsigned int status;
357
358 suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg);
359 OSMO_ASSERT(suart != NULL);
360
361 printf("======== %s(): initial status=0x%08x\n",
362 __func__, osmo_soft_uart_get_status(suart));
363
364 printf("de-asserting DCD, which was not asserted\n");
365 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DCD, false);
366 OSMO_ASSERT(osmo_soft_uart_get_status(suart) == 0x00); /* no change */
367
368 printf("asserting both RI and DCD, expecting the callback to be called twice\n");
369 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_RI, true);
370 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DCD, true);
371 status = osmo_soft_uart_get_status(suart);
372 OSMO_ASSERT(status == (OSMO_SUART_STATUS_F_RI | OSMO_SUART_STATUS_F_DCD));
373
374 printf("de-asserting RI, expecting the callback to be called\n");
375 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_RI, false);
376 status = osmo_soft_uart_get_status(suart);
377 OSMO_ASSERT(status == (OSMO_SUART_STATUS_F_DCD));
378
379 printf("resetting to 0x00, expecting the callback to be called\n");
380 osmo_soft_uart_set_status(suart, 0x00);
381 OSMO_ASSERT(osmo_soft_uart_get_status(suart) == 0x00);
382
383 osmo_soft_uart_free(suart);
384}
385
386static void test_flow_control_dtr_dsr(void)
387{
388 struct osmo_soft_uart_cfg cfg;
389 struct osmo_soft_uart *suart;
390 ubit_t tx_buf[40];
391 int rc;
392
393 g_tx_cb_cfg.data = (void *)"\x42\x42\x42\x42";
394 g_tx_cb_cfg.data_len = 4;
395
396 cfg = suart_test_default_cfg;
397 cfg.flow_ctrl_mode = OSMO_SUART_FLOW_CTRL_DTR_DSR;
398
399 suart = osmo_soft_uart_alloc(NULL, __func__, &cfg);
400 OSMO_ASSERT(suart != NULL);
401
402 osmo_soft_uart_set_tx(suart, true);
403 osmo_soft_uart_set_rx(suart, true);
404
405 /* expect the initial status to be 0 (all lines de-asserted) */
406 printf("======== %s(): initial status=0x%08x\n",
407 __func__, osmo_soft_uart_get_status(suart));
408
409 memset(&tx_buf[0], 1, sizeof(tx_buf)); /* pre-initialize */
410
411 printf("expecting osmo_soft_uart_tx_ubits() to yield nothing\n");
412 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
413 OSMO_ASSERT(rc == 0);
414
415 printf("expecting osmo_soft_uart_rx_ubits() to yield nothing\n");
416 rc = osmo_soft_uart_rx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
417 OSMO_ASSERT(rc == 0);
418 osmo_soft_uart_flush_rx(suart);
419
420 /* both DTR and DSR are asserted, expect both Rx and Tx to work */
421 printf("======== %s(): asserting both DTR and DSR\n", __func__);
422 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DTR, true);
423 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DSR, true);
424
425 memset(&tx_buf[0], 1, sizeof(tx_buf)); /* pre-initialize */
426
427 printf("expecting osmo_soft_uart_tx_ubits() to "
428 "yield %zu bits (requesting %zu bits)\n",
429 sizeof(tx_buf), sizeof(tx_buf));
430 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
431 OSMO_ASSERT(rc == sizeof(tx_buf));
432 printf("%s\n", osmo_ubit_dump(&tx_buf[0], sizeof(tx_buf)));
433
434 printf("expecting osmo_soft_uart_rx_ubits() to "
435 "consume %zu bits and yield %zu chars\n",
436 sizeof(tx_buf), sizeof(tx_buf) / 10);
437 rc = osmo_soft_uart_rx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
438 OSMO_ASSERT(rc == 0);
439 osmo_soft_uart_flush_rx(suart);
440
441 memset(&tx_buf[0], 1, sizeof(tx_buf)); /* pre-initialize */
442
443 /* make the transmitter consume one char, but pull only 2 bits */
444 printf("expecting osmo_soft_uart_tx_ubits() to "
445 "yield 2 bits (requesting 2 bits)\n");
446 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[0], 2);
447 OSMO_ASSERT(rc == 2);
448
449 /* CTS gets de-asserted, the transmitter is shutting down */
450 printf("======== %s(): de-asserting DSR\n", __func__);
451 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DSR, false);
452
453 /* expect only the remaining 8 bits to be pulled out */
454 printf("expecting osmo_soft_uart_tx_ubits() to "
455 "yield 8 bits (requesting %zu bits)\n", sizeof(tx_buf));
456 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[2], sizeof(tx_buf) - 2);
457 OSMO_ASSERT(rc == 8);
458
459 printf("expecting osmo_soft_uart_rx_ubits() to "
460 "consume %zu bits and yield a pending char\n", sizeof(tx_buf));
461 rc = osmo_soft_uart_rx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
462 OSMO_ASSERT(rc == 0);
463 osmo_soft_uart_flush_rx(suart);
464
465 osmo_soft_uart_free(suart);
466}
467
468static void test_flow_control_rts_cts(void)
469{
470 struct osmo_soft_uart_cfg cfg;
471 struct osmo_soft_uart *suart;
472 ubit_t tx_buf[40];
473 int rc;
474
475 g_tx_cb_cfg.data = (void *)"\x42\x42\x42\x42";
476 g_tx_cb_cfg.data_len = 4;
477
478 cfg = suart_test_default_cfg;
479 cfg.flow_ctrl_mode = OSMO_SUART_FLOW_CTRL_RTS_CTS;
480
481 suart = osmo_soft_uart_alloc(NULL, __func__, &cfg);
482 OSMO_ASSERT(suart != NULL);
483
484 osmo_soft_uart_set_tx(suart, true);
485 osmo_soft_uart_set_rx(suart, true);
486
487 /* expect the initial status to be 0 (all lines de-asserted) */
488 printf("======== %s(): initial status=0x%08x\n",
489 __func__, osmo_soft_uart_get_status(suart));
490
491 memset(&tx_buf[0], 1, sizeof(tx_buf)); /* pre-initialize */
492
493 printf("expecting osmo_soft_uart_tx_ubits() to yield nothing\n");
494 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
495 OSMO_ASSERT(rc == 0);
496
497 printf("expecting osmo_soft_uart_rx_ubits() to yield nothing\n");
498 rc = osmo_soft_uart_rx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
499 OSMO_ASSERT(rc == 0);
500 osmo_soft_uart_flush_rx(suart);
501
502 /* both RTS/RTR and CTS are asserted, expect both Rx and Tx to work */
503 printf("======== %s(): asserting both CTS and RTS/RTR\n", __func__);
504 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_CTS, true);
505 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_RTS_RTR, true);
506
507 memset(&tx_buf[0], 1, sizeof(tx_buf)); /* pre-initialize */
508
509 printf("expecting osmo_soft_uart_tx_ubits() to "
510 "yield %zu bits (requesting %zu bits)\n",
511 sizeof(tx_buf), sizeof(tx_buf));
512 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
513 OSMO_ASSERT(rc == sizeof(tx_buf));
514 printf("%s\n", osmo_ubit_dump(&tx_buf[0], sizeof(tx_buf)));
515
516 printf("expecting osmo_soft_uart_rx_ubits() to "
517 "consume %zu bits and yield %zu chars\n",
518 sizeof(tx_buf), sizeof(tx_buf) / 10);
519 rc = osmo_soft_uart_rx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
520 OSMO_ASSERT(rc == 0);
521 osmo_soft_uart_flush_rx(suart);
522
523 memset(&tx_buf[0], 1, sizeof(tx_buf)); /* pre-initialize */
524
525 /* make the transmitter consume one char, but pull only 2 bits */
526 printf("expecting osmo_soft_uart_tx_ubits() to "
527 "yield 2 bits (requesting 2 bits)\n");
528 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[0], 2);
529 OSMO_ASSERT(rc == 2);
530
531 /* CTS gets de-asserted, the transmitter is shutting down */
532 printf("======== %s(): de-asserting CTS\n", __func__);
533 osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_CTS, false);
534
535 /* expect only the remaining 8 bits to be pulled out */
536 printf("expecting osmo_soft_uart_tx_ubits() to "
537 "yield 8 bits (requesting %zu bits)\n", sizeof(tx_buf));
538 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[2], sizeof(tx_buf) - 2);
539 OSMO_ASSERT(rc == 8);
540
541 printf("expecting osmo_soft_uart_rx_ubits() to "
542 "consume %zu bits and yield a pending char\n", sizeof(tx_buf));
543 rc = osmo_soft_uart_rx_ubits(suart, &tx_buf[0], sizeof(tx_buf));
544 OSMO_ASSERT(rc == 0);
545 osmo_soft_uart_flush_rx(suart);
546
547 osmo_soft_uart_free(suart);
548}
549
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +0700550int main(int argc, char **argv)
551{
552 test_rx();
553 test_tx_rx();
554
Vadim Yanitskiydab66292023-11-20 23:47:18 +0700555 /* test pulling small number of bits at a time */
556 test_tx_rx_pull_n(1);
557 test_tx_rx_pull_n(2);
558 test_tx_rx_pull_n(4);
559 test_tx_rx_pull_n(8);
560
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +0700561 /* test flow control */
562 test_modem_status();
563 test_flow_control_dtr_dsr();
564 test_flow_control_rts_cts();
565
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +0700566 return 0;
567}