views:

1248

answers:

5

Hello all!

I am having some trouble reading some data from a serial port I opened the following way. I've used this instance of code plenty of times and all worked fine, but now, for some reason that I cant figure out, I am completely unable to read anything from the serial port.

I am able to write and all is correctly received on the other end, but the replies (which are correctly sent) are never received (No, the cables are all ok ;) )

The code I used to open the serial port is the following:

fd = open("/dev/ttyUSB0", O_RDWR | O_NONBLOCK | O_NOCTTY);
if (fd == -1)
{
    Aviso("Unable to open port");
    return (fd);
}
else
{
    //Get the current options for the port...
    bzero(&options, sizeof(options)); /* clear struct for new port settings */
    tcgetattr(fd, &options);

    /*-- Set baud rate -------------------------------------------------------*/
    if (cfsetispeed(&options, SerialBaudInterp(BaudRate))==-1)
        perror("On cfsetispeed:");
    if (cfsetospeed(&options, SerialBaudInterp(BaudRate))==-1)
        perror("On cfsetospeed:");

    //Enable the receiver and set local mode...
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB; /* Parity disabled */
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;  /* Mask the character size bits */
    options.c_cflag |= SerialDataBitsInterp(8);           /* CS8 - Selects 8 data bits */
    options.c_cflag &= ~CRTSCTS;                      // disable hardware flow control
    options.c_iflag &= ~(IXON | IXOFF | IXANY);           // disable XON XOFF (for transmit and receive)
    options.c_cflag |= CRTSCTS;                         /* enable hardware flow control */

    options.c_cc[VMIN] = 0;  //min carachters to be read
    options.c_cc[VTIME] = 0;    //Time to wait for data (tenths of seconds)

    //Set the new options for the port...
    tcflush(fd, TCIFLUSH);
    if (tcsetattr(fd, TCSANOW, &options)==-1)
    {
        perror("On tcsetattr:");
    }

    PortOpen[ComPort] = fd;
}

return PortOpen[ComPort];

After the port is initializeed I write some stuff to it through simple write command...

int nc = write(hCom, txchar, n);

where hCom is the file descriptor (and it's ok), and (as I said) this works. But... when I do a read afterwards, I get a "Resource Temporarily Unavailable" error from errno.

I tested select to see when the file descriptor had something t read... but it always times out!

I read data like this:

ret = read(hCom, rxchar, n);

and I always get an EAGAIN and I have no idea why.

All help would be appreciated.

Cheers

+3  A: 

Read this.

EAGAIN Non-blocking I/O has been selected using O_NONBLOCK and no data was immediately available for reading.

jldupont
That's exactly the problem, if a little terse. I guess the broader question is why are you specifying O_NONBLOCK if you aren't prepared to handle it's behavior?
Andy Ross
A: 

EAGAIN with O_NONBLOCK means there's been no data received on the port. Check that the port and cable are working properly (using minicom or some other known-good program), and that the remote really is sending some data.

bdonlan
A: 

see my code samples, if EAGAIN, you'd try to read again:

...
options.c_cflag &= ~PARENB; 
options.c_iflag &= ~INPCK; 
...
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // input
options.c_oflag &= ~OPOST; // output
...
fd = open("/dev/ttyUSB0", O_RDWR | O_NDELY | O_NOCTTY);
fcntl(fd, F_SETFL, 0);
...
int nc = write(hCom, txchar, n);
msleep(500); // wait 500ms
fcntl(hCom, F_SETFL, FNDELAY); // don't block serial read
ret = read(hCom, rxchar, n);
if (ret > 0) {
    here had read n bytes or just partial data, read again if partial.
} 
if (ret < 0) {
    if (EAGAIN == errno) {
        not a real error, just read again.
    } else {
        oops, errors.
    }
}
...
EffoStaff Effo
been there ;) loop checking. Then used select to check when data is available... all that I could remember... I tried ;)
Andre
null-modem cable or extern loopback cable? if the later, what's about the pinout?
EffoStaff Effo
just soldered the Tx and Rx of the RS232 port to another and then read form it from hyperterm on another machine
Andre
well, my code had tested and works in both external loopback case and c code vs. hyperterm case. how about use without NONBLOCK but wait(500ms) when writing, and set FNDELAY before reading, like my code? if still not works for you, i have no idea too.
EffoStaff Effo
EffoStaff Effo
hummm. not in the debug cable. The others are fully paired. I used the cables that came with the box I'm reading data from.There is something fishy going on! "Resource temporarily unavailable" is what errno says about EAGAIN, but no one else has the com open! I opened it, wrote to it and then... I can't read from it! Could the read be blocking somehow...
Andre
A: 

hey, just to clarify some things!

The HW is working fine! I can see that there is inbound data on the serial port because I've made a debug cable to read whats going on on another terminal. So...

I know what nonblocking should do. My question is... why isn't anything getting read!. The same setup works fine on windows, so all hardware is working fine...

This is driving me nuts! I'm sure it's something simple as hell! I even tried getting rid of O_NONBLOCK to see when I would receive something... but nothing...

Andre
A: 

I have this same problem. I can transmit but not receive (via USB-RS232 adapter cable). I tried on another linux box that had a RS232 port and it worked just fine. The only change I made was from /dev/ttyUSB0 to /dev/ttyS0. The first computer was Fedora the second is Debian. Other than that, idunno.

One other thing. When I close the com program and restart it, the data is read by my program! The data is the input buffer, but my program does not know it. Also, gtkterm works fine, so the h/w is all OK. My program does not see the UART interrupt.

This linux h/w abstraction layer is rather bogus. This should not be a problem.
later........don

Don Lawrence