[2/3] server: Use tcdrain() instead of tcflush() to implement FlushFileBuffers() for a COM port.

Dmitry Timoshkov dmitry at baikal.ru
Mon Aug 26 02:37:36 CDT 2013

MSDN for FlushFileBuffers says:
Flushes the buffers of a specified file and causes all buffered data to be
written to a file.

Linux man page says:
tcdrain() waits until all output written to the object referred to by fd has
been transmitted.
tcflush() discards data written to the object referred to by fd but not transmitted,
or data received but not read.

tcdrain() better matches the FlushFileBuffers() MSDN description, and this patch
allows Garmin MapSource to successfully download maps from the GPS device connected
via a USB-serial cable. Without this patch MapSource can't even see the device because
WriteFile() folowed by FlushFileBuffers() makes ClearCommError() return non-zero

A simple program which does:

    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK);
    write(fd, "\0\0\0\0\0\0\0", 7);
    tcflush(fd, TCOFLUSH);
    ioctl(fd, TIOCOUTQ, &out);
    printf("out queue %d bytes\n", out);

prints "out queue 7 bytes".

After replacing tcflush() by tcdrain() it prints
"out queue 0 bytes".
 server/serial.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/server/serial.c b/server/serial.c
index 587fee1..248f446 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -201,7 +201,7 @@ static void serial_flush( struct fd *fd, struct event **event )
     /* MSDN says: If hFile is a handle to a communications device,
      * the function only flushes the transmit buffer.
-    if (tcflush( get_unix_fd(fd), TCOFLUSH ) == -1) file_set_error();
+    if (tcdrain( get_unix_fd(fd) ) == -1) file_set_error();

More information about the wine-patches mailing list