2

Here is my code

void Reading_TtyS0()
{
     int ret;
     char mypipe_ttyS0[80] = {0};
     fcntl(fd, F_SETFL, 0);

     ret = read(fd, ttyS0_mypipe , 80 );
     printf(ret = %d\n", ret);
     if (ret > 0)
     {
         perror("Message Log, Reading /dev/ttyS0");
         printf("Message Log, Reading /dev/ttyS0 with data = %s\n",  ttyS0_mypipe);
         tcflush(fd, TCIFLUSH);
         ret = 0;
     }
}

My output is

ret = 8

Message Log, Reading /dev/ttyS0: Success

Message Log, Reading /dev/ttyS0 with data = 0066923:

I am reading only 8 bytes instead of 80.

I should receive 0066923:12:13:134:1134:112344:333...(till 80 bytes)

The output on gtkterm and I am receiving the complete data.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278

2 Answers2

3

read() does not necessarily return the number of bytes it was told to read.

So loop around read until you got what you want:

 char mypipe_ttyS0[80] = {0};
 fcntl(fd, F_SETFL, 0);

 size_t bytes_to_read = 80;
 size_t bytes_read = 0;
 while (bytes_to_read > 0)
 {
   ssize_t result = read(fd, ttyS0_mypipe + bytes_read, bytes_to_read);
   if (-1 == result)
   {
     if ((EWOULDBLOCK == errno) || (EAGAIN == errno))
     {
       continue;
     }

     perror("read() failed");

     break;
   } 
   else (0 == result)
   {
     fprintf(stderr, "Connection closed.");

     break;
   }

   printf("Read %zd bytes.\n", result);

   bytes_to_read -= result;
   bytes_read += result;
 }

 ....
alk
  • 69,737
  • 10
  • 105
  • 255
  • Check for EWOULDBLOCK and EAGAIN? Why is that? read() is a blocking call here. fcntl() sets implicitly O_NONBLOCK to zero. Maybe it is better to use EINTR check? – Michael Nov 19 '13 at 07:07
  • @Michael: No, it surely isn't a non-blocking call, and those parts of the code are needless on this serial connection and will never be accessed. I just added it to clarify what I mentioned in my comments to *Chirag Desai*'s answer. It's just the generic way to use `read()`. – alk Nov 19 '13 at 07:11
  • @akl It was not mine down. I'm ok with your answer. – Michael Nov 19 '13 at 11:58
0

Its non-blocking read operation, so its possible that read will return whatever data received in the buffer at the moment.

You have to loop through the read until all data received.

 int ret;
 char mypipe_ttyS0[80] = {0};
 fcntl(fd, F_SETFL, 0);

 int i = 5; // let say iterate 5 times
 int bytes_to_read = 80;
 ret = 0;
 while (i > 0)
 {
    ret += read(fd, mypipe_ttyS0 + ret , bytes_to_read );
    printf(ret = %d\n", ret);

    bytes_to_read -= ret;
    if(bytes_to_read == 0)
    {
         break;
    } 
    ++i;
 }

    if (bytes_to_read == 0)
    {
         perror("Message Log, Reading /dev/ttyS0");
         printf("Message Log, Reading /dev/ttyS0 with data = %s\n",  ttyS0_mypipe);
         tcflush(fd, TCIFLUSH);
         ret = 0;
    }
Chirag Desai
  • 1,249
  • 1
  • 10
  • 22
  • Why not changed the `while()` condition to be `(bytes_to_read > 0)`? Couldn't it take more then "*let' say*" `5` times to get all data? Also the code misses to check the result of `read()` for error and end-of-file/connection-closed. – alk Nov 19 '13 at 06:24
  • We can put `(bytes_to_read > 0)` but in that case the read operation will become clocking. And yeas true I did not check for `read()` errors as the loop is going to end in 5 iterations anyway... – Chirag Desai Nov 19 '13 at 06:44
  • 2
    The `read()` as shown in the OP's example is **not** a non-blocking call. It is a blocking call, as it always returns at least one byte. If it would be a non-blocking call then `read()` might return `-1` with `errno` set to `EWOULDBLOCK`. Please see `man 3 read` for details. – alk Nov 19 '13 at 06:54
  • 1
    Also your code overwrites `ttyS0_mypipe` with every iteration. – alk Nov 19 '13 at 07:00
  • See @alk , Azeemali Hashmani doesnot have issue with his code, He wants to know why read is incomplete. And I think he got his answer .. – Chirag Desai Nov 19 '13 at 07:52