Hi!

I use the serial line for communication with a device.
The communication looks like this:

1. ask the device about its state (a 4 byte packet)
2. read reply from device

3. decide what to do:
   3a. if nothing to do, go to 1.
   3b. if there is something to do, send the answer to the device
       this is a 23 byte packet
   3c. if the device ack'd the previous action, counter-ack it.

This is the function I use for sending:

void send_message(int fd, ptg_t *ptg, int sleeptime) {
        int     len;

/*      tcflush(fd, TCIOFLUSH); */
        if (sleeptime)
                usleep(sleeptime);
        len = ptg->message_out[1];  
        write(fd, ptg->message_out, len);
        tcdrain(fd);
#if DEBUG
        {
                int i;
                printf("%d sent: ", ptg->ptgnum);
                for(i = 0; i < len; i++)
                        printf("0x%02x ", ptg->message_out[i]);
                printf("\n");
        }
#endif   
}

The line is full duplex, 19200 baud, 8N1.
The serial device if opened with O_RDWR|O_NOCTTY|O_NDELAY.
My problem is that if the tcflush() is not there,
sometimes between the "there's something to do" reply 
and the longish answer somehow a "what state are you in?"
message goes out. This simply couldn't happen from the
program data flow. I have put printf()s into every possible place
and it does not show anything unusual.
But an independent serial line sniffer (another PC) shows the
above problem, no matter what the sleeptime is. (15000usec - 60000usec)

So I suspect that tcdrain() does not do what the manpage says:

       tcdrain()  waits  until  all  output written to the object
       referred to by fd has been transmitted.

The above problem happened on two different PCs, the only common
thing was the uart type: 16550A.

Both PCs are running the 2.2.17-14 RH kernel and glibc-2.1.3-22 (RH 6.2),
the serial driver compile options and version are from dmesg:

Serial driver version 4.27 with MANY_PORTS MULTIPORT SHARE_IRQ enabled

If I put the tcflush() before the write, the problem disappears.

Now the question is: Should I really issue a tcflush(), or is it a bug
in tcdrain()? Can O_NDELAY cause tcdrain() not to wait?

Please cc the answer, I am not on the list.

Regards,
Zoltan Boszormenyi

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to