blob: ad876bd23096d57764e6cb14d227de4f4678d4d2 [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
19#include <stdio.h>
20#include <stdint.h>
21
22#include <osmocom/core/msgb.h>
23#include <osmocom/core/utils.h>
24#include <osmocom/core/soft_uart.h>
25
26static struct {
27 size_t data_len;
28 const uint8_t *data;
29} g_tx_cb_cfg;
30
31static void suart_rx_cb(void *priv, struct msgb *msg, unsigned int flags)
32{
33 fprintf(stdout, "%s(flags=%02x): %s\n",
34 __func__, flags, msgb_hexdump(msg));
35 msgb_free(msg);
36}
37
38static void suart_tx_cb(void *priv, struct msgb *msg)
39{
40 size_t n_bytes;
41
42 n_bytes = OSMO_MIN(g_tx_cb_cfg.data_len, msg->data_len);
43 if (g_tx_cb_cfg.data != NULL && n_bytes > 0)
44 memcpy(msgb_put(msg, n_bytes), g_tx_cb_cfg.data, n_bytes);
45
46 fprintf(stdout, "%s(len=%u/%u): %s\n",
47 __func__, msg->len, msg->data_len, msgb_hexdump(msg));
48}
49
50static const struct osmo_soft_uart_cfg suart_test_default_cfg = {
51 .num_data_bits = 8,
52 .num_stop_bits = 1,
53 .parity_mode = OSMO_SUART_PARITY_NONE,
54 .rx_buf_size = 128,
55 .rx_cb = &suart_rx_cb,
56 .tx_cb = &suart_tx_cb,
57};
58
59static void test_rx_exec(struct osmo_soft_uart *suart,
60 const char *input)
61{
62 for (unsigned int i = 0; input[i] != '\0'; i++) {
63 ubit_t ubit;
64
65 switch (input[i]) {
66 case '0':
67 case '1':
68 ubit = input[i] - '0';
69 osmo_soft_uart_rx_ubits(suart, &ubit, 1);
70 break;
71 case 'F':
72 printf("%s() @ %u: flush the Rx buffer\n", __func__, i);
73 osmo_soft_uart_flush_rx(suart);
74 break;
75 case ' ': /* padding */
76 continue;
77 default:
78 printf("%s() @ %u: unknown opcode '%c'\n",
79 __func__, i, input[i]);
80 break;
81 }
82 }
83}
84
85static void test_rx(void)
86{
87 struct osmo_soft_uart_cfg cfg;
88 struct osmo_soft_uart *suart;
89
90 suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg);
91 OSMO_ASSERT(suart != NULL);
92
93 osmo_soft_uart_set_rx(suart, true);
94
95 printf("======== %s(): testing 8-N-1 (no data)\n", __func__);
96 test_rx_exec(suart, "F11111F11111F");
97
98 printf("======== %s(): testing 8-N-1 (fill up flush)\n", __func__);
99 cfg = suart_test_default_cfg;
100 cfg.rx_buf_size = 4;
101 osmo_soft_uart_configure(suart, &cfg);
102 test_rx_exec(suart, "11111" /* no data */
103 "0 01111011 1"
104 "0 10110101 1"
105 "0 01111101 1"
106 "0 11110111 1" /* filled up, expect flush */
107 "0 00000000 1"
108 "0 01010101 1"
109 "0 10101010 1"
110 "0 11111111 1" /* filled up, expect flush */
111 "F" /* flush! (for sanity) */
112 );
113
114 printf("======== %s(): testing 8-N-1 (HELLO)\n", __func__);
115 cfg = suart_test_default_cfg;
116 cfg.num_stop_bits = 1;
117 osmo_soft_uart_configure(suart, &cfg);
118 test_rx_exec(suart, "111111" /* no data */
119 "0 00010010 1F" /* 'H', flush! */
120 "0 10100010 1F" /* 'E', flush! */
121 "1111111111111" /* no data */
122 "0 00110010 1F" /* 'L', flush! */
123 "0 00110010 1F" /* 'L', flush! */
124 "1111111111111" /* no data */
125 "0 11110010 1F" /* 'O', flush! */
126 );
127
128 printf("======== %s(): testing 8-N-1 (framing errors)\n", __func__);
129 test_rx_exec(suart, "11111" /* no data */
130 "0 00000000 0" /* stop bit != 1, expect flush */
131 "0 01010101 0" /* stop bit != 1, expect flush */
132 "0 11111111 1" /* stop bit == 1, recovery */
133 "F" /* flush! */
134 );
135
136 printf("======== %s(): testing 8-N-2 (HELLO)\n", __func__);
137 cfg = suart_test_default_cfg;
138 cfg.num_stop_bits = 2;
139 osmo_soft_uart_configure(suart, &cfg);
140 test_rx_exec(suart, "11111111" /* no data */
141 "0 00010010 1F1F" /* 'H', flush! */
142 "0 10100010 1F1F" /* 'E', flush! */
143 "111111111111111" /* no data */
144 "0 00110010 1F1F" /* 'L', flush! */
145 "0 00110010 1F1F" /* 'L', flush! */
146 "111111111111111" /* no data */
147 "0 11110010 1F1F" /* 'O', flush! */
148 );
149
150 printf("======== %s(): testing 8-N-2 (framing errors)\n", __func__);
151 test_rx_exec(suart, "11111" /* no data */
152 "0 00000000 00" /* stop bit != 1, expect flush */
153 "0 01010101 01" /* stop bit != 1, expect flush */
154 "0 10101010 10" /* stop bit != 1, expect flush */
155 "0 11111111 11" /* stop bit == 1, recovery */
156 "F" /* flush! (for sanity) */
157 );
158
159
160 printf("======== %s(): testing 8-E-1 (invalid parity)\n", __func__);
161 cfg = suart_test_default_cfg;
162 cfg.parity_mode = OSMO_SUART_PARITY_EVEN;
163 osmo_soft_uart_configure(suart, &cfg);
164 test_rx_exec(suart, "1111111" /* no data */
165 "0 00000000 1 1" /* odd parity, expect flush */
166 "0 10000000 0 1" /* odd parity, expect flush */
167 "0 11111111 1 1" /* odd parity, expect flush */
168 "F" /* flush! (for sanity) */
169 );
170 printf("======== %s(): testing 8-E-1 (valid parity)\n", __func__);
171 test_rx_exec(suart, "1111111" /* no data */
172 "0 00000000 0 1"
173 "0 11111111 0 1"
174 "0 01010101 0 1"
175 "0 10101010 0 1"
176 "F" /* flush! */
177 "0 00000001 1 1"
178 "0 00000111 1 1"
179 "0 00011111 1 1"
180 "0 01111111 1 1"
181 "F" /* flush! */
182 );
183
184 printf("======== %s(): testing 8-O-1 (invalid parity)\n", __func__);
185 cfg = suart_test_default_cfg;
186 cfg.parity_mode = OSMO_SUART_PARITY_ODD;
187 osmo_soft_uart_configure(suart, &cfg);
188 test_rx_exec(suart,
189 "0 00000000 0 1" /* even parity, expect flush */
190 "0 10000000 1 1" /* even parity, expect flush */
191 "0 11111111 0 1" /* even parity, expect flush */
192 "F" /* flush! (for sanity) */
193 );
194 printf("======== %s(): testing 8-O-1 (valid parity)\n", __func__);
195 test_rx_exec(suart, "1111111" /* no data */
196 "0 00000000 1 1"
197 "0 11111111 1 1"
198 "0 01010101 1 1"
199 "0 10101010 1 1"
200 "F" /* flush! */
201 "0 00000001 0 1"
202 "0 00000111 0 1"
203 "0 00011111 0 1"
204 "0 01111111 0 1"
205 "F" /* flush! */
206 );
207
208 osmo_soft_uart_free(suart);
209}
210
211static void test_tx_rx_exec_one(struct osmo_soft_uart *suart,
212 size_t n_bits_total, size_t n_bits_frame)
213{
214 ubit_t tx_buf[n_bits_total];
215 ubit_t *ptr = &tx_buf[0];
216 int rc;
217
218 rc = osmo_soft_uart_tx_ubits(suart, &tx_buf[0], n_bits_total);
219 OSMO_ASSERT(rc == 0);
220
221 rc = osmo_soft_uart_rx_ubits(suart, &tx_buf[0], n_bits_total);
222 OSMO_ASSERT(rc == 0);
223 osmo_soft_uart_flush_rx(suart);
224
225 printf("%s(n_bits_total=%zu):", __func__, n_bits_total);
226 while (n_bits_total > 0) {
227 size_t n_bits = OSMO_MIN(n_bits_frame, n_bits_total);
228 printf(" %s", osmo_ubit_dump(ptr, n_bits));
229 n_bits_total -= n_bits;
230 ptr += n_bits;
231 }
232 printf("\n");
233}
234
235static void test_tx_rx_exec(struct osmo_soft_uart *suart, size_t n_bits_frame)
236{
237 const uint8_t tx_data[][4] = {
238 { 0xde, 0xad, 0xbe, 0xef },
239 { 0x00, 0xaa, 0x55, 0xff },
240 { 0x01, 0x02, 0x04, 0x08 },
241 { 0x10, 0x20, 0x40, 0x80 },
242 };
243
244 for (size_t i = 0; i < ARRAY_SIZE(tx_data); i++) {
245 g_tx_cb_cfg.data_len = 4;
246 g_tx_cb_cfg.data = tx_data[i];
247 test_tx_rx_exec_one(suart, 4 * n_bits_frame, n_bits_frame);
248 }
249
250 g_tx_cb_cfg.data_len = 0;
251 g_tx_cb_cfg.data = NULL;
252 test_tx_rx_exec_one(suart, 4 * n_bits_frame, n_bits_frame);
253}
254
255static void test_tx_rx(void)
256{
257 struct osmo_soft_uart_cfg cfg;
258 struct osmo_soft_uart *suart;
259
260 suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg);
261 OSMO_ASSERT(suart != NULL);
262
263 osmo_soft_uart_set_tx(suart, true);
264 osmo_soft_uart_set_rx(suart, true);
265
266 printf("======== %s(): testing 8-N-1\n", __func__);
267 test_tx_rx_exec(suart, (1 + 8 + 1));
268
269 printf("======== %s(): testing 8-N-2\n", __func__);
270 cfg = suart_test_default_cfg;
271 cfg.num_stop_bits = 2;
272 osmo_soft_uart_configure(suart, &cfg);
273 test_tx_rx_exec(suart, (1 + 8 + 2));
274
275 printf("======== %s(): testing 8-E-1\n", __func__);
276 cfg = suart_test_default_cfg;
277 cfg.parity_mode = OSMO_SUART_PARITY_EVEN;
278 osmo_soft_uart_configure(suart, &cfg);
279 test_tx_rx_exec(suart, (1 + 8 + 1 + 1));
280
281 printf("======== %s(): testing 8-O-1\n", __func__);
282 cfg = suart_test_default_cfg;
283 cfg.parity_mode = OSMO_SUART_PARITY_ODD;
284 osmo_soft_uart_configure(suart, &cfg);
285 test_tx_rx_exec(suart, (1 + 8 + 1 + 1));
286
Vadim Yanitskiy0d78a002023-11-19 16:15:38 +0700287 printf("======== %s(): testing 8-M-1\n", __func__);
288 cfg = suart_test_default_cfg;
289 cfg.parity_mode = OSMO_SUART_PARITY_MARK;
290 osmo_soft_uart_configure(suart, &cfg);
291 test_tx_rx_exec(suart, (1 + 8 + 1 + 1));
292
293 printf("======== %s(): testing 8-S-1\n", __func__);
294 cfg = suart_test_default_cfg;
295 cfg.parity_mode = OSMO_SUART_PARITY_SPACE;
296 osmo_soft_uart_configure(suart, &cfg);
297 test_tx_rx_exec(suart, (1 + 8 + 1 + 1));
298
Vadim Yanitskiy9ef304d2023-11-14 20:46:01 +0700299 printf("======== %s(): testing 6-N-1\n", __func__);
300 cfg = suart_test_default_cfg;
301 cfg.num_data_bits = 6;
302 osmo_soft_uart_configure(suart, &cfg);
303 test_tx_rx_exec(suart, (1 + 6 + 1));
304
305 osmo_soft_uart_free(suart);
306}
307
308int main(int argc, char **argv)
309{
310 test_rx();
311 test_tx_rx();
312
313 return 0;
314}