diff options
author | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2014-10-14 14:07:32 +0200 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2014-10-14 14:07:32 +0200 |
commit | 3bb682ea29ffaf72ff73e6eb57abdc5c59524e8a (patch) | |
tree | 4d8e828da7ea6115c6ffe26cec2d024bad60aa91 | |
parent | 14fe584d2abb1ae0776f0973b245baa79d0468d2 (diff) | |
parent | 62dfdeb3642250bdb642dbf607a8c7b95e57835e (diff) | |
download | qtserialport-3bb682ea29ffaf72ff73e6eb57abdc5c59524e8a.tar.gz |
Merge remote-tracking branch 'origin/5.3' into 5.4
Change-Id: Id7e66059233e8d07ba44cad19048d9cddc68e250
-rw-r--r-- | src/serialport/qserialport.cpp | 10 | ||||
-rw-r--r-- | src/serialport/qserialport_unix.cpp | 28 | ||||
-rw-r--r-- | src/serialport/qserialport_unix_p.h | 5 | ||||
-rw-r--r-- | src/serialport/qserialport_win.cpp | 78 | ||||
-rw-r--r-- | src/serialport/qserialport_win_p.h | 7 | ||||
-rw-r--r-- | src/serialport/qserialport_wince.cpp | 18 | ||||
-rw-r--r-- | src/serialport/qserialport_wince_p.h | 5 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_mac.cpp | 3 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_unix.cpp | 14 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_win.cpp | 6 | ||||
-rw-r--r-- | src/serialport/qtudev_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qserialport/tst_qserialport.cpp | 91 |
12 files changed, 215 insertions, 52 deletions
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 297bf62..82bcde3 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -1218,7 +1218,7 @@ qint64 QSerialPort::bytesAvailable() const qint64 QSerialPort::bytesToWrite() const { Q_D(const QSerialPort); - return d->writeBuffer.size() + QIODevice::bytesToWrite(); + return d->bytesToWrite() + QIODevice::bytesToWrite(); } /*! @@ -1335,7 +1335,7 @@ bool QSerialPort::setBreakEnabled(bool set) qint64 QSerialPort::readData(char *data, qint64 maxSize) { Q_D(QSerialPort); - return d->readBuffer.read(data, maxSize); + return d->readData(data, maxSize); } /*! @@ -1352,11 +1352,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 afdc640..9979256 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -369,10 +369,9 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) return true; } -void QSerialPortPrivate::startWriting() +qint64 QSerialPortPrivate::readData(char *data, qint64 maxSize) { - if (!isWriteNotificationEnabled()) - setWriteNotificationEnabled(true); + return readBuffer.read(data, maxSize); } bool QSerialPortPrivate::waitForReadyRead(int msecs) @@ -496,9 +495,6 @@ QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions d if (::ioctl(descriptor, TIOCGSERIAL, ¤tSerialInfo) == -1) return decodeSystemError(); - if (currentSerialInfo.baud_base % baudRate != 0) - return QSerialPort::UnsupportedOperationError; - currentSerialInfo.flags &= ~ASYNC_SPD_MASK; currentSerialInfo.flags |= (ASYNC_SPD_CUST /* | ASYNC_LOW_LATENCY*/); currentSerialInfo.custom_divisor = currentSerialInfo.baud_base / baudRate; @@ -506,6 +502,13 @@ QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions d if (currentSerialInfo.custom_divisor == 0) return QSerialPort::UnsupportedOperationError; + if (currentSerialInfo.custom_divisor * baudRate != currentSerialInfo.baud_base) { + qWarning("Baud rate of serial port %s is set to %d instead of %d: divisor %f unsupported", + qPrintable(systemLocation), + currentSerialInfo.baud_base / currentSerialInfo.custom_divisor, + baudRate, (float)currentSerialInfo.baud_base / baudRate); + } + if (::ioctl(descriptor, TIOCSSERIAL, ¤tSerialInfo) == -1) return decodeSystemError(); @@ -868,6 +871,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 e24804d..1cc767d 100644 --- a/src/serialport/qserialport_unix_p.h +++ b/src/serialport/qserialport_unix_p.h @@ -111,7 +111,7 @@ public: bool sendBreak(int duration); bool setBreakEnabled(bool set); - void startWriting(); + qint64 readData(char *data, qint64 maxSize); bool waitForReadyRead(int msecs); bool waitForBytesWritten(int msecs); @@ -128,6 +128,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 32b8d0a..64ca00e 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -90,12 +90,14 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q) , readChunkBuffer(ReadChunkSize, 0) , readyReadEmitted(0) , writeStarted(false) + , readStarted(false) , communicationNotifier(new QWinEventNotifier(q)) , readCompletionNotifier(new QWinEventNotifier(q)) , writeCompletionNotifier(new QWinEventNotifier(q)) , startAsyncWriteTimer(0) , originalEventMask(0) , triggeredEventMask(0) + , actualBytesToWrite(0) { ::ZeroMemory(&communicationOverlapped, sizeof(communicationOverlapped)); communicationOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); @@ -165,10 +167,12 @@ void QSerialPortPrivate::close() writeCompletionNotifier->setEnabled(false); communicationNotifier->setEnabled(false); + readStarted = false; readBuffer.clear(); writeStarted = false; writeBuffer.clear(); + actualBytesToWrite = 0; readyReadEmitted = false; parityErrorOccurred = false; @@ -259,17 +263,26 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions) Q_Q(QSerialPort); DWORD flags = 0; - if (directions & QSerialPort::Input) + if (directions & QSerialPort::Input) { flags |= PURGE_RXABORT | PURGE_RXCLEAR; + readStarted = false; + } if (directions & QSerialPort::Output) { flags |= PURGE_TXABORT | PURGE_TXCLEAR; writeStarted = false; + actualBytesToWrite = 0; } if (!::PurgeComm(handle, flags)) { q->setError(decodeSystemError()); return false; } + // We need start async read because a reading can be stalled. Since the + // PurgeComm can abort of current reading sequence, or a port is in hardware + // flow control mode, or a port has a limited read buffer size. + if (directions & QSerialPort::Input) + startAsyncRead(); + return true; } @@ -298,18 +311,19 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) return true; } -void QSerialPortPrivate::startWriting() +qint64 QSerialPortPrivate::readData(char *data, qint64 maxSize) { - 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); + const qint64 result = readBuffer.read(data, maxSize); + // We need try to start async reading to read a remainder from a driver's queue + // in case we have a limited read buffer size. Because the read notification can + // be stalled since Windows do not re-triggered an EV_RXCHAR event if a driver's + // buffer has a remainder of data ready to read until a new data will be received. + if (readBufferMaxSize + && result > 0 + && (result == readBufferMaxSize || flowControl == QSerialPort::HardwareControl)) { + startAsyncRead(); } + return result; } bool QSerialPortPrivate::waitForReadyRead(int msecs) @@ -515,14 +529,18 @@ bool QSerialPortPrivate::_q_completeAsyncCommunication() bool QSerialPortPrivate::_q_completeAsyncRead() { const qint64 bytesTransferred = handleOverlappedResult(QSerialPort::Input, readCompletionOverlapped); - if (bytesTransferred == qint64(-1)) + if (bytesTransferred == qint64(-1)) { + readStarted = false; return false; + } if (bytesTransferred > 0) { readBuffer.append(readChunkBuffer.left(bytesTransferred)); if (!emulateErrorPolicy()) emitReadyRead(); } + readStarted = false; + // start async read for possible remainder into driver queue if ((bytesTransferred == ReadChunkSize) && (policy == QSerialPort::IgnorePolicy)) return startAsyncRead(); @@ -570,6 +588,9 @@ bool QSerialPortPrivate::startAsyncRead() { Q_Q(QSerialPort); + if (readStarted) + return true; + DWORD bytesToRead = policy == QSerialPort::IgnorePolicy ? ReadChunkSize : 1; if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) { @@ -582,8 +603,10 @@ bool QSerialPortPrivate::startAsyncRead() } initializeOverlappedStructure(readCompletionOverlapped); - if (::ReadFile(handle, readChunkBuffer.data(), bytesToRead, NULL, &readCompletionOverlapped)) + if (::ReadFile(handle, readChunkBuffer.data(), bytesToRead, NULL, &readCompletionOverlapped)) { + readStarted = true; return true; + } QSerialPort::SerialPortError error = decodeSystemError(); if (error != QSerialPort::NoError) { @@ -595,6 +618,7 @@ bool QSerialPortPrivate::startAsyncRead() return false; } + readStarted = true; return true; } @@ -606,8 +630,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(); @@ -619,6 +645,7 @@ bool QSerialPortPrivate::_q_startAsyncWrite() } } + actualBytesToWrite -= writeBytes; writeStarted = true; return true; } @@ -659,6 +686,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 93f8591..6b009fe 100644 --- a/src/serialport/qserialport_win_p.h +++ b/src/serialport/qserialport_win_p.h @@ -78,7 +78,7 @@ public: bool sendBreak(int duration); bool setBreakEnabled(bool set); - void startWriting(); + qint64 readData(char *data, qint64 maxSize); bool waitForReadyRead(int msec); bool waitForBytesWritten(int msec); @@ -105,6 +105,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); @@ -122,6 +125,7 @@ public: QByteArray readChunkBuffer; bool readyReadEmitted; bool writeStarted; + bool readStarted; QWinEventNotifier *communicationNotifier; QWinEventNotifier *readCompletionNotifier; QWinEventNotifier *writeCompletionNotifier; @@ -131,6 +135,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 1cf79cc..a9c80b2 100644 --- a/src/serialport/qserialport_wince.cpp +++ b/src/serialport/qserialport_wince.cpp @@ -337,10 +337,9 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) return true; } -void QSerialPortPrivate::startWriting() +qint64 QSerialPortPrivate::readData(char *data, qint64 maxSize) { - // trigger write sequence - notifyWrite(); + return readBuffer.read(data, maxSize); } bool QSerialPortPrivate::waitForReadyRead(int msec) @@ -579,6 +578,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 164a87e..dedd4b1 100644 --- a/src/serialport/qserialport_wince_p.h +++ b/src/serialport/qserialport_wince_p.h @@ -77,7 +77,7 @@ public: bool sendBreak(int duration); bool setBreakEnabled(bool set); - void startWriting(); + qint64 readData(char *data, qint64 maxSize); bool waitForReadyRead(int msec); bool waitForBytesWritten(int msec); @@ -96,6 +96,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); diff --git a/src/serialport/qserialportinfo_mac.cpp b/src/serialport/qserialportinfo_mac.cpp index e307136..d400d68 100644 --- a/src/serialport/qserialportinfo_mac.cpp +++ b/src/serialport/qserialportinfo_mac.cpp @@ -64,8 +64,7 @@ static QCFType<CFTypeRef> searchProperty(io_registry_entry_t ioRegistryEntry, static QString searchStringProperty(io_registry_entry_t ioRegistryEntry, const QCFString &propertyKey) { - const QCFString result(searchProperty(ioRegistryEntry, propertyKey).as<CFStringRef>()); - return QCFString::toQString(result); + return QCFString::toQString(searchProperty(ioRegistryEntry, propertyKey).as<CFStringRef>()); } static quint16 searchShortIntProperty(io_registry_entry_t ioRegistryEntry, diff --git a/src/serialport/qserialportinfo_unix.cpp b/src/serialport/qserialportinfo_unix.cpp index 82ac91f..4479e97 100644 --- a/src/serialport/qserialportinfo_unix.cpp +++ b/src/serialport/qserialportinfo_unix.cpp @@ -161,6 +161,10 @@ QList<QSerialPortInfo> availablePortsBySysfs() if (manufacturer.open(QIODevice::ReadOnly | QIODevice::Text)) serialPortInfo.d_ptr->manufacturer = QString::fromLatin1(manufacturer.readAll()).simplified(); + QFile serialNumber(QFileInfo(targetDir, QStringLiteral("serial")).absoluteFilePath()); + if (serialNumber.open(QIODevice::ReadOnly | QIODevice::Text)) + serialPortInfo.d_ptr->serialNumber = QString::fromLatin1(serialNumber.readAll()).simplified(); + QFile vendorIdentifier(QFileInfo(targetDir, QStringLiteral("idVendor")).absoluteFilePath()); if (vendorIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) { serialPortInfo.d_ptr->vendorIdentifier = QString::fromLatin1(vendorIdentifier.readAll()) @@ -190,6 +194,9 @@ QList<QSerialPortInfo> availablePortsBySysfs() .toInt(&serialPortInfo.d_ptr->hasProductIdentifier, 16); } // TODO: Obtain more information about the device + } else if (targetPath.contains(QStringLiteral(".serial/tty/tty"))) { + // This condition matches onboard serial port on embedded devices. + // Keep those devices in the list } else { continue; } @@ -345,12 +352,7 @@ QList<QSerialPortInfo> availablePortsByUdev() QList<QSerialPortInfo> QSerialPortInfo::availablePorts() { - QList<QSerialPortInfo> serialPortInfoList; - // TODO: Remove this condition once the udev runtime symbol resolution crash - // is fixed for Qt 4. -#if defined(LINK_LIBUDEV) || (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) - serialPortInfoList = availablePortsByUdev(); -#endif + QList<QSerialPortInfo> serialPortInfoList = availablePortsByUdev(); #ifdef Q_OS_LINUX if (serialPortInfoList.isEmpty()) diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index 82f7636..0958617 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -138,7 +138,7 @@ static QString deviceInstanceIdentifier(DEVINST deviceInstanceNumber) outputBuffer.size(), 0) != CR_SUCCESS) { return QString(); } - return toStringAndTrimNullCharacter(outputBuffer); + return toStringAndTrimNullCharacter(outputBuffer).toUpper(); } static DEVINST parentDeviceInstanceNumber(DEVINST childDeviceInstanceNumber) @@ -282,7 +282,7 @@ static QString deviceSerialNumber(const QString &instanceIdentifier, QString result = parseDeviceSerialNumber(instanceIdentifier); if (result.isEmpty()) { const DEVINST parentNumber = parentDeviceInstanceNumber(deviceInstanceNumber); - const QString parentInstanceIdentifier = deviceInstanceIdentifier(parentNumber).toUpper(); + const QString parentInstanceIdentifier = deviceInstanceIdentifier(parentNumber); result = parseDeviceSerialNumber(parentInstanceIdentifier); } return result; @@ -319,7 +319,7 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() serialPortInfo.d_ptr->description = deviceDescription(deviceInfoSet, &deviceInfoData); serialPortInfo.d_ptr->manufacturer = deviceManufacturer(deviceInfoSet, &deviceInfoData); - const QString instanceIdentifier = deviceInstanceIdentifier(deviceInfoData.DevInst).toUpper(); + const QString instanceIdentifier = deviceInstanceIdentifier(deviceInfoData.DevInst); serialPortInfo.d_ptr->serialNumber = deviceSerialNumber(instanceIdentifier, deviceInfoData.DevInst); diff --git a/src/serialport/qtudev_p.h b/src/serialport/qtudev_p.h index f709f0c..c83a5c0 100644 --- a/src/serialport/qtudev_p.h +++ b/src/serialport/qtudev_p.h @@ -57,7 +57,7 @@ extern "C" #define GENERATE_SYMBOL_VARIABLE(returnType, symbolName, ...) \ typedef returnType (*fp_##symbolName)(__VA_ARGS__); \ - fp_##symbolName symbolName; + static fp_##symbolName symbolName; #define RESOLVE_SYMBOL(symbolName) \ symbolName = (fp_##symbolName)resolveSymbol(udevLibrary, #symbolName); \ diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp index d296f6d..357cef8 100644 --- a/tests/auto/qserialport/tst_qserialport.cpp +++ b/tests/auto/qserialport/tst_qserialport.cpp @@ -107,6 +107,11 @@ private slots: void asynchronousWriteByTimer_data(); void asynchronousWriteByTimer(); +#ifdef Q_OS_WIN + void readBufferOverflow(); + void readAfterInputClear(); +#endif + protected slots: void handleBytesWrittenAndExitLoopSlot(qint64 bytesWritten); void handleBytesWrittenAndExitLoopSlot2(qint64 bytesWritten); @@ -462,27 +467,27 @@ void tst_QSerialPort::twoStageSynchronousLoopback() senderPort.waitForBytesWritten(waitMsecs); QTest::qSleep(waitMsecs); receiverPort.waitForReadyRead(waitMsecs); - QCOMPARE(qint64(newlineArray.size()), receiverPort.bytesAvailable()); + QCOMPARE(receiverPort.bytesAvailable(), qint64(newlineArray.size())); receiverPort.write(receiverPort.readAll()); receiverPort.waitForBytesWritten(waitMsecs); QTest::qSleep(waitMsecs); senderPort.waitForReadyRead(waitMsecs); - QCOMPARE(qint64(newlineArray.size()), receiverPort.bytesAvailable()); - QCOMPARE(newlineArray, senderPort.readAll()); + QCOMPARE(senderPort.bytesAvailable(), qint64(newlineArray.size())); + QCOMPARE(senderPort.readAll(), newlineArray); // second stage senderPort.write(newlineArray); senderPort.waitForBytesWritten(waitMsecs); QTest::qSleep(waitMsecs); receiverPort.waitForReadyRead(waitMsecs); - QCOMPARE(qint64(newlineArray.size()), receiverPort.bytesAvailable()); + QCOMPARE(receiverPort.bytesAvailable(), qint64(newlineArray.size())); receiverPort.write(receiverPort.readAll()); receiverPort.waitForBytesWritten(waitMsecs); QTest::qSleep(waitMsecs); senderPort.waitForReadyRead(waitMsecs); - QCOMPARE(qint64(newlineArray.size()), receiverPort.bytesAvailable()); - QCOMPARE(newlineArray, senderPort.readAll()); + QCOMPARE(senderPort.bytesAvailable(), qint64(newlineArray.size())); + QCOMPARE(senderPort.readAll(), newlineArray); } void tst_QSerialPort::synchronousReadWrite() @@ -508,7 +513,7 @@ void tst_QSerialPort::synchronousReadWrite() while ((readData.size() < writeData.size()) && receiverPort.waitForReadyRead(100)) readData.append(receiverPort.readAll()); - QCOMPARE(writeData, readData); + QCOMPARE(readData, writeData); } class AsyncReader : public QObject @@ -659,5 +664,77 @@ void tst_QSerialPort::asynchronousWriteByTimer() QCOMPARE(receiverPort.readAll(), alphabetArray); } +#ifdef Q_OS_WIN +void tst_QSerialPort::readBufferOverflow() +{ + clearReceiver(); + + QSerialPort senderPort(m_senderPortName); + QVERIFY(senderPort.open(QSerialPort::WriteOnly)); + + QSerialPort receiverPort(m_receiverPortName); + QVERIFY(receiverPort.open(QSerialPort::ReadOnly)); + + const int readBufferSize = alphabetArray.size() / 2; + receiverPort.setReadBufferSize(readBufferSize); + QCOMPARE(receiverPort.readBufferSize(), qint64(readBufferSize)); + + QCOMPARE(senderPort.write(alphabetArray), qint64(alphabetArray.size())); + QVERIFY2(senderPort.waitForBytesWritten(100), "Waiting for bytes written failed"); + + QByteArray readData; + while (receiverPort.waitForReadyRead(100)) { + QVERIFY(receiverPort.bytesAvailable() > 0); + readData += receiverPort.readAll(); + } + + QCOMPARE(readData, alphabetArray); + + // No more bytes available + QVERIFY(receiverPort.bytesAvailable() == 0); +} + +void tst_QSerialPort::readAfterInputClear() +{ + clearReceiver(); + + QSerialPort senderPort(m_senderPortName); + QVERIFY(senderPort.open(QSerialPort::WriteOnly)); + + QSerialPort receiverPort(m_receiverPortName); + QVERIFY(receiverPort.open(QSerialPort::ReadOnly)); + + const int readBufferSize = alphabetArray.size() / 2; + receiverPort.setReadBufferSize(readBufferSize); + QCOMPARE(receiverPort.readBufferSize(), qint64(readBufferSize)); + + const int waitMsecs = 100; + + // First write more than read buffer size + QCOMPARE(senderPort.write(alphabetArray), qint64(alphabetArray.size())); + QVERIFY2(senderPort.waitForBytesWritten(waitMsecs), "Waiting for bytes written failed"); + + // Wait for first part of data into read buffer + while (receiverPort.waitForReadyRead(waitMsecs)); + QCOMPARE(receiverPort.bytesAvailable(), qint64(readBufferSize)); + // Wait for second part of data into driver's FIFO + QTest::qSleep(waitMsecs); + + QVERIFY(receiverPort.clear(QSerialPort::Input)); + QCOMPARE(receiverPort.bytesAvailable(), qint64(0)); + + // Second write less than read buffer size + QCOMPARE(senderPort.write(newlineArray), qint64(newlineArray.size())); + QVERIFY2(senderPort.waitForBytesWritten(waitMsecs), "Waiting for bytes written failed"); + + while (receiverPort.waitForReadyRead(waitMsecs)); + QCOMPARE(receiverPort.bytesAvailable(), qint64(newlineArray.size())); + QCOMPARE(receiverPort.readAll(), newlineArray); + + // No more bytes available + QVERIFY(receiverPort.bytesAvailable() == 0); +} +#endif + QTEST_MAIN(tst_QSerialPort) #include "tst_qserialport.moc" |