summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2014-02-12 14:11:48 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-02-12 14:11:48 +0100
commitb240d198f80e47c484f1c22d259da85227421950 (patch)
treee506824a0b7d0d6201b51a686559043c243512b0
parent296b5964c05e312a7c83ba44379ba258755e13a3 (diff)
parent65dd36db940bd9b0c1806f66c54bb672b08eb9b8 (diff)
downloadqtserialport-b240d198f80e47c484f1c22d259da85227421950.tar.gz
Merge remote-tracking branch 'origin/stable' into dev
Change-Id: I10b71332b0ec3afc50d11bcc95adb94c6343f6b1
-rw-r--r--examples/serialport/doc/blockingslave.qdoc2
-rw-r--r--examples/serialport/doc/creaderasync.qdoc2
-rw-r--r--examples/serialport/doc/terminal.qdoc2
-rw-r--r--src/serialport/qserialport.cpp81
-rw-r--r--src/serialport/qserialport.h22
-rw-r--r--src/serialport/qserialport_symbian.cpp11
-rw-r--r--src/serialport/qserialport_symbian_p.h3
-rw-r--r--src/serialport/qserialport_unix.cpp106
-rw-r--r--src/serialport/qserialport_unix_p.h3
-rw-r--r--src/serialport/qserialport_win.cpp185
-rw-r--r--src/serialport/qserialport_win_p.h7
-rw-r--r--src/serialport/qserialport_wince.cpp60
-rw-r--r--src/serialport/qserialportinfo_win.cpp152
13 files changed, 350 insertions, 286 deletions
diff --git a/examples/serialport/doc/blockingslave.qdoc b/examples/serialport/doc/blockingslave.qdoc
index c98080d..df35bfc 100644
--- a/examples/serialport/doc/blockingslave.qdoc
+++ b/examples/serialport/doc/blockingslave.qdoc
@@ -62,7 +62,7 @@
leads to simpler code, but because of its blocking behavior, it should only
be used in non-GUI threads to prevent the user interface from freezing.
But contrary to what many think, using threads with QThread does not
- necessarily add unmanagable complexity to your application.
+ necessarily add unmanageable complexity to your application.
This application is a Slave, that demonstrate the work paired with Master
application \l{Blocking Master Example}.
diff --git a/examples/serialport/doc/creaderasync.qdoc b/examples/serialport/doc/creaderasync.qdoc
index 2349856..a8b2101 100644
--- a/examples/serialport/doc/creaderasync.qdoc
+++ b/examples/serialport/doc/creaderasync.qdoc
@@ -26,7 +26,7 @@
****************************************************************************/
/*!
- \example creader
+ \example creaderasync
\title Command Line Reader Async Example
\ingroup qtserialport-examples
diff --git a/examples/serialport/doc/terminal.qdoc b/examples/serialport/doc/terminal.qdoc
index e74e237..ed8fa02 100644
--- a/examples/serialport/doc/terminal.qdoc
+++ b/examples/serialport/doc/terminal.qdoc
@@ -82,7 +82,7 @@
The serial port is instantiated in the \l{terminal/mainwindow.cpp}{MainWindow}
constructor. The main widget is passed as the parent, so the object deletion
- happens automatically according to the the parent and child mechanism in Qt:
+ happens automatically according to the parent and child mechanism in Qt:
\snippet terminal/mainwindow.cpp 0
\dots
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp
index cd0c681..060fcdc 100644
--- a/src/serialport/qserialport.cpp
+++ b/src/serialport/qserialport.cpp
@@ -116,10 +116,10 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
port to the desired setting using the setBaudRate(), setDataBits(),
setParity(), setStopBits(), and setFlowControl() methods.
- The status of the control pinout signals is determined with the
- isDataTerminalReady(), isRequestToSend, and pinoutSignals() methods. To
- change the control line status, use the setDataTerminalReady(), and
- setRequestToSend() methods.
+ There are a couple of properties to work with the pinout signals namely:
+ QSerialPort::dataTerminalReady, QSerialPort::requestToSend. It is also
+ possible to use the pinoutSignals() method to query the current pinout
+ signals set.
Once you know that the ports are ready to read or write, you can
use the read() or write() methods. Alternatively the
@@ -212,12 +212,12 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
\value Data5 The number of data bits in each character is 5. It
is used for Baudot code. It generally only makes
- sense with older equipments such as teleprinters.
+ sense with older equipment such as teleprinters.
\value Data6 The number of data bits in each character is 6. It
is rarely used.
\value Data7 The number of data bits in each character is 7. It
is used for true ASCII. It generally only makes
- sense with older equipments such as teleprinters.
+ sense with older equipment such as teleprinters.
\value Data8 The number of data bits in each character is 8. It
is used for most kinds of data, as this size matches
the size of a byte. It is almost universally used in
@@ -261,9 +261,9 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
This enum describes the number of stop bits used.
\value OneStop 1 stop bit.
- \value OneAndHalfStop 1.5 stop bits. This is only for Windows platform.
+ \value OneAndHalfStop 1.5 stop bits. This is only for the Windows platform.
\value TwoStop 2 stop bits.
- \value UnknownStopBits Unknown number of stop bit. This value is obsolete.
+ \value UnknownStopBits Unknown number of stop bits. This value is obsolete.
It is provided to keep old source code working. We
strongly advise against using it in new code.
@@ -291,8 +291,14 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
This enum describes the possible RS-232 pinout signals.
\value NoSignal No line active
- \value TransmittedDataSignal TxD (Transmitted Data).
- \value ReceivedDataSignal RxD (Received Data).
+ \value TransmittedDataSignal TxD (Transmitted Data). This value is
+ obsolete. It is provided to keep old
+ source code working. We strongly
+ advise against using it in new code.
+ \value ReceivedDataSignal RxD (Received Data). This value is
+ obsolete. It is provided to keep old
+ source code working. We strongly
+ advise against using it in new code.
\value DataTerminalReadySignal DTR (Data Terminal Ready).
\value DataCarrierDetectSignal DCD (Data Carrier Detect).
\value DataSetReadySignal DSR (Data Set Ready).
@@ -314,7 +320,7 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
while parity errors were detected.
\value SkipPolicy Skips the bad character.
- \value PassZeroPolicy Replaces bad character to zero.
+ \value PassZeroPolicy Replaces bad character with zero.
\value IgnorePolicy Ignores the error for a bad character.
\value StopReceivingPolicy Stops data reception on error.
\value UnknownPolicy Unknown policy.
@@ -422,7 +428,7 @@ QSerialPort::~QSerialPort()
/*!
Sets the \a name of the serial port.
- The name of the serial port can be passed on as either a short name or
+ The name of the serial port can be passed as either a short name or
the long system location if necessary.
\sa portName(), QSerialPortInfo
@@ -445,9 +451,9 @@ void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)
}
/*!
- Returns the name set by setPort() or to the QSerialPort constructors.
- This name is short, i.e. it extract and convert out from the internal
- variable system location of the device. Conversion algorithm is
+ Returns the name set by setPort() or passed to the QSerialPort constructor.
+ This name is short, i.e. it is extracted and converted from the internal
+ variable system location of the device. The conversion algorithm is
platform specific:
\table
\header
@@ -459,7 +465,7 @@ void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)
and returns the remainder of the string.
\row
\li Windows CE
- \li Removes the postfix ":" from the system location
+ \li Removes the suffix ":" from the system location
and returns the remainder of the string.
\row
\li Symbian
@@ -494,7 +500,7 @@ QString QSerialPort::portName() const
obtained by calling the error() method.
\note This method has to be called before setting certain serial port
- parameters. See each property documentation for details when it is
+ parameters. See each property documentation for the details of when it is
necessary.
\warning The \a mode has to be QIODevice::ReadOnly, QIODevice::WriteOnly,
@@ -552,11 +558,11 @@ void QSerialPort::close()
/*!
\property QSerialPort::settingsRestoredOnClose
- \brief the flag which allows to restore the previous settings while closing
+ \brief the flag which specifies to restore the previous settings when closing
the serial port.
If this flag is true, the settings will be restored; otherwise not.
- The default state of the QSerialPort class is configured to restore the
+ The default state of the QSerialPort class is to restore the
settings.
*/
void QSerialPort::setSettingsRestoredOnClose(bool restore)
@@ -578,9 +584,9 @@ bool QSerialPort::settingsRestoredOnClose() const
/*!
\fn void QSerialPort::settingsRestoredOnCloseChanged(bool restore)
- This signal is emitted after the flag which allows to restore the
+ This signal is emitted after the flag which specifies to restore the
previous settings while closing the serial port has been changed. The new
- flag which allows to restore the previous settings while closing the serial
+ flag which specifies to restore the previous settings while closing the serial
port is passed as \a restore.
\sa QSerialPort::settingsRestoredOnClose
@@ -602,8 +608,8 @@ bool QSerialPort::settingsRestoredOnClose() const
with the kernel and hardware. Hence, the two scenarios cannot be completely
compared to each other.
- \warning Only the AllDirections flag is support for setting this property on
- Windows, Windows CE, and Symbian.
+ \warning Setting the AllDirections flag is only supported on
+ the Windows, Windows CE, and Symbian platforms.
\warning Returns equal baud rate in any direction on Windows, Windows CE, and
Symbian.
@@ -981,8 +987,7 @@ bool QSerialPort::isRequestToSend()
\note The serial port has to be open before trying to get the pinout
signals; otherwise returns NoSignal and sets the NotOpenError error code.
- \sa isDataTerminalReady(), isRequestToSend, setDataTerminalReady(),
- setRequestToSend()
+ \sa QSerialPort::dataTerminalReady, QSerialPort::requestToSend
*/
QSerialPort::PinoutSignals QSerialPort::pinoutSignals()
{
@@ -1029,7 +1034,7 @@ bool QSerialPort::flush()
/*!
Discards all characters from the output or input buffer, depending on
- given directions \a directions. Including clear an internal class buffers and
+ given directions \a directions. This includes clearing the internal class buffers and
the UART (driver) buffers. Also terminate pending read or write operations.
If successful, returns true; otherwise returns false.
@@ -1083,8 +1088,8 @@ bool QSerialPort::atEnd() const
/*!
\property QSerialPort::dataErrorPolicy
- \brief the error policy how the process receives the character in case of
- parity error detection.
+ \brief the error policy for how the process receives characters in the case where
+ a parity error is detected.
\obsolete
If the setting is successful, returns true; otherwise returns false. The
@@ -1126,9 +1131,9 @@ QSerialPort::DataErrorPolicy QSerialPort::dataErrorPolicy() const
\fn void QSerialPort::dataErrorPolicyChanged(DataErrorPolicy policy)
\obsolete
- This signal is emitted after the error policy how the process receives the
- character in case of parity error detection has been changed. The new error
- policy how the process receives the character in case of parity error
+ This signal is emitted after the error policy for how the process receives
+ characters in case of parity error detection has been changed. The new error
+ policy for how the process receives the character in case of parity error
detection is passed as \a policy.
\sa QSerialPort::dataErrorPolicy
@@ -1159,8 +1164,8 @@ void QSerialPort::clearError()
/*!
\fn void QSerialPort::error(SerialPortError error)
- This signal is emitted after the error has been changed. The new erroris
- passed as \a error.
+ This signal is emitted after the error has been changed. The new error
+ is passed as \a error.
\sa QSerialPort::error
*/
@@ -1186,14 +1191,14 @@ qint64 QSerialPort::readBufferSize() const
size bytes.
If the buffer size is limited to a certain size, QSerialPort
- will not buffer more than this size of data. Exceptionally, a buffer
+ will not buffer more than this size of data. The special case of a buffer
size of 0 means that the read buffer is unlimited and all
incoming data is buffered. This is the default.
This option is useful if the data is only read at certain points
in time (for instance in a real-time streaming application) or if the serial
port should be protected against receiving too much data, which may
- eventually causes that the application runs out of memory.
+ eventually cause the application to run out of memory.
\sa readBufferSize(), read()
*/
@@ -1279,11 +1284,11 @@ bool QSerialPort::waitForReadyRead(int msecs)
}
/*!
- \fn QSerialPort::Handle QSerialPort::handle()
+ \fn Handle QSerialPort::handle() const
\since 5.2
- Returns the native serial port descriptor of the object. If the serial port
- is not open or the platform is not supported, handle() returns -1.
+ If the platform is supported and the serial port is open, returns the native
+ serial port handle; otherwise returns -1.
\warning This function is for expert use only; use it at your own risk.
Furthermore, this function carries no compatibility promise between minor
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h
index 1689222..30e3b8c 100644
--- a/src/serialport/qserialport.h
+++ b/src/serialport/qserialport.h
@@ -131,16 +131,6 @@ public:
UnknownFlowControl = -1
};
-#if QT_DEPRECATED_SINCE(5, 2)
-#if defined _MSC_VER
-#pragma deprecated(UnknownBaud)
-#pragma deprecated(UnknownDataBits)
-#pragma deprecated(UnknownParity)
-#pragma deprecated(UnknownStopBits)
-#pragma deprecated(UnknownFlowControl)
-#endif
-#endif
-
enum PinoutSignal {
NoSignal = 0x00,
TransmittedDataSignal = 0x01,
@@ -157,6 +147,18 @@ public:
Q_DECLARE_FLAGS(PinoutSignals, PinoutSignal)
#if QT_DEPRECATED_SINCE(5, 2)
+#if defined _MSC_VER
+#pragma deprecated(UnknownBaud)
+#pragma deprecated(UnknownDataBits)
+#pragma deprecated(UnknownParity)
+#pragma deprecated(UnknownStopBits)
+#pragma deprecated(UnknownFlowControl)
+#pragma deprecated(TransmittedDataSignal)
+#pragma deprecated(ReceivedDataSignal)
+#endif
+#endif
+
+#if QT_DEPRECATED_SINCE(5, 2)
enum DataErrorPolicy {
SkipPolicy,
PassZeroPolicy,
diff --git a/src/serialport/qserialport_symbian.cpp b/src/serialport/qserialport_symbian.cpp
index 9318696..b904d2b 100644
--- a/src/serialport/qserialport_symbian.cpp
+++ b/src/serialport/qserialport_symbian.cpp
@@ -237,17 +237,6 @@ bool QSerialPortPrivate::setBreakEnabled(bool set)
return false;
}
-qint64 QSerialPortPrivate::systemInputQueueSize () const
-{
- return descriptor.QueryReceiveBuffer();
-}
-
-qint64 QSerialPortPrivate::systemOutputQueueSize () const
-{
- // TODO: Implement me
- return 0;
-}
-
void QSerialPortPrivate::startWriting()
{
// TODO: Implement me
diff --git a/src/serialport/qserialport_symbian_p.h b/src/serialport/qserialport_symbian_p.h
index 7c3d3ef..5d95ca9 100644
--- a/src/serialport/qserialport_symbian_p.h
+++ b/src/serialport/qserialport_symbian_p.h
@@ -69,9 +69,6 @@ public:
bool sendBreak(int duration);
bool setBreakEnabled(bool set);
- qint64 systemInputQueueSize () const;
- qint64 systemOutputQueueSize () const;
-
void startWriting();
bool waitForReadyRead(int msec);
diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp
index b994a0e..84f3109 100644
--- a/src/serialport/qserialport_unix.cpp
+++ b/src/serialport/qserialport_unix.cpp
@@ -59,6 +59,8 @@
#include <QtCore/qsocketnotifier.h>
#include <QtCore/qmap.h>
+#include <private/qcore_unix_p.h>
+
QT_BEGIN_NAMESPACE
QString serialPortLockFilePath(const QString &portName)
@@ -213,7 +215,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
break;
}
- descriptor = ::open(systemLocation.toLocal8Bit().constData(), flags);
+ descriptor = qt_safe_open(systemLocation.toLocal8Bit().constData(), flags);
if (descriptor == -1) {
q->setError(decodeSystemError());
@@ -227,7 +229,8 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
}
#ifdef TIOCEXCL
- ::ioctl(descriptor, TIOCEXCL);
+ if (::ioctl(descriptor, TIOCEXCL) == -1)
+ q->setError(decodeSystemError());
#endif
if (::tcgetattr(descriptor, &restoredTermios) == -1) {
@@ -236,7 +239,15 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
}
currentTermios = restoredTermios;
+#ifdef Q_OS_SOLARIS
+ currentTermios.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ currentTermios.c_oflag &= ~OPOST;
+ currentTermios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ currentTermios.c_cflag &= ~(CSIZE|PARENB);
+ currentTermios.c_cflag |= CS8;
+#else
::cfmakeraw(&currentTermios);
+#endif
currentTermios.c_cflag |= CLOCAL;
currentTermios.c_cc[VTIME] = 0;
currentTermios.c_cc[VMIN] = 0;
@@ -258,16 +269,23 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
void QSerialPortPrivate::close()
{
+ Q_Q(QSerialPort);
+
if (settingsRestoredOnClose) {
- ::tcsetattr(descriptor, TCSANOW, &restoredTermios);
+ if (::tcsetattr(descriptor, TCSANOW, &restoredTermios) == -1)
+ q->setError(decodeSystemError());
+
#ifdef Q_OS_LINUX
- if (isCustomBaudRateSupported)
- ::ioctl(descriptor, TIOCSSERIAL, &restoredSerialInfo);
+ if (isCustomBaudRateSupported) {
+ if (::ioctl(descriptor, TIOCSSERIAL, &restoredSerialInfo) == -1)
+ q->setError(decodeSystemError());
+ }
#endif
}
#ifdef TIOCNXCL
- ::ioctl(descriptor, TIOCNXCL);
+ if (::ioctl(descriptor, TIOCNXCL) == -1)
+ q->setError(decodeSystemError());
#endif
if (readNotifier) {
@@ -288,7 +306,8 @@ void QSerialPortPrivate::close()
exceptionNotifier = 0;
}
- ::close(descriptor);
+ if (qt_safe_close(descriptor) == -1)
+ q->setError(decodeSystemError());
if (lockFileScopedPointer->isLocked())
lockFileScopedPointer->unlock();
@@ -358,14 +377,28 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals()
bool QSerialPortPrivate::setDataTerminalReady(bool set)
{
+ Q_Q(QSerialPort);
+
int status = TIOCM_DTR;
- return ::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) != -1;
+ if (::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) == -1) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ return true;
}
bool QSerialPortPrivate::setRequestToSend(bool set)
{
+ Q_Q(QSerialPort);
+
int status = TIOCM_RTS;
- return ::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) != -1;
+ if (::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) == -1) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ return true;
}
bool QSerialPortPrivate::flush()
@@ -380,38 +413,39 @@ bool QSerialPortPrivate::flush()
bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
{
- return ::tcflush(descriptor, (directions == QSerialPort::AllDirections)
- ? TCIOFLUSH : (directions & QSerialPort::Input) ? TCIFLUSH : TCOFLUSH) != -1;
+ Q_Q(QSerialPort);
+
+ if (::tcflush(descriptor, (directions == QSerialPort::AllDirections)
+ ? TCIOFLUSH : (directions & QSerialPort::Input) ? TCIFLUSH : TCOFLUSH) == -1) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ return true;
}
bool QSerialPortPrivate::sendBreak(int duration)
{
- return ::tcsendbreak(descriptor, duration) != -1;
+ Q_Q(QSerialPort);
+
+ if (::tcsendbreak(descriptor, duration) == -1) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ return true;
}
bool QSerialPortPrivate::setBreakEnabled(bool set)
{
- return ::ioctl(descriptor, set ? TIOCSBRK : TIOCCBRK) != -1;
-}
+ Q_Q(QSerialPort);
-qint64 QSerialPortPrivate::systemInputQueueSize () const
-{
- int nbytes = 0;
-#ifdef TIOCINQ
- if (::ioctl(descriptor, TIOCINQ, &nbytes) == -1)
- return -1;
-#endif
- return nbytes;
-}
+ if (::ioctl(descriptor, set ? TIOCSBRK : TIOCCBRK) == -1) {
+ q->setError(decodeSystemError());
+ return false;
+ }
-qint64 QSerialPortPrivate::systemOutputQueueSize () const
-{
- int nbytes = 0;
-#ifdef TIOCOUTQ
- if (::ioctl(descriptor, TIOCOUTQ, &nbytes) == -1)
- return -1;
-#endif
- return nbytes;
+ return true;
}
void QSerialPortPrivate::startWriting()
@@ -1044,7 +1078,7 @@ qint64 QSerialPortPrivate::readFromPort(char *data, qint64 maxSize)
if (parity != QSerialPort::MarkParity
&& parity != QSerialPort::SpaceParity) {
#endif
- bytesRead = ::read(descriptor, data, maxSize);
+ bytesRead = qt_safe_read(descriptor, data, maxSize);
} else {// Perform parity emulation.
bytesRead = readPerChar(data, maxSize);
}
@@ -1056,11 +1090,11 @@ qint64 QSerialPortPrivate::writeToPort(const char *data, qint64 maxSize)
{
qint64 bytesWritten = 0;
#if defined (CMSPAR)
- bytesWritten = ::write(descriptor, data, maxSize);
+ bytesWritten = qt_safe_write(descriptor, data, maxSize);
#else
if (parity != QSerialPort::MarkParity
&& parity != QSerialPort::SpaceParity) {
- bytesWritten = ::write(descriptor, data, maxSize);
+ bytesWritten = qt_safe_write(descriptor, data, maxSize);
} else {// Perform parity emulation.
bytesWritten = writePerChar(data, maxSize);
}
@@ -1097,7 +1131,7 @@ qint64 QSerialPortPrivate::writePerChar(const char *data, qint64 maxSize)
break;
}
- int r = ::write(descriptor, data, 1);
+ int r = qt_safe_write(descriptor, data, 1);
if (r < 0)
return -1;
if (r > 0) {
@@ -1123,7 +1157,7 @@ qint64 QSerialPortPrivate::readPerChar(char *data, qint64 maxSize)
int prefix = 0;
while (ret < maxSize) {
- qint64 r = ::read(descriptor, data, 1);
+ qint64 r = qt_safe_read(descriptor, data, 1);
if (r < 0) {
if (errno == EAGAIN) // It is ok for nonblocking mode.
break;
diff --git a/src/serialport/qserialport_unix_p.h b/src/serialport/qserialport_unix_p.h
index 7dbb760..1960316 100644
--- a/src/serialport/qserialport_unix_p.h
+++ b/src/serialport/qserialport_unix_p.h
@@ -108,9 +108,6 @@ public:
bool sendBreak(int duration);
bool setBreakEnabled(bool set);
- qint64 systemInputQueueSize () const;
- qint64 systemOutputQueueSize () const;
-
void startWriting();
bool waitForReadyRead(int msecs);
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index f9e8a5e..ecf8a62 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -98,11 +98,11 @@ static void initializeOverlappedStructure(OVERLAPPED &overlapped)
QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
: QSerialPortPrivateData(q)
- , descriptor(INVALID_HANDLE_VALUE)
+ , handle(INVALID_HANDLE_VALUE)
, parityErrorOccurred(false)
, readChunkBuffer(ReadChunkSize, 0)
, readyReadEmitted(0)
- , writeSequenceStarted(false)
+ , writeStarted(false)
, communicationNotifier(new QWinEventNotifier(q))
, readCompletionNotifier(new QWinEventNotifier(q))
, writeCompletionNotifier(new QWinEventNotifier(q))
@@ -151,15 +151,18 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
if (mode & QIODevice::WriteOnly)
desiredAccess |= GENERIC_WRITE;
- descriptor = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation.utf16()),
+ handle = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation.utf16()),
desiredAccess, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (descriptor == INVALID_HANDLE_VALUE) {
+ if (handle == INVALID_HANDLE_VALUE) {
q->setError(decodeSystemError());
return false;
}
- if (!::GetCommState(descriptor, &restoredDcb)) {
+ ::ZeroMemory(&restoredDcb, sizeof(restoredDcb));
+ restoredDcb.DCBlength = sizeof(restoredDcb);
+
+ if (!::GetCommState(handle, &restoredDcb)) {
q->setError(decodeSystemError());
return false;
}
@@ -172,10 +175,13 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
currentDcb.fNull = FALSE;
currentDcb.fErrorChar = FALSE;
+ if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
+ currentDcb.fDtrControl = DTR_CONTROL_DISABLE;
+
if (!updateDcb())
return false;
- if (!::GetCommTimeouts(descriptor, &restoredCommTimeouts)) {
+ if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) {
q->setError(decodeSystemError());
return false;
}
@@ -192,7 +198,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
if (mode & QIODevice::WriteOnly)
writeCompletionNotifier->setEnabled(true);
- if (!::SetCommMask(descriptor, originalEventMask)) {
+ if (!::SetCommMask(handle, originalEventMask)) {
q->setError(decodeSystemError());
return false;
}
@@ -210,7 +216,7 @@ void QSerialPortPrivate::close()
{
Q_Q(QSerialPort);
- if (!::CancelIo(descriptor))
+ if (!::CancelIo(handle))
q->setError(decodeSystemError());
readCompletionNotifier->setEnabled(false);
@@ -219,23 +225,23 @@ void QSerialPortPrivate::close()
readBuffer.clear();
- writeSequenceStarted = false;
+ writeStarted = false;
writeBuffer.clear();
readyReadEmitted = false;
parityErrorOccurred = false;
if (settingsRestoredOnClose) {
- if (!::SetCommState(descriptor, &restoredDcb))
+ if (!::SetCommState(handle, &restoredDcb))
q->setError(decodeSystemError());
- else if (!::SetCommTimeouts(descriptor, &restoredCommTimeouts))
+ else if (!::SetCommTimeouts(handle, &restoredCommTimeouts))
q->setError(decodeSystemError());
}
- if (!::CloseHandle(descriptor))
+ if (!::CloseHandle(handle))
q->setError(decodeSystemError());
- descriptor = INVALID_HANDLE_VALUE;
+ handle = INVALID_HANDLE_VALUE;
}
#endif // #ifndef Q_OS_WINCE
@@ -246,7 +252,7 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals()
DWORD modemStat = 0;
- if (!::GetCommModemStatus(descriptor, &modemStat)) {
+ if (!::GetCommModemStatus(handle, &modemStat)) {
q->setError(decodeSystemError());
return QSerialPort::NoSignal;
}
@@ -263,9 +269,10 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals()
ret |= QSerialPort::DataCarrierDetectSignal;
DWORD bytesReturned = 0;
- if (!::DeviceIoControl(descriptor, IOCTL_SERIAL_GET_DTRRTS, NULL, 0,
+ if (!::DeviceIoControl(handle, IOCTL_SERIAL_GET_DTRRTS, NULL, 0,
&modemStat, sizeof(modemStat),
&bytesReturned, NULL)) {
+ q->setError(decodeSystemError());
return ret;
}
@@ -279,84 +286,87 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals()
bool QSerialPortPrivate::setDataTerminalReady(bool set)
{
- return ::EscapeCommFunction(descriptor, set ? SETDTR : CLRDTR);
+ Q_Q(QSerialPort);
+
+ if (!::EscapeCommFunction(handle, set ? SETDTR : CLRDTR)) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ currentDcb.fDtrControl = set ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE;
+ return true;
}
bool QSerialPortPrivate::setRequestToSend(bool set)
{
- return ::EscapeCommFunction(descriptor, set ? SETRTS : CLRRTS);
+ Q_Q(QSerialPort);
+
+ if (!::EscapeCommFunction(handle, set ? SETRTS : CLRRTS)) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ return true;
}
#ifndef Q_OS_WINCE
bool QSerialPortPrivate::flush()
{
- return startAsyncWrite() && ::FlushFileBuffers(descriptor);
+ return startAsyncWrite() && ::FlushFileBuffers(handle);
}
bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
{
+ Q_Q(QSerialPort);
+
DWORD flags = 0;
if (directions & QSerialPort::Input)
flags |= PURGE_RXABORT | PURGE_RXCLEAR;
if (directions & QSerialPort::Output) {
flags |= PURGE_TXABORT | PURGE_TXCLEAR;
- writeSequenceStarted = false;
+ writeStarted = false;
}
- return ::PurgeComm(descriptor, flags);
+ if (!::PurgeComm(handle, flags)) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ return true;
}
#endif
bool QSerialPortPrivate::sendBreak(int duration)
{
- // FIXME:
- if (setBreakEnabled(true)) {
- ::Sleep(duration);
- if (setBreakEnabled(false))
- return true;
- }
- return false;
-}
+ if (!setBreakEnabled(true))
+ return false;
-bool QSerialPortPrivate::setBreakEnabled(bool set)
-{
- if (set)
- return ::SetCommBreak(descriptor);
- return ::ClearCommBreak(descriptor);
-}
+ ::Sleep(duration);
-qint64 QSerialPortPrivate::systemInputQueueSize ()
-{
- Q_Q(QSerialPort);
+ if (!setBreakEnabled(false))
+ return false;
- COMSTAT cs;
- ::ZeroMemory(&cs, sizeof(cs));
- if (!::ClearCommError(descriptor, NULL, &cs)) {
- q->setError(decodeSystemError());
- return -1;
- }
- return cs.cbInQue;
+ return true;
}
-qint64 QSerialPortPrivate::systemOutputQueueSize ()
+bool QSerialPortPrivate::setBreakEnabled(bool set)
{
Q_Q(QSerialPort);
- COMSTAT cs;
- ::ZeroMemory(&cs, sizeof(cs));
- if (!::ClearCommError(descriptor, NULL, &cs)) {
+ if (set ? !::SetCommBreak(handle) : !::ClearCommBreak(handle)) {
q->setError(decodeSystemError());
- return -1;
+ return false;
}
- return cs.cbOutQue;
+
+ return true;
}
#ifndef Q_OS_WINCE
void QSerialPortPrivate::startWriting()
{
- if (!writeSequenceStarted)
+ if (!writeStarted)
startAsyncWrite();
}
@@ -367,6 +377,9 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
QElapsedTimer stopWatch;
stopWatch.start();
+ const qint64 initialReadBufferSize = readBuffer.size();
+ qint64 currentReadBufferSize = initialReadBufferSize;
+
do {
bool timedOut = false;
HANDLE triggeredEvent = 0;
@@ -380,11 +393,12 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
if (triggeredEvent == communicationOverlapped.hEvent) {
_q_completeAsyncCommunication();
- if (error != QSerialPort::NoError)
- return false;
} else if (triggeredEvent == readCompletionOverlapped.hEvent) {
_q_completeAsyncRead();
- return error == QSerialPort::NoError;
+ if (qint64(readBuffer.size()) != currentReadBufferSize)
+ currentReadBufferSize = readBuffer.size();
+ else if (initialReadBufferSize != currentReadBufferSize)
+ return true;
} else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
_q_completeAsyncWrite();
} else {
@@ -536,7 +550,7 @@ void QSerialPortPrivate::_q_completeAsyncCommunication()
DWORD numberOfBytesTransferred = 0;
- if (!::GetOverlappedResult(descriptor, &communicationOverlapped, &numberOfBytesTransferred, FALSE))
+ if (!::GetOverlappedResult(handle, &communicationOverlapped, &numberOfBytesTransferred, FALSE))
q->setError(decodeSystemError());
bool error = false;
@@ -567,7 +581,7 @@ void QSerialPortPrivate::_q_completeAsyncRead()
Q_Q(QSerialPort);
DWORD numberOfBytesTransferred = 0;
- if (!::GetOverlappedResult(descriptor, &readCompletionOverlapped, &numberOfBytesTransferred, FALSE))
+ if (!::GetOverlappedResult(handle, &readCompletionOverlapped, &numberOfBytesTransferred, FALSE))
q->setError(decodeSystemError());
if (numberOfBytesTransferred > 0) {
@@ -590,20 +604,18 @@ void QSerialPortPrivate::_q_completeAsyncWrite()
Q_Q(QSerialPort);
DWORD numberOfBytesTransferred = 0;
- if (!::GetOverlappedResult(descriptor, &writeCompletionOverlapped, &numberOfBytesTransferred, FALSE)) {
+ if (!::GetOverlappedResult(handle, &writeCompletionOverlapped, &numberOfBytesTransferred, FALSE)) {
numberOfBytesTransferred = 0;
q->setError(decodeSystemError());
}
- writeBuffer.free(numberOfBytesTransferred);
-
- if (numberOfBytesTransferred > 0)
+ if (numberOfBytesTransferred > 0) {
+ writeBuffer.free(numberOfBytesTransferred);
emit q->bytesWritten(numberOfBytesTransferred);
+ }
- if (writeBuffer.isEmpty())
- writeSequenceStarted = false;
- else
- startAsyncWrite();
+ writeStarted = false;
+ startAsyncWrite();
}
bool QSerialPortPrivate::startAsyncCommunication()
@@ -611,7 +623,7 @@ bool QSerialPortPrivate::startAsyncCommunication()
Q_Q(QSerialPort);
initializeOverlappedStructure(communicationOverlapped);
- if (!::WaitCommEvent(descriptor, &triggeredEventMask, &communicationOverlapped)) {
+ if (!::WaitCommEvent(handle, &triggeredEventMask, &communicationOverlapped)) {
const QSerialPort::SerialPortError error = decodeSystemError();
if (error != QSerialPort::NoError) {
q->setError(decodeSystemError());
@@ -637,7 +649,7 @@ bool QSerialPortPrivate::startAsyncRead()
}
initializeOverlappedStructure(readCompletionOverlapped);
- if (::ReadFile(descriptor, readChunkBuffer.data(), bytesToRead, NULL, &readCompletionOverlapped))
+ if (::ReadFile(handle, readChunkBuffer.data(), bytesToRead, NULL, &readCompletionOverlapped))
return true;
QSerialPort::SerialPortError error = decodeSystemError();
@@ -656,30 +668,24 @@ bool QSerialPortPrivate::startAsyncWrite()
{
Q_Q(QSerialPort);
- qint64 nextSize = writeBuffer.nextDataBlockSize();
- const char *ptr = writeBuffer.readPointer();
-
- // no more data to write
- if (!ptr || nextSize == 0)
+ if (writeBuffer.isEmpty() || writeStarted)
return true;
- writeSequenceStarted = true;
-
initializeOverlappedStructure(writeCompletionOverlapped);
- if (::WriteFile(descriptor, ptr, nextSize, NULL, &writeCompletionOverlapped))
- return true;
+ if (!::WriteFile(handle, writeBuffer.readPointer(),
+ writeBuffer.nextDataBlockSize(),
+ NULL, &writeCompletionOverlapped)) {
- QSerialPort::SerialPortError error = decodeSystemError();
- if (error != QSerialPort::NoError) {
- writeSequenceStarted = false;
-
- if (error != QSerialPort::ResourceError)
- error = QSerialPort::WriteError;
-
- q->setError(error);
- return false;
+ QSerialPort::SerialPortError error = decodeSystemError();
+ if (error != QSerialPort::NoError) {
+ if (error != QSerialPort::ResourceError)
+ error = QSerialPort::WriteError;
+ q->setError(error);
+ return false;
+ }
}
+ writeStarted = true;
return true;
}
@@ -731,7 +737,7 @@ void QSerialPortPrivate::processIoErrors(bool error)
}
DWORD errors = 0;
- if (!::ClearCommError(descriptor, &errors, NULL)) {
+ if (!::ClearCommError(handle, &errors, NULL)) {
q->setError(decodeSystemError());
return;
}
@@ -754,7 +760,7 @@ bool QSerialPortPrivate::updateDcb()
{
Q_Q(QSerialPort);
- if (!::SetCommState(descriptor, &currentDcb)) {
+ if (!::SetCommState(handle, &currentDcb)) {
q->setError(decodeSystemError());
return false;
}
@@ -765,7 +771,7 @@ bool QSerialPortPrivate::updateCommTimeouts()
{
Q_Q(QSerialPort);
- if (!::SetCommTimeouts(descriptor, &currentCommTimeouts)) {
+ if (!::SetCommTimeouts(handle, &currentCommTimeouts)) {
q->setError(decodeSystemError());
return false;
}
@@ -862,6 +868,9 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
case ERROR_FILE_NOT_FOUND:
error = QSerialPort::DeviceNotFoundError;
break;
+ case ERROR_INVALID_NAME:
+ error = QSerialPort::DeviceNotFoundError;
+ break;
case ERROR_ACCESS_DENIED:
error = QSerialPort::PermissionError;
break;
@@ -1032,7 +1041,7 @@ QList<qint32> QSerialPortPrivate::standardBaudRates()
QSerialPort::Handle QSerialPort::handle() const
{
Q_D(const QSerialPort);
- return d->descriptor;
+ return d->handle;
}
QT_END_NAMESPACE
diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h
index 3ccdb56..ad5f267 100644
--- a/src/serialport/qserialport_win_p.h
+++ b/src/serialport/qserialport_win_p.h
@@ -78,9 +78,6 @@ public:
bool sendBreak(int duration);
bool setBreakEnabled(bool set);
- qint64 systemInputQueueSize ();
- qint64 systemOutputQueueSize ();
-
void startWriting();
bool waitForReadyRead(int msec);
@@ -123,13 +120,13 @@ public:
DCB restoredDcb;
COMMTIMEOUTS currentCommTimeouts;
COMMTIMEOUTS restoredCommTimeouts;
- HANDLE descriptor;
+ HANDLE handle;
bool parityErrorOccurred;
#ifndef Q_OS_WINCE
QByteArray readChunkBuffer;
bool readyReadEmitted;
- bool writeSequenceStarted;
+ bool writeStarted;
QWinEventNotifier *communicationNotifier;
QWinEventNotifier *readCompletionNotifier;
QWinEventNotifier *writeCompletionNotifier;
diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp
index bb76465..b987c80 100644
--- a/src/serialport/qserialport_wince.cpp
+++ b/src/serialport/qserialport_wince.cpp
@@ -62,12 +62,12 @@ public:
CommEventNotifier(DWORD mask, QSerialPortPrivate *d, QObject *parent)
: QThread(parent), dptr(d), running(true) {
connect(this, SIGNAL(eventMask(quint32)), this, SLOT(processNotification(quint32)));
- ::SetCommMask(dptr->descriptor, mask);
+ ::SetCommMask(dptr->handle, mask);
}
virtual ~CommEventNotifier() {
running = false;
- ::SetCommMask(dptr->descriptor, 0);
+ ::SetCommMask(dptr->handle, 0);
wait();
}
@@ -75,7 +75,7 @@ protected:
void run() Q_DECL_OVERRIDE {
DWORD mask = 0;
while (running) {
- if (::WaitCommEvent(dptr->descriptor, &mask, FALSE)) {
+ if (::WaitCommEvent(dptr->handle, &mask, FALSE)) {
// Wait until complete the operation changes the port settings,
// see updateDcb().
dptr->settingsChangeMutex.lock();
@@ -115,8 +115,8 @@ class WaitCommEventBreaker : public QThread
{
Q_OBJECT
public:
- WaitCommEventBreaker(HANDLE descriptor, int timeout, QObject *parent = 0)
- : QThread(parent), descriptor(descriptor), timeout(timeout), worked(false) {
+ WaitCommEventBreaker(HANDLE handle, int timeout, QObject *parent = 0)
+ : QThread(parent), handle(handle), timeout(timeout), worked(false) {
start();
}
@@ -144,12 +144,12 @@ protected:
private slots:
void processTimeout() {
- ::SetCommMask(descriptor, 0);
+ ::SetCommMask(handle, 0);
stop();
}
private:
- HANDLE descriptor;
+ HANDLE handle;
int timeout;
mutable bool worked;
};
@@ -158,7 +158,7 @@ private:
QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
: QSerialPortPrivateData(q)
- , descriptor(INVALID_HANDLE_VALUE)
+ , handle(INVALID_HANDLE_VALUE)
, parityErrorOccurred(false)
, eventNotifier(0)
{
@@ -180,15 +180,18 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
eventMask |= EV_TXEMPTY;
}
- descriptor = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation.utf16()),
+ handle = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation.utf16()),
desiredAccess, 0, NULL, OPEN_EXISTING, 0, NULL);
- if (descriptor == INVALID_HANDLE_VALUE) {
+ if (handle == INVALID_HANDLE_VALUE) {
q->setError(decodeSystemError());
return false;
}
- if (!::GetCommState(descriptor, &restoredDcb)) {
+ ::ZeroMemory(&restoredDcb, sizeof(restoredDcb));
+ restoredDcb.DCBlength = sizeof(restoredDcb);
+
+ if (!::GetCommState(handle, &restoredDcb)) {
q->setError(decodeSystemError());
return false;
}
@@ -201,10 +204,13 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
currentDcb.fNull = false;
currentDcb.fErrorChar = false;
+ if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
+ currentDcb.fDtrControl = DTR_CONTROL_DISABLE;
+
if (!updateDcb())
return false;
- if (!::GetCommTimeouts(descriptor, &restoredCommTimeouts)) {
+ if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) {
q->setError(decodeSystemError());
return false;
}
@@ -230,17 +236,17 @@ void QSerialPortPrivate::close()
}
if (settingsRestoredOnClose) {
- ::SetCommState(descriptor, &restoredDcb);
- ::SetCommTimeouts(descriptor, &restoredCommTimeouts);
+ ::SetCommState(handle, &restoredDcb);
+ ::SetCommTimeouts(handle, &restoredCommTimeouts);
}
- ::CloseHandle(descriptor);
- descriptor = INVALID_HANDLE_VALUE;
+ ::CloseHandle(handle);
+ handle = INVALID_HANDLE_VALUE;
}
bool QSerialPortPrivate::flush()
{
- return notifyWrite() && ::FlushFileBuffers(descriptor);
+ return notifyWrite() && ::FlushFileBuffers(handle);
}
bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
@@ -250,7 +256,7 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
flags |= PURGE_RXABORT | PURGE_RXCLEAR;
if (directions & QSerialPort::Output)
flags |= PURGE_TXABORT | PURGE_TXCLEAR;
- return ::PurgeComm(descriptor, flags);
+ return ::PurgeComm(handle, flags);
}
void QSerialPortPrivate::startWriting()
@@ -337,7 +343,7 @@ bool QSerialPortPrivate::notifyRead()
char *ptr = readBuffer.reserve(bytesToRead);
DWORD readBytes = 0;
- BOOL sucessResult = ::ReadFile(descriptor, ptr, bytesToRead, &readBytes, NULL);
+ BOOL sucessResult = ::ReadFile(handle, ptr, bytesToRead, &readBytes, NULL);
if (!sucessResult) {
readBuffer.truncate(bytesToRead);
@@ -383,7 +389,7 @@ bool QSerialPortPrivate::notifyWrite()
const char *ptr = writeBuffer.readPointer();
DWORD bytesWritten = 0;
- if (!::WriteFile(descriptor, ptr, nextSize, &bytesWritten, NULL)) {
+ if (!::WriteFile(handle, ptr, nextSize, &bytesWritten, NULL)) {
q->setError(QSerialPort::WriteError);
return false;
}
@@ -406,8 +412,8 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
// FIXME: Here the situation is not properly handled with zero timeout:
// breaker can work out before you call a method WaitCommEvent()
// and so it will loop forever!
- WaitCommEventBreaker breaker(descriptor, qMax(msecs, 0));
- ::WaitCommEvent(descriptor, &eventMask, NULL);
+ WaitCommEventBreaker breaker(handle, qMax(msecs, 0));
+ ::WaitCommEvent(handle, &eventMask, NULL);
breaker.stop();
if (breaker.isWorked()) {
@@ -439,17 +445,17 @@ bool QSerialPortPrivate::updateDcb()
DWORD eventMask = 0;
// Save the event mask
- if (!::GetCommMask(descriptor, &eventMask))
+ if (!::GetCommMask(handle, &eventMask))
return false;
// Break event notifier from WaitCommEvent
- ::SetCommMask(descriptor, 0);
+ ::SetCommMask(handle, 0);
// Change parameters
- bool ret = ::SetCommState(descriptor, &currentDcb);
+ bool ret = ::SetCommState(handle, &currentDcb);
if (!ret)
q->setError(decodeSystemError());
// Restore the event mask
- ::SetCommMask(descriptor, eventMask);
+ ::SetCommMask(handle, eventMask);
return ret;
}
@@ -458,7 +464,7 @@ bool QSerialPortPrivate::updateCommTimeouts()
{
Q_Q(QSerialPort);
- if (!::SetCommTimeouts(descriptor, &currentCommTimeouts)) {
+ if (!::SetCommTimeouts(handle, &currentCommTimeouts)) {
q->setError(decodeSystemError());
return false;
}
diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp
index 51f529e..85d40cc 100644
--- a/src/serialport/qserialportinfo_win.cpp
+++ b/src/serialport/qserialportinfo_win.cpp
@@ -46,15 +46,14 @@
#include "qserialport_win_p.h"
#ifndef Q_OS_WINCE
+#include <QtCore/quuid.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qstringlist.h>
+
#include <initguid.h>
#include <setupapi.h>
#endif
-#include <QtCore/qvariant.h>
-#include <QtCore/qstringlist.h>
-#include <QtCore/quuid.h>
-#include <QtCore/qpair.h>
-
QT_BEGIN_NAMESPACE
#ifndef Q_OS_WINCE
@@ -75,47 +74,56 @@ static inline const QList<GuidFlagsPair>& guidFlagsPairs()
return guidFlagsPairList;
}
-static QVariant deviceRegistryProperty(HDEVINFO deviceInfoSet,
- PSP_DEVINFO_DATA deviceInfoData,
- DWORD property)
+static QStringList portNamesFromHardwareDeviceMap()
{
- DWORD dataType = 0;
- DWORD dataSize = 0;
- ::SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData,
- property, &dataType, NULL, 0, &dataSize);
- QByteArray data(dataSize, 0);
- if (!::SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, NULL,
- reinterpret_cast<unsigned char*>(data.data()),
- dataSize, NULL)
- || !dataSize) {
- return QVariant();
- }
-
- switch (dataType) {
-
- case REG_EXPAND_SZ:
- case REG_SZ: {
- return QVariant(QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData())));
+ HKEY hKey = 0;
+ if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
+ return QStringList();
+
+ QStringList result;
+ DWORD index = 0;
+ static const DWORD maximumValueNameInChars = 16383;
+ QByteArray outputValueName(maximumValueNameInChars * sizeof(wchar_t), 0);
+ QByteArray outputBuffer;
+ DWORD requiredDataBytes = 0;
+ forever {
+ DWORD requiredValueNameChars = maximumValueNameInChars;
+ const LONG ret = ::RegEnumValue(hKey, index, reinterpret_cast<wchar_t *>(outputValueName.data()), &requiredValueNameChars,
+ NULL, NULL, reinterpret_cast<unsigned char *>(outputBuffer.data()), &requiredDataBytes);
+ if (ret == ERROR_MORE_DATA) {
+ outputBuffer.resize(requiredDataBytes);
+ } else if (ret == ERROR_SUCCESS) {
+ result.append(QString::fromWCharArray(reinterpret_cast<const wchar_t *>(outputBuffer.constData())));
+ ++index;
+ } else {
+ break;
+ }
}
+ ::RegCloseKey(hKey);
+ return result;
+}
- case REG_MULTI_SZ: {
- QStringList list;
- int i = 0;
- forever {
- QString s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()) + i);
- i += s.length() + 1;
- if (s.isEmpty())
- break;
- list.append(s);
+static QString deviceRegistryProperty(HDEVINFO deviceInfoSet,
+ PSP_DEVINFO_DATA deviceInfoData,
+ DWORD property)
+{
+ DWORD dataType = 0;
+ QByteArray devicePropertyByteArray;
+ DWORD requiredSize = 0;
+ forever {
+ if (::SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType,
+ reinterpret_cast<unsigned char *>(devicePropertyByteArray.data()),
+ devicePropertyByteArray.size(), &requiredSize)) {
+ break;
}
- return QVariant(list);
- }
- default:
- break;
+ if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER
+ || (dataType != REG_SZ && dataType != REG_EXPAND_SZ)) {
+ return QString();
+ }
+ devicePropertyByteArray.resize(requiredSize);
}
-
- return QVariant();
+ return QString::fromWCharArray(reinterpret_cast<const wchar_t *>(devicePropertyByteArray.constData()));
}
static QString deviceInstanceIdentifier(HDEVINFO deviceInfoSet,
@@ -137,28 +145,37 @@ static QString deviceInstanceIdentifier(HDEVINFO deviceInfoSet,
static QString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData)
{
- static const wchar_t portKeyName[] = L"PortName";
-
const HKEY key = ::SetupDiOpenDevRegKey(deviceInfoSet, deviceInfoData, DICS_FLAG_GLOBAL,
0, DIREG_DEV, KEY_READ);
if (key == INVALID_HANDLE_VALUE)
return QString();
- DWORD dataSize;
- if (::RegQueryValueEx(key, portKeyName, NULL, NULL, NULL, &dataSize) != ERROR_SUCCESS) {
- ::RegCloseKey(key);
- return QString();
- }
-
- QByteArray data(dataSize, 0);
+ static const QStringList portNameRegistryKeyList = QStringList()
+ << QStringLiteral("PortName")
+ << QStringLiteral("PortNumber");
- if (::RegQueryValueEx(key, portKeyName, NULL, NULL,
- reinterpret_cast<unsigned char *>(data.data()), &dataSize) != ERROR_SUCCESS) {
- ::RegCloseKey(key);
- return QString();
+ QString portName;
+ foreach (const QString &portNameKey, portNameRegistryKeyList) {
+ DWORD bytesRequired = 0;
+ DWORD dataType = 0;
+ QByteArray outputBuffer;
+ forever {
+ const LONG ret = ::RegQueryValueEx(key, reinterpret_cast<const wchar_t *>(portNameKey.utf16()), NULL, &dataType,
+ reinterpret_cast<unsigned char *>(outputBuffer.data()), &bytesRequired);
+ if (ret == ERROR_MORE_DATA) {
+ outputBuffer.resize(bytesRequired);
+ continue;
+ } else if (ret == ERROR_SUCCESS) {
+ if (dataType == REG_SZ)
+ portName = QString::fromWCharArray((reinterpret_cast<const wchar_t *>(outputBuffer.constData())));
+ else if (dataType == REG_DWORD)
+ portName = QStringLiteral("COM%1").arg(*(PDWORD(outputBuffer.constData())));
+ }
+ break;
+ }
}
::RegCloseKey(key);
- return QString::fromWCharArray(((const wchar_t *)data.constData()));
+ return portName;
}
class SerialPortNameEqualFunctor
@@ -215,9 +232,9 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
serialPortInfo.d_ptr->portName = s;
serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(s);
serialPortInfo.d_ptr->description =
- deviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_DEVICEDESC).toString();
+ deviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_DEVICEDESC);
serialPortInfo.d_ptr->manufacturer =
- deviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_MFG).toString();
+ deviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_MFG);
s = deviceInstanceIdentifier(deviceInfoSet, &deviceInfoData).toUpper();
@@ -247,6 +264,17 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
}
::SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
+
+ foreach (const QString &portName, portNamesFromHardwareDeviceMap()) {
+ if (std::find_if(serialPortInfoList.begin(), serialPortInfoList.end(),
+ SerialPortNameEqualFunctor(portName)) == serialPortInfoList.end()) {
+ QSerialPortInfo serialPortInfo;
+ serialPortInfo.d_ptr->portName = portName;
+ serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(portName);
+ serialPortInfoList.append(serialPortInfo);
+ }
+ }
+
return serialPortInfoList;
}
@@ -259,28 +287,28 @@ QList<qint32> QSerialPortInfo::standardBaudRates()
bool QSerialPortInfo::isBusy() const
{
- const HANDLE descriptor = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation().utf16()),
+ const HANDLE handle = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation().utf16()),
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
- if (descriptor == INVALID_HANDLE_VALUE) {
+ if (handle == INVALID_HANDLE_VALUE) {
if (::GetLastError() == ERROR_ACCESS_DENIED)
return true;
} else {
- ::CloseHandle(descriptor);
+ ::CloseHandle(handle);
}
return false;
}
bool QSerialPortInfo::isValid() const
{
- const HANDLE descriptor = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation().utf16()),
+ const HANDLE handle = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation().utf16()),
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
- if (descriptor == INVALID_HANDLE_VALUE) {
+ if (handle == INVALID_HANDLE_VALUE) {
if (::GetLastError() != ERROR_ACCESS_DENIED)
return false;
} else {
- ::CloseHandle(descriptor);
+ ::CloseHandle(handle);
}
return true;
}