Lomazo
Lomazo

Reputation: 11

Losing data on serial read

Im trying to writte a small app in C that reads data from serial port and stores it in a binary file. I'm using this instruction to read from serial but I loose data.

n = read(fd, &buf, sizeof(buf));

So I added this code right after the previous one in order to see what happens.

    if(n!= strlen(buf)&&n!=-1){
        printf("N= %d strlen = %d\n",n,strlen(buf));
        printf("%s",buf);
    }

I saw that the value of n is correct but the strlen(buf) is not (should be the same as n ) and I dont know why.... The buffer variable buf is defined like this char[1000] buf; and n is a integer.

The port is in raw mode on both sides, and this is how i set it on the side of my app.

tcgetattr(fd, &options);

    /*
     * Set the baud rates to 38400...
     */

    cfsetispeed(&options, B38400);
    cfsetospeed(&options, B38400);

    /*
     * Enable the receiver and set local mode...
     */

    options.c_cflag |= (CLOCAL | CREAD);

    /*
     * No parity (8N1):
     */
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    /* To disable software flow control simply mask those bits: */
    options.c_iflag &= ~(IXON | IXOFF | IXANY);
    options.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG);

    /* Disable hardware flow control: */
    /* unavailable to the gcc -> options.c_cflag &= ~CNEW_RTSCTS;*/

    /*
     * Set the new options for the port...
     */

    tcsetattr(fd, TCSANOW, &options);

Any idea what could I be doing wrong?

Thanks

Upvotes: 0

Views: 291

Answers (1)

Joe
Joe

Reputation: 7818

A couple of points. As unwind points out, if you're using binary data with strlen, your new code won't work.

However your need to check the return value from read is correct. It is likely not to return the amount of data you expect (merely being task switched while reading will give you problems).

So I suspect you're on the right track, checking that you've read what you expect and going back to get what's left if it is a short read. You just can't do that by using strlen on binary data.

It's reasonably common for people to write a "read_all" function, that keeps reading until it's got all the data needed or drops out when there's an error, read on its own does not behave like this.

I'd probably modify your check like so:

if((n = read(fd, &buf, sizeof(buf)) != sizeof(buf)) {
// Check for errors or short reads and handle appropriately.

Upvotes: 2

Related Questions