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);
}

Reply via email to