The attached program ratchets through the bitrates defined in termios.h and tests a given (as first argument) serial port. This test will indicate if tcsetattr() returns an error when invalid bitrates are attempted on a given serial port (along with perror() to print the error-message associated w/ errno.)
In the event that an invalid bitrate is attempted on a port, two events should occur. 1) tcsetattr() should return -1, and 2) errno should be set to EINVAL. Event #1 seems to work fine w/ my latest patch, but event #2 is failing because errno is always set to 0. Unless I'm doing something wrong, it appears that errno isn't being propagated back up from the call to tcsetattr() ... can someone else take a peek at this? Thanks, -Troy
/* Test all POSIX defined bitrates on a given serial port */ #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <termios.h> #include <errno.h> typedef struct { speed_t s; int speed; } speedlist_t; speedlist_t speedlist[] = { {B0,0},{B50,50},{B75,75},{B110,110}, {B134,134}, {B150,150}, {B200,200}, {B300,300}, {B600,600}, {B1200,1200},{B1800,1800}, {B2400,2400},{B4800,4800},{B9600,9600},{B19200,19200},{B38400,38400}, {B57600,57600},{B115200,115200},{B128000,128000}, #ifdef B230400 {B230400,230400}, #endif {B256000,256000} }; int main(int argc,char **argv) { struct termios dcb; int fd,i; if (argc != 2) { fprintf(stderr,"Usage: %s serial_port_name\n",argv[0]); return(1); } // Try opening the port (and validate its tty status) if ((fd = open(argv[1],O_RDWR|O_NOCTTY|O_NONBLOCK)) != -1) { if (isatty(fd)) { fprintf(stderr,"Testing all POSIX bitrates for port: %s\n",argv[1]); // Grab the existing DCB/termios parameters (to be safe) if (tcgetattr(fd,&dcb) == -1) { perror("Can't get port settings"); close(fd); return(1); } // 8N1, raw access dcb.c_cflag = CLOCAL|CS8|CREAD; // No min # chars dcb.c_cc[VMIN] = 0; // No max timeout dcb.c_cc[VTIME] = 0; // No postprocessing dcb.c_oflag = dcb.c_iflag = dcb.c_lflag = 0; // iterate through all POSIX-defined bitrates for (i=0;i<(sizeof(speedlist)/sizeof(speedlist_t));i++) { dcb.c_ispeed = dcb.c_ospeed = speedlist[i].s; fprintf(stderr,"Trying %u bps \t: ",speedlist[i].speed); // Make the DCB/termios settings effective and report error/success if (tcsetattr(fd, TCSANOW, &dcb) < 0) perror("Can't set port settings"); else fprintf(stderr,"Success\n"); } } else { perror("Port isn't a serial port"); close(fd); return(1); } } else { perror("Can't open port"); return(1); } // Close up and exit cleanly close(fd); return(0); }