summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2014-07-19 19:25:19 +0400
committerDenis Shienkov <denis.shienkov@gmail.com>2014-10-06 15:40:02 +0200
commit62dfdeb3642250bdb642dbf607a8c7b95e57835e (patch)
treea38ae8ded5ffcfd0fbe2541dcfa6ba1301e9268a
parentd9a29ff7cc479e8a9e6d418de6408866f0dce4b6 (diff)
downloadqtserialport-62dfdeb3642250bdb642dbf607a8c7b95e57835e.tar.gz
Fix QSP::bytesToWrite() on Windows
After calling the WriteFile() function, QSP::bytesToWrite() should return zero, but did return the size of writeBuffer. On Windows, we must not to cut a size of the writeBuffer until the asynchronous write operation has completed. So we need to make use of an additional actualBytesToWrite variable, the value of which is increased when new data is added to the writeBuffer, and decreased after calling the WriteFile() function. This change also entails the modification of the QSP::writeData() method and deleting the QSP::startWriting() method. Now all platform-dependent code (related to startWriting(), and to copying of memory to writeBuffer) resides in the new QSP::writeData() method. But this modification does not change the behavior on platforms other than Windows. Tested on Windows with the virtual com0com serial ports using Qt5. Change-Id: I35c1428ad374c0709d6c352a93c552898e947bde Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com>
-rw-r--r--src/serialport/qserialport.cpp8
-rw-r--r--src/serialport/qserialport_unix.cpp19
-rw-r--r--src/serialport/qserialport_unix_p.h4
-rw-r--r--src/serialport/qserialport_win.cpp45
-rw-r--r--src/serialport/qserialport_win_p.h5
-rw-r--r--src/serialport/qserialport_wince.cpp19
-rw-r--r--src/serialport/qserialport_wince_p.h4
7 files changed, 68 insertions, 36 deletions
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp
index c815dd0..1bffba0 100644
--- a/src/serialport/qserialport.cpp
+++ b/src/serialport/qserialport.cpp
@@ -1226,7 +1226,7 @@ qint64 QSerialPort::bytesAvailable() const
qint64 QSerialPort::bytesToWrite() const
{
Q_D(const QSerialPort);
- return d->writeBuffer.size() + QIODevice::bytesToWrite();
+ return d->bytesToWrite() + QIODevice::bytesToWrite();
}
/*!
@@ -1360,11 +1360,7 @@ qint64 QSerialPort::readLineData(char *data, qint64 maxSize)
qint64 QSerialPort::writeData(const char *data, qint64 maxSize)
{
Q_D(QSerialPort);
-
- ::memcpy(d->writeBuffer.reserve(maxSize), data, maxSize);
- if (!d->writeBuffer.isEmpty())
- d->startWriting();
- return maxSize;
+ return d->writeData(data, maxSize);
}
void QSerialPort::setError(QSerialPort::SerialPortError serialPortError, const QString &errorString)
diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp
index b082275..f3ddc4f 100644
--- a/src/serialport/qserialport_unix.cpp
+++ b/src/serialport/qserialport_unix.cpp
@@ -377,12 +377,6 @@ bool QSerialPortPrivate::setBreakEnabled(bool set)
return true;
}
-void QSerialPortPrivate::startWriting()
-{
- if (!isWriteNotificationEnabled())
- setWriteNotificationEnabled(true);
-}
-
qint64 QSerialPortPrivate::readData(char *data, qint64 maxSize)
{
return readBuffer.read(data, maxSize);
@@ -885,6 +879,19 @@ inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode)
return true;
}
+qint64 QSerialPortPrivate::bytesToWrite() const
+{
+ return writeBuffer.size();
+}
+
+qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
+{
+ ::memcpy(writeBuffer.reserve(maxSize), data, maxSize);
+ if (!writeBuffer.isEmpty() && !isWriteNotificationEnabled())
+ setWriteNotificationEnabled(true);
+ return maxSize;
+}
+
bool QSerialPortPrivate::updateTermios()
{
Q_Q(QSerialPort);
diff --git a/src/serialport/qserialport_unix_p.h b/src/serialport/qserialport_unix_p.h
index 408fdc5..14e3cea 100644
--- a/src/serialport/qserialport_unix_p.h
+++ b/src/serialport/qserialport_unix_p.h
@@ -119,7 +119,6 @@ public:
bool sendBreak(int duration);
bool setBreakEnabled(bool set);
- void startWriting();
qint64 readData(char *data, qint64 maxSize);
bool waitForReadyRead(int msecs);
@@ -137,6 +136,9 @@ public:
bool startAsyncWrite();
bool completeAsyncWrite();
+ qint64 bytesToWrite() const;
+ qint64 writeData(const char *data, qint64 maxSize);
+
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 84d1db7..9635325 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -105,6 +105,7 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
, startAsyncWriteTimer(0)
, originalEventMask(0)
, triggeredEventMask(0)
+ , actualBytesToWrite(0)
{
::ZeroMemory(&communicationOverlapped, sizeof(communicationOverlapped));
communicationOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -179,6 +180,7 @@ void QSerialPortPrivate::close()
writeStarted = false;
writeBuffer.clear();
+ actualBytesToWrite = 0;
readyReadEmitted = false;
parityErrorOccurred = false;
@@ -276,6 +278,7 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
if (directions & QSerialPort::Output) {
flags |= PURGE_TXABORT | PURGE_TXCLEAR;
writeStarted = false;
+ actualBytesToWrite = 0;
}
if (!::PurgeComm(handle, flags)) {
q->setError(decodeSystemError());
@@ -316,20 +319,6 @@ bool QSerialPortPrivate::setBreakEnabled(bool set)
return true;
}
-void QSerialPortPrivate::startWriting()
-{
- Q_Q(QSerialPort);
-
- if (!writeStarted) {
- if (!startAsyncWriteTimer) {
- startAsyncWriteTimer = new QTimer(q);
- q->connect(startAsyncWriteTimer, SIGNAL(timeout()), q, SLOT(_q_startAsyncWrite()));
- startAsyncWriteTimer->setSingleShot(true);
- }
- startAsyncWriteTimer->start(0);
- }
-}
-
qint64 QSerialPortPrivate::readData(char *data, qint64 maxSize)
{
const qint64 result = readBuffer.read(data, maxSize);
@@ -649,8 +638,10 @@ bool QSerialPortPrivate::_q_startAsyncWrite()
return true;
initializeOverlappedStructure(writeCompletionOverlapped);
+
+ const int writeBytes = writeBuffer.nextDataBlockSize();
if (!::WriteFile(handle, writeBuffer.readPointer(),
- writeBuffer.nextDataBlockSize(),
+ writeBytes,
NULL, &writeCompletionOverlapped)) {
QSerialPort::SerialPortError error = decodeSystemError();
@@ -662,6 +653,7 @@ bool QSerialPortPrivate::_q_startAsyncWrite()
}
}
+ actualBytesToWrite -= writeBytes;
writeStarted = true;
return true;
}
@@ -702,6 +694,29 @@ void QSerialPortPrivate::emitReadyRead()
emit q->readyRead();
}
+qint64 QSerialPortPrivate::bytesToWrite() const
+{
+ return actualBytesToWrite;
+}
+
+qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
+{
+ Q_Q(QSerialPort);
+
+ ::memcpy(writeBuffer.reserve(maxSize), data, maxSize);
+ actualBytesToWrite += maxSize;
+
+ if (!writeBuffer.isEmpty() && !writeStarted) {
+ if (!startAsyncWriteTimer) {
+ startAsyncWriteTimer = new QTimer(q);
+ q->connect(startAsyncWriteTimer, SIGNAL(timeout()), q, SLOT(_q_completeAsyncWrite()));
+ startAsyncWriteTimer->setSingleShot(true);
+ }
+ startAsyncWriteTimer->start(0);
+ }
+ return maxSize;
+}
+
void QSerialPortPrivate::handleLineStatusErrors()
{
Q_Q(QSerialPort);
diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h
index 8db3a74..c6a8330 100644
--- a/src/serialport/qserialport_win_p.h
+++ b/src/serialport/qserialport_win_p.h
@@ -86,7 +86,6 @@ public:
bool sendBreak(int duration);
bool setBreakEnabled(bool set);
- void startWriting();
qint64 readData(char *data, qint64 maxSize);
bool waitForReadyRead(int msec);
@@ -114,6 +113,9 @@ public:
bool emulateErrorPolicy();
void emitReadyRead();
+ qint64 bytesToWrite() const;
+ qint64 writeData(const char *data, qint64 maxSize);
+
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);
@@ -141,6 +143,7 @@ public:
OVERLAPPED writeCompletionOverlapped;
DWORD originalEventMask;
DWORD triggeredEventMask;
+ qint64 actualBytesToWrite;
private:
bool initialize(QIODevice::OpenMode mode);
diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp
index d6c58aa..0a442dd 100644
--- a/src/serialport/qserialport_wince.cpp
+++ b/src/serialport/qserialport_wince.cpp
@@ -345,12 +345,6 @@ bool QSerialPortPrivate::setBreakEnabled(bool set)
return true;
}
-void QSerialPortPrivate::startWriting()
-{
- // trigger write sequence
- notifyWrite();
-}
-
qint64 QSerialPortPrivate::readData(char *data, qint64 maxSize)
{
return readBuffer.read(data, maxSize);
@@ -592,6 +586,19 @@ bool QSerialPortPrivate::notifyWrite()
return true;
}
+qint64 QSerialPortPrivate::bytesToWrite() const
+{
+ return writeBuffer.size();
+}
+
+qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
+{
+ ::memcpy(writeBuffer.reserve(maxSize), data, maxSize);
+ if (!writeBuffer.isEmpty())
+ notifyWrite();
+ return maxSize;
+}
+
void QSerialPortPrivate::processIoErrors(bool error)
{
Q_Q(QSerialPort);
diff --git a/src/serialport/qserialport_wince_p.h b/src/serialport/qserialport_wince_p.h
index be08bc1..d212d3a 100644
--- a/src/serialport/qserialport_wince_p.h
+++ b/src/serialport/qserialport_wince_p.h
@@ -85,7 +85,6 @@ public:
bool sendBreak(int duration);
bool setBreakEnabled(bool set);
- void startWriting();
qint64 readData(char *data, qint64 maxSize);
bool waitForReadyRead(int msec);
@@ -105,6 +104,9 @@ public:
bool notifyRead();
bool notifyWrite();
+ qint64 bytesToWrite() const;
+ qint64 writeData(const char *data, qint64 maxSize);
+
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);