diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-08-12 13:09:58 +0200 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-08-12 13:09:58 +0200 |
commit | c6027a9c0e6182bde7106bc97b927c544e76e155 (patch) | |
tree | cb0ee001e8204df9643e04ed4b8961b8eb6c68f5 | |
parent | 789c0ebcd4ed976eb124e2da1958a48b478751c0 (diff) | |
parent | 3c3b23b32c6d4a9067363f758aaf4ff9819b7fd8 (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.qdoc | 12 | ||||
-rw-r--r-- | examples/serialport/doc/blockingslave.qdoc | 10 | ||||
-rw-r--r-- | examples/serialport/doc/cenumerator.qdoc | 14 | ||||
-rw-r--r-- | examples/serialport/doc/creaderasync.qdoc | 8 | ||||
-rw-r--r-- | examples/serialport/doc/creadersync.qdoc | 12 | ||||
-rw-r--r-- | examples/serialport/doc/cwriterasync.qdoc | 13 | ||||
-rw-r--r-- | examples/serialport/doc/cwritersync.qdoc | 12 | ||||
-rw-r--r-- | examples/serialport/doc/enumerator.qdoc | 8 | ||||
-rw-r--r-- | examples/serialport/doc/terminal.qdoc | 10 | ||||
-rw-r--r-- | examples/serialport/examples.qdoc | 24 | ||||
-rw-r--r-- | src/serialport/qserialport.h | 2 | ||||
-rw-r--r-- | src/serialport/qserialport_unix.cpp | 79 | ||||
-rw-r--r-- | src/serialport/qserialport_unix_p.h | 1 | ||||
-rw-r--r-- | src/serialport/qserialport_win.cpp | 130 | ||||
-rw-r--r-- | src/serialport/qserialport_win_p.h | 1 | ||||
-rw-r--r-- | src/serialport/qserialport_wince.cpp | 83 | ||||
-rw-r--r-- | src/serialport/qserialport_wince_p.h | 1 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_win.cpp | 26 | ||||
-rw-r--r-- | tests/auto/qserialport/tst_qserialport.cpp | 79 |
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(¤tTermios); -#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(¤tTermios); +#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(¤tCommTimeouts, 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(¤tCommTimeouts, 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(¤tCommTimeouts, 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(¤tCommTimeouts, 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" |