summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2014-08-12 13:09:58 +0200
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-08-12 13:09:58 +0200
commitc6027a9c0e6182bde7106bc97b927c544e76e155 (patch)
treecb0ee001e8204df9643e04ed4b8961b8eb6c68f5
parent789c0ebcd4ed976eb124e2da1958a48b478751c0 (diff)
parent3c3b23b32c6d4a9067363f758aaf4ff9819b7fd8 (diff)
Merge remote-tracking branch 'origin/5.3' into 5.4
Conflicts: examples/serialport/examples.qdoc Change-Id: If79f2f140e72f0a499f8e61e3897848f454a5042
-rw-r--r--examples/serialport/doc/blockingmaster.qdoc12
-rw-r--r--examples/serialport/doc/blockingslave.qdoc10
-rw-r--r--examples/serialport/doc/cenumerator.qdoc14
-rw-r--r--examples/serialport/doc/creaderasync.qdoc8
-rw-r--r--examples/serialport/doc/creadersync.qdoc12
-rw-r--r--examples/serialport/doc/cwriterasync.qdoc13
-rw-r--r--examples/serialport/doc/cwritersync.qdoc12
-rw-r--r--examples/serialport/doc/enumerator.qdoc8
-rw-r--r--examples/serialport/doc/terminal.qdoc10
-rw-r--r--examples/serialport/examples.qdoc24
-rw-r--r--src/serialport/qserialport.h2
-rw-r--r--src/serialport/qserialport_unix.cpp79
-rw-r--r--src/serialport/qserialport_unix_p.h1
-rw-r--r--src/serialport/qserialport_win.cpp130
-rw-r--r--src/serialport/qserialport_win_p.h1
-rw-r--r--src/serialport/qserialport_wince.cpp83
-rw-r--r--src/serialport/qserialport_wince_p.h1
-rw-r--r--src/serialport/qserialportinfo_win.cpp26
-rw-r--r--tests/auto/qserialport/tst_qserialport.cpp79
19 files changed, 332 insertions, 193 deletions
diff --git a/examples/serialport/doc/blockingmaster.qdoc b/examples/serialport/doc/blockingmaster.qdoc
index 32176a13..0aa0c3f2 100644
--- a/examples/serialport/doc/blockingmaster.qdoc
+++ b/examples/serialport/doc/blockingmaster.qdoc
@@ -2,6 +2,7 @@
**
** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2012 - 2013 Laszlo Papp <lpapp@kde.org>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -30,13 +31,12 @@
\example blockingmaster
\title Blocking Master Example
\ingroup qtserialport-examples
- \brief Explains how to use the synchronous API of QSerialPort.
+ \brief Shows how to use the synchronous API of QSerialPort in a worker thread.
- The blocking master example shows how to create an application for a
- serial interface using the synchronous API of QSerialPort in a worker
- thread.
+ \e{Blocking Master} shows how to create an application for a serial
+ interface using the synchronous API of QSerialPort in a worker thread.
- \image blockingmaster-example.png Screenshot of the blocking master example
+ \image blockingmaster-example.png
QSerialPort supports two programming alternatives:
@@ -162,4 +162,6 @@
\snippet blockingmaster/masterthread.cpp 13
\sa {Terminal Example}, {Blocking Slave Example}
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/serialport/doc/blockingslave.qdoc b/examples/serialport/doc/blockingslave.qdoc
index df35bfc0..a2e3a6b1 100644
--- a/examples/serialport/doc/blockingslave.qdoc
+++ b/examples/serialport/doc/blockingslave.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -29,11 +30,12 @@
\example blockingslave
\title Blocking Slave Example
\ingroup qtserialport-examples
+ \brief Shows how to use the synchronous API of QSerialPort in a non-GUI thread.
- The Blocking Slave example shows how to create a application for a
- serial interface using QSerialPort's synchronous API in a non-GUI thread.
+ \e{Blocking Slave} shows how to create an application for a serial interface
+ using QSerialPort's synchronous API in a non-GUI thread.
- \image blockingslave-example.png Screenshot of the Blocking Slave example
+ \image blockingslave-example.png
QSerialPort supports two general programming approaches:
@@ -160,4 +162,6 @@
\snippet blockingslave/slavethread.cpp 13
\sa {Terminal Example}, {Blocking Master Example}
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/serialport/doc/cenumerator.qdoc b/examples/serialport/doc/cenumerator.qdoc
index 0766931a..83718982 100644
--- a/examples/serialport/doc/cenumerator.qdoc
+++ b/examples/serialport/doc/cenumerator.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -28,18 +29,19 @@
/*!
\example cenumerator
\title Command Line Enumerator Example
- \ingroup qtserialport-examples
+ \ingroup qtserialport-example
+ \brief Shows how to get information about serial devices in a system.
- The Command Line Enumerator example shows how to use the class
- QSerialPortInfo for getting information about serial devices that are present
- in the system.
+ \e{Command Line Enumerator} shows how to use the class QSerialPortInfo for
+ getting information about serial devices that are present in the system.
- \image cenumerator-example.png Screenshot of the Command Line Enumerator
- example
+ \image cenumerator-example.png
This command line example displays information about serial ports in a
console, provided by the class QSerialPortInfo.
For getting information about the available ports, use the static method
\l{QSerialPortInfo::availablePorts()}{availablePorts()}.
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/serialport/doc/creaderasync.qdoc b/examples/serialport/doc/creaderasync.qdoc
index a8b21013..ff5e9c61 100644
--- a/examples/serialport/doc/creaderasync.qdoc
+++ b/examples/serialport/doc/creaderasync.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -29,12 +30,13 @@
\example creaderasync
\title Command Line Reader Async Example
\ingroup qtserialport-examples
+ \brief Shows how to receive data asynchronously over serial port.
- The Command Line Reader Async example shows how to use the QSerialPort class for
+ \e{Command Line Reader Async} shows how to use the QSerialPort class for
receiving data asynchronously over the selected serial port with the desired
settings.
- \image creaderasync-example.png Screenshot of the Command Line Reader Async example
+ \image creaderasync-example.png
This command line reader async example receives data asynchronously over the
selected serial port in a console, provided by the QSerialPort class.
@@ -42,4 +44,6 @@
For receiving data synchronously over the selected serial port, use the
\l{QSerialPort::read()}{read()} or \l{QSerialPort::readAll()}{readAll()}
methods, and \l{QIODevice::readyRead()}{readyRead()} signal.
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/serialport/doc/creadersync.qdoc b/examples/serialport/doc/creadersync.qdoc
index 3b6c968f..6c3f4a89 100644
--- a/examples/serialport/doc/creadersync.qdoc
+++ b/examples/serialport/doc/creadersync.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -29,12 +30,13 @@
\example creadersync
\title Command Line Reader Sync Example
\ingroup qtserialport-examples
+ \brief Shows how to receive data synchronously over serial port.
- The Command Line Reader Sync example shows how to use the QSerialPort class for
- receiving data synchronously over the selected serial port with the desired
- settings.
+ \e{Command Line Reader Sync} shows how to use the QSerialPort class
+ for receiving data synchronously over the selected serial port with the
+ desired settings.
- \image creadersync-example.png Screenshot of the Command Line Reader Sync example
+ \image creadersync-example.png
This command line reader sync example receives data synchronously over the
selected serial port in a console, provided by the QSerialPort class.
@@ -42,4 +44,6 @@
For receiving data synchronously over the selected serial port, use the
\l{QSerialPort::read()}{read()} or \l{QSerialPort::readAll()}{readAll()},
and \l{QIODevice::waitForReadyRead()}{waitForReadyRead()} methods.
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/serialport/doc/cwriterasync.qdoc b/examples/serialport/doc/cwriterasync.qdoc
index 884435bc..b10f2aaf 100644
--- a/examples/serialport/doc/cwriterasync.qdoc
+++ b/examples/serialport/doc/cwriterasync.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -29,13 +30,13 @@
\example cwriterasync
\title Command Line Writer Async Example
\ingroup qtserialport-examples
+ \brief Shows how to send data asynchronously over serial port.
- The Command Line Writer Async example shows how to use the QSerialPort class
- for sending data asynchronously over the selected serial port with the
- desired settings.
+ \e{Command Line Writer Async} shows how to use the QSerialPort class for
+ sending data asynchronously over the selected serial port with the desired
+ settings.
- \image cwriterasync-example.png Screenshot of the Command Line Writer Async
- example
+ \image cwriterasync-example.png
This command line writer async example sends data asynchronously over the
selected serial port in a console, provided by the QSerialPort class.
@@ -43,4 +44,6 @@
For sending data asynchronously over the selected serial port, use the
\l{QIODevice::write()}{write()} method and
\l{QIODevice::bytesWritten()}{bytesWritten()} signal.
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/serialport/doc/cwritersync.qdoc b/examples/serialport/doc/cwritersync.qdoc
index 05858ef7..03086e05 100644
--- a/examples/serialport/doc/cwritersync.qdoc
+++ b/examples/serialport/doc/cwritersync.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -29,12 +30,13 @@
\example cwritersync
\title Command Line Writer Sync Example
\ingroup qtserialport-examples
+ \brief Shows how to send data synchronously over serial port.
- The Command Line Writer Sync example shows how to use the QSerialPort class
- for sending data synchronously over the selected serial port with the
- desired settings.
+ \e{Command Line Writer Sync} shows how to use the QSerialPort class for
+ sending data synchronously over the selected serial port with the desired
+ settings.
- \image cwritersync-example.png Screenshot of the Command Line Writer Sync example
+ \image cwritersync-example.png
This command line writer sync example sends data synchronously over the
selected serial port in a console, provided by the QSerialPort class.
@@ -42,4 +44,6 @@
For sending data synchronously over the selected serial port, use the
\l{QIODevice::write()}{write()} and
\l{QIODevice::waitForBytesWritten()}{waitForBytesWritten()} methods.
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/serialport/doc/enumerator.qdoc b/examples/serialport/doc/enumerator.qdoc
index 0847d8a8..326fdb4b 100644
--- a/examples/serialport/doc/enumerator.qdoc
+++ b/examples/serialport/doc/enumerator.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -29,15 +30,18 @@
\example enumerator
\title Enumerator Example
\ingroup qtserialport-examples
+ \brief Shows how to display information about serial devices in a system.
- The Enumerator example shows how to use the class QSerialPortInfo for
+ \e Enumerator shows how to use the class QSerialPortInfo for
getting information about serial devices that are present in the system.
- \image enumerator-example.png Screenshot of the Enumerator example
+ \image enumerator-example.png
This GUI example displays information about serial ports in a widget,
provided by the class QSerialPortInfo.
For getting information about the available ports, use the static method
\l{QSerialPortInfo::availablePorts()}{availablePorts()}.
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/serialport/doc/terminal.qdoc b/examples/serialport/doc/terminal.qdoc
index ed8fa023..423d6108 100644
--- a/examples/serialport/doc/terminal.qdoc
+++ b/examples/serialport/doc/terminal.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -29,11 +30,12 @@
\example terminal
\title Terminal Example
\ingroup qtserialport-examples
+ \brief Shows how to use various features of QSerialPort.
- The Terminal example shows how to create a terminal for a simple serial
- interface by using Qt Serial Port.
+ \e Terminal shows how to create a terminal for a simple serial interface by
+ using \l{Qt Serial Port}.
- \image terminal-example.png Screenshot of the Terminal example
+ \image terminal-example.png
This example shows the main features of the QSerialPort class, like
configuration, I/O implementation and so forth. Also, the class
@@ -143,4 +145,6 @@
port.
\sa {Blocking Slave Example}
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/serialport/examples.qdoc b/examples/serialport/examples.qdoc
index 3b780160..e8e4c2b3 100644
--- a/examples/serialport/examples.qdoc
+++ b/examples/serialport/examples.qdoc
@@ -2,6 +2,7 @@
**
** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -29,20 +30,17 @@
/*!
\title Qt Serial Port Examples
\page examples-serialport.html
+ \group qtserialport-examples
\brief List of serial port examples
- The module provides the following examples for reference to
- help understand the API usage:
+ The \l{Qt Serial Port} module provides the following examples for reference
+ to help understand the API usage.
+
+ \section1 Running the Examples
+
+ To run the examples from \l{Qt Creator Manual}{Qt Creator}, open the \gui
+ Welcome mode and select the example from \gui Examples.
+ For more information, visit
+ \l{Qt Creator: Building and Running an Example}{Building and Running an Example}.
- \list
- \li \l blockingmaster
- \li \l blockingslave
- \li \l cenumerator
- \li \l cwriterasync
- \li \l cwritersync
- \li \l creaderasync
- \li \l creadersync
- \li \l enumerator
- \li \l terminal
- \endlist
*/
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h
index 45b9bbff..d0f65b5e 100644
--- a/src/serialport/qserialport.h
+++ b/src/serialport/qserialport.h
@@ -263,7 +263,9 @@ Q_SIGNALS:
void parityChanged(QSerialPort::Parity parity);
void stopBitsChanged(QSerialPort::StopBits stopBits);
void flowControlChanged(QSerialPort::FlowControl flowControl);
+#if QT_DEPRECATED_SINCE(5, 2)
void dataErrorPolicyChanged(QSerialPort::DataErrorPolicy policy);
+#endif
void dataTerminalReadyChanged(bool set);
void requestToSendChanged(bool set);
void error(QSerialPort::SerialPortError serialPortError);
diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp
index 29822d51..d555805c 100644
--- a/src/serialport/qserialport_unix.cpp
+++ b/src/serialport/qserialport_unix.cpp
@@ -204,39 +204,11 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
return false;
}
-#ifdef TIOCEXCL
- if (::ioctl(descriptor, TIOCEXCL) == -1)
- q->setError(decodeSystemError());
-#endif
-
- if (::tcgetattr(descriptor, &restoredTermios) == -1) {
- q->setError(decodeSystemError());
+ if (!initialize(mode)) {
+ qt_safe_close(descriptor);
return false;
}
- 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;
-
- if (mode & QIODevice::ReadOnly)
- currentTermios.c_cflag |= CREAD;
-
- if (!updateTermios())
- return false;
-
- if ((flags & O_WRONLY) == 0)
- setReadNotificationEnabled(true);
-
lockFileScopedPointer.swap(newLockFileScopedPointer);
return true;
@@ -365,12 +337,7 @@ bool QSerialPortPrivate::setRequestToSend(bool set)
bool QSerialPortPrivate::flush()
{
- return completeAsyncWrite()
-#ifndef Q_OS_ANDROID
- && (::tcdrain(descriptor) != -1);
-#else
- && (::ioctl(descriptor, TCSBRK, 1) != -1);
-#endif
+ return completeAsyncWrite();
}
bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
@@ -869,6 +836,46 @@ bool QSerialPortPrivate::completeAsyncWrite()
return startAsyncWrite();
}
+inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode)
+{
+ Q_Q(QSerialPort);
+
+#ifdef TIOCEXCL
+ if (::ioctl(descriptor, TIOCEXCL) == -1)
+ q->setError(decodeSystemError());
+#endif
+
+ if (::tcgetattr(descriptor, &restoredTermios) == -1) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ 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;
+
+ if (mode & QIODevice::ReadOnly)
+ currentTermios.c_cflag |= CREAD;
+
+ if (!updateTermios())
+ return false;
+
+ if (mode & QIODevice::ReadOnly)
+ setReadNotificationEnabled(true);
+
+ return true;
+}
+
bool QSerialPortPrivate::updateTermios()
{
Q_Q(QSerialPort);
diff --git a/src/serialport/qserialport_unix_p.h b/src/serialport/qserialport_unix_p.h
index 64d1d9ec..ee3d82d5 100644
--- a/src/serialport/qserialport_unix_p.h
+++ b/src/serialport/qserialport_unix_p.h
@@ -153,6 +153,7 @@ public:
QScopedPointer<QLockFile> lockFileScopedPointer;
private:
+ bool initialize(QIODevice::OpenMode mode);
bool updateTermios();
QSerialPort::SerialPortError setBaudRate_helper(qint32 baudRate,
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 3432fc94..19f35b74 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -155,56 +155,11 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
return false;
}
- ::ZeroMemory(&restoredDcb, sizeof(restoredDcb));
- restoredDcb.DCBlength = sizeof(restoredDcb);
-
- if (!::GetCommState(handle, &restoredDcb)) {
- q->setError(decodeSystemError());
- return false;
- }
-
- currentDcb = restoredDcb;
- currentDcb.fBinary = TRUE;
- currentDcb.fInX = FALSE;
- currentDcb.fOutX = FALSE;
- currentDcb.fAbortOnError = FALSE;
- currentDcb.fNull = FALSE;
- currentDcb.fErrorChar = FALSE;
-
- if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
- currentDcb.fDtrControl = DTR_CONTROL_DISABLE;
-
- if (!updateDcb())
- return false;
-
- if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) {
- q->setError(decodeSystemError());
- return false;
- }
-
- ::ZeroMemory(&currentCommTimeouts, sizeof(currentCommTimeouts));
- currentCommTimeouts.ReadIntervalTimeout = MAXDWORD;
-
- if (!updateCommTimeouts())
- return false;
-
- if (mode & QIODevice::ReadOnly)
- readCompletionNotifier->setEnabled(true);
-
- if (mode & QIODevice::WriteOnly)
- writeCompletionNotifier->setEnabled(true);
-
- if (!::SetCommMask(handle, originalEventMask)) {
- q->setError(decodeSystemError());
- return false;
- }
-
- if (!startAsyncCommunication())
- return false;
-
- communicationNotifier->setEnabled(true);
+ if (initialize(mode))
+ return true;
- return true;
+ ::CloseHandle(handle);
+ return false;
}
void QSerialPortPrivate::close()
@@ -304,20 +259,7 @@ bool QSerialPortPrivate::setRequestToSend(bool set)
bool QSerialPortPrivate::flush()
{
- Q_Q(QSerialPort);
-
- bool returnValue = true;
-
- if (!startAsyncWrite())
- returnValue = false;
-
- if (!::FlushFileBuffers(handle)) {
- q->setError(decodeSystemError());
- returnValue = false;
- }
-
- return returnValue;
-
+ return startAsyncWrite();
}
bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
@@ -449,8 +391,10 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs)
return false;
}
- if (triggeredEvent == communicationOverlapped.hEvent
- || triggeredEvent == readCompletionOverlapped.hEvent) {
+ if (triggeredEvent == communicationOverlapped.hEvent) {
+ if (!_q_completeAsyncCommunication())
+ return false;
+ } else if (triggeredEvent == readCompletionOverlapped.hEvent) {
if (!_q_completeAsyncRead())
return false;
} else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
@@ -741,6 +685,62 @@ void QSerialPortPrivate::handleLineStatusErrors()
}
}
+inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode)
+{
+ Q_Q(QSerialPort);
+
+ ::ZeroMemory(&restoredDcb, sizeof(restoredDcb));
+ restoredDcb.DCBlength = sizeof(restoredDcb);
+
+ if (!::GetCommState(handle, &restoredDcb)) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ currentDcb = restoredDcb;
+ currentDcb.fBinary = TRUE;
+ currentDcb.fInX = FALSE;
+ currentDcb.fOutX = FALSE;
+ currentDcb.fAbortOnError = FALSE;
+ currentDcb.fNull = FALSE;
+ currentDcb.fErrorChar = FALSE;
+
+ if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
+ currentDcb.fDtrControl = DTR_CONTROL_DISABLE;
+
+ if (!updateDcb())
+ return false;
+
+ if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ ::ZeroMemory(&currentCommTimeouts, sizeof(currentCommTimeouts));
+ currentCommTimeouts.ReadIntervalTimeout = MAXDWORD;
+
+ if (!updateCommTimeouts())
+ return false;
+
+ if (mode & QIODevice::ReadOnly)
+ readCompletionNotifier->setEnabled(true);
+
+ if (mode & QIODevice::WriteOnly)
+ writeCompletionNotifier->setEnabled(true);
+
+ if (!::SetCommMask(handle, originalEventMask)) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ if (!startAsyncCommunication())
+ return false;
+
+ communicationNotifier->setEnabled(true);
+
+ return true;
+}
+
bool QSerialPortPrivate::updateDcb()
{
Q_Q(QSerialPort);
diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h
index daf57884..a997315b 100644
--- a/src/serialport/qserialport_win_p.h
+++ b/src/serialport/qserialport_win_p.h
@@ -130,6 +130,7 @@ public:
DWORD triggeredEventMask;
private:
+ bool initialize(QIODevice::OpenMode mode);
bool updateDcb();
bool updateCommTimeouts();
qint64 handleOverlappedResult(int direction, OVERLAPPED &overlapped);
diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp
index 4a523ae6..c06e748c 100644
--- a/src/serialport/qserialport_wince.cpp
+++ b/src/serialport/qserialport_wince.cpp
@@ -219,43 +219,11 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
return false;
}
- ::ZeroMemory(&restoredDcb, sizeof(restoredDcb));
- restoredDcb.DCBlength = sizeof(restoredDcb);
-
- if (!::GetCommState(handle, &restoredDcb)) {
- q->setError(decodeSystemError());
- return false;
- }
-
- currentDcb = restoredDcb;
- currentDcb.fBinary = true;
- currentDcb.fInX = false;
- currentDcb.fOutX = false;
- currentDcb.fAbortOnError = false;
- currentDcb.fNull = false;
- currentDcb.fErrorChar = false;
-
- if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
- currentDcb.fDtrControl = DTR_CONTROL_DISABLE;
-
- if (!updateDcb())
- return false;
-
- if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) {
- q->setError(decodeSystemError());
- return false;
- }
-
- ::memset(&currentCommTimeouts, 0, sizeof(currentCommTimeouts));
- currentCommTimeouts.ReadIntervalTimeout = MAXDWORD;
-
- if (!updateCommTimeouts())
- return false;
-
- eventNotifier = new CommEventNotifier(eventMask, this, q);
- eventNotifier->start();
+ if (initialize(eventMask))
+ return true;
- return true;
+ ::CloseHandle(handle);
+ return false;
}
void QSerialPortPrivate::close()
@@ -646,6 +614,49 @@ void QSerialPortPrivate::processIoErrors(bool error)
}
}
+inline bool QSerialPortPrivate::initialize(DWORD eventMask)
+{
+ Q_Q(QSerialPort);
+
+ ::ZeroMemory(&restoredDcb, sizeof(restoredDcb));
+ restoredDcb.DCBlength = sizeof(restoredDcb);
+
+ if (!::GetCommState(handle, &restoredDcb)) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ currentDcb = restoredDcb;
+ currentDcb.fBinary = true;
+ currentDcb.fInX = false;
+ currentDcb.fOutX = false;
+ currentDcb.fAbortOnError = false;
+ currentDcb.fNull = false;
+ currentDcb.fErrorChar = false;
+
+ if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
+ currentDcb.fDtrControl = DTR_CONTROL_DISABLE;
+
+ if (!updateDcb())
+ return false;
+
+ if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ ::memset(&currentCommTimeouts, 0, sizeof(currentCommTimeouts));
+ currentCommTimeouts.ReadIntervalTimeout = MAXDWORD;
+
+ if (!updateCommTimeouts())
+ return false;
+
+ eventNotifier = new CommEventNotifier(eventMask, this, q);
+ eventNotifier->start();
+
+ return true;
+}
+
bool QSerialPortPrivate::updateDcb()
{
Q_Q(QSerialPort);
diff --git a/src/serialport/qserialport_wince_p.h b/src/serialport/qserialport_wince_p.h
index 11d05345..9697dc72 100644
--- a/src/serialport/qserialport_wince_p.h
+++ b/src/serialport/qserialport_wince_p.h
@@ -112,6 +112,7 @@ public:
QMutex settingsChangeMutex;
private:
+ bool initialize(DWORD eventMask);
bool updateDcb();
bool updateCommTimeouts();
diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp
index dbef3141..8250d2a7 100644
--- a/src/serialport/qserialportinfo_win.cpp
+++ b/src/serialport/qserialportinfo_win.cpp
@@ -71,6 +71,15 @@ static inline const QList<GuidFlagsPair>& guidFlagsPairs()
return guidFlagsPairList;
}
+static QString toStringAndTrimNullCharacter(const QByteArray &buffer)
+{
+ QString result = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(buffer.constData()),
+ buffer.size() / sizeof(wchar_t));
+ while (!result.isEmpty() && (result.at(result.size() - 1).unicode() == 0))
+ result.chop(1);
+ return result;
+}
+
static QStringList portNamesFromHardwareDeviceMap()
{
HKEY hKey = 0;
@@ -80,7 +89,8 @@ static QStringList portNamesFromHardwareDeviceMap()
QStringList result;
DWORD index = 0;
static const DWORD maximumValueNameInChars = 16383;
- QByteArray outputValueName(maximumValueNameInChars * sizeof(wchar_t), 0);
+ QByteArray outputValueName;
+ outputValueName.resize(maximumValueNameInChars * sizeof(wchar_t));
QByteArray outputBuffer;
DWORD requiredDataBytes = 0;
forever {
@@ -90,7 +100,7 @@ static QStringList portNamesFromHardwareDeviceMap()
if (ret == ERROR_MORE_DATA) {
outputBuffer.resize(requiredDataBytes);
} else if (ret == ERROR_SUCCESS) {
- result.append(QString::fromWCharArray(reinterpret_cast<const wchar_t *>(outputBuffer.constData())));
+ result.append(toStringAndTrimNullCharacter(outputBuffer));
++index;
} else {
break;
@@ -120,7 +130,7 @@ static QString deviceRegistryProperty(HDEVINFO deviceInfoSet,
}
devicePropertyByteArray.resize(requiredSize);
}
- return QString::fromWCharArray(reinterpret_cast<const wchar_t *>(devicePropertyByteArray.constData()));
+ return toStringAndTrimNullCharacter(devicePropertyByteArray);
}
static QString deviceInstanceIdentifier(DEVINST deviceInstanceNumber)
@@ -130,12 +140,13 @@ static QString deviceInstanceIdentifier(DEVINST deviceInstanceNumber)
return QString();
// The size does not include the terminating null character.
++numberOfChars;
- QByteArray outputBuffer(numberOfChars * sizeof(wchar_t), 0);
+ 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) {
return QString();
}
- return QString::fromWCharArray(reinterpret_cast<const wchar_t *>(outputBuffer.constData()));
+ return toStringAndTrimNullCharacter(outputBuffer);
}
static DEVINST parentDeviceInstanceNumber(DEVINST childDeviceInstanceNumber)
@@ -176,12 +187,15 @@ static QString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInf
continue;
} else if (ret == ERROR_SUCCESS) {
if (dataType == REG_SZ)
- portName = QString::fromWCharArray((reinterpret_cast<const wchar_t *>(outputBuffer.constData())));
+ portName = toStringAndTrimNullCharacter(outputBuffer);
else if (dataType == REG_DWORD)
portName = QStringLiteral("COM%1").arg(*(PDWORD(outputBuffer.constData())));
}
break;
}
+
+ if (!portName.isEmpty())
+ break;
}
::RegCloseKey(key);
return portName;
diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp
index 192541ce..9e8f6594 100644
--- a/tests/auto/qserialport/tst_qserialport.cpp
+++ b/tests/auto/qserialport/tst_qserialport.cpp
@@ -104,13 +104,17 @@ private slots:
void waitForReadyReadWithOneByte();
void waitForReadyReadWithAlphabet();
+ void twoStageSynchronousLoopback();
+
+ void synchronousReadWrite();
+
protected slots:
void handleBytesWrittenAndExitLoopSlot(qint64 bytesWritten);
void handleBytesWrittenAndExitLoopSlot2(qint64 bytesWritten);
private:
#ifdef Q_OS_WIN
- void clearReceiver();
+ void clearReceiver(const QString &customReceiverName = QString());
#endif
QString m_senderPortName;
@@ -142,9 +146,10 @@ tst_QSerialPort::tst_QSerialPort()
// not expected). It is recommended to use this method for cleaning of
// read FIFO of receiver for those tests in which reception of data is
// required.
-void tst_QSerialPort::clearReceiver()
+void tst_QSerialPort::clearReceiver(const QString &customReceiverName)
{
- QSerialPort receiver(m_receiverPortName);
+ QSerialPort receiver(customReceiverName.isEmpty()
+ ? m_receiverPortName : customReceiverName);
if (receiver.open(QIODevice::ReadOnly))
enterLoopMsecs(100);
}
@@ -438,5 +443,73 @@ void tst_QSerialPort::waitForReadyReadWithAlphabet()
QVERIFY(readyReadSpy.count() > 0);
}
+void tst_QSerialPort::twoStageSynchronousLoopback()
+{
+#ifdef Q_OS_WIN
+ clearReceiver();
+ clearReceiver(m_senderPortName);
+#endif
+
+ QSerialPort senderPort(m_senderPortName);
+ QVERIFY(senderPort.open(QSerialPort::ReadWrite));
+
+ QSerialPort receiverPort(m_receiverPortName);
+ QVERIFY(receiverPort.open(QSerialPort::ReadWrite));
+
+ const int waitMsecs = 50;
+
+ // first stage
+ senderPort.write(newlineArray);
+ senderPort.waitForBytesWritten(waitMsecs);
+ QTest::qSleep(waitMsecs);
+ receiverPort.waitForReadyRead(waitMsecs);
+ QCOMPARE(newlineArray.size(), receiverPort.bytesAvailable());
+ receiverPort.write(receiverPort.readAll());
+ receiverPort.waitForBytesWritten(waitMsecs);
+ QTest::qSleep(waitMsecs);
+ senderPort.waitForReadyRead(waitMsecs);
+ QCOMPARE(newlineArray.size(), senderPort.bytesAvailable());
+ QCOMPARE(newlineArray, senderPort.readAll());
+
+ // second stage
+ senderPort.write(newlineArray);
+ senderPort.waitForBytesWritten(waitMsecs);
+ QTest::qSleep(waitMsecs);
+ receiverPort.waitForReadyRead(waitMsecs);
+ QCOMPARE(newlineArray.size(), receiverPort.bytesAvailable());
+ receiverPort.write(receiverPort.readAll());
+ receiverPort.waitForBytesWritten(waitMsecs);
+ QTest::qSleep(waitMsecs);
+ senderPort.waitForReadyRead(waitMsecs);
+ QCOMPARE(newlineArray.size(), senderPort.bytesAvailable());
+ QCOMPARE(newlineArray, senderPort.readAll());
+}
+
+void tst_QSerialPort::synchronousReadWrite()
+{
+#ifdef Q_OS_WIN
+ clearReceiver();
+#endif
+
+ QSerialPort senderPort(m_senderPortName);
+ QVERIFY(senderPort.open(QSerialPort::WriteOnly));
+
+ QSerialPort receiverPort(m_receiverPortName);
+ QVERIFY(receiverPort.open(QSerialPort::ReadOnly));
+
+ QByteArray writeData;
+ for (int i = 0; i < 1024; ++i)
+ writeData.append(static_cast<char>(i));
+
+ senderPort.write(writeData);
+ senderPort.waitForBytesWritten(-1);
+
+ QByteArray readData;
+ while ((readData.size() < writeData.size()) && receiverPort.waitForReadyRead(100))
+ readData.append(receiverPort.readAll());
+
+ QCOMPARE(writeData, readData);
+}
+
QTEST_MAIN(tst_QSerialPort)
#include "tst_qserialport.moc"