Thread: read() is not reading the whole data

  1. #1
    Registered User
    Join Date
    Dec 2005
    Posts
    136

    Unhappy read() is not reading the whole data

    Hi all,

    I am doing serial port programming very first time.
    what i am trying to do is some machine is there which is communicating to the computer(LINUX) through serial port. whatever data machine writes comes on a device file "/dev/ttyS0".
    now after setting all the configuration settings, i am trying to read the file.
    suppose machine writes 240 bytes on the file. but when i read that file in a buffer it gives only first 8 bytes. rest of data doesnt comes.

    one thing i would also like to say that , the behavior of this program is very confusing to me.
    like sometime after doing some manipulation it goes working in right way. but as i close the terminal and restart the program again it shows only 8 bytes of data. machine is inserting some carriage return ,linefeed also.

    with read even EOF is not working.

    Code:
    int main(){
            struct termios new_options;
            int fd;         /* File descriptor for the port         */
            int i,t=0,b_read=0;
            char c[240];
            char *outbuf=NULL,cr;
            cr='\xd';
            outbuf=(char*)malloc(10);
            bzero(c,240);
            //Open the first serial port, read/write, no controlling terminal,
            // not care about the Data Carrier Detect signal
                                                                                                     
            fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY |O_ASYNC);
            if (fd == -1){
            // Could not open the port.
             perror("Unable to open /dev/ttyS0\n");
     }
            else {
            // Set all flags to 0 for the read call to be blocking!???
                  fcntl(fd, F_SETFL, 0);
            // Get the current options for the port...
                  tcgetattr(fd, &new_options);
            // Set the baud rates to 2400...
                  cfsetispeed(&new_options, B2400);
                  cfsetospeed(&new_options, B2400);
            // Enable the receiver and set local mode...
                  new_options.c_cflag |= (CLOCAL | CREAD);
            // Set the option for 8N1
                  new_options.c_iflag |= IGNPAR;
                  new_options.c_cflag &= ~PARENB;
                  new_options.c_cflag &= ~CSTOPB;
                  new_options.c_cflag &= ~CSIZE;
                  new_options.c_cc[VTIME]=20;
                  new_options.c_cflag |= CS8;
            //Set the option for raw input
                  new_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
            // Set the option for raw output
                  new_options.c_oflag &=~OPOST;
                                                                                                     
            // Set the new options for the port...
                  tcsetattr(fd, TCSANOW, &new_options);
          //we r sending password to the machine to active for furthe communication.
                  bzero(outbuf,10);
                  sprintf(outbuf,"$U876",5);
                  write(fd,outbuf,5);
                  write(fd,&cr,1);
            }
                                                                                                     
                    do{
                    t=read(fd,c,sizeof(c));
                    printf("%d\n",t);
                    }while(t==240);
                                                                                                                                                                                                    
            for(i=3; i<=240; i++){
                    printf("%c",c[i]);
                    }
    
     close(fd);
                                                                                                         
            return 0;
    }
    thanks in advance.
    S_ccess is waiting for u. Go Ahead, put u there.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > suppose machine writes 240 bytes on the file. but when i read that file in a buffer it gives only first 8 bytes.
    1. It is an assumption on your part that anything if anything outside the machine which sends a block of data, that some part of your machine will magically reassemble those bytes into the SAME sized block. It doesn't work for serial ports, and it doesn't work for networking.

    2. 8 bytes is a common buffer size for serial ports. The first 8 bytes are received, then the others are either lost, or are held up because the hardware negated the "CTS" line to cause data transmission to stop, or the low level driver sent "xoff" to pause transmission at the other end.

    > while(t==240)
    Try some other condition, like
    while ( totalBytesReceived < 240 );
    and implement some kind of counter inside the while loop.

    > for(i=3; i<=240; i++)
    This runs off the end of the array by 1 char

    > outbuf=(char*)malloc(10);
    Why not
    char outbuf[10];
    and save yourself a free() call, and a check for NULL (neither of which you do)

    > bzero(outbuf,10);
    1. bzero is a non-standard function.
    2. it's a waste of time before sprintf, since sprintf always adds a \0 anyway.

    > sprintf(outbuf,"$U876",5);
    The 5 does nothing, since there are no conversions inside the string.
    In particular, it is NOT limiting the output to 5 characters.
    You can save yourself a write call by doing
    sprintf(outbuf,"$U876\r");
    write(fd,outbuf,strlen(outbuf));

  3. #3
    Registered User
    Join Date
    Dec 2005
    Posts
    136

    Serial port read problem

    Thanks a lot dear, but my problem isn't solved.

    1. It is an assumption on your part that anything if anything outside the machine which sends a block of data, that some part of your machine will magically reassemble those bytes into the SAME sized block. It doesn't work for serial ports, and it doesn't work for networking.

    2. 8 bytes is a common buffer size for serial ports. The first 8 bytes are received, then the others are either lost, or are held up because the hardware negated the "CTS" line to cause data transmission to stop, or the low level driver sent "xoff" to pause transmission at the other end.
    I tried it in lot of ways but neither a single method is going to solve my problem.
    MY problem is under many constraints.
    like "/dev/ttyS0" conatins some data

    READY SIGNAL

    HI PROGRAM. 18:30:12

    AD 18:30:10

    now first i have to check whether ready comes in file or not (usually it comes when program send password to machine on serial port after which only the machine can send data to "ttyS0").
    then whatever data comes i need to parse that in different variables.

    please tell me how can i do that.
    S_ccess is waiting for u. Go Ahead, put u there.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Perhaps here http://www.lvr.com/serport.htm
    And read the relevant linux howto's

    Since you've enabled a timeout with new_options.c_cc[VTIME]=20;, and put the port into non-canonical mode, you need to examine your data stream to determine whether the message is complete or not.
    This means you need a more complex while loop, which potentially can receive ONE character at a time.

    So you need to take whatever read() returns, and assemble the message yourself. If read() returns -1, then look at errno to decide what to do about it. Eg. call read again in the case of say EINTR or EAGAIN, or bail out if say the timeout limit is exceeded.

  5. #5
    Registered User
    Join Date
    Dec 2005
    Posts
    136
    i have removed this timeout option from my program.

    and as a read() case, its behaving anonymously. after giving it that u have to read 240 bytes [read(fd,buff,240);] its reading only 8 bytes. and one amazing behaviour of it is after mutliple run of the program it gives the bytes after those 8 bytes and then after run it give the desired result.

    and as again i close the terminal and start the same program it gives again the same first 8 bytes.

    i am very confused. about wahts going wrong with it.
    S_ccess is waiting for u. Go Ahead, put u there.

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Why is this confusing? You're saying, "Hey, read this amount please." Read replies, "Well, when I tried, I got 8 bytes." ... So why are you confused? You're sending a request for up to 240 bytes. Read tells you how many it received. Where's the problem? And why would it be surprising that you get different, or even the same, results from multiple runs? You're communicating with another program. Why does it have to give you what you ask?

    I connect to and play various games over the "interweb". Some times it tells me my connection speed is fast. Some times it says it is slow. It's the same game, connecting to the same server. I'm surprised! ... No, wait, I'm not surprised at all. So why are you?


    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > after giving it that u have to read 240 bytes [read(fd,buff,240);]
    Try to understand that 240 is an upper maximum, not a lower minimum.
    You already call it in a loop, just pay attention to the return result of read()
    Code:
    int totalRead = 0;
    int numToRead = 240;
    while ( numToRead > 0 ) {
      t = read ( fd, &buff[totalRead], numToRead );
      if ( t > 0 ) {
        totalRead += t;
        numToRead -= t;
      } else if ( t == 0 ) {
      } else {
      }
    }
    See - easy money.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 03-10-2008, 11:57 AM
  2. reading in file data
    By sickofc in forum C Programming
    Replies: 2
    Last Post: 03-01-2006, 05:16 PM
  3. Reading data from a file..
    By lamiamike in forum C++ Programming
    Replies: 4
    Last Post: 02-23-2006, 02:54 PM
  4. read data from file
    By matth in forum C++ Programming
    Replies: 3
    Last Post: 04-21-2005, 09:37 AM
  5. gcc problem
    By bjdea1 in forum Linux Programming
    Replies: 13
    Last Post: 04-29-2002, 06:51 PM