source: rtems/testsuites/libtests/termios/init.c @ f8b2eb03

4.115
Last change on this file since f8b2eb03 was f8b2eb03, checked in by Sebastian Huber <sebastian.huber@…>, on 03/17/14 at 07:10:40

tests/libtests: Use <rtems/test.h>

  • Property mode set to 100644
File size: 18.0 KB
Line 
1/*
2 * RTEMS configuration/initialization
3 *
4 * This program may be distributed and used for any purpose.
5 * I ask only that you:
6 *  1. Leave this author information intact.
7 *  2. Document any changes you make.
8 *
9 * W. Eric Norum
10 * Saskatchewan Accelerator Laboratory
11 * University of Saskatchewan
12 * Saskatoon, Saskatchewan, CANADA
13 * eric@skatter.usask.ca
14 *
15 * Additions:
16 * Charles-Antoine Gauthier
17 * Software Engineering Group
18 * Institute for Information Technology
19 * National Research Council of Canada
20 * charles.gauthier@nrc.ca
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <bsp.h>
28
29#include <rtems/shell.h>
30
31#include <stdio.h>
32#include <unistd.h>
33#include <termios.h>
34#include <errno.h>
35#include <string.h>
36
37#include <tmacros.h>
38
39const char rtems_test_name[] = "TERMIOS";
40
41/* forward declarations to avoid warnings */
42rtems_task Init(rtems_task_argument argument);
43void print_32bits(unsigned long bits, unsigned char size, char * names[]);
44void print_c_iflag(struct termios * tp);
45void print_c_oflag(struct termios * tp);
46void print_c_lflag(struct termios * tp);
47void print_c_cflag(struct termios * tp);
48void print_c_cc(struct termios * tp);
49void print_termios(struct termios *tp);
50unsigned long get_baud_rate(void);
51unsigned long get_parity(void);
52unsigned long get_stop_bits(void);
53unsigned long get_data_bits(void);
54void change_line_settings(struct termios *tp);
55void canonical_input(struct termios *tp);
56void do_raw_input(int vmin, int vtime);
57void usage(void);
58
59#if !defined(fileno)
60int fileno( FILE *stream); /* beyond ANSI */
61#endif
62
63/* Some of the termios dumping code depends on bit positions! */
64
65void print_32bits( unsigned long bits, unsigned char size, char * names[] )
66{
67  unsigned char i;
68
69  for( i = 0; i < size; i++ ) {
70    if( (bits >> i) & 0x1 )
71      printf( "%s ", names[i] );
72  }
73}
74
75
76void print_c_iflag( struct termios * tp )
77{
78  char * c_iflag_bits [] = {
79    "IGNBRK",   /* 0000001 */
80    "BRKINT",   /* 0000002 */
81    "IGNPAR",   /* 0000004 */
82    "PARMRK",   /* 0000010 */
83    "INPCK",    /* 0000020 */
84    "ISTRIP",   /* 0000040 */
85    "INLCR",    /* 0000100 */
86    "IGNCR",    /* 0000200 */
87    "ICRNL",    /* 0000400 */
88    "IUCLC",    /* 0001000 */
89    "IXON",     /* 0002000 */
90    "IXANY",    /* 0004000 */
91    "IXOFF",    /* 0010000 */
92    "IMAXBEL",  /* 0020000 */
93    "unknown",  /* 0040000 */
94    "unknown",  /* 0100000 */
95    "unknown",  /* 0200000 */
96    "unknown",  /* 0400000 */
97    "unknown",  /* 1000000 */
98    "unknown",  /* 2000000 */
99    "unknown"   /* 4000000 */
100  };
101
102  printf( "c_iflag = 0x%08x\n\t", tp->c_iflag );
103  print_32bits( tp->c_iflag, sizeof( c_iflag_bits )/sizeof( char * ), c_iflag_bits );
104  printf( "\n" );
105}
106
107
108void print_c_oflag( struct termios * tp )
109{
110  printf( "c_oflag = 0x%08x\n\t", tp->c_oflag );
111
112  if( tp->c_oflag & OPOST )
113    printf( "OPOST " );
114
115  if( tp->c_oflag & OLCUC )
116    printf( "OLCUC " );
117
118  if( tp->c_oflag & ONLCR )
119    printf( "ONLCR " );
120
121  if( tp->c_oflag & OCRNL )
122    printf( "OCRNL " );
123
124  if( tp->c_oflag & ONOCR )
125    printf( "ONOCR " );
126
127  if( tp->c_oflag & ONLRET )
128    printf( "ONLRET " );
129
130  if( tp->c_oflag & OFILL )
131    printf( "OFILL " );
132
133  if( tp->c_oflag & OFDEL )
134    printf( "OFDEL " );
135
136  switch( tp->c_oflag & NLDLY ) {
137    case NL0:
138      printf( "NL0 " );
139      break;
140
141    case NL1:
142      printf( "NL1 " );
143      break;
144  }
145
146  switch( tp->c_oflag & CRDLY ) {
147    case CR0:
148      printf( "CR0 " );
149      break;
150
151    case CR1:
152      printf( "CR1 " );
153      break;
154
155    case CR2:
156      printf( "CR2 " );
157      break;
158
159    case CR3:
160      printf( "CR3 " );
161      break;
162  }
163
164  switch( tp->c_oflag & TABDLY ) {
165    case TAB0:
166      printf( "TAB0 " );
167      break;
168
169    case TAB1:
170      printf( "TAB1 " );
171      break;
172
173    case TAB2:
174      printf( "TAB2 " );
175      break;
176
177    case TAB3:
178      printf( "TAB3 " );
179      break;
180  }
181
182  switch( tp->c_oflag & BSDLY ) {
183    case BS0:
184      printf( "BS0 " );
185      break;
186
187    case BS1:
188      printf( "BS1 " );
189      break;
190  }
191
192  switch( tp->c_oflag & VTDLY ) {
193    case VT0:
194      printf( "VT0 " );
195      break;
196
197    case VT1:
198      printf( "VT1 " );
199      break;
200  }
201
202  switch( tp->c_oflag & FFDLY ) {
203    case FF0:
204      printf( "FF0" );
205      break;
206
207    case FF1:
208      printf( "FF1" );
209      break;
210  }
211  printf( "\n" );
212}
213
214
215void print_c_lflag( struct termios * tp )
216{
217  char * c_lflag_bits [] = {
218    "ISIG",        /* 0000001 */
219    "ICANON",      /* 0000002 */
220    "XCASE",       /* 0000004 */
221    "ECHO",        /* 0000010 */
222    "ECHOE",       /* 0000020 */
223    "ECHOK",       /* 0000040 */
224    "ECHONL",      /* 0000100 */
225    "NOFLSH",      /* 0000200 */
226    "TOSTOP",      /* 0000400 */
227    "ECHOCTL",     /* 0001000 */
228    "ECHOPRT",     /* 0002000 */
229    "ECHOKE",      /* 0004000 */
230    "FLUSHO",      /* 0010000 */
231    "unknown",     /* 0020000 */
232    "PENDIN",      /* 0040000 */
233    "IEXTEN",      /* 0100000 */
234    "unknown",     /* 0200000 */
235    "unknown",     /* 0400000 */
236    "unknown",     /* 1000000 */
237    "unknown",     /* 2000000 */
238    "unknown",     /* 4000000 */
239  };
240
241  printf( "c_lflag = 0x%08x\n\t", tp->c_lflag );
242  print_32bits( tp->c_lflag, sizeof( c_lflag_bits )/sizeof( char * ), c_lflag_bits );
243  printf( "\n" );
244}
245
246
247void print_c_cflag( struct termios * tp )
248{
249  unsigned int baud;
250
251  printf( "c_cflag = 0x%08x\n", tp->c_cflag );
252
253  baud = (tp->c_cflag & CBAUD) ;
254  if ( tp->c_cflag & CBAUDEX )
255  switch( baud ) {
256    case B0:
257      printf( "\tCBAUD =\tB0\n" );
258      break;
259
260    case B50:
261      printf( "\tCBAUD =\tB50\n" );
262      break;
263
264    case B75:
265      printf( "\tCBAUD =\tB75\n" );
266      break;
267
268    case B110:
269      printf( "\tCBAUD =\tB110\n" );
270      break;
271
272    case B134:
273      printf( "\tCBAUD =\tB134\n" );
274      break;
275
276    case B150:
277      printf( "\tCBAUD =\tB150\n" );
278      break;
279
280    case B200:
281      printf( "\tCBAUD =\tB200\n" );
282      break;
283
284    case B300:
285      printf( "\tCBAUD =\tB300\n" );
286      break;
287
288    case B600:
289      printf( "\tCBAUD =\tB600\n" );
290      break;
291
292    case B1200:
293      printf( "\tCBAUD =\tB1200\n" );
294      break;
295
296    case B1800:
297      printf( "\tCBAUD =\tB1800\n" );
298      break;
299
300    case B2400:
301      printf( "\tCBAUD =\tB2400\n" );
302      break;
303
304    case B4800:
305      printf( "\tCBAUD =\tB4800\n" );
306      break;
307
308    case B9600:
309      printf( "\tCBAUD =\tB9600\n" );
310      break;
311
312    case B19200:
313      printf( "\tCBAUD =\tB19200\n" );
314      break;
315
316    case B38400:
317      printf( "\tCBAUD =\tB38400\n" );
318      break;
319
320    case B57600:
321      printf( "\tCBAUD =\tB57600\n" );
322      break;
323
324    case B115200:
325      printf( "\tCBAUD =\tB115200\n" );
326      break;
327
328    case B230400:
329      printf( "\tCBAUD =\tB230400\n" );
330      break;
331
332    case B460800:
333      printf( "\tCBAUD =\tB460800\n" );
334      break;
335
336    default:
337      printf( "\tCBAUD =\tunknown (0x%08x)\n", baud );
338      break;
339    }
340
341  switch( tp->c_cflag & CSIZE ) {
342    case CS5:
343      printf( "\tCSIZE =\tCS5\n" );
344      break;
345
346    case CS6:
347      printf( "\tCSIZE =\tCS6\n" );
348      break;
349
350    case CS7:
351      printf( "\tCSIZE =\tCS7\n" );
352      break;
353
354    case CS8:
355      printf( "\tCSIZE =\tCS8\n" );
356      break;
357  }
358
359  if( tp->c_cflag & CSTOPB )
360    printf( "\tCSTOPB set: send 2 stop bits\n" );
361  else
362    printf( "\tCSTOPB clear: send 1 stop bit\n" );
363
364  if( tp->c_cflag & PARENB )
365    printf( "\tPARENB set: parity enabled\n" );
366  else
367    printf( "\tPARENB clear: parity disabled\n" );
368
369  if( tp->c_cflag & PARODD )
370    printf( "\tPARODD set: parity odd\n" );
371  else
372    printf( "\tPARODD clear: parity even\n" );
373
374  if( tp->c_cflag & CREAD )
375    printf( "\tCREAD set: receiver enabled\n" );
376  else
377    printf( "\tCREAD clear: treceiver disabled\n" );
378
379  if( tp->c_cflag & HUPCL )
380    printf( "\tHUPCL set: enabled\n" );
381  else
382    printf( "\tHUPCL clear: disabled\n" );
383
384  if( tp->c_cflag & CLOCAL )
385    printf( "\tCLOCAL set: ignore modem lines\n" );
386  else
387    printf( "\tCLOCAL clear: don't ignore modem lines\n" );
388
389#if defined(CBAUDEX)
390  if( tp->c_cflag & CBAUDEX )
391    printf( "\tCBAUDEX set: What does this do?\n" );
392  else
393    printf( "\tCBAUDEX clear: What does this do?\n" );
394#endif
395
396  if( tp->c_cflag & CRTSCTS )
397    printf( "\tCRTSCTS: harware flow control enabled?\n" );
398  else
399    printf( "\tCRTSCTS: hardware flow control disabled?\n" );
400}
401
402
403void print_c_cc( struct termios * tp )
404{
405  size_t i;
406  char * cc_index_names [ /* NCCS */ ] = {
407    "[VINTR]   ",   /* 0 */
408    "[VQUIT]   ",   /* 1 */
409    "[VERASE]  ",   /* 2 */
410    "[VKILL]   ",   /* 3 */
411    "[VEOF]    ",   /* 4 */
412    "[VTIME]   ",   /* 5 */
413    "[VMIN]    ",   /* 6 */
414    "[VSWTC    ",   /* 7 */
415    "[VSTART]  ",   /* 8 */
416    "[VSTOP]   ",   /* 9 */
417    "[VSUSP]   ",   /* 10 */
418    "[VEOL]    ",   /* 11 */
419    "[VREPRINT]",   /* 12 */
420    "[VDISCARD]",   /* 13 */
421    "[VWERASE] ",   /* 14 */
422    "[VLNEXT   ",   /* 15 */
423    "[VEOL2]   ",   /* 16 */
424    "unknown   ",   /* 17 */
425    "unknown   ",   /* 18 */
426  };
427
428  for( i = 0; i < sizeof(cc_index_names)/sizeof(char*) ; i++ ) {
429    printf( "c_cc%s = 0x%08x\n", cc_index_names[i], tp->c_cc[i] );
430  }
431}
432
433
434void print_termios( struct termios *tp )
435{
436  printf( "\nLooking at the current termios settings:\n\n" );
437  print_c_iflag( tp );
438  print_c_oflag( tp );
439  print_c_cflag( tp );
440  print_c_lflag( tp );
441  print_c_cc( tp );
442  printf( "\n" );
443}
444
445
446unsigned long get_baud_rate(void)
447{
448  unsigned long baud_rate;
449
450  while( 1 ) {
451    printf( "Enter the numerical value for the new baud rate.\n" );
452    printf( "Choices are: 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800\n" );
453    printf( "2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800\n" );
454    printf( "\nYour choice: " );
455    scanf( "%lu", &baud_rate );
456    printf( "\n" );
457    switch( baud_rate ) {
458      case 50:     return B50;
459      case 75:     return B75;
460      case 110:    return B110;
461      case 134:    return B134;
462      case 150:    return B150;
463      case 200:    return B200;
464      case 300:    return B300;
465      case 600:    return B600;
466      case 1200:   return B1200;
467      case 1800:   return B1800;
468      case 2400:   return B2400;
469      case 4800:   return B4800;
470      case 9600:   return B9600;
471      case 19200:  return B19200;
472      case 38400:  return B38400;
473      case 57600:  return B57600;
474      case 115200: return B115200;
475      case 230400: return B230400;
476      case 460800: return B460800;
477
478      default:
479        printf( "%lu is not a valid choice. Try again.\n\n", baud_rate );
480        break;
481    }
482  }
483}
484
485
486unsigned long get_parity(void)
487{
488  int parity;
489
490  while( 1 ) {
491    printf( "Enter the numerical value for the new parity\n" );
492    printf( "Choices are: 0 for no parity, 1 for even parity, 2 for odd parity\n" );
493    printf( "\nYour choice: " );
494    scanf( "%d", &parity );
495    printf( "\n" );
496    switch( parity ) {
497      case 0:
498        return 0;
499
500      case 1:
501        return PARENB;
502
503      case 2:
504        return PARENB | PARODD;
505
506      default:
507        printf( "%d is not a valid choice. Try again.\n\n", parity );
508        break;
509    }
510  }
511}
512
513
514unsigned long get_stop_bits(void)
515{
516  int stop_bits;
517
518  while( 1 ) {
519    printf( "Enter the numerical value for the new number of stop bits\n" );
520    printf( "Choices are: 1 or 2\n" );
521    printf( "\nYour choice: " );
522    scanf( "%d", &stop_bits );
523    printf( "\n" );
524    switch( stop_bits ) {
525      case 1:
526        return 0;
527
528      case 2:
529        return CSTOPB;
530
531      default:
532        printf( "%d is not a valid choice. Try again.\n\n", stop_bits );
533        break;
534    }
535  }
536}
537
538
539unsigned long get_data_bits(void)
540{
541  int data_bits;
542
543  while( 1 ) {
544    printf( "Enter the numerical value for the new number of data bits\n" );
545    printf( "Choices are: 5, 6, 7 or 8\n" );
546    printf( "\nYour choice: " );
547    scanf( "%d", &data_bits );
548    printf( "\n" );
549    switch( data_bits ) {
550      case 5:
551        return CS5;
552
553      case 6:
554        return CS6;
555
556      case 7:
557        return CS7;
558
559      case 8:
560        return CS8;
561
562      default:
563        printf( "%d is not a valid choice. Try again.\n\n", data_bits );
564        break;
565    }
566  }
567}
568
569
570void change_line_settings( struct termios *tp )
571{
572  unsigned long baud_rate, parity, stop_bits, data_bits, sleep_time;
573
574  printf( "\nSetting line characteristics\n\n" );
575
576  baud_rate = get_baud_rate();
577  parity = get_parity();
578  stop_bits = get_stop_bits();
579  data_bits = get_data_bits();
580
581  printf( "NOTE: You will not see output until you switch your terminal settings!\n" );
582  printf( "WARNING: If you do not switch your terminal settings, your terminal may hang.\n" );
583  printf( "Enter the number of seconds the test will wait for you to switch your terminal\n" );
584  printf( "settings before it continues\n" );
585  printf( "Sleep time (in seconds): " );
586  scanf( "%lu", &sleep_time );
587  printf( "\n" );
588  printf( "Setting line to new termios settings in %lu seconds.\n", sleep_time );
589
590  sleep( sleep_time );
591
592  tp->c_cflag = CLOCAL | CREAD | parity | stop_bits | data_bits | baud_rate;
593  if( tcsetattr( fileno( stdin ), TCSADRAIN, tp ) < 0 ) {
594    perror( "change_line_settings(): tcsetattr() failed" );
595    rtems_test_exit( 1 );
596  }
597  printf( "Line settings set.\n" );
598}
599
600
601void canonical_input( struct termios *tp )
602{
603  char c;
604  bool first_time = true;
605
606  printf( "\nTesting canonical input\n\n" );
607
608  printf( "Setting line to canonical input mode.\n" );
609  tp->c_lflag = ISIG | ICANON | ECHO | ECHONL | ECHOK | ECHOE | ECHOPRT | ECHOCTL | IEXTEN;
610  tp->c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
611  if( tcsetattr( fileno( stdin ), TCSADRAIN, tp ) < 0 ) {
612    perror( "canonical_input(): tcsetattr() failed" );
613    rtems_test_exit( 1 );
614  }
615
616  while ( ( c = getchar () ) != '\n');
617  printf( "Testing getchar(). Type some text followed by carriage return\n" );
618  printf( "Each character you entered will be echoed back to you\n\n" );
619  while ( ( c = getchar () ) != '\n') {
620    if( first_time ) {
621      printf( "\nYou typed:\n");
622      first_time = false;
623    }
624    printf( "%c", c );
625  }
626  printf( "\n\nCanonical input test done.\n" );
627}
628
629
630/*
631 * Test raw (ICANON=0) input
632 */
633void do_raw_input( int vmin, int vtime )
634{
635  int i;
636  struct termios old, new;
637  rtems_interval ticksPerSecond, then, now;
638  unsigned int msec;
639  unsigned long count;
640  int nread;
641  unsigned char cbuf[100];
642
643  printf( "Raw input test with VMIN=%d  VTIME=%d\n", vmin, vtime );
644
645  ticksPerSecond = rtems_clock_get_ticks_per_second();
646  if ( tcgetattr( fileno ( stdin ), &old ) < 0 ) {
647    perror( "do_raw_input(): tcgetattr() failed" );
648    return;
649  }
650
651  new = old;
652  new.c_lflag &= ~( ICANON | ECHO | ECHONL | ECHOK | ECHOE | ECHOPRT | ECHOCTL );
653  new.c_cc[VMIN] = vmin;
654  new.c_cc[VTIME] = vtime;
655  if( tcsetattr( fileno( stdin ), TCSADRAIN, &new ) < 0 ) {
656    perror ("do_raw_input(): tcsetattr() failed" );
657    return;
658  }
659
660  do {
661    then = rtems_clock_get_ticks_since_boot();
662    count = 0;
663    for(;;) {
664      nread = read( fileno( stdin ), cbuf, sizeof cbuf );
665      if( nread < 0 ) {
666        perror( "do_raw_input(): read() failed" );
667        goto out;
668      }
669      count++;
670      if( nread != 0 )
671        break;
672    }
673    now = rtems_clock_get_ticks_since_boot();
674    msec = (now - then) * 1000 / ticksPerSecond;
675    printf( "Count:%-10lu  Interval:%3u.%3.3d  Char:",
676          count, msec / 1000, msec % 1000 );
677
678    for( i = 0 ; i < nread ; i++ )
679      printf (" 0x%2.2x", cbuf[i]);
680    printf ("\n");
681
682  } while( cbuf[0] != 'q' );
683
684out:
685  if( tcsetattr( fileno( stdin ), TCSADRAIN, &old) < 0 )
686    perror("do_raw_input(): tcsetattr() failed: %s\n" );
687
688  TEST_BEGIN();
689}
690
691
692static void raw_input( struct termios *tp )
693{
694  printf( "\nTesting raw input input\n\n" );
695  printf( "Hit 'q' to terminate the test\n" );
696
697  do_raw_input( 0, 0 );
698  do_raw_input( 0, 20 );
699  do_raw_input( 5, 0 );
700  do_raw_input( 5, 20 );
701
702  printf( "\nRaw input test done.\n" );
703}
704
705
706void usage( void )
707{
708  printf( "\nYou have the following choices:\n" );
709  printf( "  1 - Reset the struct termios\n" );
710  printf( "  2 - Look at the current termios setting\n" );
711  printf( "  3 - Change the line characteristics\n" );
712  printf( "  4 - Test canonical input\n" );
713  printf( "  5 - Test raw input\n" );
714  printf( "  9 - Exit\n" );
715  printf( "Enter your choice (1 to 5 or 9, followed by a carriage return): " );
716}
717
718static void notification( int fd, int seconds_remaining, void *arg )
719{
720  printf(
721    "Press any key to check the termios input capabilities (%is remaining)\n",
722    seconds_remaining
723  );
724}
725
726/*
727 * RTEMS Startup Task
728 */
729rtems_task
730Init (rtems_task_argument ignored)
731{
732  rtems_status_code status;
733  char c ;
734  struct termios orig_termios, test_termios;
735
736  TEST_BEGIN();
737
738  status = rtems_shell_wait_for_input(
739    STDIN_FILENO,
740    20,
741    notification,
742    NULL
743  );
744  if (status == RTEMS_SUCCESSFUL) {
745    if( tcgetattr( fileno( stdin ), &orig_termios ) < 0 ) {
746      perror( "tcgetattr() failed" );
747      rtems_test_exit( 0 );
748    }
749
750    test_termios = orig_termios;
751
752    usage();
753    for(;;) {
754      switch( c = getchar() ) {
755        case '1':
756          printf( "\nResetting the line to the original termios setting\n\n" );
757          test_termios = orig_termios;
758          if( tcsetattr( fileno( stdin ), TCSADRAIN, &test_termios ) < 0 ) {
759            perror( "tcsetattr() failed" );
760            rtems_test_exit( 1 );
761          }
762          usage();
763          break;
764
765        case '2':
766          print_termios( &test_termios );
767          usage();
768          break;
769
770        case '3':
771          change_line_settings( &test_termios );
772          usage();
773          break;
774
775        case '4':
776          canonical_input( &test_termios );
777          usage();
778          break;
779
780        case '5':
781          raw_input( &test_termios );
782          usage();
783          break;
784
785        case '9':
786          rtems_test_exit( 1 );
787
788        case '\n':
789          break;
790
791        default:
792          printf( "\n%c is not a valid choice. Try again\n\n", c );
793          usage();
794          break;
795      }
796    }
797  } else {
798    TEST_END();
799
800    rtems_test_exit( 0 );
801  }
802}
803
804/* application configuration */
805#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
806#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
807
808#define CONFIGURE_MAXIMUM_TASKS       1
809
810#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
811
812#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
813
814#define CONFIGURE_MICROSECONDS_PER_TICK 1000
815
816#define CONFIGURE_INIT
817
818#include <rtems/confdefs.h>
819/* end of configuration */
820
Note: See TracBrowser for help on using the repository browser.