Enhancements from Charles-Antoine Gauthier <charles.gauthier@nrc.ca>.

This commit is contained in:
Joel Sherrill
2000-04-03 15:31:17 +00:00
parent effc2c4e6b
commit 33677ef548
2 changed files with 776 additions and 97 deletions

View File

@@ -4,6 +4,53 @@
These tests are brought to you by the letter `q'.
When you start the test, you should see:
You have the following choices:
1 - Reset the struct termios
2 - Look at the current termios setting
3 - Change the line characteristics
4 - Test canonical input
5 - Test raw input
9 - Exit
Enter your choice (1 to 5 or 9, followed by a carriage return):
The individual tests are briefly described below:
1. Reset the struct termios.
Included just in case you get into trouble. More than likely, if you are in
trouble, neither input nor output are likely to work and this won't help. But
hey, it should give you some warm fuzzy feeling that its there...
2. Look at the current termios setting
Dumps the current state of the termios settings in hex and with symbolic flag
names.
3. Change the line characteristics
Allows you to change the line speed, parity, number of data bits and number of
stop bits. You must supply a delay before the change takes effect. This gives
you time to switch your terminal settings to continue with the test.
WARNING: Minicom under Linux gets extremely unhappy (as does the /dev/ttyS?
underlying devices) if you change the line characteristics and do not make the
corresponding change in the terminal emulator.
4. Test canonical input
Simple test of canonical or cooked input mode. Try typing some tabs and/or control characters and make sure that you can backspace over them properly.
5. Test raw input
The line is placed into raw mode and four separate test are done:
VMIN=0, VTIME=0
Each letter you type should produce a line of output.
The `count' should be quite large, since (as you correctly
@@ -23,18 +70,19 @@ VMIN=5, VTIME=0
the test.
VMIN=5, VTIME=20
Type a character. Two seconds later a line should be printed.
Count should be 1. Type a character, and another within 2
seconds.
Two seconds after last character (or right after the 5th
character)
Count should be 1. Type a character, and another within 2 seconds.
Two seconds after last character (or right after the 5th character)
a line should be printed.
Type a `q' as the first character of a group to finish the test.
9. Exit
Gets you out of the test.
Clear???
Also, when testing the cooked mode input, try typing some tabs
and/or control characters and make sure that you can backspace over
them properly.
---
Eric Norum
@@ -43,3 +91,9 @@ Saskatchewan Accelerator Laboratory
University of Saskatchewan
Saskatoon, Canada.
Charles-Antoine Gauthier
Software Engineering Group
Institute for Information Technology
National Research Council of Canada
charles.gauthier@nrc.ca

View File

@@ -3,14 +3,21 @@
*
* This program may be distributed and used for any purpose.
* I ask only that you:
* 1. Leave this author information intact.
* 2. Document any changes you make.
* 1. Leave this author information intact.
* 2. Document any changes you make.
*
* W. Eric Norum
* Saskatchewan Accelerator Laboratory
* University of Saskatchewan
* Saskatoon, Saskatchewan, CANADA
* eric@skatter.usask.ca
*
* Additions:
* Charles-Antoine Gauthier
* Software Engineering Group
* Institute for Information Technology
* National Research Council of Canada
* charles.gauthier@nrc.ca
*
* $Id$
*/
@@ -22,13 +29,11 @@
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_MAXIMUM_SEMAPHORES 20
#define CONFIGURE_MAXIMUM_TIMERS 5
#define CONFIGURE_MAXIMUM_PERIODS 1
#define CONFIGURE_MAXIMUM_SEMAPHORES 20
#define CONFIGURE_MAXIMUM_TIMERS 5
#define CONFIGURE_MAXIMUM_PERIODS 1
#define CONFIGURE_MICROSECONDS_PER_TICK 1000
#define CONFIGURE_MICROSECONDS_PER_TICK 1000
#define CONFIGURE_INIT
rtems_task Init (rtems_task_argument argument);
@@ -43,103 +48,723 @@ rtems_task Init (rtems_task_argument argument);
int fileno( FILE *stream); /* beyond ANSI */
/* 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 & 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 [] = {
"ISIG", /* 0000001 */
"ICANON", /* 0000002 */
"XCASE", /* 0000004 */
"ECHO", /* 0000010 */
"ECHOE", /* 0000020 */
"ECHOK", /* 0000040 */
"ECHONL", /* 0000100 */
"NOFLSH", /* 0000200 */
"TOSTOP", /* 0000400 */
"ECHOCTL", /* 0001000 */
"ECHOPRT", /* 0002000 */
"ECHOKE", /* 0004000 */
"FLUSHO", /* 0010000 */
"unknown", /* 0020000 */
"PENDIN", /* 0040000 */
"IEXTEN", /* 0100000 */
"unknown", /* 0200000 */
"unknown", /* 0400000 */
"unknown", /* 1000000 */
"unknown", /* 2000000 */
"unknown", /* 4000000 */
};
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 )
{
int baud;
printf( "c_cflag = 0x%08x\n", tp->c_cflag );
switch( baud = (tp->c_cflag & CBAUD) ) {
case B0:
printf( "\tCBAUD =\tB0\n" );
break;
case B50:
printf( "\tCBAUD =\tB50\n" );
break;
case B75:
printf( "\tCBAUD =\tB75\n" );
break;
case B110:
printf( "\tCBAUD =\tB110\n" );
break;
case B134:
printf( "\tCBAUD =\tB134\n" );
break;
case B150:
printf( "\tCBAUD =\tB150\n" );
break;
case B200:
printf( "\tCBAUD =\tB200\n" );
break;
case B300:
printf( "\tCBAUD =\tB300\n" );
break;
case B600:
printf( "\tCBAUD =\tB600\n" );
break;
case B1200:
printf( "\tCBAUD =\tB1200\n" );
break;
case B1800:
printf( "\tCBAUD =\tB1800\n" );
break;
case B2400:
printf( "\tCBAUD =\tB2400\n" );
break;
case B4800:
printf( "\tCBAUD =\tB4800\n" );
break;
case B9600:
printf( "\tCBAUD =\tB9600\n" );
break;
case B19200:
printf( "\tCBAUD =\tB19200\n" );
break;
case B38400:
printf( "\tCBAUD =\tB38400\n" );
break;
case B57600:
printf( "\tCBAUD =\tB57600\n" );
break;
case B115200:
printf( "\tCBAUD =\tB115200\n" );
break;
case B230400:
printf( "\tCBAUD =\tB230400\n" );
break;
case B460800:
printf( "\tCBAUD =\tB460800\n" );
break;
default:
printf( "\tCBAUD =\tunknown (0x%08x)\n", baud );
break;
}
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 & 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 & CBAUDEX )
printf( "\tCBAUDEX set: What does this do?\n" );
else
printf( "\tCBAUDEX clear: What does this do?\n" );
if( tp->c_cflag & CRTSCTS )
printf( "\tCRTSCTS: harware flow control enabled?\n" );
else
printf( "\tCRTSCTS: hardware flow control disabled?\n" );
}
void print_c_cc( struct termios * tp )
{
int i;
char * cc_index_names [NCCS] = {
"[VINTR] ", /* 0 */
"[VQUIT] ", /* 1 */
"[VERASE] ", /* 2 */
"[VKILL] ", /* 3 */
"[VEOF] ", /* 4 */
"[VTIME] ", /* 5 */
"[VMIN] ", /* 6 */
"[VSWTC ", /* 7 */
"[VSTART] ", /* 8 */
"[VSTOP] ", /* 9 */
"[VSUSP] ", /* 10 */
"[VEOL] ", /* 11 */
"[VREPRINT]", /* 12 */
"[VDISCARD]", /* 13 */
"[VWERASE] ", /* 14 */
"[VLNEXT ", /* 15 */
"[VEOL2] ", /* 16 */
"unknown ", /* 17 */
"unknown ", /* 18 */
};
for( i = 0; i < NCCS; i++ ) {
printf( "c_cc%s = 0x%08x\n", cc_index_names[i], tp->c_cc[i] );
}
}
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 );
printf( "\n" );
}
unsigned long get_baud_rate( void )
{
unsigned long baud_rate;
while( TRUE ) {
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, 57600, 115200, 230400, 460800\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 57600: return B57600;
case 115200: return B115200;
case 230400: return B230400;
case 460800: return B460800;
default:
printf( "%lu is not a valid choice. Try again.\n\n", baud_rate );
break;
}
}
}
unsigned long get_parity()
{
int parity;
while( TRUE ) {
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()
{
int stop_bits;
while( TRUE ) {
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()
{
int data_bits;
while( TRUE ) {
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 | 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 buffer[256];
char c, 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;
sleep( 1 );
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
*/
static void
testRawInput (int vmin, int vtime)
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];
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 VMIN=%d VTIME=%d ***\n", vmin, vtime);
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
i = tcgetattr (fileno (stdin), &old);
if (i < 0) {
printf ("tcgetattr failed: %s\n", strerror (errno));
return;
}
new = old;
new.c_lflag &= ~(ICANON|ECHO|ECHONL|ECHOK|ECHOE|ECHOPRT|ECHOCTL);
new.c_cc[VMIN] = vmin;
new.c_cc[VTIME] = vtime;
i = tcsetattr (fileno (stdin), TCSANOW, &new);
if (i < 0) {
printf ("tcsetattr failed: %s\n", strerror (errno));
return;
}
do {
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
count = 0;
for (;;) {
nread = read (fileno (stdin), cbuf, sizeof cbuf);
if (nread < 0) {
printf ("Read error: %s\n", strerror (errno));
goto out;
}
count++;
if (nread != 0)
break;
}
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
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 (" %2.2x", cbuf[i]);
printf ("\n");
} while (cbuf[0] != 'q');
out:
i = tcsetattr (fileno (stdin), TCSANOW, &old);
if (i < 0)
printf ("tcsetattr failed: %s\n", strerror (errno));
printf ("*** End of Raw input VMIN=%d VTIME=%d ***\n", vmin, vtime);
printf( "Raw input test with VMIN=%d VTIME=%d\n", vmin, vtime );
rtems_clock_get( RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond );
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;
sleep( 1 );
if( tcsetattr( fileno( stdin ), TCSADRAIN, &new ) < 0 ) {
perror ("do_raw_input(): tcsetattr() failed" );
return;
}
do {
rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then );
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;
}
rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now );
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:
sleep( 1 );
if( tcsetattr( fileno( stdin ), TCSADRAIN, &old) < 0 )
perror("do_raw_input(): tcsetattr() failed: %s\n" );
printf ("*** End of Raw input VMIN=%d VTIME=%d ***\n", vmin, vtime);
}
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): " );
}
/*
* RTEMS Startup Task
*/
rtems_task
Init (rtems_task_argument ignored)
{
int i, j;
char c, done;
struct termios orig_termios, test_termios;
printf( "\n\n*** TEST OF TERMIOS INPUT CAPABILITIES ***\n" );
printf( "\n\n*** HELLO WORLD TEST ***\n" );
printf( "Hello World\n" );
printf( "*** END OF HELLO WORLD TEST ***\n" );
if( tcgetattr( fileno( stdin ), &orig_termios ) < 0 ) {
perror( "tcgetattr() failed" );
exit( 0 );
}
printf( "\n\ntype 'q' to exit raw input tests\n\n" );
test_termios = orig_termios;
for (;;) {
/*
* Test blocking, line-oriented input
*/
do {
printf (">>> ");
fflush (stdout);
i = scanf (" %d", &j);
printf ("Return: %d Value: %d\n", i, j);
} while (i != 0);
usage();
for(;;) {
switch( c = getchar() ) {
case '1':
printf( "\nResetting the line to the original termios setting\n\n" );
test_termios = orig_termios;
sleep( 1 );
if( tcsetattr( fileno( stdin ), TCSADRAIN, &test_termios ) < 0 ) {
perror( "tcsetattr() failed" );
exit( 1 );
}
usage();
break;
/*
* Consume what scanf rejected
*/
while ((i = getchar ()) != '\n')
if (i == EOF)
break;
case '2':
print_termios( &test_termios );
usage();
break;
/*
* Test character-oriented input
*/
testRawInput (0, 0);
testRawInput (0, 20);
testRawInput (5, 0);
testRawInput (5, 20);
}
exit (1);
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':
exit( 1 );
case '\n':
break;
default:
printf( "\n%c is not a valid choice. Try again\n\n", c );
usage();
break;
}
}
}