Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:34

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  COPYRIGHT (c) 1989-2010.
0005  *  On-Line Applications Research Corporation (OAR).
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032 
0033 #include "tmacros.h"
0034 #define TTYDEFCHARS
0035 #include <termios.h>
0036 #include <rtems/libcsupport.h>
0037 #include <rtems/malloc.h>
0038 #include <rtems/termiostypes.h>
0039 #include <fcntl.h>
0040 #include <limits.h>
0041 #include <unistd.h>
0042 #include <sys/errno.h>
0043 #include <sys/stat.h>
0044 
0045 const char rtems_test_name[] = "TERMIOS 1";
0046 
0047 /* rtems_termios_baud_t is a typedefs to int32_t */
0048 #define PRIdrtems_termios_baud_t PRId32
0049 
0050 /*
0051  *  Termios Test Driver
0052  */
0053 #include "termios_testdriver.h"
0054 
0055 static const rtems_driver_address_table test_driver =
0056   TERMIOS_TEST_DRIVER_TABLE_ENTRY;
0057 
0058 /*
0059  *  Baud Rate Constant Mapping Entry
0060  */
0061 typedef struct {
0062   tcflag_t constant;
0063   rtems_termios_baud_t baud;
0064 } termios_baud_test_r;
0065 
0066 #define INVALID_CONSTANT ((tcflag_t) -2)
0067 
0068 #define INVALID_BAUD ((rtems_termios_baud_t) -2)
0069 /*
0070  *  Baud Rate Constant Mapping Table
0071  */
0072 static const termios_baud_test_r baud_table[] = {
0073   { B0,           0 },
0074   { B50,         50 },
0075   { B75,         75 },
0076   { B110,       110 },
0077   { B134,       134 },
0078   { B150,       150 },
0079   { B200,       200 },
0080   { B300,       300 },
0081   { B600,       600 },
0082   { B1200,     1200 },
0083   { B1800,     1800 },
0084   { B2400,     2400 },
0085   { B4800,     4800 },
0086   { B9600,     9600 },
0087   { B19200,   19200 },
0088   { B38400,   38400 },
0089   { B7200,     7200 },
0090   { B14400,   14400 },
0091   { B28800,   28800 },
0092   { B57600,   57600 },
0093   { B76800,   76800 },
0094   { B115200, 115200 },
0095   { B230400, 230400 },
0096   { B460800, 460800 },
0097   { B921600, 921600 },
0098   { INVALID_CONSTANT, INVALID_BAUD }
0099 };
0100 
0101 /*
0102  *  Character Size Constant Mapping Entry
0103  */
0104 typedef struct {
0105   tcflag_t constant;
0106   int bits;
0107 } termios_character_size_test_r;
0108 
0109 /*
0110  *  Character Size Constant Mapping Table
0111  */
0112 static const termios_character_size_test_r char_size_table[] = {
0113   { CS5,      5 },
0114   { CS6,      6 },
0115   { CS7,      7 },
0116   { CS8,      8 },
0117   { INVALID_CONSTANT, -1 }
0118 };
0119 
0120 /*
0121  *  Parity Constant Mapping Entry
0122  */
0123 typedef struct {
0124   tcflag_t constant;
0125   const char *parity;
0126 } termios_parity_test_r;
0127 
0128 /*
0129  *  Parity Constant Mapping Table
0130  */
0131 static const termios_parity_test_r parity_table[] = {
0132   { 0,                "none" },
0133   { PARENB,           "even" },
0134   { PARENB | PARODD,  "odd" },
0135   { INVALID_CONSTANT, NULL }
0136 };
0137 
0138 /*
0139  *  Stop Bit Constant Mapping Entry
0140  */
0141 typedef struct {
0142   tcflag_t constant;
0143   int stop;
0144 } termios_stop_bits_test_r;
0145 
0146 /*
0147  *  Stop Bit Constant Mapping Table
0148  */
0149 static const termios_stop_bits_test_r stop_bits_table[] = {
0150   { 0,       1 },
0151   { CSTOPB,  2 },
0152   { INVALID_CONSTANT, -1 }
0153 };
0154 
0155 /*
0156  *  Test converting baud rate into an index
0157  */
0158 static void test_termios_baud2index(void)
0159 {
0160   int i;
0161   int index;
0162 
0163   puts( "Test termios_baud2index..." );
0164   puts( "termios_baud_to_index(-2) - NOT OK" );
0165   i = rtems_termios_baud_to_index( INVALID_CONSTANT );
0166   rtems_test_assert( i == -1 );
0167 
0168   for (i=0 ; baud_table[i].constant != INVALID_CONSTANT ; i++ ) {
0169     printf(
0170       "termios_baud_to_index(B%" PRIdrtems_termios_baud_t ") - OK\n",
0171       baud_table[i].baud
0172     );
0173     index = rtems_termios_baud_to_index( baud_table[i].constant );
0174     if ( index != i ) {
0175       printf( "ERROR - returned %d should be %d\n", index, i );
0176       rtems_test_exit(0);
0177     }
0178   }
0179 }
0180 
0181 /*
0182  *  Test converting termios baud constant to baud number
0183  */
0184 static void test_termios_baud2number(void)
0185 {
0186   int i;
0187   rtems_termios_baud_t number;
0188 
0189   puts(
0190     "\n"
0191     "Test termios_baud2number..."
0192   );
0193   puts( "termios_baud_to_number(-2) - NOT OK" );
0194   number = rtems_termios_baud_to_number( INVALID_CONSTANT );
0195   rtems_test_assert( number == 0 );
0196 
0197   for (i=0 ; baud_table[i].constant != INVALID_CONSTANT ; i++ ) {
0198     printf(
0199       "termios_baud_to_number(B%" PRIdrtems_termios_baud_t ") - OK\n",
0200       baud_table[i].baud
0201     );
0202     number = rtems_termios_baud_to_number( baud_table[i].constant );
0203     if ( number != baud_table[i].baud ) {
0204       printf(
0205         "ERROR - returned %" PRIdrtems_termios_baud_t
0206         " should be %" PRIdrtems_termios_baud_t "\n",
0207         number,
0208         baud_table[i].baud
0209       );
0210       rtems_test_exit(0);
0211     }
0212   }
0213 }
0214 
0215 /*
0216  *  Test converting baud number to termios baud constant
0217  */
0218 static void test_termios_number_to_baud(void)
0219 {
0220   int i;
0221   tcflag_t termios_baud;
0222 
0223   puts(
0224     "\n"
0225     "Test termios_number_to_baud..."
0226   );
0227   puts( "termios_number_to_baud(-2) - NOT OK" );
0228   termios_baud = rtems_termios_number_to_baud( INVALID_BAUD );
0229   rtems_test_assert( termios_baud == 0 );
0230 
0231   for (i=0 ; baud_table[i].constant != INVALID_CONSTANT ; i++ ) {
0232     printf(
0233       "termios_number_to_baud(B%" PRIdrtems_termios_baud_t ") - OK\n",
0234       baud_table[i].baud
0235     );
0236     termios_baud = rtems_termios_number_to_baud( baud_table[i].baud );
0237     if ( termios_baud != baud_table[i].constant ) {
0238       printf(
0239         "ERROR - returned %d should be %d\n",
0240         termios_baud,
0241         baud_table[i].constant
0242       );
0243       rtems_test_exit(0);
0244     }
0245   }
0246 }
0247 
0248 /*
0249  *  Test all the baud rate options
0250  */
0251 static void test_termios_set_baud(
0252   int test
0253 )
0254 {
0255   int             sc;
0256   int             i;
0257   struct termios  attr;
0258 
0259   puts( "Test termios setting device baud rate..." );
0260   for (i=0 ; baud_table[i].constant != INVALID_CONSTANT ; i++ ) {
0261     sc = tcgetattr( test, &attr );
0262     if ( sc != 0 ) {
0263       printf( "ERROR - return %d\n", sc );
0264       rtems_test_exit(0);
0265     }
0266 
0267     attr.c_ispeed = baud_table[i].constant;
0268     attr.c_ospeed = baud_table[i].constant;
0269 
0270     printf(
0271       "tcsetattr(TCSANOW, B%" PRIdrtems_termios_baud_t ") - OK\n",
0272       baud_table[i].baud
0273     );
0274     sc = tcsetattr( test, TCSANOW, &attr );
0275     if ( sc != 0 ) {
0276       printf( "ERROR - return %d\n", sc );
0277       rtems_test_exit(0);
0278     }
0279 
0280     printf(
0281       "tcsetattr(TCSADRAIN, B%" PRIdrtems_termios_baud_t ") - OK\n",
0282       baud_table[i].baud
0283     );
0284     sc = tcsetattr( test, TCSADRAIN, &attr );
0285     if ( sc != 0 ) {
0286       printf( "ERROR - return %d\n", sc );
0287       rtems_test_exit(0);
0288     }
0289 
0290     printf(
0291       "tcsetattr(TCSAFLUSH, B%" PRIdrtems_termios_baud_t ") - OK\n",
0292       baud_table[i].baud
0293     );
0294     sc = tcsetattr( test, TCSAFLUSH, &attr );
0295     if ( sc != 0 ) {
0296       printf( "ERROR - return %d\n", sc );
0297       rtems_test_exit(0);
0298     }
0299   }
0300 }
0301 
0302 /*
0303  *  Test all the character size options
0304  */
0305 static void test_termios_set_charsize(
0306   int test
0307 )
0308 {
0309   int             sc;
0310   int             i;
0311   struct termios  attr;
0312 
0313   puts(
0314     "\n"
0315     "Test termios setting device character size ..."
0316   );
0317   for (i=0 ; char_size_table[i].constant != INVALID_CONSTANT ; i++ ) {
0318     tcflag_t csize = CSIZE;
0319 
0320     sc = tcgetattr( test, &attr );
0321     if ( sc != 0 ) {
0322       printf( "ERROR - return %d\n", sc );
0323       rtems_test_exit(0);
0324     }
0325 
0326     attr.c_cflag &= ~csize;
0327     attr.c_cflag |= char_size_table[i].constant;
0328 
0329     printf( "tcsetattr(TCSANOW, CS%d) - OK\n", char_size_table[i].bits );
0330     sc = tcsetattr( test, TCSANOW, &attr );
0331     if ( sc != 0 ) {
0332       printf( "ERROR - return %d\n", sc );
0333       rtems_test_exit(0);
0334     }
0335 
0336     printf( "tcsetattr(TCSADRAIN, CS%d) - OK\n", char_size_table[i].bits );
0337     sc = tcsetattr( test, TCSADRAIN, &attr );
0338     if ( sc != 0 ) {
0339       printf( "ERROR - return %d\n", sc );
0340       rtems_test_exit(0);
0341     }
0342 
0343     printf( "tcsetattr(TCSAFLUSH, CS%d) - OK\n", char_size_table[i].bits );
0344     sc = tcsetattr( test, TCSAFLUSH, &attr );
0345     if ( sc != 0 ) {
0346       printf( "ERROR - return %d\n", sc );
0347       rtems_test_exit(0);
0348     }
0349 
0350     printf( "tcsetattr(TCSASOFT, CS%d) - OK\n", char_size_table[i].bits );
0351     sc = tcsetattr( test, TCSASOFT, &attr );
0352     if ( sc != 0 ) {
0353       printf( "ERROR - return %d\n", sc );
0354       rtems_test_exit(0);
0355     }
0356   }
0357 }
0358 
0359 /*
0360  *  Test all the parity options
0361  */
0362 static void test_termios_set_parity(
0363   int test
0364 )
0365 {
0366   int             sc;
0367   int             i;
0368   struct termios  attr;
0369 
0370   puts(
0371     "\n"
0372     "Test termios setting device parity ..."
0373   );
0374   for (i=0 ; parity_table[i].constant != INVALID_CONSTANT ; i++ ) {
0375     tcflag_t par = PARENB | PARODD;
0376 
0377     sc = tcgetattr( test, &attr );
0378     if ( sc != 0 ) {
0379       printf( "ERROR - return %d\n", sc );
0380       rtems_test_exit(0);
0381     }
0382 
0383     attr.c_cflag &= ~par;
0384     attr.c_cflag |= parity_table[i].constant;
0385 
0386     printf( "tcsetattr(TCSANOW, %s) - OK\n", parity_table[i].parity );
0387     sc = tcsetattr( test, TCSANOW, &attr );
0388     if ( sc != 0 ) {
0389       printf( "ERROR - return %d\n", sc );
0390       rtems_test_exit(0);
0391     }
0392 
0393     printf( "tcsetattr(TCSADRAIN, %s) - OK\n", parity_table[i].parity );
0394     sc = tcsetattr( test, TCSADRAIN, &attr );
0395     if ( sc != 0 ) {
0396       printf( "ERROR - return %d\n", sc );
0397       rtems_test_exit(0);
0398     }
0399 
0400     printf( "tcsetattr(TCSAFLUSH, %s) - OK\n", parity_table[i].parity );
0401     sc = tcsetattr( test, TCSAFLUSH, &attr );
0402     if ( sc != 0 ) {
0403       printf( "ERROR - return %d\n", sc );
0404       rtems_test_exit(0);
0405     }
0406 
0407     printf( "tcsetattr(TCSASOFT, %s) - OK\n", parity_table[i].parity );
0408     sc = tcsetattr( test, TCSASOFT, &attr );
0409     if ( sc != 0 ) {
0410       printf( "ERROR - return %d\n", sc );
0411       rtems_test_exit(0);
0412     }
0413   }
0414 }
0415 
0416 /*
0417  *  Test all the stop bit options
0418  */
0419 static void test_termios_set_stop_bits(
0420   int test
0421 )
0422 {
0423   int             sc;
0424   int             i;
0425   struct termios  attr;
0426 
0427   puts(
0428     "\n"
0429     "Test termios setting device character size ..."
0430   );
0431   for (i=0 ; stop_bits_table[i].constant != INVALID_CONSTANT ; i++ ) {
0432     tcflag_t cstopb = CSTOPB;
0433 
0434     sc = tcgetattr( test, &attr );
0435     if ( sc != 0 ) {
0436       printf( "ERROR - return %d\n", sc );
0437       rtems_test_exit(0);
0438     }
0439 
0440     attr.c_cflag &= ~cstopb;
0441     attr.c_cflag |= stop_bits_table[i].constant;
0442 
0443     printf( "tcsetattr(TCSANOW, %d bit%s) - OK\n",
0444       stop_bits_table[i].stop,
0445       ((stop_bits_table[i].stop == 1) ? "" : "s")
0446     );
0447     sc = tcsetattr( test, TCSANOW, &attr );
0448     if ( sc != 0 ) {
0449       printf( "ERROR - return %d\n", sc );
0450       rtems_test_exit(0);
0451     }
0452 
0453     printf( "tcsetattr(TCSADRAIN, %d bits) - OK\n", stop_bits_table[i].stop );
0454     sc = tcsetattr( test, TCSADRAIN, &attr );
0455     if ( sc != 0 ) {
0456       printf( "ERROR - return %d\n", sc );
0457       rtems_test_exit(0);
0458     }
0459 
0460     printf( "tcsetattr(TCSAFLUSH, %d bits) - OK\n", stop_bits_table[i].stop );
0461     sc = tcsetattr( test, TCSAFLUSH, &attr );
0462     if ( sc != 0 ) {
0463       printf( "ERROR - return %d\n", sc );
0464       rtems_test_exit(0);
0465     }
0466 
0467     printf( "tcsetattr(TCSASOFT, %d bits) - OK\n", stop_bits_table[i].stop );
0468     sc = tcsetattr( test, TCSASOFT, &attr );
0469     if ( sc != 0 ) {
0470       printf( "ERROR - return %d\n", sc );
0471       rtems_test_exit(0);
0472     }
0473   }
0474 }
0475 
0476 static void test_termios_cfoutspeed(void)
0477 {
0478   int i;
0479   int sc;
0480   speed_t speed;
0481   struct termios term;
0482   speed_t bad;
0483 
0484   bad = B921600 << 1;
0485   memset( &term, '\0', sizeof(term) );
0486   puts( "cfsetospeed(BAD BAUD) - EINVAL" );
0487   sc = cfsetospeed( &term, bad );
0488   rtems_test_assert( sc == -1 );
0489   rtems_test_assert( errno == EINVAL );
0490 
0491   for (i=0 ; baud_table[i].constant != INVALID_CONSTANT ; i++ ) {
0492     memset( &term, '\0', sizeof(term) );
0493     printf(
0494       "cfsetospeed(B%" PRIdrtems_termios_baud_t ") - OK\n",
0495       baud_table[i].baud
0496     );
0497     sc = cfsetospeed( &term, baud_table[i].constant );
0498     rtems_test_assert( !sc );
0499     printf(
0500       "cfgetospeed(B%" PRIdrtems_termios_baud_t ") - OK\n",
0501       baud_table[i].baud
0502     );
0503     speed = cfgetospeed( &term );
0504     rtems_test_assert( speed == baud_table[i].constant );
0505   }
0506 }
0507 
0508 static void test_termios_cfinspeed(void)
0509 {
0510   int             i;
0511   int             sc;
0512   speed_t         speed;
0513   struct termios  term;
0514   speed_t         bad;
0515 
0516   bad = B921600 << 1;
0517   memset( &term, '\0', sizeof(term) );
0518   puts( "cfsetispeed(BAD BAUD) - EINVAL" );
0519   sc = cfsetispeed( &term, bad );
0520   rtems_test_assert( sc == -1 );
0521   rtems_test_assert( errno == EINVAL );
0522 
0523   for (i=0 ; baud_table[i].constant != INVALID_CONSTANT ; i++ ) {
0524     memset( &term, '\0', sizeof(term) );
0525     printf(
0526       "cfsetispeed(B%" PRIdrtems_termios_baud_t ") - OK\n",
0527       baud_table[i].baud
0528     );
0529     sc = cfsetispeed( &term, baud_table[i].constant );
0530     rtems_test_assert( !sc );
0531 
0532     printf(
0533       "cfgetispeed(B%" PRIdrtems_termios_baud_t ") - OK\n",
0534       baud_table[i].baud
0535     );
0536     speed = cfgetispeed( &term );
0537     rtems_test_assert( speed == baud_table[i].constant );
0538   }
0539 }
0540 
0541 static void test_termios_cfsetspeed(void)
0542 {
0543   int             i;
0544   int             status;
0545   speed_t         speed;
0546   struct termios  term;
0547   speed_t         bad;
0548 
0549   bad = B921600 << 1;
0550   memset( &term, '\0', sizeof(term) );
0551   puts( "cfsetspeed(BAD BAUD) - EINVAL" );
0552   status = cfsetspeed( &term, bad );
0553   rtems_test_assert( status == -1 );
0554   rtems_test_assert( errno == EINVAL );
0555 
0556   for (i=0 ; baud_table[i].constant != INVALID_CONSTANT ; i++ ) {
0557     memset( &term, '\0', sizeof(term) );
0558     printf(
0559       "cfsetspeed(B%" PRIdrtems_termios_baud_t ") - OK\n",
0560       baud_table[i].baud
0561     );
0562     status = cfsetspeed( &term, baud_table[i].constant );
0563     rtems_test_assert( !status );
0564 
0565     printf(
0566       "cfgetspeed(B%" PRIdrtems_termios_baud_t ") - checking both inspeed and outspeed - OK\n",
0567       baud_table[i].baud
0568     );
0569     speed = cfgetispeed( &term );
0570     rtems_test_assert( speed == baud_table[i].constant );
0571 
0572     speed = cfgetospeed( &term );
0573     rtems_test_assert( speed == baud_table[i].constant );
0574   }
0575 }
0576 
0577 static void test_termios_cfmakeraw(void)
0578 {
0579   struct termios  term;
0580 
0581   memset( &term, '\0', sizeof(term) );
0582   cfmakeraw( &term );
0583   puts( "cfmakeraw - OK" );
0584 
0585   /* Check that all of the flags were set correctly */
0586   rtems_test_assert( ~(term.c_iflag & (IMAXBEL|IXOFF|INPCK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IGNPAR)) );
0587 
0588   rtems_test_assert( term.c_iflag & (IGNBRK) );
0589 
0590   rtems_test_assert( ~(term.c_oflag & OPOST) );
0591 
0592   rtems_test_assert( ~(term.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN|NOFLSH|TOSTOP|PENDIN)) );
0593 
0594   rtems_test_assert( ~(term.c_cflag & (CSIZE|PARENB)) );
0595 
0596   rtems_test_assert( term.c_cflag & (CS8|CREAD) );
0597 
0598   rtems_test_assert( term.c_cc[VMIN] == 1 );
0599 
0600   rtems_test_assert( term.c_cc[VTIME] == 0 );
0601 }
0602 
0603 static void test_termios_cfmakesane(void)
0604 {
0605   struct termios  term;
0606 
0607   memset( &term, '\0', sizeof(term) );
0608   cfmakesane( &term );
0609   puts( "cfmakesane - OK" );
0610 
0611   /* Check that all of the flags were set correctly */
0612   rtems_test_assert( term.c_iflag == TTYDEF_IFLAG );
0613 
0614   rtems_test_assert( term.c_oflag == TTYDEF_OFLAG );
0615 
0616   rtems_test_assert( term.c_lflag == TTYDEF_LFLAG );
0617 
0618   rtems_test_assert( term.c_cflag == TTYDEF_CFLAG );
0619 
0620   rtems_test_assert( term.c_ispeed == TTYDEF_SPEED );
0621 
0622   rtems_test_assert( term.c_ospeed == TTYDEF_SPEED );
0623 
0624   rtems_test_assert( memcmp(&term.c_cc, ttydefchars, sizeof(term.c_cc)) == 0 );
0625 }
0626 
0627 typedef struct {
0628   rtems_termios_device_context base;
0629   bool done;
0630 } device_context;
0631 
0632 static rtems_status_code test_early_device_install(
0633   rtems_device_major_number major,
0634   rtems_device_minor_number minor,
0635   void *arg
0636 )
0637 {
0638   static const rtems_termios_device_handler handler;
0639   static const char dev[] = "/foobar";
0640 
0641   rtems_resource_snapshot snapshot;
0642   rtems_status_code sc;
0643   int fd;
0644   int rv;
0645   int i;
0646 
0647   rtems_resource_snapshot_take( &snapshot );
0648 
0649   sc = rtems_termios_device_install( &dev[0], &handler, NULL, NULL );
0650   rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0651 
0652   /*
0653    * The loop ensures that file descriptor 0 is the first free file descriptor
0654    * after this test case.
0655    */
0656   for (i = 0; i < 4; ++i) {
0657     fd = open( &dev[0], O_RDWR );
0658     rtems_test_assert( fd == i );
0659 
0660     rv = close( fd );
0661     rtems_test_assert( rv == 0 );
0662   }
0663 
0664   rv = unlink( &dev[0] );
0665   rtems_test_assert( rv == 0 );
0666 
0667   rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );
0668 
0669   return RTEMS_SUCCESSFUL;
0670 }
0671 
0672 static void test_device_install_remove(void)
0673 {
0674   static const rtems_termios_device_handler handler;
0675   static const char dev[] = "/foobar";
0676 
0677   rtems_resource_snapshot snapshot;
0678   rtems_status_code sc;
0679   void *greedy;
0680   int rv;
0681 
0682   rtems_resource_snapshot_take( &snapshot );
0683 
0684   greedy = rtems_heap_greedy_allocate( NULL, 0 );
0685 
0686   sc = rtems_termios_device_install( "/", &handler, NULL, NULL );
0687   rtems_test_assert( sc == RTEMS_NO_MEMORY );
0688 
0689   rtems_heap_greedy_free( greedy );
0690 
0691   rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );
0692 
0693   sc = rtems_termios_device_install( "/", &handler, NULL, NULL );
0694   rtems_test_assert( sc == RTEMS_UNSATISFIED );
0695 
0696   rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );
0697 
0698   sc = rtems_termios_device_install( &dev[0], &handler, NULL, NULL );
0699   rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0700 
0701   rv = unlink( &dev[0] );
0702   rtems_test_assert( rv == 0 );
0703 
0704   rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );
0705 }
0706 
0707 static bool first_open_error(
0708   rtems_termios_tty *tty,
0709   rtems_termios_device_context *base,
0710   struct termios *term,
0711   rtems_libio_open_close_args_t *args
0712 )
0713 {
0714   device_context *ctx = (device_context *) base;
0715 
0716   (void) tty;
0717   (void) term;
0718   (void) args;
0719 
0720   ctx->done = true;
0721 
0722   return false;
0723 }
0724 
0725 static void test_first_open_error(void)
0726 {
0727   static const rtems_termios_device_handler handler = {
0728     .first_open = first_open_error
0729   };
0730   static const char dev[] = "/foobar";
0731 
0732   rtems_resource_snapshot snapshot;
0733   rtems_status_code sc;
0734   int fd;
0735   int rv;
0736   device_context ctx = {
0737     .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "abc" ),
0738     .done = false
0739   };
0740 
0741   rtems_resource_snapshot_take( &snapshot );
0742 
0743   sc = rtems_termios_device_install( &dev[0], &handler, NULL, &ctx.base );
0744   rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0745 
0746   rtems_test_assert( !ctx.done );
0747   errno = 0;
0748   fd = open( &dev[0], O_RDWR );
0749   rtems_test_assert( fd == -1 );
0750   rtems_test_assert( errno == ENOMEM );
0751   rtems_test_assert( ctx.done );
0752 
0753   rv = unlink( &dev[0] );
0754   rtems_test_assert( rv == 0 );
0755 
0756   rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );
0757 }
0758 
0759 static bool set_attributes_error(
0760   rtems_termios_device_context *base,
0761   const struct termios *term
0762 )
0763 {
0764   device_context *ctx = (device_context *) base;
0765 
0766   (void) term;
0767 
0768   ctx->done = true;
0769 
0770   return false;
0771 }
0772 
0773 static void test_set_attributes_error(void)
0774 {
0775   static const rtems_termios_device_handler handler = {
0776     .set_attributes = set_attributes_error
0777   };
0778   static const char dev[] = "/foobar";
0779 
0780   rtems_resource_snapshot snapshot;
0781   rtems_status_code sc;
0782   struct termios term;
0783   device_context ctx = {
0784     .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "abc" ),
0785     .done = false
0786   };
0787   int fd;
0788   int rv;
0789 
0790   rtems_resource_snapshot_take( &snapshot );
0791 
0792   sc = rtems_termios_device_install( &dev[0], &handler, NULL, &ctx.base );
0793   rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0794 
0795   fd = open( &dev[0], O_RDWR );
0796   rtems_test_assert( fd >= 0 );
0797 
0798   rtems_test_assert( !ctx.done );
0799   errno = 0;
0800   rv = ioctl( fd, TIOCSETA, &term );
0801   rtems_test_assert( rv == -1 );
0802   rtems_test_assert( errno == EIO );
0803   rtems_test_assert( ctx.done );
0804 
0805   rv = close( fd );
0806   rtems_test_assert( rv == 0 );
0807 
0808   rv = unlink( &dev[0] );
0809   rtems_test_assert( rv == 0 );
0810 
0811   rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );
0812 }
0813 
0814 static void test_set_best_baud(void)
0815 {
0816   static const struct {
0817     uint32_t baud;
0818     speed_t speed;
0819   } baud_to_speed_table[] = {
0820     { 0,          B0 },
0821     { 25,         B0 },
0822     { 26,         B50 },
0823     { 50,         B50 },
0824     { 62,         B50 },
0825     { 63,         B75 },
0826     { 75,         B75 },
0827     { 110,        B110 },
0828     { 134,        B134 },
0829     { 150,        B150 },
0830     { 200,        B200 },
0831     { 300,        B300 },
0832     { 600,        B600 },
0833     { 1200,       B1200 },
0834     { 1800,       B1800 },
0835     { 2400,       B2400 },
0836     { 4800,       B4800 },
0837     { 9600,       B9600 },
0838     { 19200,      B19200 },
0839     { 38400,      B38400 },
0840     { 57600,      B57600 },
0841     { 115200,     B115200 },
0842     { 230400,     B230400 },
0843     { 460800,     B460800 },
0844     { 0xffffffff, B460800 }
0845   };
0846 
0847   size_t n = RTEMS_ARRAY_SIZE(baud_to_speed_table);
0848   size_t i;
0849 
0850   for ( i = 0; i < n; ++i ) {
0851     struct termios term;
0852 
0853     memset( &term, 0xff, sizeof( term ) );
0854     rtems_termios_set_best_baud( &term, baud_to_speed_table[ i ].baud );
0855 
0856     rtems_test_assert( term.c_ispeed == baud_to_speed_table[ i ].speed );
0857     rtems_test_assert( term.c_ospeed == baud_to_speed_table[ i ].speed );
0858   }
0859 }
0860 
0861 static rtems_task Init(
0862   rtems_task_argument ignored
0863 )
0864 {
0865   int                       rc;
0866   rtems_status_code         sc;
0867   rtems_device_major_number registered;
0868   int                       test;
0869   struct termios            t;
0870   int index = 0;
0871 
0872   TEST_BEGIN();
0873 
0874   test_termios_baud2index();
0875   test_termios_baud2number();
0876   test_termios_number_to_baud();
0877 
0878   sc = rtems_termios_bufsize( 256, 128, 64 );
0879   directive_failed( sc, "rtems_termios_bufsize" );
0880 
0881   /*
0882    * Register a driver
0883    */
0884   puts(
0885     "\n"
0886     "Init - rtems_io_register_driver - Termios Test Driver - OK"
0887   );
0888   sc = rtems_io_register_driver( 0, &test_driver, &registered );
0889   printf( "Init - Major slot returned = %d\n", (int) registered );
0890   directive_failed( sc, "rtems_io_register_driver" );
0891 
0892   /*
0893    * Test baud rate
0894    */
0895   puts( "Init - open - " TERMIOS_TEST_DRIVER_DEVICE_NAME " - OK" );
0896   test = open( TERMIOS_TEST_DRIVER_DEVICE_NAME, O_RDWR );
0897   if ( test == -1 ) {
0898     printf( "ERROR - baud opening test device (%d)\n", test );
0899     rtems_test_exit(0);
0900   }
0901 
0902   /*
0903    * tcsetattr - ERROR invalid operation
0904    */
0905   puts( "tcsetattr - invalid operation - EINVAL" );
0906   rc = tcsetattr( test, INT_MAX, &t );
0907   rtems_test_assert( rc == -1 );
0908   rtems_test_assert( errno == EINVAL );
0909 
0910   test_termios_cfmakeraw();
0911   test_termios_cfmakesane();
0912 
0913   /*
0914    * tcsetattr - TCSADRAIN
0915    */
0916   puts( "\ntcsetattr - drain - OK" );
0917   rc = tcsetattr( test, TCSADRAIN, &t );
0918   rtems_test_assert( rc == 0 );
0919 
0920   test_termios_set_baud(test);
0921 
0922   puts( "Init - close - " TERMIOS_TEST_DRIVER_DEVICE_NAME " - OK" );
0923   rc = close( test );
0924   if ( rc != 0 ) {
0925     printf( "ERROR - baud close test device (%d) %s\n", test, strerror(errno) );
0926     rtems_test_exit(0);
0927   }
0928 
0929   /*
0930    * Test character size
0931    */
0932   puts(
0933     "\n"
0934     "Init - open - " TERMIOS_TEST_DRIVER_DEVICE_NAME " - OK"
0935   );
0936   test = open( TERMIOS_TEST_DRIVER_DEVICE_NAME, O_RDWR );
0937   if ( test == -1 ) {
0938     printf( "ERROR - size open test device (%d) %s\n", test, strerror(errno) );
0939     rtems_test_exit(0);
0940   }
0941 
0942   test_termios_set_charsize(test);
0943 
0944   puts( "Init - close - " TERMIOS_TEST_DRIVER_DEVICE_NAME " - OK" );
0945   rc = close( test );
0946   if ( rc != 0 ) {
0947     printf( "ERROR - size close test device (%d) %s\n", test, strerror(errno) );
0948     rtems_test_exit(0);
0949   }
0950 
0951   /*
0952    * Test parity
0953    */
0954   puts(
0955     "\n"
0956     "Init - open - " TERMIOS_TEST_DRIVER_DEVICE_NAME " - OK"
0957   );
0958   test = open( TERMIOS_TEST_DRIVER_DEVICE_NAME, O_RDWR );
0959   if ( test == -1 ) {
0960     printf( "ERROR - parity open test device (%d) %s\n",
0961       test, strerror(errno) );
0962     rtems_test_exit(0);
0963   }
0964 
0965   test_termios_set_parity(test);
0966 
0967   puts( "Init - close - " TERMIOS_TEST_DRIVER_DEVICE_NAME " - OK" );
0968   rc = close( test );
0969   if ( rc != 0 ) {
0970     printf( "ERROR - parity close test device (%d) %s\n",
0971       test, strerror(errno) );
0972     rtems_test_exit(0);
0973   }
0974 
0975   /*
0976    * Test stop bits
0977    */
0978   puts(
0979     "\n"
0980     "Init - open - " TERMIOS_TEST_DRIVER_DEVICE_NAME " - OK"
0981   );
0982   test = open( TERMIOS_TEST_DRIVER_DEVICE_NAME, O_RDWR );
0983   if ( test == -1 ) {
0984     printf( "ERROR - stop bits open test device (%d) %s\n",
0985       test, strerror(errno) );
0986     rtems_test_exit(0);
0987   }
0988 
0989   test_termios_set_stop_bits(test);
0990 
0991   test_termios_cfoutspeed();
0992 
0993   test_termios_cfinspeed();
0994 
0995   test_termios_cfsetspeed();
0996 
0997   puts( "Init - close - " TERMIOS_TEST_DRIVER_DEVICE_NAME " - OK" );
0998   rc = close( test );
0999   if ( rc != 0 ) {
1000     printf( "ERROR - stop bits close test device (%d) %s\n",
1001       test, strerror(errno) );
1002     rtems_test_exit(0);
1003   }
1004 
1005 
1006   puts( "Multiple open of the device" );
1007   for( ; index < 26; ++index ) {
1008     test = open( TERMIOS_TEST_DRIVER_DEVICE_NAME, O_RDWR );
1009     rtems_test_assert( test != -1 );
1010     rc = close( test );
1011     rtems_test_assert( rc == 0 );
1012   }
1013   puts( "" );
1014 
1015   test_device_install_remove();
1016   test_first_open_error();
1017   test_set_attributes_error();
1018   test_set_best_baud();
1019 
1020   TEST_END();
1021   rtems_test_exit(0);
1022 }
1023 
1024 /* configuration information */
1025 
1026 #define CONFIGURE_APPLICATION_PREREQUISITE_DRIVERS \
1027   { .initialization_entry = test_early_device_install }
1028 
1029 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
1030 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
1031 
1032 /* include an extra slot for registering the termios one dynamically */
1033 #define CONFIGURE_MAXIMUM_DRIVERS 4
1034 
1035 /* we need to be able to open the test device */
1036 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
1037 
1038 #define CONFIGURE_MAXIMUM_TASKS         1
1039 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
1040 
1041 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
1042 
1043 #define CONFIGURE_INIT
1044 #include <rtems/confdefs.h>
1045 
1046 /* global variables */