LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   termios /dev/ttyUSB0 "resource unavailable" (https://www.linuxquestions.org/questions/programming-9/termios-dev-ttyusb0-resource-unavailable-738915/)

nanoo 07-09-2009 11:09 AM

termios /dev/ttyUSB0 "resource unavailable"
 
Hi!
I am working on simple project which will extract temperature from microcontroller. It is connected to computer through serial-to-usb chip.
The testing of connection is: I send to mc one char "p" and it answer me with "p\0" (2 bytes). And even with this simple interchange I have encountered a problem.
Code:

#include<stdio.h>
#include<errno.h>
#include<termios.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>

int tty_set(int tty)
{
        struct termios tty_opts;
        int foo;
       
        foo=tcgetattr(tty,&tty_opts);
        if(foo<0) return -1;
       
        foo=cfsetispeed(&tty_opts,B9600);
        if(foo<0) return -2;
       
        foo=cfsetospeed(&tty_opts,B9600);
        if(foo<0) return -3;
       
        //3
        // 8N1
        tty_opts.c_cflag &= ~PARENB;
        tty_opts.c_cflag &= ~CSTOPB;
        tty_opts.c_cflag &= ~CSIZE;
        tty_opts.c_cflag |= CS8;
        // no flow control
        tty_opts.c_cflag &= ~CRTSCTS;

        tty_opts.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
        tty_opts.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl

        tty_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
        tty_opts.c_oflag &= ~OPOST; // make raw

        // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
        tty_opts.c_cc[VMIN]  = 0;
        tty_opts.c_cc[VTIME] = 0;
        //end3

        foo=tcsetattr(tty,TCSANOW, &tty_opts);
        if(foo<0) return -4;
       
        return 0;
}

int tty_test_connection(int tty)
{
        int foo;
        char buf[4]={'p',0,0,0};
       
        foo=write(tty,buf,1);
        if(foo<0){
                perror("write");
                return foo;
        }
        if(foo==0){
                puts("nothing written");
                return foo;
        }
L0:
        foo=read(tty,buf,2); //mc should return 2 bytes p and \0
        if(foo<0){
                perror("read");
                return foo;
        }
        if(foo<2){
                puts("less then 2 bytes was red");
                return foo;
        }

        buf[foo]='\0';
        printf("ping was: %s\n",buf);
        return foo;
}

int main(int ac,char *av[])
{
        int tty_dev;
        int foo;
       
        tty_dev=0;
        tty_dev = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
        if(tty_dev < 0){
                perror("open");
                return -1;
        }
        puts("open: ok");
       
        foo=tty_set(tty_dev);
        if(foo<0){
                perror("tty_set");
                close(tty_dev);
                return -1;
        }
        puts("tty_set: ok");
       
       
        foo=tty_test_connection(tty_dev);
        if(foo<0){
                perror("tty_test_connection");
                printf("foo: %d\n",foo);
                return -1;
        }
        printf("tty_test_connection: %d characters red\n",foo);
        close(tty_dev);
        return 0;
}

The problem is: when read() (see L0 lebel) is executed it returns either "resource temporarily unavailable" or 0.
* mc is working fine. I tested it with screen(1) and minicom(1)
* if set VTIME or VMIN in not 0 value it behaves the same.
* using fscanf(3) just block the program.
* google does not give sufficient results.
Does anyone know where is the problem?
Thanks in advance.

osor 07-12-2009 07:59 PM

Quote:

Originally Posted by nanoo (Post 3602298)
The problem is: when read() (see L0 lebel) is executed it returns either "resource temporarily unavailable" or 0.

This is because you have open()ed as a non-blocking file descriptor. I suggest you either open() as blocking or use select()/poll().
Quote:

Originally Posted by nanoo (Post 3602298)
* using fscanf(3) just block the program.

fscanf() should block until it encounters a newline.

nanoo 07-13-2009 06:02 AM

Ok. I tried to open it in blocking mode removing NDELAY flag in open() func. But now read() returns 0 a couple of thousands times and then returns what it should. As I understand all of this time buffer was empty (0 means eof as written in man page) and when data arrive it read data.
Am I right?
I think there are only two solutions. Either using sigaction to react on SIGIO or using select/poll as you advice. Do any other ways exist?
Thank for help!

osor 07-13-2009 06:15 PM

Quote:

Originally Posted by nanoo (Post 3605874)
I tried to open it in blocking mode removing NDELAY flag in open() func.

If you want to make normal non-blocking I/O, you will need to get rid of the VTIME and VMIN stuff.

Unless I misunderstood your motives, it seems as though blocking I/O is sufficient, as non-blocking will some extra code for no real benefit (unless your device is timing-sensitive or something).

nanoo 07-14-2009 10:53 AM

Ok. Now tty_test_connection looks like that:
Code:

int tty_test_connection(int tty)
{
        int foo;
        char buf[4]={'p',0,0,0};
       
        struct pollfd descriptor;
        memset(&descriptor,0,sizeof(struct pollfd));
       
        foo=write(tty,buf,1);
        if(foo<0){
                perror("write");
                return foo;
        }
        if(foo==0){
                puts("nothing written");
                return foo;
        }

L0:
        descriptor.fd=tty;
        descriptor.events = POLLIN;
        foo=poll(&descriptor,1,2000);
        if(foo<0){
                perror("poll");
                return foo;
        }
        if(foo==0){
                puts("poll timeout");
                goto L0;
        }
        if(descriptor.revents && POLLIN == POLLIN){
                foo=read(tty,buf,4);
                if(foo<0){
                        perror("read");
                        return foo;
                }
        } else {
                puts("no POLLIN in revents");
                return 0;
        }
       
        buf[foo]='\0';
        printf("ping was: %s\n",buf);
        return foo;
}

I also commented VTIME and VMIN stuff.
It seems it is working know, but program behave a bit strange. If I plug usb cable in, wait when /dev/ttyUSB0 appears an start program I get
[CODE]
./a.out
open: ok
tty_set: ok
poll timeout
poll timeout
.....
[\CODE]
after C-c and restarting program several times it work perfect then.
Can you explain what I did wrong?
Thanks!


All times are GMT -5. The time now is 04:40 AM.