From 4679301c184b7964fd197cca5bf5b30fefaee386 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Fri, 22 Apr 2016 18:47:41 +0300 Subject: Fix reading of data remainder with CDC USB device on Windows In some cases the WaitCommEvent function does not triggered, even if the input driver's queue has an unread bytes. Most likely this happens if a bytes has been arrived between calls of ReadFile and WaitCommEvent. Thus, it can be avoided by means of ClearCommError function which should be called in end of ReadFile to require amount of bytes that has been arrived but still are unread. If it returns more than zero, then we start reading again, without calling of WaitCommEvent. Task-number: QTBUG-48677 Change-Id: I054975971a7c1823f7de879669c3d97f31348ed8 Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport_p.h | 2 ++ src/serialport/qserialport_win.cpp | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/serialport/qserialport_p.h b/src/serialport/qserialport_p.h index 29c1d5a..81febed 100644 --- a/src/serialport/qserialport_p.h +++ b/src/serialport/qserialport_p.h @@ -206,6 +206,8 @@ public: bool getDcb(DCB *dcb); OVERLAPPED *waitForNotified(int msecs); + qint64 queuedBytesCount(QSerialPort::Direction direction) const; + bool completeAsyncCommunication(qint64 bytesTransferred); bool completeAsyncRead(qint64 bytesTransferred); bool completeAsyncWrite(qint64 bytesTransferred); diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 6d5dac0..e356e4c 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -437,10 +437,13 @@ bool QSerialPortPrivate::completeAsyncRead(qint64 bytesTransferred) readStarted = false; bool result = true; - if (bytesTransferred == ReadChunkSize) + if (bytesTransferred == ReadChunkSize + || queuedBytesCount(QSerialPort::Input) > 0) { result = startAsyncRead(); - else if (readBufferMaxSize == 0 || readBufferMaxSize > buffer.size()) + } else if (readBufferMaxSize == 0 + || readBufferMaxSize > buffer.size()) { result = startAsyncCommunication(); + } if (bytesTransferred > 0) emitReadyRead(); @@ -598,6 +601,16 @@ OVERLAPPED *QSerialPortPrivate::waitForNotified(int msecs) return overlapped; } +qint64 QSerialPortPrivate::queuedBytesCount(QSerialPort::Direction direction) const +{ + COMSTAT comstat; + if (::ClearCommError(handle, Q_NULLPTR, &comstat) == 0) + return -1; + return (direction == QSerialPort::Input) + ? comstat.cbInQue + : ((direction == QSerialPort::Output) ? comstat.cbOutQue : -1); +} + inline bool QSerialPortPrivate::initialize() { Q_Q(QSerialPort); -- cgit v1.2.1