summaryrefslogtreecommitdiffstats
path: root/testsuite/termios
diff options
context:
space:
mode:
authorKevin Kirspel <kevin-kirspel@idexx.com>2017-05-04 08:28:00 -0400
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-05-11 11:15:41 +0200
commit333bfb618bf21fc3f7cca7411acf0f42fcdc4b57 (patch)
treeed0321198cee02ab0365c28726297bab8a2862ce /testsuite/termios
parentAdding RTEMS support for FREEBSD TTY (diff)
downloadrtems-libbsd-333bfb618bf21fc3f7cca7411acf0f42fcdc4b57.tar.bz2
Adding test cases for FREEBSD termios support through tty
Diffstat (limited to 'testsuite/termios')
-rw-r--r--testsuite/termios/test_main.c856
-rw-r--r--testsuite/termios/test_termios_driver.c136
-rw-r--r--testsuite/termios/test_termios_driver.h32
-rw-r--r--testsuite/termios/test_termios_utilities.c233
-rw-r--r--testsuite/termios/test_termios_utilities.h33
5 files changed, 1290 insertions, 0 deletions
diff --git a/testsuite/termios/test_main.c b/testsuite/termios/test_main.c
new file mode 100644
index 00000000..90e33826
--- /dev/null
+++ b/testsuite/termios/test_main.c
@@ -0,0 +1,856 @@
+/*
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems/console.h>
+#include <rtems/shell.h>
+#include <rtems/bsd/bsd.h>
+
+#include <termios.h>
+
+#include "test_termios_driver.h"
+
+#define TEST_NAME "LIBBSD TERMIOS"
+
+/* forward declarations to avoid warnings */
+void print_32bits(unsigned long bits, unsigned char size, char * names[]);
+void print_c_iflag(struct termios * tp);
+void print_c_oflag(struct termios * tp);
+void print_c_lflag(struct termios * tp);
+void print_c_cflag(struct termios * tp);
+void print_c_cc(struct termios * tp);
+void print_baud(const char* name, speed_t spd);
+void print_termios(struct termios *tp);
+unsigned long get_baud_rate(void);
+unsigned long get_parity(void);
+unsigned long get_stop_bits(void);
+unsigned long get_data_bits(void);
+void change_line_settings(struct termios *tp);
+void canonical_input(struct termios *tp);
+void do_raw_input(int vmin, int vtime);
+void usage(void);
+
+#if !defined(fileno)
+int fileno( FILE *stream); /* beyond ANSI */
+#endif
+
+/* Some of the termios dumping code depends on bit positions! */
+
+void print_32bits( unsigned long bits, unsigned char size, char * names[] )
+{
+ unsigned char i;
+
+ for( i = 0; i < size; i++ ) {
+ if( (bits >> i) & 0x1 )
+ printf( "%s ", names[i] );
+ }
+}
+
+
+void print_c_iflag( struct termios * tp )
+{
+ char * c_iflag_bits [] = {
+ "IGNBRK", /* 0000001 */
+ "BRKINT", /* 0000002 */
+ "IGNPAR", /* 0000004 */
+ "PARMRK", /* 0000010 */
+ "INPCK", /* 0000020 */
+ "ISTRIP", /* 0000040 */
+ "INLCR", /* 0000100 */
+ "IGNCR", /* 0000200 */
+ "ICRNL", /* 0000400 */
+ "IUCLC", /* 0001000 */
+ "IXON", /* 0002000 */
+ "IXANY", /* 0004000 */
+ "IXOFF", /* 0010000 */
+ "IMAXBEL", /* 0020000 */
+ "unknown", /* 0040000 */
+ "unknown", /* 0100000 */
+ "unknown", /* 0200000 */
+ "unknown", /* 0400000 */
+ "unknown", /* 1000000 */
+ "unknown", /* 2000000 */
+ "unknown" /* 4000000 */
+ };
+
+ printf( "c_iflag = 0x%08x\n\t", tp->c_iflag );
+ print_32bits( tp->c_iflag, sizeof( c_iflag_bits )/sizeof( char * ), c_iflag_bits );
+ printf( "\n" );
+}
+
+
+void print_c_oflag( struct termios * tp )
+{
+ printf( "c_oflag = 0x%08x\n\t", tp->c_oflag );
+
+ if( tp->c_oflag & OPOST )
+ printf( "OPOST " );
+
+ if( tp->c_oflag & OLCUC )
+ printf( "OLCUC " );
+
+ if( tp->c_oflag & ONLCR )
+ printf( "ONLCR " );
+
+ if( tp->c_oflag & ONOEOT )
+ printf( "ONOEOT " );
+
+ if( tp->c_oflag & OCRNL )
+ printf( "OCRNL " );
+
+ if( tp->c_oflag & ONOCR )
+ printf( "ONOCR " );
+
+ if( tp->c_oflag & ONLRET )
+ printf( "ONLRET " );
+
+ if( tp->c_oflag & OFILL )
+ printf( "OFILL " );
+
+ if( tp->c_oflag & OFDEL )
+ printf( "OFDEL " );
+
+ switch( tp->c_oflag & NLDLY ) {
+ case NL0:
+ printf( "NL0 " );
+ break;
+
+ case NL1:
+ printf( "NL1 " );
+ break;
+ }
+
+ switch( tp->c_oflag & CRDLY ) {
+ case CR0:
+ printf( "CR0 " );
+ break;
+
+ case CR1:
+ printf( "CR1 " );
+ break;
+
+ case CR2:
+ printf( "CR2 " );
+ break;
+
+ case CR3:
+ printf( "CR3 " );
+ break;
+ }
+
+ switch( tp->c_oflag & TABDLY ) {
+ case TAB0:
+ printf( "TAB0 " );
+ break;
+
+ case TAB1:
+ printf( "TAB1 " );
+ break;
+
+ case TAB2:
+ printf( "TAB2 " );
+ break;
+
+ case TAB3:
+ printf( "TAB3 " );
+ break;
+ }
+
+ switch( tp->c_oflag & BSDLY ) {
+ case BS0:
+ printf( "BS0 " );
+ break;
+
+ case BS1:
+ printf( "BS1 " );
+ break;
+ }
+
+ switch( tp->c_oflag & VTDLY ) {
+ case VT0:
+ printf( "VT0 " );
+ break;
+
+ case VT1:
+ printf( "VT1 " );
+ break;
+ }
+
+ switch( tp->c_oflag & FFDLY ) {
+ case FF0:
+ printf( "FF0" );
+ break;
+
+ case FF1:
+ printf( "FF1" );
+ break;
+ }
+ printf( "\n" );
+}
+
+
+void print_c_lflag( struct termios * tp )
+{
+ char * c_lflag_bits [] = {
+ "ECHOKE", /* 0x00000001 */
+ "ECHOE", /* 0x00000002 */
+ "ECHOK", /* 0x00000004 */
+ "ECHO", /* 0x00000008 */
+ "ECHONL", /* 0x00000010 */
+ "ECHOPRT", /* 0x00000020 */
+ "ECHOCTL", /* 0x00000040 */
+ "ISIG", /* 0x00000080 */
+ "ICANON", /* 0x00000100 */
+ "ALTWERASE", /* 0x00000200 */
+ "IEXTEN", /* 0x00000400 */
+ "EXTPROC", /* 0x00000800 */
+ "XCASE", /* 0x00001000 */
+ "unknown", /* 0x00002000 */
+ "unknown", /* 0x00004000 */
+ "unknown", /* 0x00008000 */
+ "unknown", /* 0x00010000 */
+ "unknown", /* 0x00020000 */
+ "unknown", /* 0x00040000 */
+ "unknown", /* 0x00080000 */
+ "unknown", /* 0x00100000 */
+ "unknown", /* 0x00200000 */
+ "TOSTOP", /* 0x00400000 */
+ "FLUSHO", /* 0x00800000 */
+ "unknown", /* 0x01000000 */
+ "NOKERNINFO", /* 0x02000000 */
+ "unknown", /* 0x04000000 */
+ "unknown", /* 0x08000000 */
+ "unknown", /* 0x10000000 */
+ "PENDIN", /* 0x20000000 */
+ "unknown", /* 0x40000000 */
+ "NOFLSH", /* 0x80000000 */
+ };
+
+ printf( "c_lflag = 0x%08x\n\t", tp->c_lflag );
+ print_32bits( tp->c_lflag, sizeof( c_lflag_bits )/sizeof( char * ), c_lflag_bits );
+ printf( "\n" );
+}
+
+
+void print_c_cflag( struct termios * tp )
+{
+ printf( "c_cflag = 0x%08x\n", tp->c_cflag );
+
+ switch( tp->c_cflag & CSIZE ) {
+ case CS5:
+ printf( "\tCSIZE =\tCS5\n" );
+ break;
+
+ case CS6:
+ printf( "\tCSIZE =\tCS6\n" );
+ break;
+
+ case CS7:
+ printf( "\tCSIZE =\tCS7\n" );
+ break;
+
+ case CS8:
+ printf( "\tCSIZE =\tCS8\n" );
+ break;
+ }
+
+ if( tp->c_cflag & CIGNORE )
+ printf( "\tCIGNORE set: iqnore c_cflags enabled\n" );
+ else
+ printf( "\tCIGNORE clear: iqnore c_cflags disabled\n" );
+
+ if( tp->c_cflag & CSTOPB )
+ printf( "\tCSTOPB set: send 2 stop bits\n" );
+ else
+ printf( "\tCSTOPB clear: send 1 stop bit\n" );
+
+ if( tp->c_cflag & PARENB )
+ printf( "\tPARENB set: parity enabled\n" );
+ else
+ printf( "\tPARENB clear: parity disabled\n" );
+
+ if( tp->c_cflag & PARODD )
+ printf( "\tPARODD set: parity odd\n" );
+ else
+ printf( "\tPARODD clear: parity even\n" );
+
+ if( tp->c_cflag & CREAD )
+ printf( "\tCREAD set: receiver enabled\n" );
+ else
+ printf( "\tCREAD clear: treceiver disabled\n" );
+
+ if( tp->c_cflag & HUPCL )
+ printf( "\tHUPCL set: enabled\n" );
+ else
+ printf( "\tHUPCL clear: disabled\n" );
+
+ if( tp->c_cflag & CLOCAL )
+ printf( "\tCLOCAL set: ignore modem lines\n" );
+ else
+ printf( "\tCLOCAL clear: don't ignore modem lines\n" );
+
+ if( tp->c_cflag & CCTS_OFLOW )
+ printf( "\tCCTS_OFLOW: hardware CTS output flow control enabled\n" );
+ else
+ printf( "\tCCTS_OFLOW: hardware CTS output flow control disabled\n" );
+
+ if( tp->c_cflag & CRTS_IFLOW )
+ printf( "\tCRTS_IFLOW: hardware RTS input flow control enabled\n" );
+ else
+ printf( "\tCRTS_IFLOW: hardware RTS input flow control disabled\n" );
+
+ if( tp->c_cflag & CRTSCTS )
+ printf( "\tCRTSCTS: harware flow control enabled?\n" );
+ else
+ printf( "\tCRTSCTS: hardware flow control disabled?\n" );
+
+ if( tp->c_cflag & CDSR_OFLOW )
+ printf( "\tCDSR_OFLOW: hardware DSR output flow control enabled\n" );
+ else
+ printf( "\tCDSR_OFLOW: hardware DSR output flow control disabled\n" );
+
+ if( tp->c_cflag & CDTR_IFLOW )
+ printf( "\tCDTR_IFLOW: hardware DTR input flow control enabled\n" );
+ else
+ printf( "\tCDTR_IFLOW: hardware DTR input flow control disabled\n" );
+
+ if( tp->c_cflag & CCAR_OFLOW )
+ printf( "\tCCAR_OFLOW: hardware CD output flow control enabled\n" );
+ else
+ printf( "\tCCAR_OFLOW: hardware CD output flow control disabled\n" );
+}
+
+
+void print_c_cc( struct termios * tp )
+{
+ size_t i;
+ char * cc_index_names [ /* NCCS */ ] = {
+ "[VEOF] ", /* 0 */
+ "[VEOL] ", /* 1 */
+ "[VEOL2] ", /* 2 */
+ "[VERASE] ", /* 3 */
+ "[VWERASE] ", /* 4 */
+ "[VKILL] ", /* 5 */
+ "[VREPRINT]", /* 6 */
+ "[VERASE2] ", /* 7 */
+ "[VINTR] ", /* 8 */
+ "[VQUIT] ", /* 9 */
+ "[VSUSP] ", /* 10 */
+ "[VDSUSP] ", /* 11 */
+ "[VSTART] ", /* 12 */
+ "[VSTOP] ", /* 13 */
+ "[VLNEXT] ", /* 14 */
+ "[VDISCARD]", /* 15 */
+ "[VMIN] ", /* 16 */
+ "[VTIME] ", /* 17 */
+ "[VSTATUS] ", /* 18 */
+ "unknown ", /* 19 */
+ };
+
+ for( i = 0; i < sizeof(cc_index_names)/sizeof(char*) ; i++ ) {
+ printf( "c_cc%s = 0x%08x\n", cc_index_names[i], tp->c_cc[i] );
+ }
+}
+
+
+void print_baud( const char* name, speed_t spd )
+{
+ switch( spd ) {
+ case B0:
+ printf( "%s = B0\n", name );
+ break;
+
+ case B50:
+ printf( "%s = B50\n", name );
+ break;
+
+ case B75:
+ printf( "%s = B75\n", name );
+ break;
+
+ case B110:
+ printf( "%s = B110\n", name );
+ break;
+
+ case B134:
+ printf( "%s = B134\n", name );
+ break;
+
+ case B150:
+ printf( "%s = B150\n", name );
+ break;
+
+ case B200:
+ printf( "%s = B200\n", name );
+ break;
+
+ case B300:
+ printf( "%s = B300\n", name );
+ break;
+
+ case B600:
+ printf( "%s = B600\n", name );
+ break;
+
+ case B1200:
+ printf( "%s = B1200\n", name );
+ break;
+
+ case B1800:
+ printf( "%s = B1800\n", name );
+ break;
+
+ case B2400:
+ printf( "%s = B2400\n", name );
+ break;
+
+ case B4800:
+ printf( "%s = B4800\n", name );
+ break;
+
+ case B9600:
+ printf( "%s = B9600\n", name );
+ break;
+
+ case B19200:
+ printf( "%s = B19200\n", name );
+ break;
+
+ case B38400:
+ printf( "%s = B38400\n", name );
+ break;
+
+ case B7200:
+ printf( "%s = B7200\n", name );
+ break;
+
+ case B14400:
+ printf( "%s = B14400\n", name );
+ break;
+
+ case B28800:
+ printf( "%s = B28800\n", name );
+ break;
+
+ case B57600:
+ printf( "%s = B57600\n", name );
+ break;
+
+ case B76800:
+ printf( "%s = B76800\n", name );
+ break;
+
+ case B115200:
+ printf( "%s = B115200\n", name );
+ break;
+
+ case B230400:
+ printf( "%s = B230400\n", name );
+ break;
+
+ case B460800:
+ printf( "%s = B460800\n", name );
+ break;
+
+ case B921600:
+ printf( "%s = B921600\n", name );
+ break;
+
+ default:
+ printf( "%s = unknown (0x%08x)\n", name, (unsigned int)spd );
+ break;
+ }
+}
+
+
+void print_termios( struct termios *tp )
+{
+ printf( "\nLooking at the current termios settings:\n\n" );
+ print_c_iflag( tp );
+ print_c_oflag( tp );
+ print_c_cflag( tp );
+ print_c_lflag( tp );
+ print_c_cc( tp );
+ print_baud( "c_ispeed", tp->c_ispeed );
+ print_baud( "c_ospeed", tp->c_ospeed );
+ printf( "\n" );
+}
+
+
+unsigned long get_baud_rate(void)
+{
+ unsigned long baud_rate;
+
+ while( 1 ) {
+ printf( "Enter the numerical value for the new baud rate.\n" );
+ printf( "Choices are: 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800\n" );
+ printf( "2400, 4800, 9600, 19200, 38400, 7200, 14400, 28800, 57600, 76800\n" );
+ printf( "115200, 230400, 460800, 921600\n" );
+ printf( "\nYour choice: " );
+ scanf( "%lu", &baud_rate );
+ printf( "\n" );
+ switch( baud_rate ) {
+ case 50: return B50;
+ case 75: return B75;
+ case 110: return B110;
+ case 134: return B134;
+ case 150: return B150;
+ case 200: return B200;
+ case 300: return B300;
+ case 600: return B600;
+ case 1200: return B1200;
+ case 1800: return B1800;
+ case 2400: return B2400;
+ case 4800: return B4800;
+ case 9600: return B9600;
+ case 19200: return B19200;
+ case 38400: return B38400;
+ case 7200: return B7200;
+ case 14400: return B14400;
+ case 28800: return B28800;
+ case 57600: return B57600;
+ case 76800: return B76800;
+ case 115200: return B115200;
+ case 230400: return B230400;
+ case 460800: return B460800;
+ case 921600: return B921600;
+
+ default:
+ printf( "%lu is not a valid choice. Try again.\n\n", baud_rate );
+ break;
+ }
+ }
+}
+
+
+unsigned long get_parity(void)
+{
+ int parity;
+
+ while( 1 ) {
+ printf( "Enter the numerical value for the new parity\n" );
+ printf( "Choices are: 0 for no parity, 1 for even parity, 2 for odd parity\n" );
+ printf( "\nYour choice: " );
+ scanf( "%d", &parity );
+ printf( "\n" );
+ switch( parity ) {
+ case 0:
+ return 0;
+
+ case 1:
+ return PARENB;
+
+ case 2:
+ return PARENB | PARODD;
+
+ default:
+ printf( "%d is not a valid choice. Try again.\n\n", parity );
+ break;
+ }
+ }
+}
+
+
+unsigned long get_stop_bits(void)
+{
+ int stop_bits;
+
+ while( 1 ) {
+ printf( "Enter the numerical value for the new number of stop bits\n" );
+ printf( "Choices are: 1 or 2\n" );
+ printf( "\nYour choice: " );
+ scanf( "%d", &stop_bits );
+ printf( "\n" );
+ switch( stop_bits ) {
+ case 1:
+ return 0;
+
+ case 2:
+ return CSTOPB;
+
+ default:
+ printf( "%d is not a valid choice. Try again.\n\n", stop_bits );
+ break;
+ }
+ }
+}
+
+
+unsigned long get_data_bits(void)
+{
+ int data_bits;
+
+ while( 1 ) {
+ printf( "Enter the numerical value for the new number of data bits\n" );
+ printf( "Choices are: 5, 6, 7 or 8\n" );
+ printf( "\nYour choice: " );
+ scanf( "%d", &data_bits );
+ printf( "\n" );
+ switch( data_bits ) {
+ case 5:
+ return CS5;
+
+ case 6:
+ return CS6;
+
+ case 7:
+ return CS7;
+
+ case 8:
+ return CS8;
+
+ default:
+ printf( "%d is not a valid choice. Try again.\n\n", data_bits );
+ break;
+ }
+ }
+}
+
+
+void change_line_settings( struct termios *tp )
+{
+ unsigned long baud_rate, parity, stop_bits, data_bits, sleep_time;
+
+ printf( "\nSetting line characteristics\n\n" );
+
+ baud_rate = get_baud_rate();
+ parity = get_parity();
+ stop_bits = get_stop_bits();
+ data_bits = get_data_bits();
+
+ printf( "NOTE: You will not see output until you switch your terminal settings!\n" );
+ printf( "WARNING: If you do not switch your terminal settings, your terminal may hang.\n" );
+ printf( "Enter the number of seconds the test will wait for you to switch your terminal\n" );
+ printf( "settings before it continues\n" );
+ printf( "Sleep time (in seconds): " );
+ scanf( "%lu", &sleep_time );
+ printf( "\n" );
+ printf( "Setting line to new termios settings in %lu seconds.\n", sleep_time );
+
+ sleep( sleep_time );
+
+ tp->c_cflag = CLOCAL | CREAD | parity | stop_bits | data_bits;
+ tp->c_ispeed = baud_rate;
+ tp->c_ospeed = baud_rate;
+ if( tcsetattr( fileno( stdin ), TCSADRAIN, tp ) < 0 ) {
+ perror( "change_line_settings(): tcsetattr() failed" );
+ exit( 1 );
+ }
+ printf( "Line settings set.\n" );
+}
+
+
+void canonical_input( struct termios *tp )
+{
+ char c;
+ bool first_time = true;
+
+ printf( "\nTesting canonical input\n\n" );
+
+ printf( "Setting line to canonical input mode.\n" );
+ tp->c_lflag = ISIG | ICANON | ECHO | ECHONL | ECHOK | ECHOE | ECHOPRT | ECHOCTL | IEXTEN;
+ tp->c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
+ if( tcsetattr( fileno( stdin ), TCSADRAIN, tp ) < 0 ) {
+ perror( "canonical_input(): tcsetattr() failed" );
+ exit( 1 );
+ }
+
+ while ( ( c = getchar () ) != '\n');
+ printf( "Testing getchar(). Type some text followed by carriage return\n" );
+ printf( "Each character you entered will be echoed back to you\n\n" );
+ while ( ( c = getchar () ) != '\n') {
+ if( first_time ) {
+ printf( "\nYou typed:\n");
+ first_time = false;
+ }
+ printf( "%c", c );
+ }
+ printf( "\n\nCanonical input test done.\n" );
+}
+
+
+/*
+ * Test raw (ICANON=0) input
+ */
+void do_raw_input( int vmin, int vtime )
+{
+ int i;
+ struct termios old, new;
+ rtems_interval ticksPerSecond, then, now;
+ unsigned int msec;
+ unsigned long count;
+ int nread;
+ unsigned char cbuf[100];
+
+ printf( "Raw input test with VMIN=%d VTIME=%d\n", vmin, vtime );
+
+ ticksPerSecond = rtems_clock_get_ticks_per_second();
+ if ( tcgetattr( fileno ( stdin ), &old ) < 0 ) {
+ perror( "do_raw_input(): tcgetattr() failed" );
+ return;
+ }
+
+ new = old;
+ new.c_lflag &= ~( ICANON | ECHO | ECHONL | ECHOK | ECHOE | ECHOPRT | ECHOCTL );
+ new.c_cc[VMIN] = vmin;
+ new.c_cc[VTIME] = vtime;
+ if( tcsetattr( fileno( stdin ), TCSADRAIN, &new ) < 0 ) {
+ perror ("do_raw_input(): tcsetattr() failed" );
+ return;
+ }
+
+ do {
+ then = rtems_clock_get_ticks_since_boot();
+ count = 0;
+ for(;;) {
+ nread = read( fileno( stdin ), cbuf, sizeof cbuf );
+ if( nread < 0 ) {
+ perror( "do_raw_input(): read() failed" );
+ goto out;
+ }
+ count++;
+ if( nread != 0 )
+ break;
+ }
+ now = rtems_clock_get_ticks_since_boot();
+ msec = (now - then) * 1000 / ticksPerSecond;
+ printf( "Count:%-10lu Interval:%3u.%3.3d Char:",
+ count, msec / 1000, msec % 1000 );
+
+ for( i = 0 ; i < nread ; i++ )
+ printf (" 0x%2.2x", cbuf[i]);
+ printf ("\n");
+
+ } while( cbuf[0] != 'q' );
+
+out:
+ if( tcsetattr( fileno( stdin ), TCSADRAIN, &old) < 0 )
+ perror("do_raw_input(): tcsetattr() failed: %s\n" );
+}
+
+
+static void raw_input( struct termios *tp )
+{
+ printf( "\nTesting raw input input\n\n" );
+ printf( "Hit 'q' to terminate the test\n" );
+
+ do_raw_input( 0, 0 );
+ do_raw_input( 0, 20 );
+ do_raw_input( 5, 0 );
+ do_raw_input( 5, 20 );
+
+ printf( "\nRaw input test done.\n" );
+}
+
+
+void usage( void )
+{
+ printf( "\nYou have the following choices:\n" );
+ printf( " 1 - Reset the struct termios\n" );
+ printf( " 2 - Look at the current termios setting\n" );
+ printf( " 3 - Change the line characteristics\n" );
+ printf( " 4 - Test canonical input\n" );
+ printf( " 5 - Test raw input\n" );
+ printf( " 9 - Exit\n" );
+ printf( "Enter your choice (1 to 5 or 9, followed by a carriage return): " );
+}
+
+static void notification( int fd, int seconds_remaining, void *arg )
+{
+ printf(
+ "Press any key to check the termios input capabilities (%is remaining)\n",
+ seconds_remaining
+ );
+}
+
+static void
+test_main(void)
+{
+ rtems_status_code status = RTEMS_SUCCESSFUL;
+ bool quit = false;
+ char c;
+ struct termios orig_termios, test_termios;
+
+ puts( "*** " TEST_NAME " TEST ***" );
+
+ test_termios_make_dev();
+
+ status = rtems_shell_wait_for_input(
+ STDIN_FILENO,
+ 20,
+ notification,
+ NULL
+ );
+ if (status == RTEMS_SUCCESSFUL) {
+ if( tcgetattr( fileno( stdin ), &orig_termios ) < 0 ) {
+ perror( "tcgetattr() failed" );
+ exit( 0 );
+ }
+
+ test_termios = orig_termios;
+
+ usage();
+ while(!quit) {
+ switch( c = getchar() ) {
+ case '1':
+ printf( "\nResetting the line to the original termios setting\n\n" );
+ test_termios = orig_termios;
+ if( tcsetattr( fileno( stdin ), TCSADRAIN, &test_termios ) < 0 ) {
+ perror( "tcsetattr() failed" );
+ exit( 1 );
+ }
+ usage();
+ break;
+
+ case '2':
+ print_termios( &test_termios );
+ usage();
+ break;
+
+ case '3':
+ change_line_settings( &test_termios );
+ usage();
+ break;
+
+ case '4':
+ canonical_input( &test_termios );
+ usage();
+ break;
+
+ case '5':
+ raw_input( &test_termios );
+ usage();
+ break;
+
+ case '9':
+ quit = true;
+ break;
+
+ case '\n':
+ break;
+
+ default:
+ printf( "\n%c is not a valid choice. Try again\n\n", c );
+ usage();
+ break;
+ }
+ }
+ }
+
+ status = rtems_shell_init("SHLL", 16 * 1024, 1, CONSOLE_DEVICE_NAME,
+ false, true, NULL);
+ assert(status == RTEMS_SUCCESSFUL);
+
+ exit(0);
+}
+
+#include <rtems/bsd/test/default-termios-init.h> \ No newline at end of file
diff --git a/testsuite/termios/test_termios_driver.c b/testsuite/termios/test_termios_driver.c
new file mode 100644
index 00000000..35637b99
--- /dev/null
+++ b/testsuite/termios/test_termios_driver.c
@@ -0,0 +1,136 @@
+/*
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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.
+ */
+
+#include <machine/rtems-bsd-kernel-space.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/tty.h>
+#include <sys/serial.h>
+#include <assert.h>
+#include <rtems/seterr.h>
+
+#include "../termios/test_termios_driver.h"
+
+static tsw_open_t test_termios_open;
+static tsw_close_t test_termios_close;
+static tsw_ioctl_t test_termios_ioctl;
+static tsw_modem_t test_termios_modem;
+static tsw_param_t test_termios_param;
+static tsw_outwakeup_t test_termios_outwakeup;
+static tsw_inwakeup_t test_termios_inwakeup;
+static tsw_free_t test_termios_free;
+
+static struct ttydevsw test_termios_class = {
+ .tsw_flags = TF_INITLOCK | TF_CALLOUT,
+ .tsw_open = test_termios_open,
+ .tsw_close = test_termios_close,
+ .tsw_outwakeup = test_termios_outwakeup,
+ .tsw_inwakeup = test_termios_inwakeup,
+ .tsw_ioctl = test_termios_ioctl,
+ .tsw_param = test_termios_param,
+ .tsw_modem = test_termios_modem,
+ .tsw_free = test_termios_free,
+};
+
+struct test_termios_softc tt_softc;
+
+static int
+test_termios_open(struct tty *tp)
+{
+ return (0);
+}
+
+static void
+test_termios_close(struct tty *tp)
+{
+}
+
+static void
+test_termios_outwakeup(struct tty *tp)
+{
+}
+
+static void
+test_termios_inwakeup(struct tty *tp)
+{
+}
+
+static int
+test_termios_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
+{
+ return (ENOIOCTL);
+}
+
+static int
+test_termios_param(struct tty *tp, struct termios *t)
+{
+ return (0);
+}
+
+static int
+test_termios_modem(struct tty *tp, int sigon, int sigoff)
+{
+ struct test_termios_softc *sc = tty_softc(tp);
+
+ if ((sigon == 0) && (sigoff == 0)) {
+ if (sc->sc_mcr & SER_DTR) {
+ sigon |= SER_DTR;
+ }
+ if (sc->sc_mcr & SER_RTS) {
+ sigon |= SER_RTS;
+ }
+ if (sc->sc_msr & SER_CTS) {
+ sigon |= SER_CTS;
+ }
+ if (sc->sc_msr & SER_DCD) {
+ sigon |= SER_DCD;
+ }
+ if (sc->sc_msr & SER_DSR) {
+ sigon |= SER_DSR;
+ }
+ if (sc->sc_msr & SER_RI) {
+ sigon |= SER_RI;
+ }
+ return (sigon);
+ }
+ if (sigon & SER_DTR) {
+ sc->sc_mcr |= SER_DTR;
+ }
+ if (sigoff & SER_DTR) {
+ sc->sc_mcr &= ~SER_DTR;
+ }
+ if (sigon & SER_RTS) {
+ sc->sc_mcr |= SER_RTS;
+ }
+ if (sigoff & SER_RTS) {
+ sc->sc_mcr &= ~SER_RTS;
+ }
+ return (0);
+}
+
+static void
+test_termios_free(void *xsc)
+{
+}
+
+void
+test_termios_make_dev(void)
+{
+ struct tty *tp = NULL;
+
+ memset( &tt_softc, 0, sizeof( tt_softc ));
+ tt_softc.sc_msr = SER_DCD | SER_CTS | SER_DSR;
+
+ tp = tty_alloc_mutex(&test_termios_class, &tt_softc, NULL);
+ assert(tp != NULL);
+ tt_softc.tp = tp;
+
+ tty_makedev( tp, NULL, "%s", TERMIOS_TEST_DRIVER_TTY_PREFIX TERMIOS_TEST_DRIVER_TTY_UNIT);
+ assert(tp != NULL);
+} \ No newline at end of file
diff --git a/testsuite/termios/test_termios_driver.h b/testsuite/termios/test_termios_driver.h
new file mode 100644
index 00000000..b8cf0b91
--- /dev/null
+++ b/testsuite/termios/test_termios_driver.h
@@ -0,0 +1,32 @@
+/*
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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.
+ */
+
+#ifndef TEST_TERMIOS_DRIVER_H
+#define TEST_TERMIOS_DRIVER_H
+
+/**
+ * This macro defines the standard name for the USB serial device
+ * that is available to applications.
+ */
+#define TERMIOS_TEST_DRIVER_TTY_PREFIX "T"
+#define TERMIOS_TEST_DRIVER_TTY_UNIT "0"
+#define TERMIOS_TEST_DRIVER_DEVICE_NAME "/dev/tty" TERMIOS_TEST_DRIVER_TTY_PREFIX TERMIOS_TEST_DRIVER_TTY_UNIT
+
+struct test_termios_softc {
+ uint8_t sc_lsr;
+ uint8_t sc_msr;
+ uint8_t sc_mcr;
+ struct tty *tp;
+};
+
+extern void test_termios_make_dev(void);
+
+extern struct test_termios_softc tt_softc;
+
+#endif /* TEST_TERMIOS_DRIVER_H */ \ No newline at end of file
diff --git a/testsuite/termios/test_termios_utilities.c b/testsuite/termios/test_termios_utilities.c
new file mode 100644
index 00000000..e8caf812
--- /dev/null
+++ b/testsuite/termios/test_termios_utilities.c
@@ -0,0 +1,233 @@
+/*
+ * COPYRIGHT (c) 1989-2017.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include <rtems/console.h>
+#include <rtems/shell.h>
+#include <rtems/bsd/bsd.h>
+
+#include <termios.h>
+#include <rtems/libcsupport.h>
+#include <rtems/termiostypes.h>
+
+#include "../termios/test_termios_driver.h"
+#include "../termios/test_termios_utilities.h"
+
+int Test_fd;
+uint8_t read_helper_buffer[256];
+uint8_t Tx_Buffer[TX_MAX];
+
+void open_it(void)
+{
+ puts( "open(" TERMIOS_TEST_DRIVER_DEVICE_NAME ") - OK " );
+ Test_fd = open( TERMIOS_TEST_DRIVER_DEVICE_NAME, O_RDWR );
+ assert( Test_fd != -1 );
+
+ change_iflag("BRKINT|ICRNL|IXON|IMAXBEL", 0xFFFFFFFF, BRKINT|ICRNL|IXON|IMAXBEL);
+ change_lflag("ISIG|ICANON|IEXTEN|ECHO|ECHOK|ECHOE|ECHOCTL", 0xFFFFFFFF, ISIG|ICANON|IEXTEN|ECHO|ECHOK|ECHOE|ECHOCTL);
+ change_oflag("OPOST|ONLCR|XTABS", 0xFFFFFFFF, OPOST|ONLCR|XTABS);
+}
+
+void close_it(void)
+{
+ int rc;
+
+ puts( "close(" TERMIOS_TEST_DRIVER_DEVICE_NAME ") - OK " );
+ rc = close( Test_fd );
+ assert( rc == 0 );
+}
+
+void read_it( ssize_t expected )
+{
+ ssize_t rc;
+ char buf[32];
+
+ assert( expected <= sizeof(buf) );
+
+ printf( "read - %zd expected\n", expected );
+ rc = read( Test_fd, buf, expected );
+ if ( expected != rc )
+ printf( "ERROR - expected=%zd rc=%zd\n", expected, rc );
+ assert( expected == rc );
+}
+
+void write_it(void)
+{
+ ssize_t sc;
+ char ch[10] = "PPPD TEST";
+
+ puts( "write(PPPD TEST) - OK " );
+ sc = write(Test_fd, ch, sizeof(ch));
+ assert( sc == sizeof(ch) );
+}
+
+void change_iflag( const char *desc, int mask, int new )
+{
+ int rc;
+ struct termios attr;
+
+ printf( "Changing c_iflag to: %s\n", desc );
+ rc = tcgetattr( Test_fd, &attr );
+ assert( rc == 0 );
+
+ attr.c_iflag &= ~mask;
+ attr.c_iflag |= new;
+
+ rc = tcsetattr( Test_fd, TCSANOW, &attr );
+ assert( rc == 0 );
+}
+
+void change_lflag( const char *desc, int mask, int new )
+{
+ int rc;
+ struct termios attr;
+
+ printf( "Changing c_lflag to: %s\n", desc );
+ rc = tcgetattr( Test_fd, &attr );
+ assert( rc == 0 );
+
+ attr.c_lflag &= ~mask;
+ attr.c_lflag |= new;
+
+ rc = tcsetattr( Test_fd, TCSANOW, &attr );
+ assert( rc == 0 );
+}
+
+void change_oflag( const char *desc, int mask, int new )
+{
+ int rc;
+ struct termios attr;
+
+ printf( "Changing c_oflag to: %s\n", desc );
+ rc = tcgetattr( Test_fd, &attr );
+ assert( rc == 0 );
+
+ attr.c_oflag &= ~mask;
+ attr.c_oflag |= new;
+
+ rc = tcsetattr( Test_fd, TCSANOW, &attr );
+ assert( rc == 0 );
+}
+
+void change_vmin_vtime( const char *desc, int min, int time )
+{
+ int rc;
+ struct termios attr;
+
+ printf( "Changing %s - VMIN=%d VTIME=%d\n", desc, min, time );
+ rc = tcgetattr( Test_fd, &attr );
+ assert( rc == 0 );
+
+ attr.c_cc[VMIN] = min;
+ attr.c_cc[VTIME] = time;
+
+ rc = tcsetattr( Test_fd, TCSANOW, &attr );
+ assert( rc == 0 );
+}
+
+void enable_non_blocking(bool enable)
+{
+ int flags;
+ int rv;
+
+ flags = fcntl(Test_fd, F_GETFL, 0);
+ assert(flags >= 0);
+
+ if (enable) {
+ flags |= O_NONBLOCK;
+ } else {
+ flags &= ~O_NONBLOCK;
+ }
+
+ rv = fcntl(Test_fd, F_SETFL, flags);
+ assert(rv == 0);
+}
+
+void write_helper( int fd, const char *c )
+{
+ size_t len;
+ int rc;
+
+ len = strlen( c );
+ printf( "Writing: %s", c );
+
+ rc = write( fd, c, len );
+ assert( rc == len );
+
+ termios_test_driver_dump_tx("Transmitted");
+}
+
+void read_helper( int fd, const char *expected )
+{
+ int rc;
+ size_t len;
+
+ len = strlen( expected );
+
+ termios_test_driver_set_rx( expected, len );
+ printf( "\nReading (expected):\n" );
+ rtems_print_buffer( (unsigned char *)expected, len-1 );
+
+ rc = read( fd, read_helper_buffer, sizeof(read_helper_buffer) );
+ assert( rc != -1 );
+
+ printf( "Read %d bytes from read(2)\n", rc );
+ rtems_print_buffer( read_helper_buffer, rc );
+
+ termios_test_driver_dump_tx("Echoed");
+}
+
+int termios_test_driver_read_tx(void)
+{
+ int Tx_Index = 0;
+ int Tx_Size = TX_MAX;
+ int Tx_Length;
+
+ for (;;) {
+ Tx_Length = ttydisc_getc(tt_softc.tp, &Tx_Buffer[Tx_Index], Tx_Size);
+ if (Tx_Length == 0)
+ break;
+ Tx_Index += Tx_Length;
+ Tx_Size -= Tx_Length;
+ }
+
+ return Tx_Index;
+}
+
+void termios_test_driver_dump_tx(const char *c)
+{
+ int Tx_Index;
+
+ Tx_Index = termios_test_driver_read_tx();
+ printf( "%s %d characters\n", c, Tx_Index );
+ if( Tx_Index > 0 ) {
+ rtems_print_buffer( &Tx_Buffer[0], Tx_Index );
+ }
+}
+
+void termios_test_driver_set_rx( const void *p, size_t len )
+{
+ tcflush(Test_fd, TCIFLUSH );
+ ttydisc_rint_simple(tt_softc.tp, p, len);
+ ttydisc_rint_done(tt_softc.tp);
+}
+
+void termios_test_driver_set_rx_char( char ch )
+{
+ char chs[1];
+
+ chs[0] = ch;
+ termios_test_driver_set_rx( &chs[0], 1 );
+} \ No newline at end of file
diff --git a/testsuite/termios/test_termios_utilities.h b/testsuite/termios/test_termios_utilities.h
new file mode 100644
index 00000000..c655c6f9
--- /dev/null
+++ b/testsuite/termios/test_termios_utilities.h
@@ -0,0 +1,33 @@
+/*
+ * COPYRIGHT (c) 1989-2017.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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.
+ */
+
+#ifndef TEST_TERMIOS_UTILITIES_H
+#define TEST_TERMIOS_UTILITIES_H
+
+#define TX_MAX 1024
+
+extern void open_it(void);
+extern void close_it(void);
+extern void change_iflag(const char *desc, int mask, int new);
+extern void change_lflag(const char *desc, int mask, int new);
+extern void change_oflag(const char *desc, int mask, int new);
+extern void change_vmin_vtime( const char *desc, int min, int time );
+extern void enable_non_blocking(bool enable);
+extern void write_helper(int fd, const char *c);
+extern void read_helper(int fd, const char *expected);
+extern void termios_test_driver_dump_tx(const char *c);
+extern int termios_test_driver_read_tx(void);
+extern void termios_test_driver_set_rx( const void *p, size_t len );
+extern void termios_test_driver_set_rx_char( char ch );
+
+extern int Test_fd;
+extern uint8_t read_helper_buffer[256];
+extern uint8_t Tx_Buffer[TX_MAX];
+
+#endif /* TEST_TERMIOS_UTILITIES_H */ \ No newline at end of file