Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

select() does not seem to work on TTY

I'm currently writing a program that needs to communicate with an AT interface over an UART interface (the operating system is Linux). But I'm having trouble using select() on the file descriptor. For some reason select does not consider the file descriptor to be ready for reading, but To narrow down the problem I have used the following program.

int main()
{
    char buffer[BSIZE];
    fd_set rfds;
    int ret;
    struct termios cnf;
    struct timeval tv;

    fd = open("/dev/ttyO1", O_RDWR);
    // Have also tried to set fd = 0 for stdin, as a reference
    signal(SIGINT, sig_handler);
    tcgetattr(fd, &cnf);
    old = cnf;
    cfmakeraw(&cnf);
    tcsetattr(fd, TCSANOW, &cnf);
    while (1) {
        tv.tv_sec = 5;
        tv.tv_usec = 0;
        FD_ZERO(&rfds);
        FD_SET(0, &rfds);
        write(fd, "AT\r", 3);
        ret = select(fd+1, &rfds, NULL, NULL, &tv);
        printf("ret = %d\n", ret);
        if (ret < 0) {
            perror("select()");
        }
        else {
            ret = read(fd, buffer, BSIZE-1);
            buffer[ret] = '\0';
            printf("read: \"%s\"\n", buffer);
        }
    }
    return 0;
}

The run looks something like this

    root@linux:~# ./stuff
    ret = 0
    read: "AT
    OK
    "

Which indicates that select thinks that there is no data, but when trying to read there is data. This seems very strange to me. Also, I've tried to exchange the tty with stdin, and that works just fine.

The code is being run on Texas Instruments EZSDK PSP kernel, but that shouldn't be the problem. Also, the stty settings looks like the following

    root@linux:~# stty -aF /dev/ttyO1
    speed 9600 baud; rows 24; columns 80;
    intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
    eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
    lnext = ^V; flush = ^O; min = 1; time = 0;
    -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
    -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
    -iuclc -ixany -imaxbel
    opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
    isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
    echoctl echoke

Have I missed som crucial flag to open()? or perhaps need to set some setting using termios? Does this method require some special hardware

EDIT: I get the same problem when trying to run the program /dev/ttyUSB0, which also happens to be is an AT interface. Seems to me that it is tty related.

changed fd to what I actually used and wondered about.

like image 549
Kotte Avatar asked Apr 14 '26 03:04

Kotte


1 Answers

You don't add file descriptor of serial port to fd set.

Change line:

FD_SET(0, &rfds);

to:

FD_SET(fd, &rfds);

Or add the following line, if you need fd zero in the set.

FD_SET(fd, &rfds);
like image 156
SKi Avatar answered Apr 15 '26 17:04

SKi