summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/libcsupport/src/termios.c25
-rw-r--r--testsuites/libtests/Makefile.am1
-rw-r--r--testsuites/libtests/configure.ac1
-rw-r--r--testsuites/libtests/termios09/Makefile.am19
-rw-r--r--testsuites/libtests/termios09/init.c269
-rw-r--r--testsuites/libtests/termios09/termios09.doc11
-rw-r--r--testsuites/libtests/termios09/termios09.scn2
7 files changed, 322 insertions, 6 deletions
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index f88494f15d..c1d6cd5297 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -1295,12 +1295,11 @@ iproc (unsigned char c, struct rtems_termios_tty *tty)
c = tolower (c);
if (c == '\r') {
- if (tty->termios.c_iflag & IGNCR)
- return 0;
if (tty->termios.c_iflag & ICRNL)
c = '\n';
- } else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
- c = '\r';
+ } else if (c == '\n') {
+ if (tty->termios.c_iflag & INLCR)
+ c = '\r';
}
if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
@@ -1366,6 +1365,16 @@ siproc (unsigned char c, struct rtems_termios_tty *tty)
return i;
}
+static int
+siprocPoll (unsigned char c, rtems_termios_tty *tty)
+{
+ if (c == '\r' && (tty->termios.c_iflag & IGNCR) != 0) {
+ return 0;
+ }
+
+ return siproc (c, tty);
+}
+
/*
* Fill the input buffer by polling the device
*/
@@ -1380,7 +1389,7 @@ fillBufferPoll (struct rtems_termios_tty *tty)
if (n < 0) {
rtems_task_wake_after (1);
} else {
- if (siproc (n, tty))
+ if (siprocPoll (n, tty))
break;
}
}
@@ -1408,7 +1417,7 @@ fillBufferPoll (struct rtems_termios_tty *tty)
}
rtems_task_wake_after (1);
} else {
- siproc (n, tty);
+ siprocPoll (n, tty);
if (tty->ccount >= tty->termios.c_cc[VMIN])
break;
if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
@@ -1637,6 +1646,10 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len)
unsigned int oldTail;
unsigned int newTail;
+ if (c == '\r' && (tty->termios.c_iflag & IGNCR) != 0) {
+ continue;
+ }
+
rtems_termios_device_lock_acquire (ctx, &lock_context);
head = tty->rawInBuf.Head;
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index 9ff4394f9e..286875d143 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -1,6 +1,7 @@
ACLOCAL_AMFLAGS = -I ../aclocal
_SUBDIRS = POSIX
+_SUBDIRS += termios09
_SUBDIRS += libfdt01
_SUBDIRS += defaultconfig01
_SUBDIRS += pwdgrp02
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index 8e74b3e979..4e82caff18 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -172,6 +172,7 @@ termios05/Makefile
termios06/Makefile
termios07/Makefile
termios08/Makefile
+termios09/Makefile
top/Makefile
tztest/Makefile
capture01/Makefile
diff --git a/testsuites/libtests/termios09/Makefile.am b/testsuites/libtests/termios09/Makefile.am
new file mode 100644
index 0000000000..18714de490
--- /dev/null
+++ b/testsuites/libtests/termios09/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = termios09
+termios09_SOURCES = init.c
+
+dist_rtems_tests_DATA = termios09.scn termios09.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(termios09_OBJECTS)
+LINK_LIBS = $(termios09_LDLIBS)
+
+termios09$(EXEEXT): $(termios09_OBJECTS) $(termios09_DEPENDENCIES)
+ @rm -f termios09$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/libtests/termios09/init.c b/testsuites/libtests/termios09/init.c
new file mode 100644
index 0000000000..6e651bfafa
--- /dev/null
+++ b/testsuites/libtests/termios09/init.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2017 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <rtems/termiostypes.h>
+
+#include "tmacros.h"
+
+const char rtems_test_name[] = "TERMIOS 9";
+
+#define INTERRUPT 0
+
+#define POLLED 1
+
+#define DEVICE_COUNT 2
+
+#define OUTPUT_BUFFER_SIZE 64
+
+static const char * const paths[DEVICE_COUNT] = {
+ "/interrupt",
+ "/polled"
+};
+
+typedef struct {
+ rtems_termios_device_context base;
+ rtems_termios_tty *tty;
+ size_t output_pending;
+ size_t output_count;
+ char output_buf[OUTPUT_BUFFER_SIZE];
+ int input_char;
+} device_context;
+
+typedef struct {
+ device_context devices[DEVICE_COUNT];
+ int fds[DEVICE_COUNT];
+ struct termios term[DEVICE_COUNT];
+} test_context;
+
+static test_context test_instance = {
+ .devices = {
+ {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("Interrupt")
+ }, {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("Polled"),
+ .input_char = -1
+ }
+ }
+};
+
+static bool first_open(
+ rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
+ rtems_libio_open_close_args_t *args
+)
+{
+ device_context *dev = (device_context *) base;
+
+ dev->tty = tty;
+
+ return true;
+}
+
+static void write_polled(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+)
+{
+ device_context *dev = (device_context *) base;
+
+ rtems_test_assert(dev->output_count + len <= OUTPUT_BUFFER_SIZE);
+ memcpy(&dev->output_buf[dev->output_count], buf, len);
+ dev->output_count += len;
+}
+
+static void write_interrupt(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+)
+{
+ device_context *dev = (device_context *) base;
+
+ write_polled(base, buf, len);
+ dev->output_pending = len;
+}
+
+static int read_polled(rtems_termios_device_context *base)
+{
+ device_context *dev = (device_context *) base;
+ int c = dev->input_char;
+
+ dev->input_char = -1;
+
+ return c;
+}
+
+static const rtems_termios_device_handler handlers[DEVICE_COUNT] = {
+ {
+ .first_open = first_open,
+ .write = write_interrupt,
+ .mode = TERMIOS_IRQ_DRIVEN
+ }, {
+ .first_open = first_open,
+ .write = write_polled,
+ .poll_read = read_polled,
+ .mode = TERMIOS_POLLED
+ }
+};
+
+static void set_term(test_context *ctx, size_t i)
+{
+ int rv;
+
+ rv = tcsetattr(ctx->fds[i], TCSANOW, &ctx->term[i]);
+ rtems_test_assert(rv == 0);
+}
+
+static void init_term(test_context *ctx, size_t i)
+{
+ int rv;
+
+ rv = tcgetattr(ctx->fds[i], &ctx->term[i]);
+ rtems_test_assert(rv == 0);
+
+ ctx->term[i].c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
+ | INLCR | IGNCR | ICRNL | IXON);
+ ctx->term[i].c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ ctx->term[i].c_cflag &= ~(CSIZE | PARENB);
+ ctx->term[i].c_cflag |= CS8;
+ ctx->term[i].c_oflag &= ~(OPOST | ONLRET | ONLCR | OCRNL | ONLRET
+ | TABDLY | OLCUC);
+
+ ctx->term[i].c_cc[VMIN] = 0;
+ ctx->term[i].c_cc[VTIME] = 0;
+
+ set_term(ctx, i);
+}
+
+static void setup(test_context *ctx)
+{
+ rtems_status_code sc;
+ size_t i;
+
+ rtems_termios_initialize();
+
+ for (i = 0; i < DEVICE_COUNT; ++i) {
+ sc = rtems_termios_device_install(
+ paths[i],
+ &handlers[i],
+ NULL,
+ &ctx->devices[i].base
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ ctx->fds[i] = open(paths[i], O_RDWR);
+ rtems_test_assert(ctx->fds[i] >= 0);
+
+ init_term(ctx, i);
+ }
+}
+
+static void input(test_context *ctx, size_t i, char c)
+{
+ switch (i) {
+ case INTERRUPT:
+ rtems_termios_enqueue_raw_characters(ctx->devices[i].tty, &c, sizeof(c));
+ break;
+ case POLLED:
+ ctx->devices[i].input_char = (unsigned char) c;
+ break;
+ default:
+ rtems_test_assert(0);
+ }
+}
+
+static void clear_set_iflag(
+ test_context *ctx,
+ size_t i,
+ tcflag_t clear,
+ tcflag_t set
+)
+{
+ ctx->term[i].c_iflag &= ~clear;
+ ctx->term[i].c_iflag |= set;
+ set_term(ctx, i);
+}
+
+static void test_igncr(test_context *ctx)
+{
+ size_t i;
+
+ for (i = 0; i < DEVICE_COUNT; ++i) {
+ ssize_t n;
+ char c;
+
+ c = 'x';
+
+ clear_set_iflag(ctx, i, 0, IGNCR);
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 0);
+ rtems_test_assert(c == 'x');
+
+ input(ctx, i, '\r');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 0);
+ rtems_test_assert(c == 'x');
+
+ clear_set_iflag(ctx, i, IGNCR, 0);
+ input(ctx, i, '\r');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 1);
+ rtems_test_assert(c == '\r');
+ }
+}
+
+static void Init(rtems_task_argument arg)
+{
+ test_context *ctx = &test_instance;
+
+ TEST_BEGIN();
+
+ setup(ctx);
+ test_igncr(ctx);
+
+ TEST_END();
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 5
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_MAXIMUM_SEMAPHORES 7
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/libtests/termios09/termios09.doc b/testsuites/libtests/termios09/termios09.doc
new file mode 100644
index 0000000000..d2c0be4336
--- /dev/null
+++ b/testsuites/libtests/termios09/termios09.doc
@@ -0,0 +1,11 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: termios09
+
+directives:
+
+ - Termios
+
+concepts:
+
+ - Ensure that carriage return characters are ignored if desired (IGNCR).
diff --git a/testsuites/libtests/termios09/termios09.scn b/testsuites/libtests/termios09/termios09.scn
new file mode 100644
index 0000000000..5e0d17d757
--- /dev/null
+++ b/testsuites/libtests/termios09/termios09.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST TERMIOS 9 ***
+*** END OF TEST TERMIOS 9 ***