diff options
author | Kevin Kirspel <kevin-kirspel@idexx.com> | 2017-05-04 08:28:00 -0400 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-05-11 11:15:41 +0200 |
commit | 333bfb618bf21fc3f7cca7411acf0f42fcdc4b57 (patch) | |
tree | ed0321198cee02ab0365c28726297bab8a2862ce /testsuite/termios | |
parent | Adding RTEMS support for FREEBSD TTY (diff) | |
download | rtems-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.c | 856 | ||||
-rw-r--r-- | testsuite/termios/test_termios_driver.c | 136 | ||||
-rw-r--r-- | testsuite/termios/test_termios_driver.h | 32 | ||||
-rw-r--r-- | testsuite/termios/test_termios_utilities.c | 233 | ||||
-rw-r--r-- | testsuite/termios/test_termios_utilities.h | 33 |
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 |