summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-10-14 19:52:01 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-10-14 19:52:01 +0200
commitd6584a7f1cc540eba1fed1fc7423459e9cfc8bb8 (patch)
tree07bd7c13cacaa42cebf15da8a85382ab08db5841
parent4280d29fff431a87a2771cc37a555fc8cb54be8e (diff)
parent5f8f57dfb53c1954715257be926915d24734b391 (diff)
downloadqtserialport-d6584a7f1cc540eba1fed1fc7423459e9cfc8bb8.tar.gz
Merge remote-tracking branch 'origin/5.6' into dev
Change-Id: I2d36b5263242f91101e3720812ecf7e91c60df2d
-rw-r--r--dist/changes-5.5.141
-rw-r--r--examples/serialport/doc/terminal.qdoc4
-rw-r--r--src/serialport/qserialport.cpp16
-rw-r--r--src/serialport/qserialport_p.h3
-rw-r--r--src/serialport/qserialport_unix.cpp18
-rw-r--r--src/serialport/qserialport_win.cpp17
-rw-r--r--src/serialport/qserialport_wince.cpp13
-rw-r--r--src/serialport/qserialportinfo_win.cpp74
-rw-r--r--tests/auto/qserialport/tst_qserialport.cpp45
9 files changed, 143 insertions, 88 deletions
diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1
new file mode 100644
index 0000000..8215a3f
--- /dev/null
+++ b/dist/changes-5.5.1
@@ -0,0 +1,41 @@
+Qt 5.5.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.5.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+ http://doc.qt.io/qt-5/index.html
+
+The Qt version 5.5 series is binary compatible with the 5.4.x series.
+Applications compiled for 5.4 will continue to run with 5.5.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+ https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+ - Improved the Terminal example:
+ * The example has a permanent status message now.
+
+ - QSerialPortInfo:
+ * [QTBUG-46875] Fixed crash while enumerating available ports
+ on OS X 10.10
+ * [QTBUG-47127] Available serial port information is not duplicated
+ anymore on Windows.
+ * [QTBUG-47210] Now do not return devices which are not serial ports
+ on FreeBSD.
+ * Now returns the full information about the serial port on FreeBSD.
+
+ - QSerialPort:
+ * Fixed the serial ports closing and data reading on WinCE.
+ * [QTBUG-45338] Fixed opening of the serial ports when using the
+ App Sandbox on OS X.
+ * [QTBUG-46993] Fixed opening of the serial ports on Windows, which
+ are provided by the "Exar VCP" driver.
diff --git a/examples/serialport/doc/terminal.qdoc b/examples/serialport/doc/terminal.qdoc
index 16f12fe..d9b2d8d 100644
--- a/examples/serialport/doc/terminal.qdoc
+++ b/examples/serialport/doc/terminal.qdoc
@@ -91,7 +91,7 @@
\snippet terminal/mainwindow.cpp 1
The only QSerialPort signal invoked in this example is
- \l{QIODevice::readyRead()}{readyRead()}, which shows that new data has been
+ \l{QIODevice::}{readyRead()}, which shows that new data has been
received and hence available:
\dots
@@ -127,7 +127,7 @@
\l{terminal/console.cpp}{Console} widget to the serial port.
When the serial port receives new data, the signal
- \l{QTcpSocket::readyRead()}{readyRead()} is emitted, and that signal is
+ \l{QIODevice::}{readyRead()} is emitted, and that signal is
connected to the \c MainWindow::readData() slot:
\snippet terminal/mainwindow.cpp 7
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp
index 690eb65..6832883 100644
--- a/src/serialport/qserialport.cpp
+++ b/src/serialport/qserialport.cpp
@@ -123,14 +123,6 @@ QSerialPortPrivate::QSerialPortPrivate()
{
}
-int QSerialPortPrivate::timeoutValue(int msecs, int elapsed)
-{
- if (msecs == -1)
- return msecs;
- msecs -= elapsed;
- return qMax(msecs, 0);
-}
-
void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo)
{
Q_Q(QSerialPort);
@@ -1409,7 +1401,7 @@ qint64 QSerialPort::readData(char *data, qint64 maxSize)
Q_UNUSED(data);
Q_UNUSED(maxSize);
-#ifdef Q_OS_WIN32
+#if defined(Q_OS_WIN32)
// 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
@@ -1417,6 +1409,12 @@ qint64 QSerialPort::readData(char *data, qint64 maxSize)
Q_D(QSerialPort);
if (d->readBufferMaxSize || d->flowControl == QSerialPort::HardwareControl)
d->startAsyncRead();
+#elif defined(Q_OS_UNIX)
+ // We need try to re-trigger the read notification to read a remainder from a
+ // driver's queue in case we have a limited read buffer size.
+ Q_D(QSerialPort);
+ if (d->readBufferMaxSize && !d->isReadNotificationEnabled())
+ d->setReadNotificationEnabled(true);
#endif
// return 0 indicating there may be more data in the future
diff --git a/src/serialport/qserialport_p.h b/src/serialport/qserialport_p.h
index d2527e3..4d37254 100644
--- a/src/serialport/qserialport_p.h
+++ b/src/serialport/qserialport_p.h
@@ -126,8 +126,6 @@ public:
QSerialPortPrivate();
- static int timeoutValue(int msecs, int elapsed);
-
bool open(QIODevice::OpenMode mode);
void close();
@@ -161,7 +159,6 @@ public:
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);
- static qint32 baudRateFromSetting(qint32 setting);
static qint32 settingFromBaudRate(qint32 baudRate);
static QList<qint32> standardBaudRates();
diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp
index 4659a18..4a558be 100644
--- a/src/serialport/qserialport_unix.cpp
+++ b/src/serialport/qserialport_unix.cpp
@@ -389,7 +389,7 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
bool readyToRead = false;
bool readyToWrite = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite, true, !writeBuffer.isEmpty(),
- timeoutValue(msecs, stopWatch.elapsed()))) {
+ qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
return false;
}
@@ -398,7 +398,7 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
if (readyToWrite && !completeAsyncWrite())
return false;
- } while (msecs == -1 || timeoutValue(msecs, stopWatch.elapsed()) > 0);
+ } while (msecs == -1 || qt_subtract_from_timeout(msecs, stopWatch.elapsed()) > 0);
return false;
}
@@ -414,7 +414,7 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs)
bool readyToRead = false;
bool readyToWrite = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite, true, !writeBuffer.isEmpty(),
- timeoutValue(msecs, stopWatch.elapsed()))) {
+ qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
return false;
}
@@ -727,6 +727,7 @@ bool QSerialPortPrivate::readNotification()
if (bytesToRead == 0) {
// Buffer is full. User must read data from the buffer
// before we can read more from the port.
+ setReadNotificationEnabled(false);
return false;
}
}
@@ -991,11 +992,11 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
if (checkWrite)
FD_SET(descriptor, &fdwrite);
- struct timeval tv;
+ struct timespec tv;
tv.tv_sec = msecs / 1000;
- tv.tv_usec = (msecs % 1000) * 1000;
+ tv.tv_nsec = (msecs % 1000) * 1000 * 1000;
- const int ret = ::select(descriptor + 1, &fdread, &fdwrite, 0, msecs < 0 ? 0 : &tv);
+ const int ret = qt_safe_select(descriptor + 1, &fdread, &fdwrite, 0, msecs < 0 ? 0 : &tv);
if (ret < 0) {
setError(getSystemError());
return false;
@@ -1230,11 +1231,6 @@ static const BaudRateMap& standardBaudRateMap()
return baudRateMap;
}
-qint32 QSerialPortPrivate::baudRateFromSetting(qint32 setting)
-{
- return standardBaudRateMap().key(setting);
-}
-
qint32 QSerialPortPrivate::settingFromBaudRate(qint32 baudRate)
{
return standardBaudRateMap().value(baudRate);
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 39d7e33..8e7c278 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -260,7 +260,8 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
stopWatch.start();
do {
- OVERLAPPED *overlapped = waitForNotified(timeoutValue(msecs, stopWatch.elapsed()));
+ OVERLAPPED *overlapped = waitForNotified(
+ qt_subtract_from_timeout(msecs, stopWatch.elapsed()));
if (!overlapped)
return false;
@@ -276,7 +277,7 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
}
}
- } while (msecs == -1 || timeoutValue(msecs, stopWatch.elapsed()) > 0);
+ } while (msecs == -1 || qt_subtract_from_timeout(msecs, stopWatch.elapsed()) > 0);
return false;
}
@@ -293,7 +294,8 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs)
stopWatch.start();
forever {
- OVERLAPPED *overlapped = waitForNotified(timeoutValue(msecs, stopWatch.elapsed()));
+ OVERLAPPED *overlapped = waitForNotified(
+ qt_subtract_from_timeout(msecs, stopWatch.elapsed()));
if (!overlapped)
return false;
@@ -811,15 +813,6 @@ static const QList<qint32> standardBaudRatePairList()
return standardBaudRatesTable;
};
-qint32 QSerialPortPrivate::baudRateFromSetting(qint32 setting)
-{
- const QList<qint32> baudRatePairs = standardBaudRatePairList();
- const QList<qint32>::const_iterator baudRatePairListConstIterator
- = std::find(baudRatePairs.constBegin(), baudRatePairs.constEnd(), setting);
-
- return (baudRatePairListConstIterator != baudRatePairs.constEnd()) ? *baudRatePairListConstIterator : 0;
-}
-
qint32 QSerialPortPrivate::settingFromBaudRate(qint32 baudRate)
{
const QList<qint32> baudRatePairList = standardBaudRatePairList();
diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp
index 18dd15d..b1975af 100644
--- a/src/serialport/qserialport_wince.cpp
+++ b/src/serialport/qserialport_wince.cpp
@@ -329,7 +329,7 @@ bool QSerialPortPrivate::waitForReadyRead(int msec)
bool readyToWrite = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite,
true, !writeBuffer.isEmpty(),
- timeoutValue(msec, stopWatch.elapsed()))) {
+ qt_subtract_from_timeout(msec, stopWatch.elapsed()))) {
return false;
}
if (readyToRead) {
@@ -355,7 +355,7 @@ bool QSerialPortPrivate::waitForBytesWritten(int msec)
bool readyToWrite = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite,
true, !writeBuffer.isEmpty(),
- timeoutValue(msec, stopWatch.elapsed()))) {
+ qt_subtract_from_timeout(msec, stopWatch.elapsed()))) {
return false;
}
if (readyToRead) {
@@ -743,15 +743,6 @@ static const QList<qint32> standardBaudRatePairList()
return standardBaudRatesTable;
};
-qint32 QSerialPortPrivate::baudRateFromSetting(qint32 setting)
-{
- const QList<qint32> baudRatePairs = standardBaudRatePairList();
- const QList<qint32>::const_iterator baudRatePairListConstIterator
- = std::find(baudRatePairs.constBegin(), baudRatePairs.constEnd(), setting);
-
- return (baudRatePairListConstIterator != baudRatePairs.constEnd()) ? *baudRatePairListConstIterator : 0;
-}
-
qint32 QSerialPortPrivate::settingFromBaudRate(qint32 baudRate)
{
const QList<qint32> baudRatePairList = standardBaudRatePairList();
diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp
index 38190b7..06987f2 100644
--- a/src/serialport/qserialportinfo_win.cpp
+++ b/src/serialport/qserialportinfo_win.cpp
@@ -41,6 +41,8 @@
#include <QtCore/qpair.h>
#include <QtCore/qstringlist.h>
+#include <vector>
+
#include <initguid.h>
#include <setupapi.h>
#include <cfgmgr32.h>
@@ -63,14 +65,6 @@ static inline const QList<GuidFlagsPair>& guidFlagsPairs()
return guidFlagsPairList;
}
-static QString toStringAndTrimNullCharacter(const QByteArray &buffer)
-{
- const QString result = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(buffer.constData()),
- buffer.size() / sizeof(wchar_t));
- const int index = result.indexOf(QChar(0));
- return index == -1 ? result : result.mid(0, index);
-}
-
static QStringList portNamesFromHardwareDeviceMap()
{
HKEY hKey = Q_NULLPTR;
@@ -79,19 +73,22 @@ static QStringList portNamesFromHardwareDeviceMap()
QStringList result;
DWORD index = 0;
- static const DWORD maximumValueNameInChars = 16383;
- QByteArray outputValueName;
- outputValueName.resize(maximumValueNameInChars * sizeof(wchar_t));
- QByteArray outputBuffer;
- DWORD requiredDataBytes = 0;
+
+ // This is a maximum length of value name, see:
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872%28v=vs.85%29.aspx
+ enum { MaximumValueNameInChars = 16383 };
+
+ std::vector<wchar_t> outputValueName(MaximumValueNameInChars, 0);
+ std::vector<wchar_t> outputBuffer(MAX_PATH + 1, 0);
+ DWORD bytesRequired = MAX_PATH;
forever {
- DWORD requiredValueNameChars = maximumValueNameInChars;
- const LONG ret = ::RegEnumValue(hKey, index, reinterpret_cast<wchar_t *>(outputValueName.data()), &requiredValueNameChars,
- Q_NULLPTR, Q_NULLPTR, reinterpret_cast<unsigned char *>(outputBuffer.data()), &requiredDataBytes);
+ DWORD requiredValueNameChars = MaximumValueNameInChars;
+ const LONG ret = ::RegEnumValue(hKey, index, &outputValueName[0], &requiredValueNameChars,
+ Q_NULLPTR, Q_NULLPTR, reinterpret_cast<PBYTE>(&outputBuffer[0]), &bytesRequired);
if (ret == ERROR_MORE_DATA) {
- outputBuffer.resize(requiredDataBytes);
+ outputBuffer.resize(bytesRequired / sizeof(wchar_t) + 2, 0);
} else if (ret == ERROR_SUCCESS) {
- result.append(toStringAndTrimNullCharacter(outputBuffer));
+ result.append(QString::fromWCharArray(&outputBuffer[0]));
++index;
} else {
break;
@@ -106,12 +103,12 @@ static QString deviceRegistryProperty(HDEVINFO deviceInfoSet,
DWORD property)
{
DWORD dataType = 0;
- QByteArray devicePropertyByteArray;
- DWORD requiredSize = 0;
+ std::vector<wchar_t> outputBuffer(MAX_PATH + 1, 0);
+ DWORD bytesRequired = MAX_PATH;
forever {
if (::SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType,
- reinterpret_cast<unsigned char *>(devicePropertyByteArray.data()),
- devicePropertyByteArray.size(), &requiredSize)) {
+ reinterpret_cast<PBYTE>(&outputBuffer[0]),
+ bytesRequired, &bytesRequired)) {
break;
}
@@ -119,25 +116,22 @@ static QString deviceRegistryProperty(HDEVINFO deviceInfoSet,
|| (dataType != REG_SZ && dataType != REG_EXPAND_SZ)) {
return QString();
}
- devicePropertyByteArray.resize(requiredSize);
+ outputBuffer.resize(bytesRequired / sizeof(wchar_t) + 2, 0);
}
- return toStringAndTrimNullCharacter(devicePropertyByteArray);
+ return QString::fromWCharArray(&outputBuffer[0]);
}
static QString deviceInstanceIdentifier(DEVINST deviceInstanceNumber)
{
- ULONG numberOfChars = 0;
- if (::CM_Get_Device_ID_Size(&numberOfChars, deviceInstanceNumber, 0) != CR_SUCCESS)
- return QString();
- // The size does not include the terminating null character.
- ++numberOfChars;
- QByteArray outputBuffer;
- outputBuffer.resize(numberOfChars * sizeof(wchar_t));
- if (::CM_Get_Device_ID(deviceInstanceNumber, reinterpret_cast<wchar_t *>(outputBuffer.data()),
- outputBuffer.size(), 0) != CR_SUCCESS) {
+ std::vector<wchar_t> outputBuffer(MAX_DEVICE_ID_LEN + 1, 0);
+ if (::CM_Get_Device_ID(
+ deviceInstanceNumber,
+ &outputBuffer[0],
+ MAX_DEVICE_ID_LEN,
+ 0) != CR_SUCCESS) {
return QString();
}
- return toStringAndTrimNullCharacter(outputBuffer).toUpper();
+ return QString::fromWCharArray(&outputBuffer[0]).toUpper();
}
static DEVINST parentDeviceInstanceNumber(DEVINST childDeviceInstanceNumber)
@@ -167,20 +161,20 @@ static QString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInf
QString portName;
foreach (const QString &portNameKey, portNameRegistryKeyList) {
- DWORD bytesRequired = 0;
DWORD dataType = 0;
- QByteArray outputBuffer;
+ std::vector<wchar_t> outputBuffer(MAX_PATH + 1, 0);
+ DWORD bytesRequired = MAX_PATH;
forever {
const LONG ret = ::RegQueryValueEx(key, reinterpret_cast<const wchar_t *>(portNameKey.utf16()), Q_NULLPTR, &dataType,
- reinterpret_cast<unsigned char *>(outputBuffer.data()), &bytesRequired);
+ reinterpret_cast<PBYTE>(&outputBuffer[0]), &bytesRequired);
if (ret == ERROR_MORE_DATA) {
- outputBuffer.resize(bytesRequired);
+ outputBuffer.resize(bytesRequired / sizeof(wchar_t) + 2, 0);
continue;
} else if (ret == ERROR_SUCCESS) {
if (dataType == REG_SZ)
- portName = toStringAndTrimNullCharacter(outputBuffer);
+ portName = QString::fromWCharArray(&outputBuffer[0]);
else if (dataType == REG_DWORD)
- portName = QStringLiteral("COM%1").arg(*(PDWORD(outputBuffer.constData())));
+ portName = QStringLiteral("COM%1").arg(*(PDWORD(&outputBuffer[0])));
}
break;
}
diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp
index d50afe9..3a62bfa 100644
--- a/tests/auto/qserialport/tst_qserialport.cpp
+++ b/tests/auto/qserialport/tst_qserialport.cpp
@@ -120,6 +120,8 @@ private slots:
void asynchronousWriteByTimer_data();
void asynchronousWriteByTimer();
+ void asyncReadWithLimitedReadBufferSize();
+
void readBufferOverflow();
void readAfterInputClear();
void synchronousReadWriteAfterAsynchronousReadWrite();
@@ -808,6 +810,49 @@ void tst_QSerialPort::asynchronousWriteByTimer()
QCOMPARE(receiverPort.readAll(), alphabetArray);
}
+class AsyncReader2 : public QObject
+{
+ Q_OBJECT
+public:
+ explicit AsyncReader2(QSerialPort &port, const QByteArray &expectedData)
+ : serialPort(port), expectedData(expectedData)
+ {
+ connect(&serialPort, &QSerialPort::readyRead, this, &AsyncReader2::receive);
+ }
+
+private slots:
+ void receive()
+ {
+ receivedData.append(serialPort.readAll());
+ if (receivedData == expectedData)
+ tst_QSerialPort::exitLoop();
+ }
+
+private:
+ QSerialPort &serialPort;
+ const QByteArray expectedData;
+ QByteArray receivedData;
+};
+
+void tst_QSerialPort::asyncReadWithLimitedReadBufferSize()
+{
+ QSerialPort senderPort(m_senderPortName);
+ QVERIFY(senderPort.open(QSerialPort::WriteOnly));
+
+ QSerialPort receiverPort(m_receiverPortName);
+ QVERIFY(receiverPort.open(QSerialPort::ReadOnly));
+
+ receiverPort.setReadBufferSize(1);
+ QCOMPARE(receiverPort.readBufferSize(), qint64(1));
+
+ AsyncReader2 reader(receiverPort, alphabetArray);
+
+ QCOMPARE(senderPort.write(alphabetArray), qint64(alphabetArray.size()));
+
+ enterLoop(1);
+ QVERIFY2(!timeout(), "Timed out when waiting for the read or write.");
+}
+
void tst_QSerialPort::readBufferOverflow()
{
QSerialPort senderPort(m_senderPortName);