1 | /* |
---|
2 | * Copyright (c) 2017 embedded brains GmbH. All rights reserved. |
---|
3 | * |
---|
4 | * embedded brains GmbH |
---|
5 | * Dornierstr. 4 |
---|
6 | * 82178 Puchheim |
---|
7 | * Germany |
---|
8 | * <rtems@embedded-brains.de> |
---|
9 | * |
---|
10 | * The license and distribution terms for this file may be |
---|
11 | * found in the file LICENSE in this distribution or at |
---|
12 | * http://www.rtems.org/license/LICENSE. |
---|
13 | */ |
---|
14 | |
---|
15 | #ifdef HAVE_CONFIG_H |
---|
16 | #include "config.h" |
---|
17 | #endif |
---|
18 | |
---|
19 | #include <sys/stat.h> |
---|
20 | #include <fcntl.h> |
---|
21 | #include <string.h> |
---|
22 | #include <termios.h> |
---|
23 | #include <unistd.h> |
---|
24 | |
---|
25 | #include <rtems/termiostypes.h> |
---|
26 | |
---|
27 | #include "tmacros.h" |
---|
28 | |
---|
29 | const char rtems_test_name[] = "TERMIOS 9"; |
---|
30 | |
---|
31 | #define INTERRUPT 0 |
---|
32 | |
---|
33 | #define POLLED 1 |
---|
34 | |
---|
35 | #define DEVICE_COUNT 2 |
---|
36 | |
---|
37 | #define OUTPUT_BUFFER_SIZE 64 |
---|
38 | |
---|
39 | static const char * const paths[DEVICE_COUNT] = { |
---|
40 | "/interrupt", |
---|
41 | "/polled" |
---|
42 | }; |
---|
43 | |
---|
44 | typedef struct { |
---|
45 | rtems_termios_device_context base; |
---|
46 | rtems_termios_tty *tty; |
---|
47 | size_t output_pending; |
---|
48 | size_t output_count; |
---|
49 | char output_buf[OUTPUT_BUFFER_SIZE]; |
---|
50 | int input_char; |
---|
51 | int callback_counter; |
---|
52 | } device_context; |
---|
53 | |
---|
54 | typedef struct { |
---|
55 | device_context devices[DEVICE_COUNT]; |
---|
56 | int fds[DEVICE_COUNT]; |
---|
57 | struct termios term[DEVICE_COUNT]; |
---|
58 | int context_switch_counter; |
---|
59 | rtems_id flush_task_id; |
---|
60 | } test_context; |
---|
61 | |
---|
62 | static test_context test_instance = { |
---|
63 | .devices = { |
---|
64 | { |
---|
65 | .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("Interrupt") |
---|
66 | }, { |
---|
67 | .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("Polled"), |
---|
68 | .input_char = -1 |
---|
69 | } |
---|
70 | } |
---|
71 | }; |
---|
72 | |
---|
73 | static bool first_open( |
---|
74 | rtems_termios_tty *tty, |
---|
75 | rtems_termios_device_context *base, |
---|
76 | struct termios *term, |
---|
77 | rtems_libio_open_close_args_t *args |
---|
78 | ) |
---|
79 | { |
---|
80 | device_context *dev = (device_context *) base; |
---|
81 | |
---|
82 | dev->tty = tty; |
---|
83 | |
---|
84 | return true; |
---|
85 | } |
---|
86 | |
---|
87 | static void write_polled( |
---|
88 | rtems_termios_device_context *base, |
---|
89 | const char *buf, |
---|
90 | size_t len |
---|
91 | ) |
---|
92 | { |
---|
93 | device_context *dev = (device_context *) base; |
---|
94 | |
---|
95 | rtems_test_assert(dev->output_count + len <= OUTPUT_BUFFER_SIZE); |
---|
96 | memcpy(&dev->output_buf[dev->output_count], buf, len); |
---|
97 | dev->output_count += len; |
---|
98 | } |
---|
99 | |
---|
100 | static void write_interrupt( |
---|
101 | rtems_termios_device_context *base, |
---|
102 | const char *buf, |
---|
103 | size_t len |
---|
104 | ) |
---|
105 | { |
---|
106 | device_context *dev = (device_context *) base; |
---|
107 | |
---|
108 | write_polled(base, buf, len); |
---|
109 | dev->output_pending = len; |
---|
110 | } |
---|
111 | |
---|
112 | static int read_polled(rtems_termios_device_context *base) |
---|
113 | { |
---|
114 | device_context *dev = (device_context *) base; |
---|
115 | int c = dev->input_char; |
---|
116 | |
---|
117 | dev->input_char = -1; |
---|
118 | |
---|
119 | return c; |
---|
120 | } |
---|
121 | |
---|
122 | static const rtems_termios_device_handler handlers[DEVICE_COUNT] = { |
---|
123 | { |
---|
124 | .first_open = first_open, |
---|
125 | .write = write_interrupt, |
---|
126 | .mode = TERMIOS_IRQ_DRIVEN |
---|
127 | }, { |
---|
128 | .first_open = first_open, |
---|
129 | .write = write_polled, |
---|
130 | .poll_read = read_polled, |
---|
131 | .mode = TERMIOS_POLLED |
---|
132 | } |
---|
133 | }; |
---|
134 | |
---|
135 | static void set_term(test_context *ctx, size_t i) |
---|
136 | { |
---|
137 | int rv; |
---|
138 | |
---|
139 | rv = tcsetattr(ctx->fds[i], TCSANOW, &ctx->term[i]); |
---|
140 | rtems_test_assert(rv == 0); |
---|
141 | } |
---|
142 | |
---|
143 | static void init_term(test_context *ctx, size_t i) |
---|
144 | { |
---|
145 | int rv; |
---|
146 | |
---|
147 | rv = tcgetattr(ctx->fds[i], &ctx->term[i]); |
---|
148 | rtems_test_assert(rv == 0); |
---|
149 | |
---|
150 | ctx->term[i].c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
---|
151 | | INLCR | IGNCR | ICRNL | IXON); |
---|
152 | ctx->term[i].c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT |
---|
153 | | ECHOCTL | ECHOKE | ICANON | ISIG | IEXTEN); |
---|
154 | ctx->term[i].c_cflag &= ~(CSIZE | PARENB); |
---|
155 | ctx->term[i].c_cflag |= CS8; |
---|
156 | ctx->term[i].c_oflag &= ~(OPOST | ONLRET | ONLCR | OCRNL | ONLRET |
---|
157 | | TABDLY | OLCUC); |
---|
158 | |
---|
159 | ctx->term[i].c_cc[VMIN] = 0; |
---|
160 | ctx->term[i].c_cc[VTIME] = 0; |
---|
161 | |
---|
162 | set_term(ctx, i); |
---|
163 | } |
---|
164 | |
---|
165 | static void setup(test_context *ctx) |
---|
166 | { |
---|
167 | rtems_status_code sc; |
---|
168 | size_t i; |
---|
169 | |
---|
170 | rtems_termios_initialize(); |
---|
171 | |
---|
172 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
173 | sc = rtems_termios_device_install( |
---|
174 | paths[i], |
---|
175 | &handlers[i], |
---|
176 | NULL, |
---|
177 | &ctx->devices[i].base |
---|
178 | ); |
---|
179 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
180 | |
---|
181 | ctx->fds[i] = open(paths[i], O_RDWR); |
---|
182 | rtems_test_assert(ctx->fds[i] >= 0); |
---|
183 | |
---|
184 | init_term(ctx, i); |
---|
185 | } |
---|
186 | } |
---|
187 | |
---|
188 | static void input(test_context *ctx, size_t i, char c) |
---|
189 | { |
---|
190 | switch (i) { |
---|
191 | case INTERRUPT: |
---|
192 | rtems_termios_enqueue_raw_characters(ctx->devices[i].tty, &c, sizeof(c)); |
---|
193 | break; |
---|
194 | case POLLED: |
---|
195 | ctx->devices[i].input_char = (unsigned char) c; |
---|
196 | break; |
---|
197 | default: |
---|
198 | rtems_test_assert(0); |
---|
199 | } |
---|
200 | } |
---|
201 | |
---|
202 | static void enable_non_blocking(test_context *ctx, size_t i, bool enable) |
---|
203 | { |
---|
204 | int flags; |
---|
205 | int rv; |
---|
206 | |
---|
207 | flags = fcntl(ctx->fds[i], F_GETFL, 0); |
---|
208 | rtems_test_assert(flags >= 0); |
---|
209 | |
---|
210 | if (enable) { |
---|
211 | flags |= O_NONBLOCK; |
---|
212 | } else { |
---|
213 | flags &= ~O_NONBLOCK; |
---|
214 | } |
---|
215 | |
---|
216 | rv = fcntl(ctx->fds[i], F_SETFL, flags); |
---|
217 | rtems_test_assert(rv == 0); |
---|
218 | } |
---|
219 | |
---|
220 | static void clear_set_iflag( |
---|
221 | test_context *ctx, |
---|
222 | size_t i, |
---|
223 | tcflag_t clear, |
---|
224 | tcflag_t set |
---|
225 | ) |
---|
226 | { |
---|
227 | ctx->term[i].c_iflag &= ~clear; |
---|
228 | ctx->term[i].c_iflag |= set; |
---|
229 | set_term(ctx, i); |
---|
230 | } |
---|
231 | |
---|
232 | static void clear_set_lflag( |
---|
233 | test_context *ctx, |
---|
234 | size_t i, |
---|
235 | tcflag_t clear, |
---|
236 | tcflag_t set |
---|
237 | ) |
---|
238 | { |
---|
239 | ctx->term[i].c_lflag &= ~clear; |
---|
240 | ctx->term[i].c_lflag |= set; |
---|
241 | set_term(ctx, i); |
---|
242 | } |
---|
243 | |
---|
244 | static void clear_set_oflag( |
---|
245 | test_context *ctx, |
---|
246 | size_t i, |
---|
247 | tcflag_t clear, |
---|
248 | tcflag_t set |
---|
249 | ) |
---|
250 | { |
---|
251 | ctx->term[i].c_oflag &= ~clear; |
---|
252 | ctx->term[i].c_oflag |= set; |
---|
253 | set_term(ctx, i); |
---|
254 | } |
---|
255 | |
---|
256 | static void set_vmin_vtime( |
---|
257 | test_context *ctx, |
---|
258 | size_t i, |
---|
259 | cc_t vmin, |
---|
260 | cc_t vtime |
---|
261 | ) |
---|
262 | { |
---|
263 | ctx->term[i].c_cc[VMIN] = vmin; |
---|
264 | ctx->term[i].c_cc[VTIME] = vtime; |
---|
265 | set_term(ctx, i); |
---|
266 | } |
---|
267 | |
---|
268 | static void set_veol_veol2( |
---|
269 | test_context *ctx, |
---|
270 | size_t i, |
---|
271 | cc_t veol, |
---|
272 | cc_t veol2 |
---|
273 | ) |
---|
274 | { |
---|
275 | ctx->term[i].c_cc[VEOL] = veol; |
---|
276 | ctx->term[i].c_cc[VEOL2] = veol2; |
---|
277 | set_term(ctx, i); |
---|
278 | } |
---|
279 | |
---|
280 | static void test_igncr(test_context *ctx) |
---|
281 | { |
---|
282 | size_t i; |
---|
283 | |
---|
284 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
285 | ssize_t n; |
---|
286 | char c; |
---|
287 | |
---|
288 | c = 'x'; |
---|
289 | |
---|
290 | clear_set_iflag(ctx, i, 0, IGNCR); |
---|
291 | |
---|
292 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
293 | rtems_test_assert(n == 0); |
---|
294 | rtems_test_assert(c == 'x'); |
---|
295 | |
---|
296 | input(ctx, i, '\r'); |
---|
297 | |
---|
298 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
299 | rtems_test_assert(n == 0); |
---|
300 | rtems_test_assert(c == 'x'); |
---|
301 | |
---|
302 | clear_set_iflag(ctx, i, IGNCR, 0); |
---|
303 | input(ctx, i, '\r'); |
---|
304 | |
---|
305 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
306 | rtems_test_assert(n == 1); |
---|
307 | rtems_test_assert(c == '\r'); |
---|
308 | } |
---|
309 | } |
---|
310 | |
---|
311 | static void test_istrip(test_context *ctx) |
---|
312 | { |
---|
313 | size_t i; |
---|
314 | |
---|
315 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
316 | ssize_t n; |
---|
317 | char c; |
---|
318 | |
---|
319 | c = 'x'; |
---|
320 | |
---|
321 | clear_set_iflag(ctx, i, 0, ISTRIP); |
---|
322 | |
---|
323 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
324 | rtems_test_assert(n == 0); |
---|
325 | rtems_test_assert(c == 'x'); |
---|
326 | |
---|
327 | input(ctx, i, '\376'); |
---|
328 | |
---|
329 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
330 | rtems_test_assert(n == 1); |
---|
331 | rtems_test_assert(c == '~'); |
---|
332 | |
---|
333 | clear_set_iflag(ctx, i, ISTRIP, 0); |
---|
334 | input(ctx, i, '\376'); |
---|
335 | |
---|
336 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
337 | rtems_test_assert(n == 1); |
---|
338 | rtems_test_assert(c == '\376'); |
---|
339 | } |
---|
340 | } |
---|
341 | |
---|
342 | static void test_iuclc(test_context *ctx) |
---|
343 | { |
---|
344 | size_t i; |
---|
345 | |
---|
346 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
347 | ssize_t n; |
---|
348 | char c; |
---|
349 | |
---|
350 | c = 'x'; |
---|
351 | |
---|
352 | clear_set_iflag(ctx, i, 0, IUCLC); |
---|
353 | |
---|
354 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
355 | rtems_test_assert(n == 0); |
---|
356 | rtems_test_assert(c == 'x'); |
---|
357 | |
---|
358 | input(ctx, i, 'A'); |
---|
359 | |
---|
360 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
361 | rtems_test_assert(n == 1); |
---|
362 | rtems_test_assert(c == 'a'); |
---|
363 | |
---|
364 | clear_set_iflag(ctx, i, IUCLC, 0); |
---|
365 | input(ctx, i, 'A'); |
---|
366 | |
---|
367 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
368 | rtems_test_assert(n == 1); |
---|
369 | rtems_test_assert(c == 'A'); |
---|
370 | } |
---|
371 | } |
---|
372 | |
---|
373 | static void test_icrnl(test_context *ctx) |
---|
374 | { |
---|
375 | size_t i; |
---|
376 | |
---|
377 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
378 | ssize_t n; |
---|
379 | char c; |
---|
380 | |
---|
381 | c = 'x'; |
---|
382 | |
---|
383 | clear_set_iflag(ctx, i, 0, ICRNL); |
---|
384 | |
---|
385 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
386 | rtems_test_assert(n == 0); |
---|
387 | rtems_test_assert(c == 'x'); |
---|
388 | |
---|
389 | input(ctx, i, '\r'); |
---|
390 | |
---|
391 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
392 | rtems_test_assert(n == 1); |
---|
393 | rtems_test_assert(c == '\n'); |
---|
394 | |
---|
395 | clear_set_iflag(ctx, i, ICRNL, 0); |
---|
396 | input(ctx, i, '\r'); |
---|
397 | |
---|
398 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
399 | rtems_test_assert(n == 1); |
---|
400 | rtems_test_assert(c == '\r'); |
---|
401 | } |
---|
402 | } |
---|
403 | |
---|
404 | static void test_inlcr(test_context *ctx) |
---|
405 | { |
---|
406 | size_t i; |
---|
407 | |
---|
408 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
409 | ssize_t n; |
---|
410 | char c; |
---|
411 | |
---|
412 | c = 'x'; |
---|
413 | |
---|
414 | clear_set_iflag(ctx, i, 0, INLCR); |
---|
415 | |
---|
416 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
417 | rtems_test_assert(n == 0); |
---|
418 | rtems_test_assert(c == 'x'); |
---|
419 | |
---|
420 | input(ctx, i, '\n'); |
---|
421 | |
---|
422 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
423 | rtems_test_assert(n == 1); |
---|
424 | rtems_test_assert(c == '\r'); |
---|
425 | |
---|
426 | clear_set_iflag(ctx, i, INLCR, 0); |
---|
427 | input(ctx, i, '\n'); |
---|
428 | |
---|
429 | n = read(ctx->fds[i], &c, sizeof(c)); |
---|
430 | rtems_test_assert(n == 1); |
---|
431 | rtems_test_assert(c == '\n'); |
---|
432 | } |
---|
433 | } |
---|
434 | |
---|
435 | static void callback(struct termios *tty, void *arg) |
---|
436 | { |
---|
437 | device_context *ctx = arg; |
---|
438 | |
---|
439 | ++ctx->callback_counter; |
---|
440 | } |
---|
441 | |
---|
442 | static void test_rx_callback(test_context *ctx) |
---|
443 | { |
---|
444 | size_t i = INTERRUPT; |
---|
445 | device_context *dev = &ctx->devices[i]; |
---|
446 | ssize_t n; |
---|
447 | char buf[3]; |
---|
448 | |
---|
449 | buf[0] = 'x'; |
---|
450 | |
---|
451 | dev->callback_counter = 0; |
---|
452 | dev->tty->tty_rcv.sw_pfn = callback; |
---|
453 | dev->tty->tty_rcv.sw_arg = dev; |
---|
454 | clear_set_lflag(ctx, i, ICANON, 0); |
---|
455 | |
---|
456 | set_vmin_vtime(ctx, i, 0, 0); |
---|
457 | |
---|
458 | n = read(ctx->fds[i], buf, 1); |
---|
459 | rtems_test_assert(n == 0); |
---|
460 | rtems_test_assert(buf[0] == 'x'); |
---|
461 | |
---|
462 | input(ctx, i, 'a'); |
---|
463 | rtems_test_assert(dev->callback_counter == 1); |
---|
464 | |
---|
465 | input(ctx, i, 'b'); |
---|
466 | rtems_test_assert(dev->callback_counter == 1); |
---|
467 | |
---|
468 | n = read(ctx->fds[i], buf, 2); |
---|
469 | rtems_test_assert(n == 2); |
---|
470 | rtems_test_assert(buf[0] == 'a'); |
---|
471 | rtems_test_assert(buf[1] == 'b'); |
---|
472 | |
---|
473 | set_vmin_vtime(ctx, i, 2, 0); |
---|
474 | |
---|
475 | input(ctx, i, 'd'); |
---|
476 | rtems_test_assert(dev->callback_counter == 1); |
---|
477 | |
---|
478 | input(ctx, i, 'e'); |
---|
479 | rtems_test_assert(dev->callback_counter == 2); |
---|
480 | |
---|
481 | input(ctx, i, 'f'); |
---|
482 | rtems_test_assert(dev->callback_counter == 2); |
---|
483 | |
---|
484 | n = read(ctx->fds[i], buf, 3); |
---|
485 | rtems_test_assert(n == 3); |
---|
486 | rtems_test_assert(buf[0] == 'd'); |
---|
487 | rtems_test_assert(buf[1] == 'e'); |
---|
488 | rtems_test_assert(buf[2] == 'f'); |
---|
489 | |
---|
490 | dev->tty->tty_rcv.sw_pfn = NULL; |
---|
491 | dev->tty->tty_rcv.sw_arg = NULL; |
---|
492 | } |
---|
493 | |
---|
494 | static void test_rx_callback_icanon(test_context *ctx) |
---|
495 | { |
---|
496 | size_t i = INTERRUPT; |
---|
497 | device_context *dev = &ctx->devices[i]; |
---|
498 | ssize_t n; |
---|
499 | char buf[255]; |
---|
500 | size_t j; |
---|
501 | |
---|
502 | buf[0] = 'x'; |
---|
503 | |
---|
504 | dev->callback_counter = 0; |
---|
505 | dev->tty->tty_rcv.sw_pfn = callback; |
---|
506 | dev->tty->tty_rcv.sw_arg = dev; |
---|
507 | |
---|
508 | set_vmin_vtime(ctx, i, 0, 0); |
---|
509 | |
---|
510 | n = read(ctx->fds[i], buf, 1); |
---|
511 | rtems_test_assert(n == 0); |
---|
512 | rtems_test_assert(buf[0] == 'x'); |
---|
513 | |
---|
514 | clear_set_lflag(ctx, i, 0, ICANON); |
---|
515 | set_veol_veol2(ctx, i, '1', '2'); |
---|
516 | |
---|
517 | input(ctx, i, '\n'); |
---|
518 | rtems_test_assert(dev->callback_counter == 1); |
---|
519 | |
---|
520 | input(ctx, i, 'a'); |
---|
521 | rtems_test_assert(dev->callback_counter == 1); |
---|
522 | |
---|
523 | input(ctx, i, '\n'); |
---|
524 | rtems_test_assert(dev->callback_counter == 1); |
---|
525 | |
---|
526 | n = read(ctx->fds[i], buf, 3); |
---|
527 | rtems_test_assert(n == 3); |
---|
528 | rtems_test_assert(buf[0] == '\n'); |
---|
529 | rtems_test_assert(buf[1] == 'a'); |
---|
530 | rtems_test_assert(buf[2] == '\n'); |
---|
531 | |
---|
532 | input(ctx, i, '\4'); |
---|
533 | rtems_test_assert(dev->callback_counter == 2); |
---|
534 | |
---|
535 | input(ctx, i, 'b'); |
---|
536 | rtems_test_assert(dev->callback_counter == 2); |
---|
537 | |
---|
538 | input(ctx, i, '\n'); |
---|
539 | rtems_test_assert(dev->callback_counter == 2); |
---|
540 | |
---|
541 | n = read(ctx->fds[i], buf, 2); |
---|
542 | rtems_test_assert(n == 2); |
---|
543 | rtems_test_assert(buf[0] == 'b'); |
---|
544 | rtems_test_assert(buf[1] == '\n'); |
---|
545 | |
---|
546 | input(ctx, i, '1'); |
---|
547 | rtems_test_assert(dev->callback_counter == 3); |
---|
548 | |
---|
549 | input(ctx, i, 'c'); |
---|
550 | rtems_test_assert(dev->callback_counter == 3); |
---|
551 | |
---|
552 | input(ctx, i, '\n'); |
---|
553 | rtems_test_assert(dev->callback_counter == 3); |
---|
554 | |
---|
555 | n = read(ctx->fds[i], buf, 3); |
---|
556 | rtems_test_assert(n == 3); |
---|
557 | rtems_test_assert(buf[0] == '1'); |
---|
558 | rtems_test_assert(buf[1] == 'c'); |
---|
559 | rtems_test_assert(buf[2] == '\n'); |
---|
560 | |
---|
561 | input(ctx, i, '2'); |
---|
562 | rtems_test_assert(dev->callback_counter == 4); |
---|
563 | |
---|
564 | input(ctx, i, 'd'); |
---|
565 | rtems_test_assert(dev->callback_counter == 4); |
---|
566 | |
---|
567 | input(ctx, i, '\n'); |
---|
568 | rtems_test_assert(dev->callback_counter == 4); |
---|
569 | |
---|
570 | n = read(ctx->fds[i], buf, 3); |
---|
571 | rtems_test_assert(n == 3); |
---|
572 | rtems_test_assert(buf[0] == '2'); |
---|
573 | rtems_test_assert(buf[1] == 'd'); |
---|
574 | rtems_test_assert(buf[2] == '\n'); |
---|
575 | |
---|
576 | for (j = 0; j < 255; ++j) { |
---|
577 | input(ctx, i, 'e'); |
---|
578 | rtems_test_assert(dev->callback_counter == 4); |
---|
579 | } |
---|
580 | |
---|
581 | /* Raw input buffer overflow */ |
---|
582 | input(ctx, i, 'e'); |
---|
583 | rtems_test_assert(dev->callback_counter == 5); |
---|
584 | |
---|
585 | n = read(ctx->fds[i], buf, 255); |
---|
586 | rtems_test_assert(n == 255); |
---|
587 | |
---|
588 | dev->tty->tty_rcv.sw_pfn = NULL; |
---|
589 | dev->tty->tty_rcv.sw_arg = NULL; |
---|
590 | set_veol_veol2(ctx, i, '\0', '\0'); |
---|
591 | clear_set_lflag(ctx, i, ICANON, 0); |
---|
592 | } |
---|
593 | |
---|
594 | static void flush_output(test_context *ctx, size_t i) |
---|
595 | { |
---|
596 | if (i == INTERRUPT) { |
---|
597 | device_context *dev = &ctx->devices[i]; |
---|
598 | int left; |
---|
599 | |
---|
600 | do { |
---|
601 | left = rtems_termios_dequeue_characters(dev->tty, dev->output_pending); |
---|
602 | } while (left > 0); |
---|
603 | } |
---|
604 | } |
---|
605 | |
---|
606 | static void clear_output(test_context *ctx, size_t i) |
---|
607 | { |
---|
608 | device_context *dev = &ctx->devices[i]; |
---|
609 | |
---|
610 | flush_output(ctx, i); |
---|
611 | dev->output_count = 0; |
---|
612 | memset(&dev->output_buf, 0, OUTPUT_BUFFER_SIZE); |
---|
613 | } |
---|
614 | |
---|
615 | static void test_onlret(test_context *ctx) |
---|
616 | { |
---|
617 | tcflag_t oflags = OPOST | ONLRET; |
---|
618 | size_t i; |
---|
619 | |
---|
620 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
621 | device_context *dev = &ctx->devices[i]; |
---|
622 | char c; |
---|
623 | ssize_t n; |
---|
624 | |
---|
625 | dev->tty->column = 0; |
---|
626 | clear_output(ctx, i); |
---|
627 | |
---|
628 | clear_set_oflag(ctx, i, 0, oflags); |
---|
629 | |
---|
630 | c = 'a'; |
---|
631 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
632 | rtems_test_assert(n == 1); |
---|
633 | rtems_test_assert(dev->tty->column == 1); |
---|
634 | flush_output(ctx, i); |
---|
635 | rtems_test_assert(dev->output_count == 1); |
---|
636 | rtems_test_assert(dev->output_buf[0] == 'a'); |
---|
637 | |
---|
638 | c = '\n'; |
---|
639 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
640 | rtems_test_assert(n == 1); |
---|
641 | rtems_test_assert(dev->tty->column == 0); |
---|
642 | flush_output(ctx, i); |
---|
643 | rtems_test_assert(dev->output_count == 2); |
---|
644 | rtems_test_assert(dev->output_buf[1] == '\n'); |
---|
645 | |
---|
646 | clear_set_oflag(ctx, i, oflags, 0); |
---|
647 | } |
---|
648 | } |
---|
649 | |
---|
650 | static void test_onlcr(test_context *ctx) |
---|
651 | { |
---|
652 | tcflag_t oflags = OPOST | ONLCR; |
---|
653 | size_t i; |
---|
654 | |
---|
655 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
656 | device_context *dev = &ctx->devices[i]; |
---|
657 | char c; |
---|
658 | ssize_t n; |
---|
659 | |
---|
660 | dev->tty->column = 0; |
---|
661 | clear_output(ctx, i); |
---|
662 | |
---|
663 | clear_set_oflag(ctx, i, 0, oflags); |
---|
664 | |
---|
665 | c = 'a'; |
---|
666 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
667 | rtems_test_assert(n == 1); |
---|
668 | rtems_test_assert(dev->tty->column == 1); |
---|
669 | flush_output(ctx, i); |
---|
670 | rtems_test_assert(dev->output_count == 1); |
---|
671 | rtems_test_assert(dev->output_buf[0] == 'a'); |
---|
672 | |
---|
673 | c = '\n'; |
---|
674 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
675 | rtems_test_assert(n == 1); |
---|
676 | rtems_test_assert(dev->tty->column == 0); |
---|
677 | flush_output(ctx, i); |
---|
678 | rtems_test_assert(dev->output_count == 3); |
---|
679 | rtems_test_assert(dev->output_buf[1] == '\r'); |
---|
680 | rtems_test_assert(dev->output_buf[2] == '\n'); |
---|
681 | |
---|
682 | clear_set_oflag(ctx, i, oflags, 0); |
---|
683 | } |
---|
684 | } |
---|
685 | |
---|
686 | static void test_onocr(test_context *ctx) |
---|
687 | { |
---|
688 | tcflag_t oflags = OPOST | ONOCR; |
---|
689 | size_t i; |
---|
690 | |
---|
691 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
692 | device_context *dev = &ctx->devices[i]; |
---|
693 | char c; |
---|
694 | ssize_t n; |
---|
695 | |
---|
696 | dev->tty->column = 0; |
---|
697 | clear_output(ctx, i); |
---|
698 | |
---|
699 | clear_set_oflag(ctx, i, 0, oflags); |
---|
700 | |
---|
701 | c = '\r'; |
---|
702 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
703 | rtems_test_assert(n == 1); |
---|
704 | rtems_test_assert(dev->tty->column == 0); |
---|
705 | flush_output(ctx, i); |
---|
706 | rtems_test_assert(dev->output_count == 0); |
---|
707 | |
---|
708 | c = 'a'; |
---|
709 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
710 | rtems_test_assert(n == 1); |
---|
711 | rtems_test_assert(dev->tty->column == 1); |
---|
712 | flush_output(ctx, i); |
---|
713 | rtems_test_assert(dev->output_count == 1); |
---|
714 | rtems_test_assert(dev->output_buf[0] == 'a'); |
---|
715 | |
---|
716 | c = '\r'; |
---|
717 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
718 | rtems_test_assert(n == 1); |
---|
719 | rtems_test_assert(dev->tty->column == 0); |
---|
720 | flush_output(ctx, i); |
---|
721 | rtems_test_assert(dev->output_count == 2); |
---|
722 | rtems_test_assert(dev->output_buf[1] == '\r'); |
---|
723 | |
---|
724 | clear_set_oflag(ctx, i, oflags, 0); |
---|
725 | } |
---|
726 | } |
---|
727 | |
---|
728 | static void test_ocrnl(test_context *ctx) |
---|
729 | { |
---|
730 | tcflag_t oflags = OPOST | OCRNL; |
---|
731 | size_t i; |
---|
732 | |
---|
733 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
734 | device_context *dev = &ctx->devices[i]; |
---|
735 | char c; |
---|
736 | ssize_t n; |
---|
737 | |
---|
738 | dev->tty->column = 0; |
---|
739 | clear_output(ctx, i); |
---|
740 | |
---|
741 | clear_set_oflag(ctx, i, 0, oflags); |
---|
742 | |
---|
743 | c = '\r'; |
---|
744 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
745 | rtems_test_assert(n == 1); |
---|
746 | rtems_test_assert(dev->tty->column == 0); |
---|
747 | flush_output(ctx, i); |
---|
748 | rtems_test_assert(dev->output_count == 1); |
---|
749 | rtems_test_assert(dev->output_buf[0] == '\n'); |
---|
750 | |
---|
751 | clear_set_oflag(ctx, i, oflags, 0); |
---|
752 | } |
---|
753 | } |
---|
754 | |
---|
755 | static void test_ocrnl_onlret(test_context *ctx) |
---|
756 | { |
---|
757 | tcflag_t oflags = OPOST | OCRNL | ONLRET; |
---|
758 | size_t i; |
---|
759 | |
---|
760 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
761 | device_context *dev = &ctx->devices[i]; |
---|
762 | char c; |
---|
763 | ssize_t n; |
---|
764 | |
---|
765 | dev->tty->column = 0; |
---|
766 | clear_output(ctx, i); |
---|
767 | |
---|
768 | clear_set_oflag(ctx, i, 0, oflags); |
---|
769 | |
---|
770 | c = 'a'; |
---|
771 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
772 | rtems_test_assert(n == 1); |
---|
773 | rtems_test_assert(dev->tty->column == 1); |
---|
774 | flush_output(ctx, i); |
---|
775 | rtems_test_assert(dev->output_count == 1); |
---|
776 | rtems_test_assert(dev->output_buf[0] == 'a'); |
---|
777 | |
---|
778 | c = '\r'; |
---|
779 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
780 | rtems_test_assert(n == 1); |
---|
781 | rtems_test_assert(dev->tty->column == 0); |
---|
782 | flush_output(ctx, i); |
---|
783 | rtems_test_assert(dev->output_count == 2); |
---|
784 | rtems_test_assert(dev->output_buf[1] == '\n'); |
---|
785 | |
---|
786 | clear_set_oflag(ctx, i, oflags, 0); |
---|
787 | } |
---|
788 | } |
---|
789 | |
---|
790 | static void test_opost(test_context *ctx) |
---|
791 | { |
---|
792 | tcflag_t oflags = OPOST; |
---|
793 | size_t i; |
---|
794 | |
---|
795 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
796 | device_context *dev = &ctx->devices[i]; |
---|
797 | char c; |
---|
798 | ssize_t n; |
---|
799 | |
---|
800 | dev->tty->column = 0; |
---|
801 | clear_output(ctx, i); |
---|
802 | |
---|
803 | clear_set_oflag(ctx, i, 0, oflags); |
---|
804 | |
---|
805 | c = 'a'; |
---|
806 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
807 | rtems_test_assert(n == 1); |
---|
808 | rtems_test_assert(dev->tty->column == 1); |
---|
809 | flush_output(ctx, i); |
---|
810 | rtems_test_assert(dev->output_count == 1); |
---|
811 | rtems_test_assert(dev->output_buf[0] == 'a'); |
---|
812 | |
---|
813 | c = '\33'; |
---|
814 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
815 | rtems_test_assert(n == 1); |
---|
816 | rtems_test_assert(dev->tty->column == 1); |
---|
817 | flush_output(ctx, i); |
---|
818 | rtems_test_assert(dev->output_count == 2); |
---|
819 | rtems_test_assert(dev->output_buf[1] == '\33'); |
---|
820 | |
---|
821 | c = '\t'; |
---|
822 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
823 | rtems_test_assert(n == 1); |
---|
824 | rtems_test_assert(dev->tty->column == 8); |
---|
825 | flush_output(ctx, i); |
---|
826 | rtems_test_assert(dev->output_count == 3); |
---|
827 | rtems_test_assert(dev->output_buf[2] == '\t'); |
---|
828 | |
---|
829 | c = '\b'; |
---|
830 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
831 | rtems_test_assert(n == 1); |
---|
832 | rtems_test_assert(dev->tty->column == 7); |
---|
833 | flush_output(ctx, i); |
---|
834 | rtems_test_assert(dev->output_count == 4); |
---|
835 | rtems_test_assert(dev->output_buf[3] == '\b'); |
---|
836 | |
---|
837 | c = '\r'; |
---|
838 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
839 | rtems_test_assert(n == 1); |
---|
840 | rtems_test_assert(dev->tty->column == 0); |
---|
841 | flush_output(ctx, i); |
---|
842 | rtems_test_assert(dev->output_count == 5); |
---|
843 | rtems_test_assert(dev->output_buf[4] == '\r'); |
---|
844 | |
---|
845 | clear_set_oflag(ctx, i, oflags, 0); |
---|
846 | } |
---|
847 | } |
---|
848 | |
---|
849 | static void test_xtabs(test_context *ctx) |
---|
850 | { |
---|
851 | tcflag_t oflags = OPOST | XTABS; |
---|
852 | size_t i; |
---|
853 | |
---|
854 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
855 | device_context *dev = &ctx->devices[i]; |
---|
856 | char c; |
---|
857 | ssize_t n; |
---|
858 | |
---|
859 | dev->tty->column = 0; |
---|
860 | clear_output(ctx, i); |
---|
861 | |
---|
862 | clear_set_oflag(ctx, i, 0, oflags); |
---|
863 | |
---|
864 | c = 'a'; |
---|
865 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
866 | rtems_test_assert(n == 1); |
---|
867 | rtems_test_assert(dev->tty->column == 1); |
---|
868 | flush_output(ctx, i); |
---|
869 | rtems_test_assert(dev->output_count == 1); |
---|
870 | rtems_test_assert(dev->output_buf[0] == 'a'); |
---|
871 | |
---|
872 | c = '\t'; |
---|
873 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
874 | rtems_test_assert(n == 1); |
---|
875 | rtems_test_assert(dev->tty->column == 8); |
---|
876 | flush_output(ctx, i); |
---|
877 | rtems_test_assert(dev->output_count == 8); |
---|
878 | rtems_test_assert(dev->output_buf[1] == ' '); |
---|
879 | rtems_test_assert(dev->output_buf[2] == ' '); |
---|
880 | rtems_test_assert(dev->output_buf[3] == ' '); |
---|
881 | rtems_test_assert(dev->output_buf[4] == ' '); |
---|
882 | rtems_test_assert(dev->output_buf[5] == ' '); |
---|
883 | rtems_test_assert(dev->output_buf[6] == ' '); |
---|
884 | rtems_test_assert(dev->output_buf[7] == ' '); |
---|
885 | |
---|
886 | clear_set_oflag(ctx, i, oflags, 0); |
---|
887 | } |
---|
888 | } |
---|
889 | |
---|
890 | static void test_olcuc(test_context *ctx) |
---|
891 | { |
---|
892 | tcflag_t oflags = OPOST | OLCUC; |
---|
893 | size_t i; |
---|
894 | |
---|
895 | for (i = 0; i < DEVICE_COUNT; ++i) { |
---|
896 | device_context *dev = &ctx->devices[i]; |
---|
897 | char c; |
---|
898 | ssize_t n; |
---|
899 | |
---|
900 | dev->tty->column = 0; |
---|
901 | clear_output(ctx, i); |
---|
902 | |
---|
903 | clear_set_oflag(ctx, i, 0, oflags); |
---|
904 | |
---|
905 | c = 'a'; |
---|
906 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
907 | rtems_test_assert(n == 1); |
---|
908 | rtems_test_assert(dev->tty->column == 1); |
---|
909 | flush_output(ctx, i); |
---|
910 | rtems_test_assert(dev->output_count == 1); |
---|
911 | rtems_test_assert(dev->output_buf[0] == 'A'); |
---|
912 | |
---|
913 | c = 'B'; |
---|
914 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
915 | rtems_test_assert(n == 1); |
---|
916 | rtems_test_assert(dev->tty->column == 2); |
---|
917 | flush_output(ctx, i); |
---|
918 | rtems_test_assert(dev->output_count == 2); |
---|
919 | rtems_test_assert(dev->output_buf[1] == 'B'); |
---|
920 | |
---|
921 | c = '9'; |
---|
922 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
923 | rtems_test_assert(n == 1); |
---|
924 | rtems_test_assert(dev->tty->column == 3); |
---|
925 | flush_output(ctx, i); |
---|
926 | rtems_test_assert(dev->output_count == 3); |
---|
927 | rtems_test_assert(dev->output_buf[2] == '9'); |
---|
928 | |
---|
929 | clear_set_oflag(ctx, i, oflags, 0); |
---|
930 | } |
---|
931 | } |
---|
932 | |
---|
933 | static void |
---|
934 | set_self_prio(rtems_task_priority prio) |
---|
935 | { |
---|
936 | rtems_status_code sc; |
---|
937 | |
---|
938 | sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio); |
---|
939 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
940 | } |
---|
941 | |
---|
942 | static void flush_task(rtems_task_argument arg) |
---|
943 | { |
---|
944 | test_context *ctx = (test_context *) arg; |
---|
945 | |
---|
946 | while (true) { |
---|
947 | set_self_prio(1); |
---|
948 | flush_output(ctx, INTERRUPT); |
---|
949 | set_self_prio(2); |
---|
950 | } |
---|
951 | } |
---|
952 | |
---|
953 | static void test_write(test_context *ctx) |
---|
954 | { |
---|
955 | tcflag_t oflags = OPOST | ONLCR | XTABS; |
---|
956 | rtems_status_code sc; |
---|
957 | size_t i = INTERRUPT; |
---|
958 | device_context *dev = &ctx->devices[i]; |
---|
959 | char buf[OUTPUT_BUFFER_SIZE]; |
---|
960 | ssize_t n; |
---|
961 | |
---|
962 | ctx->context_switch_counter = 0; |
---|
963 | |
---|
964 | sc = rtems_task_create( |
---|
965 | rtems_build_name('F', 'L', 'S', 'H'), |
---|
966 | 2, |
---|
967 | RTEMS_MINIMUM_STACK_SIZE, |
---|
968 | RTEMS_DEFAULT_MODES, |
---|
969 | RTEMS_DEFAULT_ATTRIBUTES, |
---|
970 | &ctx->flush_task_id |
---|
971 | ); |
---|
972 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
973 | |
---|
974 | sc = rtems_task_start( |
---|
975 | ctx->flush_task_id, |
---|
976 | flush_task, |
---|
977 | (rtems_task_argument) ctx |
---|
978 | ); |
---|
979 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
980 | |
---|
981 | clear_output(ctx, i); |
---|
982 | memset(buf, 'a', OUTPUT_BUFFER_SIZE); |
---|
983 | |
---|
984 | n = write(ctx->fds[i], &buf[0], OUTPUT_BUFFER_SIZE); |
---|
985 | rtems_test_assert(n == OUTPUT_BUFFER_SIZE - 1); |
---|
986 | |
---|
987 | rtems_test_assert(ctx->context_switch_counter == 0); |
---|
988 | |
---|
989 | enable_non_blocking(ctx, i, true); |
---|
990 | n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 1], 1); |
---|
991 | rtems_test_assert(n == 0); |
---|
992 | |
---|
993 | enable_non_blocking(ctx, i, false); |
---|
994 | n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 1], 1); |
---|
995 | rtems_test_assert(n == 1); |
---|
996 | |
---|
997 | rtems_test_assert(ctx->context_switch_counter == 2); |
---|
998 | rtems_test_assert(dev->output_count == OUTPUT_BUFFER_SIZE); |
---|
999 | rtems_test_assert(memcmp(dev->output_buf, buf, OUTPUT_BUFFER_SIZE) == 0); |
---|
1000 | |
---|
1001 | clear_set_oflag(ctx, i, 0, oflags); |
---|
1002 | |
---|
1003 | /* Ensure that ONLCR output expansion is taken into account */ |
---|
1004 | |
---|
1005 | dev->tty->column = 0; |
---|
1006 | clear_output(ctx, i); |
---|
1007 | memset(buf, 'b', OUTPUT_BUFFER_SIZE - 1); |
---|
1008 | buf[OUTPUT_BUFFER_SIZE - 2] = '\n'; |
---|
1009 | |
---|
1010 | n = write(ctx->fds[i], &buf[0], OUTPUT_BUFFER_SIZE - 3); |
---|
1011 | rtems_test_assert(n == OUTPUT_BUFFER_SIZE - 3); |
---|
1012 | |
---|
1013 | rtems_test_assert(ctx->context_switch_counter == 2); |
---|
1014 | |
---|
1015 | n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 3], 2); |
---|
1016 | rtems_test_assert(n == 1); |
---|
1017 | |
---|
1018 | rtems_test_assert(ctx->context_switch_counter == 2); |
---|
1019 | |
---|
1020 | enable_non_blocking(ctx, i, true); |
---|
1021 | n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 2], 1); |
---|
1022 | rtems_test_assert(n == 0); |
---|
1023 | |
---|
1024 | enable_non_blocking(ctx, i, false); |
---|
1025 | n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 2], 1); |
---|
1026 | rtems_test_assert(n == 1); |
---|
1027 | |
---|
1028 | rtems_test_assert(ctx->context_switch_counter == 4); |
---|
1029 | rtems_test_assert(dev->output_count == OUTPUT_BUFFER_SIZE); |
---|
1030 | buf[OUTPUT_BUFFER_SIZE - 2] = '\r'; |
---|
1031 | buf[OUTPUT_BUFFER_SIZE - 1] = '\n'; |
---|
1032 | rtems_test_assert(memcmp(dev->output_buf, buf, OUTPUT_BUFFER_SIZE) == 0); |
---|
1033 | |
---|
1034 | /* Ensure that XTABS output expansion is taken into account */ |
---|
1035 | |
---|
1036 | dev->tty->column = 0; |
---|
1037 | clear_output(ctx, i); |
---|
1038 | memset(buf, 'c', OUTPUT_BUFFER_SIZE - 8); |
---|
1039 | buf[OUTPUT_BUFFER_SIZE - 8] = '\t'; |
---|
1040 | |
---|
1041 | n = write(ctx->fds[i], &buf[0], OUTPUT_BUFFER_SIZE - 9); |
---|
1042 | rtems_test_assert(n == OUTPUT_BUFFER_SIZE - 9); |
---|
1043 | |
---|
1044 | rtems_test_assert(ctx->context_switch_counter == 4); |
---|
1045 | |
---|
1046 | n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 9], 2); |
---|
1047 | rtems_test_assert(n == 1); |
---|
1048 | |
---|
1049 | rtems_test_assert(ctx->context_switch_counter == 4); |
---|
1050 | |
---|
1051 | enable_non_blocking(ctx, i, true); |
---|
1052 | n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 8], 1); |
---|
1053 | rtems_test_assert(n == 0); |
---|
1054 | |
---|
1055 | enable_non_blocking(ctx, i, false); |
---|
1056 | n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 8], 1); |
---|
1057 | rtems_test_assert(n == 1); |
---|
1058 | |
---|
1059 | rtems_test_assert(ctx->context_switch_counter == 6); |
---|
1060 | rtems_test_assert(dev->output_count == OUTPUT_BUFFER_SIZE); |
---|
1061 | memset(&buf[OUTPUT_BUFFER_SIZE - 8], ' ', 8); |
---|
1062 | rtems_test_assert(memcmp(dev->output_buf, buf, OUTPUT_BUFFER_SIZE) == 0); |
---|
1063 | |
---|
1064 | clear_set_oflag(ctx, i, oflags, 0); |
---|
1065 | |
---|
1066 | sc = rtems_task_delete(ctx->flush_task_id); |
---|
1067 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
1068 | } |
---|
1069 | |
---|
1070 | static void test_tx_callback(test_context *ctx) |
---|
1071 | { |
---|
1072 | size_t i = INTERRUPT; |
---|
1073 | device_context *dev = &ctx->devices[i]; |
---|
1074 | char c; |
---|
1075 | ssize_t n; |
---|
1076 | |
---|
1077 | clear_output(ctx, i); |
---|
1078 | dev->callback_counter = 0; |
---|
1079 | dev->tty->tty_snd.sw_pfn = callback; |
---|
1080 | dev->tty->tty_snd.sw_arg = dev; |
---|
1081 | |
---|
1082 | c = 'a'; |
---|
1083 | n = write(ctx->fds[i], &c, sizeof(c)); |
---|
1084 | rtems_test_assert(n == 1); |
---|
1085 | rtems_test_assert(dev->callback_counter == 0); |
---|
1086 | flush_output(ctx, i); |
---|
1087 | rtems_test_assert(dev->callback_counter == 1); |
---|
1088 | rtems_test_assert(dev->output_count == 1); |
---|
1089 | rtems_test_assert(dev->output_buf[0] == 'a'); |
---|
1090 | |
---|
1091 | dev->tty->tty_snd.sw_pfn = NULL; |
---|
1092 | dev->tty->tty_snd.sw_arg = NULL; |
---|
1093 | } |
---|
1094 | |
---|
1095 | static void Init(rtems_task_argument arg) |
---|
1096 | { |
---|
1097 | test_context *ctx = &test_instance; |
---|
1098 | |
---|
1099 | TEST_BEGIN(); |
---|
1100 | |
---|
1101 | setup(ctx); |
---|
1102 | test_igncr(ctx); |
---|
1103 | test_istrip(ctx); |
---|
1104 | test_iuclc(ctx); |
---|
1105 | test_icrnl(ctx); |
---|
1106 | test_inlcr(ctx); |
---|
1107 | test_rx_callback(ctx); |
---|
1108 | test_rx_callback_icanon(ctx); |
---|
1109 | test_onlret(ctx); |
---|
1110 | test_onlcr(ctx); |
---|
1111 | test_onocr(ctx); |
---|
1112 | test_ocrnl(ctx); |
---|
1113 | test_ocrnl_onlret(ctx); |
---|
1114 | test_opost(ctx); |
---|
1115 | test_xtabs(ctx); |
---|
1116 | test_olcuc(ctx); |
---|
1117 | test_write(ctx); |
---|
1118 | test_tx_callback(ctx); |
---|
1119 | |
---|
1120 | TEST_END(); |
---|
1121 | rtems_test_exit(0); |
---|
1122 | } |
---|
1123 | |
---|
1124 | static void switch_extension(Thread_Control *executing, Thread_Control *heir) |
---|
1125 | { |
---|
1126 | test_context *ctx = &test_instance; |
---|
1127 | |
---|
1128 | ++ctx->context_switch_counter; |
---|
1129 | } |
---|
1130 | |
---|
1131 | #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER |
---|
1132 | #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER |
---|
1133 | |
---|
1134 | #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 5 |
---|
1135 | |
---|
1136 | #define CONFIGURE_MAXIMUM_TASKS 2 |
---|
1137 | |
---|
1138 | #define CONFIGURE_MAXIMUM_SEMAPHORES 7 |
---|
1139 | |
---|
1140 | #define CONFIGURE_INITIAL_EXTENSIONS \ |
---|
1141 | { .thread_switch = switch_extension }, \ |
---|
1142 | RTEMS_TEST_INITIAL_EXTENSION |
---|
1143 | |
---|
1144 | #define CONFIGURE_RTEMS_INIT_TASKS_TABLE |
---|
1145 | |
---|
1146 | #define CONFIGURE_INIT |
---|
1147 | |
---|
1148 | #include <rtems/confdefs.h> |
---|