diff options
Diffstat (limited to 'src')
43 files changed, 708 insertions, 1836 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..ebdbadf --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(serialport) diff --git a/src/serialport/CMakeLists.txt b/src/serialport/CMakeLists.txt new file mode 100644 index 0000000..b7957f3 --- /dev/null +++ b/src/serialport/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## SerialPort Module: +##################################################################### +qt_find_package(Libudev) + +qt_internal_add_module(SerialPort + SOURCES + qserialport.cpp qserialport.h qserialport_p.h + qserialportglobal.h + qserialportinfo.cpp qserialportinfo.h qserialportinfo_p.h + INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_SOURCE_DIR} + LIBRARIES + Qt::CorePrivate + PUBLIC_LIBRARIES + Qt::Core + PRIVATE_MODULE_INTERFACE + Qt::CorePrivate + GENERATE_CPP_EXPORTS +) + +## Scopes: +##################################################################### + +qt_internal_extend_target(SerialPort CONDITION QT_FEATURE_libudev AND UNIX + DEFINES + LINK_LIBUDEV + LIBRARIES + PkgConfig::Libudev +) + +qt_internal_extend_target(SerialPort CONDITION WIN32 + SOURCES + qserialport_win.cpp + qserialportinfo_win.cpp + qwinoverlappedionotifier.cpp + qwinoverlappedionotifier_p.h + LIBRARIES + advapi32 + setupapi +) + +qt_internal_extend_target(SerialPort CONDITION UNIX + SOURCES + qserialport_unix.cpp +) + +qt_internal_extend_target(SerialPort CONDITION MACOS + SOURCES + qserialportinfo_osx.cpp + LIBRARIES + ${FWCoreFoundation} + ${FWIOKit} +) + +qt_internal_extend_target(SerialPort CONDITION FREEBSD + SOURCES + qserialportinfo_freebsd.cpp +) + +qt_internal_extend_target(SerialPort CONDITION UNIX AND NOT FREEBSD AND NOT MACOS + SOURCES + qserialportinfo_unix.cpp +) + +qt_internal_add_docs(SerialPort + doc/qtserialport.qdocconf +) + diff --git a/src/serialport/configure.cmake b/src/serialport/configure.cmake new file mode 100644 index 0000000..2160603 --- /dev/null +++ b/src/serialport/configure.cmake @@ -0,0 +1,46 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + + + +#### Inputs + + + +#### Libraries + + + +#### Tests + +# ntddmodm +qt_config_compile_test(ntddmodm + LABEL "ntddmodm" + CODE +" +#include <windows.h> +#include <ntddmodm.h> + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + /* BEGIN TEST: */ +GUID guid = GUID_DEVINTERFACE_MODEM; + /* END TEST: */ + return 0; +} +") + + + +#### Features + +qt_feature("ntddmodm" PRIVATE + LABEL "ntddmodm" + CONDITION TEST_ntddmodm + DISABLE INPUT_ntddmodm STREQUAL 'no' +) +qt_feature_definition("ntddmodm" "QT_NO_REDEFINE_GUID_DEVINTERFACE_MODEM") +qt_configure_add_summary_section(NAME "Serial Port") +qt_configure_add_summary_entry(ARGS "ntddmodm") +qt_configure_end_summary_section() # end of "Serial Port" section diff --git a/src/serialport/configure.json b/src/serialport/configure.json deleted file mode 100644 index c969b86..0000000 --- a/src/serialport/configure.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "module": "serialport", - "condition": "!config.integrity && !config.vxworks && !config.winrt && !config.uikit && !config.wasm", - "depends": [ - "core" - ], - - "tests": { - "ntddmodm": { - "label": "ntddmodm", - "type": "compile", - "test": { - "include": [ "windows.h", "ntddmodm.h"], - "main": [ - "GUID guid = GUID_DEVINTERFACE_MODEM;" - ] - } - } - }, - - "features": { - "ntddmodm": { - "label": "ntddmodm", - "disable": "input.ntddmodm == 'no'", - "condition": "tests.ntddmodm", - "output": [ - "privateFeature", - { "type": "define", "negative": true, "name": "QT_NO_REDEFINE_GUID_DEVINTERFACE_MODEM" } - ] - } - }, - - "summary": [ - { - "section": "Serial Port", - "entries": [ - "ntddmodm" - ] - } - ] -} diff --git a/src/serialport/doc/images/blockingmaster-example.png b/src/serialport/doc/images/blockingmaster-example.png Binary files differdeleted file mode 100644 index 9b5fc4a..0000000 --- a/src/serialport/doc/images/blockingmaster-example.png +++ /dev/null diff --git a/src/serialport/doc/images/blockingreceiver-example.png b/src/serialport/doc/images/blockingreceiver-example.png Binary files differnew file mode 100644 index 0000000..7bdafde --- /dev/null +++ b/src/serialport/doc/images/blockingreceiver-example.png diff --git a/src/serialport/doc/images/blockingsender-example.png b/src/serialport/doc/images/blockingsender-example.png Binary files differnew file mode 100644 index 0000000..14ee55c --- /dev/null +++ b/src/serialport/doc/images/blockingsender-example.png diff --git a/src/serialport/doc/images/blockingslave-example.png b/src/serialport/doc/images/blockingslave-example.png Binary files differdeleted file mode 100644 index c02ae85..0000000 --- a/src/serialport/doc/images/blockingslave-example.png +++ /dev/null diff --git a/src/serialport/doc/images/cenumerator-example.png b/src/serialport/doc/images/cenumerator-example.png Binary files differdeleted file mode 100644 index 03792e7..0000000 --- a/src/serialport/doc/images/cenumerator-example.png +++ /dev/null diff --git a/src/serialport/doc/images/creaderasync-example.png b/src/serialport/doc/images/creaderasync-example.png Binary files differdeleted file mode 100644 index ffa3636..0000000 --- a/src/serialport/doc/images/creaderasync-example.png +++ /dev/null diff --git a/src/serialport/doc/images/creadersync-example.png b/src/serialport/doc/images/creadersync-example.png Binary files differdeleted file mode 100644 index 476dcbe..0000000 --- a/src/serialport/doc/images/creadersync-example.png +++ /dev/null diff --git a/src/serialport/doc/images/cwriterasync-example.png b/src/serialport/doc/images/cwriterasync-example.png Binary files differdeleted file mode 100644 index ebe11dc..0000000 --- a/src/serialport/doc/images/cwriterasync-example.png +++ /dev/null diff --git a/src/serialport/doc/images/cwritersync-example.png b/src/serialport/doc/images/cwritersync-example.png Binary files differdeleted file mode 100644 index 669985d..0000000 --- a/src/serialport/doc/images/cwritersync-example.png +++ /dev/null diff --git a/src/serialport/doc/images/enumerator-example.png b/src/serialport/doc/images/enumerator-example.png Binary files differdeleted file mode 100644 index c96d990..0000000 --- a/src/serialport/doc/images/enumerator-example.png +++ /dev/null diff --git a/src/serialport/doc/images/terminal-example.png b/src/serialport/doc/images/terminal-example.png Binary files differindex 9affaae..7cdbd21 100644 --- a/src/serialport/doc/images/terminal-example.png +++ b/src/serialport/doc/images/terminal-example.png diff --git a/src/serialport/doc/qtserialport.qdocconf b/src/serialport/doc/qtserialport.qdocconf index fbb8e42..a852fb3 100644 --- a/src/serialport/doc/qtserialport.qdocconf +++ b/src/serialport/doc/qtserialport.qdocconf @@ -13,10 +13,6 @@ qhp.QtSerialPort.virtualFolder = qtserialport qhp.QtSerialPort.indexTitle = Qt Serial Port qhp.QtSerialPort.indexRoot = -qhp.QtSerialPort.filterAttributes = qtserialport $QT_VERSION qtrefdoc -qhp.QtSerialPort.customFilters.Qt.name = QtSerialPort $QT_VERSION -qhp.QtSerialPort.customFilters.Qt.filterAttributes = qtserialport $QT_VERSION - qhp.QtSerialPort.subprojects = classes examples qhp.QtSerialPort.subprojects.classes.title = C++ Classes @@ -31,13 +27,16 @@ qhp.QtSerialPort.subprojects.examples.sortPages = true headerdirs += .. sourcedirs += .. -exampledirs += ../../../examples/serialport +exampledirs += \ + ../../../examples/serialport \ + snippets + +excludedirs += snippets imagedirs += images -excludedirs += ../qt4support examplesinstallpath = serialport -depends += qtcore qtdoc qtnetwork qmake +depends += qtcore qtdoc qtnetwork qmake qtcmake navigation.landingpage = "Qt Serial Port" navigation.cppclassespage = "Qt Serial Port C++ Classes" diff --git a/src/serialport/doc/snippets/doc_src_serialport.cpp b/src/serialport/doc/snippets/doc_src_serialport.cpp new file mode 100644 index 0000000..11476c9 --- /dev/null +++ b/src/serialport/doc/snippets/doc_src_serialport.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QtCore/qcoreapplication.h> +#include <QtCore/qdebug.h> + +#include <QtSerialPort/qserialportinfo.h> + +void enumeratePorts() +{ +//! [enumerate_ports] + const auto serialPortInfos = QSerialPortInfo::availablePorts(); + for (const QSerialPortInfo &portInfo : serialPortInfos) { + qDebug() << "\n" + << "Port:" << portInfo.portName() << "\n" + << "Location:" << portInfo.systemLocation() << "\n" + << "Description:" << portInfo.description() << "\n" + << "Manufacturer:" << portInfo.manufacturer() << "\n" + << "Serial number:" << portInfo.serialNumber() << "\n" + << "Vendor Identifier:" + << (portInfo.hasVendorIdentifier() + ? QByteArray::number(portInfo.vendorIdentifier(), 16) + : QByteArray()) << "\n" + << "Product Identifier:" + << (portInfo.hasProductIdentifier() + ? QByteArray::number(portInfo.productIdentifier(), 16) + : QByteArray()); + } +//! [enumerate_ports] +} + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + enumeratePorts(); + + return app.exec(); +} + +#include "doc_src_serialport.moc" diff --git a/src/serialport/doc/src/index.qdoc b/src/serialport/doc/src/index.qdoc index 041188e..d91f25c 100644 --- a/src/serialport/doc/src/index.qdoc +++ b/src/serialport/doc/src/index.qdoc @@ -1,29 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \page qtserialport-index.html @@ -31,9 +7,9 @@ \title Qt Serial Port \brief Provides an API to make serial programming simple and portable. - Qt Serial Port provides the basic functionality, which includes - configuring, I/O operations, getting and setting the control signals of the - RS-232 pinouts. + Qt Serial Port provides basic functionality for configuration, I/O + operations, and getting and setting the control signals of the RS-232 + pinouts. The following items are not supported by this module: \list @@ -43,26 +19,21 @@ \li Pinout signal change notification. \endlist - To use the serial port in your application, add the following include - statement: + \section1 Using the Module - \code - #include <QSerialPort> - \endcode + \include {module-use.qdocinc} {using the c++ api} - For information about available serial ports, use the following include - statement: + \section2 Building with Cmake - \code - #include <QSerialPortInfo> - \endcode + \include {module-use.qdocinc} {building with cmake} {SerialPort} - To link against the module, add this line to your \l qmake \c - .pro file: + \section2 Building with qmake - \code - QT += serialport - \endcode + \include {module-use.qdocinc} {building_with_qmake} {serialport} + + \section1 Module Evolution + \l{Changes to Qt SerialPort} lists important changes in the module API + and functionality that were done for the Qt 6 series of Qt. \section1 Related Information \list diff --git a/src/serialport/doc/src/qt6-changes.qdoc b/src/serialport/doc/src/qt6-changes.qdoc new file mode 100644 index 0000000..d3ded94 --- /dev/null +++ b/src/serialport/doc/src/qt6-changes.qdoc @@ -0,0 +1,26 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only +/*! + \page qtserialport-changes-qt6.html + + \title Changes to Qt SerialPort + \ingroup changes-qt-5-to-6 + \brief Migrate Qt SerialPort to Qt 6. + + Qt 6 is a result of the conscious effort to make the framework more + efficient and easy to use. + We try to maintain binary and source compatibility for all the public + APIs in each release. But some changes were inevitable in an effort to + make Qt a better framework. + In this topic we summarize those changes in Qt SerialPort module, and + provide guidance to handle them. + + \section1 Changes overview + The Qt SerialPort module is generally speaking source compatible with the + Qt5 version and users of the library should be able to continue with no or + minor changes to their project. + + \section1 Build system + As with Qt6 in general, the Qt SerialPort module has cmake support in + addition to qmake. +*/ diff --git a/src/serialport/doc/src/qtserialport-examples.qdoc b/src/serialport/doc/src/qtserialport-examples.qdoc index c680224..51bd949 100644 --- a/src/serialport/doc/src/qtserialport-examples.qdoc +++ b/src/serialport/doc/src/qtserialport-examples.qdoc @@ -1,31 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \title Qt Serial Port Examples diff --git a/src/serialport/doc/src/qtserialport-module-use.qdocinc b/src/serialport/doc/src/qtserialport-module-use.qdocinc new file mode 100644 index 0000000..e723fd9 --- /dev/null +++ b/src/serialport/doc/src/qtserialport-module-use.qdocinc @@ -0,0 +1,15 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +//! [cmakebuild] + \code + find_package(Qt6 REQUIRED COMPONENTS SerialPort) + target_link_libraries(mytarget PRIVATE Qt6::SerialPort) + \endcode +//! [cmakebuild] + +//! [qmakebuild] + \code + QT += serialport + \endcode +//! [qmakebuild] diff --git a/src/serialport/doc/src/qtserialport-module.qdoc b/src/serialport/doc/src/qtserialport-module.qdoc index 6c153a0..cf4523b 100644 --- a/src/serialport/doc/src/qtserialport-module.qdoc +++ b/src/serialport/doc/src/qtserialport-module.qdoc @@ -1,35 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \module QtSerialPort \title Qt Serial Port C++ Classes \ingroup modules \qtvariable serialport + \qtcmakepackage SerialPort \brief List of C++ classes that enable access to a serial port. To use QSerialPort in your application, add the following include @@ -45,10 +22,11 @@ #include <QSerialPortInfo> \endcode - To link against the module, add this line to your \l qmake \c - .pro file: + To use the module with cmake, use the \c{find_package()} command to locate + the needed module components in the \c{Qt6} package: + \include qtserialport-module-use.qdocinc cmakebuild - \code - QT += serialport - \endcode + To use the module for building with qmake, add the module as a value of the + \c QT variable in the project's .pro file: + \include qtserialport-module-use.qdocinc qmakebuild */ diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 44d6cd1..d4265b6 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -1,44 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Copyright (C) 2012 Andre Hartmann <aha_1980@gmx.de> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// Copyright (C) 2012 Andre Hartmann <aha_1980@gmx.de> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qserialport.h" #include "qserialportinfo.h" @@ -99,12 +63,10 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) { Q_Q(QSerialPort); - error = errorInfo.errorCode; q->setErrorString(errorInfo.errorString); + error.setValue(errorInfo.errorCode); + error.notify(); emit q->errorOccurred(error); -#if QT_DEPRECATED_SINCE(5, 8) - emit q->error(error); -#endif } /*! @@ -235,9 +197,6 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) \value Baud38400 38400 baud. \value Baud57600 57600 baud. \value Baud115200 115200 baud. - \value UnknownBaud Unknown baud. This value is obsolete. It is provided to - keep old source code working. We strongly advise against - using it in new code. \sa QSerialPort::baudRate */ @@ -259,9 +218,6 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) is used for most kinds of data, as this size matches the size of a byte. It is almost universally used in newer applications. - \value UnknownDataBits Unknown number of bits. This value is obsolete. It - is provided to keep old source code working. We - strongly advise against using it in new code. \sa QSerialPort::dataBits */ @@ -285,9 +241,6 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) \value MarkParity Mark parity. The parity bit is always set to the mark signal condition (logical 1). It does not provide error detection information. - \value UnknownParity Unknown parity. This value is obsolete. It is - provided to keep old source code working. We - strongly advise against using it in new code. \sa QSerialPort::parity */ @@ -300,9 +253,6 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) \value OneStop 1 stop bit. \value OneAndHalfStop 1.5 stop bits. This is only for the Windows platform. \value TwoStop 2 stop bits. - \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. \sa QSerialPort::stopBits */ @@ -315,9 +265,6 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) \value NoFlowControl No flow control. \value HardwareControl Hardware flow control (RTS/CTS). \value SoftwareControl Software flow control (XON/XOFF). - \value UnknownFlowControl Unknown flow control. This value is obsolete. It - is provided to keep old source code working. We - strongly advise against using it in new code. \sa QSerialPort::flowControl */ @@ -328,14 +275,6 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) This enum describes the possible RS-232 pinout signals. \value NoSignal No line active - \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). @@ -349,24 +288,6 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) QSerialPort::requestToSend */ -#if QT_DEPRECATED_SINCE(5, 2) -/*! - \enum QSerialPort::DataErrorPolicy - \obsolete - - This enum describes the policies for the received symbols - while parity errors were detected. - - \value SkipPolicy Skips the bad character. - \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. - - \sa QSerialPort::dataErrorPolicy -*/ -#endif - /*! \enum QSerialPort::SerialPortError @@ -391,18 +312,6 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) device is open. This value was introduced in QtSerialPort 5.2. - \value ParityError Parity error detected by the hardware while - reading data. This value is obsolete. We strongly - advise against using it in new code. - - \value FramingError Framing error detected by the hardware while - reading data. This value is obsolete. We strongly - advise against using it in new code. - - \value BreakConditionError Break condition detected by the hardware on - the input line. This value is obsolete. We strongly - advise against using it in new code. - \value WriteError An I/O error occurred while writing the data. \value ReadError An I/O error occurred while reading the data. @@ -429,7 +338,6 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) */ QSerialPort::QSerialPort(QObject *parent) : QIODevice(*new QSerialPortPrivate, parent) - , d_dummy(0) { } @@ -441,7 +349,6 @@ QSerialPort::QSerialPort(QObject *parent) */ QSerialPort::QSerialPort(const QString &name, QObject *parent) : QIODevice(*new QSerialPortPrivate, parent) - , d_dummy(0) { setPortName(name); } @@ -453,7 +360,6 @@ QSerialPort::QSerialPort(const QString &name, QObject *parent) */ QSerialPort::QSerialPort(const QSerialPortInfo &serialPortInfo, QObject *parent) : QIODevice(*new QSerialPortPrivate, parent) - , d_dummy(0) { setPort(serialPortInfo); } @@ -531,10 +437,10 @@ QString QSerialPort::portName() const not set any of the port settings successfully. In that case, the port is closed automatically not to leave the port around with incorrect settings. - \warning The \a mode has to be QIODevice::ReadOnly, QIODevice::WriteOnly, - or QIODevice::ReadWrite. Other modes are unsupported. + \warning The \a mode has to be QIODeviceBase::ReadOnly, QIODeviceBase::WriteOnly, + or QIODeviceBase::ReadWrite. Other modes are unsupported. - \sa QIODevice::OpenMode, setPort() + \sa QIODeviceBase::OpenMode, setPort() */ bool QSerialPort::open(OpenMode mode) { @@ -577,57 +483,10 @@ void QSerialPort::close() } d->close(); - d->isBreakEnabled = false; + d->isBreakEnabled.setValue(false); QIODevice::close(); } -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - -#if QT_DEPRECATED_SINCE(5, 3) -/*! - \property QSerialPort::settingsRestoredOnClose - \brief the flag which specifies to restore the previous settings when closing - the serial port. - \obsolete - - If this flag is \c true, the settings will be restored; otherwise not. - The default state of the QSerialPort class is to restore the - settings. -*/ -void QSerialPort::setSettingsRestoredOnClose(bool restore) -{ - Q_D(QSerialPort); - - if (d->settingsRestoredOnClose != restore) { - d->settingsRestoredOnClose = restore; - emit settingsRestoredOnCloseChanged(d->settingsRestoredOnClose); - } -} - -QT_WARNING_POP - -bool QSerialPort::settingsRestoredOnClose() const -{ - Q_D(const QSerialPort); - return d->settingsRestoredOnClose; -} -#endif // QT_DEPRECATED_SINCE(5,3) - -#if QT_DEPRECATED_SINCE(5, 5) -/*! - \fn void QSerialPort::settingsRestoredOnCloseChanged(bool restore) - \obsolete - - 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 specifies to restore the previous settings while closing the serial - port is passed as \a restore. - - \sa QSerialPort::settingsRestoredOnClose -*/ -#endif // QT_DEPRECATED_SINCE(5, 5) - /*! \property QSerialPort::baudRate \brief the data baud rate for the desired direction @@ -712,15 +571,16 @@ qint32 QSerialPort::baudRate(Directions directions) const bool QSerialPort::setDataBits(DataBits dataBits) { Q_D(QSerialPort); - + d->dataBits.removeBindingUnlessInWrapper(); + const auto currentDataBits = d->dataBits.value(); if (!isOpen() || d->setDataBits(dataBits)) { - if (d->dataBits != dataBits) { - d->dataBits = dataBits; - emit dataBitsChanged(d->dataBits); + d->dataBits.setValueBypassingBindings(dataBits); + if (currentDataBits != dataBits) { + d->dataBits.notify(); + emit dataBitsChanged(dataBits); } return true; } - return false; } @@ -730,6 +590,11 @@ QSerialPort::DataBits QSerialPort::dataBits() const return d->dataBits; } +QBindable<QSerialPort::DataBits> QSerialPort::bindableDataBits() +{ + return &d_func()->dataBits; +} + /*! \fn void QSerialPort::dataBitsChanged(DataBits dataBits) @@ -757,15 +622,16 @@ QSerialPort::DataBits QSerialPort::dataBits() const bool QSerialPort::setParity(Parity parity) { Q_D(QSerialPort); - + d->parity.removeBindingUnlessInWrapper(); + const auto currentParity = d->parity.value(); if (!isOpen() || d->setParity(parity)) { - if (d->parity != parity) { - d->parity = parity; - emit parityChanged(d->parity); + d->parity.setValueBypassingBindings(parity); + if (currentParity != parity) { + d->parity.notify(); + emit parityChanged(parity); } return true; } - return false; } @@ -775,6 +641,11 @@ QSerialPort::Parity QSerialPort::parity() const return d->parity; } +QBindable<QSerialPort::Parity> QSerialPort::bindableParity() +{ + return &d_func()->parity; +} + /*! \fn void QSerialPort::parityChanged(Parity parity) @@ -801,15 +672,16 @@ QSerialPort::Parity QSerialPort::parity() const bool QSerialPort::setStopBits(StopBits stopBits) { Q_D(QSerialPort); - + d->stopBits.removeBindingUnlessInWrapper(); + const auto currentStopBits = d->stopBits.value(); if (!isOpen() || d->setStopBits(stopBits)) { - if (d->stopBits != stopBits) { - d->stopBits = stopBits; - emit stopBitsChanged(d->stopBits); + d->stopBits.setValueBypassingBindings(stopBits); + if (currentStopBits != stopBits) { + d->stopBits.notify(); + emit stopBitsChanged(stopBits); } return true; } - return false; } @@ -819,6 +691,11 @@ QSerialPort::StopBits QSerialPort::stopBits() const return d->stopBits; } +QBindable<bool> QSerialPort::bindableStopBits() +{ + return &d_func()->stopBits; +} + /*! \fn void QSerialPort::stopBitsChanged(StopBits stopBits) @@ -845,15 +722,16 @@ QSerialPort::StopBits QSerialPort::stopBits() const bool QSerialPort::setFlowControl(FlowControl flowControl) { Q_D(QSerialPort); - + d->flowControl.removeBindingUnlessInWrapper(); + const auto currentFlowControl = d->flowControl.value(); if (!isOpen() || d->setFlowControl(flowControl)) { - if (d->flowControl != flowControl) { - d->flowControl = flowControl; - emit flowControlChanged(d->flowControl); + d->flowControl.setValueBypassingBindings(flowControl); + if (currentFlowControl != flowControl) { + d->flowControl.notify(); + emit flowControlChanged(flowControl); } return true; } - return false; } @@ -863,6 +741,11 @@ QSerialPort::FlowControl QSerialPort::flowControl() const return d->flowControl; } +QBindable<QSerialPort::FlowControl> QSerialPort::bindableFlowControl() +{ + return &d_func()->flowControl; +} + /*! \fn void QSerialPort::flowControlChanged(FlowControl flow) @@ -1061,89 +944,6 @@ bool QSerialPort::clear(Directions directions) } /*! - \reimp - - Returns \c true if no more data is currently available for reading; otherwise - returns \c false. - - This function is most commonly used when reading data from the - serial port in a loop. For example: - - \code - // This slot is connected to QSerialPort::readyRead() - void QSerialPortClass::readyReadSlot() - { - while (!port.atEnd()) { - QByteArray data = port.read(100); - .... - } - } - \endcode - - \sa bytesAvailable(), readyRead() - */ -bool QSerialPort::atEnd() const -{ - return QIODevice::atEnd(); -} - -#if QT_DEPRECATED_SINCE(5, 2) -/*! - \property QSerialPort::dataErrorPolicy - \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 \c true; otherwise returns \c false. The - default policy set is IgnorePolicy. - - \note The serial port has to be open before trying to set this property; - otherwise returns \c false and sets the NotOpenError error code. This is a bit - unusual as opposed to the regular Qt property settings of a class. However, - this is a special use case since the property is set through the interaction - with the kernel and hardware. Hence, the two scenarios cannot be completely - compared to each other. -*/ -bool QSerialPort::setDataErrorPolicy(DataErrorPolicy policy) -{ - Q_D(QSerialPort); - - if (!isOpen()) { - d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError)); - qWarning("%s: device not open", Q_FUNC_INFO); - return false; - } - - if (policy != QSerialPort::IgnorePolicy) { - d->setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError, - tr("The device supports only the ignoring policy"))); - return false; - } - - return true; -} - -QSerialPort::DataErrorPolicy QSerialPort::dataErrorPolicy() const -{ - return QSerialPort::IgnorePolicy; -} -#endif // QT_DEPRECATED_SINCE(5, 2) - -#if QT_DEPRECATED_SINCE(5, 5) -/*! - \fn void QSerialPort::dataErrorPolicyChanged(DataErrorPolicy policy) - \obsolete - - 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 -*/ -#endif // QT_DEPRECATED_SINCE(5, 5) - -/*! \property QSerialPort::error \brief the error status of the serial port @@ -1166,14 +966,10 @@ void QSerialPort::clearError() d->setError(QSerialPortErrorInfo(QSerialPort::NoError)); } -#if QT_DEPRECATED_SINCE(5, 8) -/*! - \fn void QSerialPort::error(SerialPortError error) - \obsolete - - Use errorOccurred() instead. -*/ -#endif +QBindable<QSerialPort::SerialPortError> QSerialPort::bindableError() const +{ + return &d_func()->error; +} /*! \fn void QSerialPort::errorOccurred(SerialPortError error) @@ -1327,37 +1123,6 @@ bool QSerialPort::waitForBytesWritten(int msecs) return d->waitForBytesWritten(msecs); } -#if QT_DEPRECATED_SINCE(5, 5) -/*! - Sends a continuous stream of zero bits during a specified period - of time \a duration in msec if the terminal is using asynchronous - serial data. If successful, returns \c true; otherwise returns \c false. - - If the duration is zero then zero bits are transmitted by at least - \c 0.25 seconds, but no more than \c 0.5 seconds. - - If the duration is non zero then zero bits are transmitted within a certain - period of time depending on the implementation. - - \note The serial port has to be open before trying to send a break - duration; otherwise returns \c false and sets the NotOpenError error code. - - \sa setBreakEnabled() -*/ -bool QSerialPort::sendBreak(int duration) -{ - Q_D(QSerialPort); - - if (!isOpen()) { - d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError)); - qWarning("%s: device not open", Q_FUNC_INFO); - return false; - } - - return d->sendBreak(duration); -} -#endif // QT_DEPRECATED_SINCE(5, 5) - /*! \property QSerialPort::breakEnabled \since 5.5 @@ -1377,19 +1142,20 @@ bool QSerialPort::sendBreak(int duration) bool QSerialPort::setBreakEnabled(bool set) { Q_D(QSerialPort); - - if (!isOpen()) { + d->isBreakEnabled.removeBindingUnlessInWrapper(); + const auto currentSet = d->isBreakEnabled.value(); + if (isOpen()) { + if (d->setBreakEnabled(set)) { + d->isBreakEnabled.setValueBypassingBindings(set); + if (currentSet != set) { + d->isBreakEnabled.notify(); + emit breakEnabledChanged(set); + } + return true; + } + } else { d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError)); qWarning("%s: device not open", Q_FUNC_INFO); - return false; - } - - if (d->setBreakEnabled(set)) { - if (d->isBreakEnabled != set) { - d->isBreakEnabled = set; - emit breakEnabledChanged(d->isBreakEnabled); - } - return true; } return false; } @@ -1400,6 +1166,11 @@ bool QSerialPort::isBreakEnabled() const return d->isBreakEnabled; } +QBindable<bool> QSerialPort::bindableIsBreakEnabled() +{ + return &d_func()->isBreakEnabled; +} + /*! \reimp diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h index c4c7367..3352fdb 100644 --- a/src/serialport/qserialport.h +++ b/src/serialport/qserialport.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSERIALPORT_H #define QSERIALPORT_H @@ -56,20 +20,19 @@ class Q_SERIALPORT_EXPORT QSerialPort : public QIODevice Q_DECLARE_PRIVATE(QSerialPort) Q_PROPERTY(qint32 baudRate READ baudRate WRITE setBaudRate NOTIFY baudRateChanged) - Q_PROPERTY(DataBits dataBits READ dataBits WRITE setDataBits NOTIFY dataBitsChanged) - Q_PROPERTY(Parity parity READ parity WRITE setParity NOTIFY parityChanged) - Q_PROPERTY(StopBits stopBits READ stopBits WRITE setStopBits NOTIFY stopBitsChanged) - Q_PROPERTY(FlowControl flowControl READ flowControl WRITE setFlowControl NOTIFY flowControlChanged) -#if QT_DEPRECATED_SINCE(5, 2) - Q_PROPERTY(DataErrorPolicy dataErrorPolicy READ dataErrorPolicy WRITE setDataErrorPolicy NOTIFY dataErrorPolicyChanged) -#endif - Q_PROPERTY(bool dataTerminalReady READ isDataTerminalReady WRITE setDataTerminalReady NOTIFY dataTerminalReadyChanged) + Q_PROPERTY(DataBits dataBits READ dataBits WRITE setDataBits NOTIFY dataBitsChanged + BINDABLE bindableDataBits) + Q_PROPERTY(Parity parity READ parity WRITE setParity NOTIFY parityChanged BINDABLE bindableParity) + Q_PROPERTY(StopBits stopBits READ stopBits WRITE setStopBits NOTIFY stopBitsChanged + BINDABLE bindableStopBits) + Q_PROPERTY(FlowControl flowControl READ flowControl WRITE setFlowControl NOTIFY flowControlChanged + BINDABLE bindableFlowControl) + Q_PROPERTY(bool dataTerminalReady READ isDataTerminalReady WRITE setDataTerminalReady + NOTIFY dataTerminalReadyChanged) Q_PROPERTY(bool requestToSend READ isRequestToSend WRITE setRequestToSend NOTIFY requestToSendChanged) - Q_PROPERTY(SerialPortError error READ error RESET clearError NOTIFY error) -#if QT_DEPRECATED_SINCE(5, 3) - Q_PROPERTY(bool settingsRestoredOnClose READ settingsRestoredOnClose WRITE setSettingsRestoredOnClose NOTIFY settingsRestoredOnCloseChanged) -#endif - Q_PROPERTY(bool breakEnabled READ isBreakEnabled WRITE setBreakEnabled NOTIFY breakEnabledChanged) + Q_PROPERTY(SerialPortError error READ error RESET clearError NOTIFY errorOccurred BINDABLE bindableError) + Q_PROPERTY(bool breakEnabled READ isBreakEnabled WRITE setBreakEnabled NOTIFY breakEnabledChanged + BINDABLE bindableIsBreakEnabled) #if defined(Q_OS_WIN32) typedef void* Handle; @@ -95,8 +58,7 @@ public: Baud19200 = 19200, Baud38400 = 38400, Baud57600 = 57600, - Baud115200 = 115200, - UnknownBaud = -1 + Baud115200 = 115200 }; Q_ENUM(BaudRate) @@ -104,8 +66,7 @@ public: Data5 = 5, Data6 = 6, Data7 = 7, - Data8 = 8, - UnknownDataBits = -1 + Data8 = 8 }; Q_ENUM(DataBits) @@ -114,31 +75,26 @@ public: EvenParity = 2, OddParity = 3, SpaceParity = 4, - MarkParity = 5, - UnknownParity = -1 + MarkParity = 5 }; Q_ENUM(Parity) enum StopBits { OneStop = 1, OneAndHalfStop = 3, - TwoStop = 2, - UnknownStopBits = -1 + TwoStop = 2 }; Q_ENUM(StopBits) enum FlowControl { NoFlowControl, HardwareControl, - SoftwareControl, - UnknownFlowControl = -1 + SoftwareControl }; Q_ENUM(FlowControl) enum PinoutSignal { NoSignal = 0x00, - TransmittedDataSignal = 0x01, - ReceivedDataSignal = 0x02, DataTerminalReadySignal = 0x04, DataCarrierDetectSignal = 0x08, DataSetReadySignal = 0x10, @@ -151,37 +107,11 @@ public: Q_FLAG(PinoutSignal) Q_DECLARE_FLAGS(PinoutSignals, PinoutSignal) -#if QT_DEPRECATED_SINCE(5, 2) -#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG) -#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, - IgnorePolicy, - StopReceivingPolicy, - UnknownPolicy = -1 - }; - Q_ENUM(DataErrorPolicy) -#endif - enum SerialPortError { NoError, DeviceNotFoundError, PermissionError, OpenError, - ParityError, - FramingError, - BreakConditionError, WriteError, ReadError, ResourceError, @@ -192,14 +122,6 @@ public: }; Q_ENUM(SerialPortError) -#if QT_DEPRECATED_SINCE(5, 6) -#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG) -#pragma deprecated(ParityError) -#pragma deprecated(FramingError) -#pragma deprecated(BreakConditionError) -#endif -#endif - explicit QSerialPort(QObject *parent = nullptr); explicit QSerialPort(const QString &name, QObject *parent = nullptr); explicit QSerialPort(const QSerialPortInfo &info, QObject *parent = nullptr); @@ -213,25 +135,24 @@ public: bool open(OpenMode mode) override; void close() override; -#if QT_DEPRECATED_SINCE(5, 3) - QT_DEPRECATED void setSettingsRestoredOnClose(bool restore); - QT_DEPRECATED bool settingsRestoredOnClose() const; -#endif - bool setBaudRate(qint32 baudRate, Directions directions = AllDirections); qint32 baudRate(Directions directions = AllDirections) const; bool setDataBits(DataBits dataBits); DataBits dataBits() const; + QBindable<DataBits> bindableDataBits(); bool setParity(Parity parity); Parity parity() const; + QBindable<Parity> bindableParity(); bool setStopBits(StopBits stopBits); StopBits stopBits() const; + QBindable<bool> bindableStopBits(); bool setFlowControl(FlowControl flowControl); FlowControl flowControl() const; + QBindable<FlowControl> bindableFlowControl(); bool setDataTerminalReady(bool set); bool isDataTerminalReady(); @@ -243,15 +164,10 @@ public: bool flush(); bool clear(Directions directions = AllDirections); - bool atEnd() const override; // ### Qt6: remove me - -#if QT_DEPRECATED_SINCE(5, 2) - QT_DEPRECATED bool setDataErrorPolicy(DataErrorPolicy policy = IgnorePolicy); - QT_DEPRECATED DataErrorPolicy dataErrorPolicy() const; -#endif SerialPortError error() const; void clearError(); + QBindable<SerialPortError> bindableError() const; qint64 readBufferSize() const; void setReadBufferSize(qint64 size); @@ -265,11 +181,9 @@ public: bool waitForReadyRead(int msecs = 30000) override; bool waitForBytesWritten(int msecs = 30000) override; -#if QT_DEPRECATED_SINCE(5, 5) - QT_DEPRECATED bool sendBreak(int duration = 0); -#endif bool setBreakEnabled(bool set = true); bool isBreakEnabled() const; + QBindable<bool> bindableIsBreakEnabled(); Handle handle() const; @@ -279,18 +193,9 @@ Q_SIGNALS: void parityChanged(QSerialPort::Parity parity); void stopBitsChanged(QSerialPort::StopBits stopBits); void flowControlChanged(QSerialPort::FlowControl flowControl); -#if QT_DEPRECATED_SINCE(5, 5) - QT_DEPRECATED void dataErrorPolicyChanged(QSerialPort::DataErrorPolicy policy); -#endif void dataTerminalReadyChanged(bool set); void requestToSendChanged(bool set); -#if QT_DEPRECATED_SINCE(5, 8) - void error(QSerialPort::SerialPortError serialPortError); -#endif void errorOccurred(QSerialPort::SerialPortError error); -#if QT_DEPRECATED_SINCE(5, 5) - QT_DEPRECATED void settingsRestoredOnCloseChanged(bool restore); -#endif void breakEnabledChanged(bool set); protected: @@ -299,13 +204,11 @@ protected: qint64 writeData(const char *data, qint64 maxSize) override; private: - // ### Qt6: remove me. - QSerialPortPrivate * const d_dummy; - Q_DISABLE_COPY(QSerialPort) #if defined(Q_OS_WIN32) Q_PRIVATE_SLOT(d_func(), bool _q_startAsyncWrite()) + Q_PRIVATE_SLOT(d_func(), void _q_notified(quint32, quint32, OVERLAPPED*)) #endif }; diff --git a/src/serialport/qserialport_p.h b/src/serialport/qserialport_p.h index 7348aed..fd9fee3 100644 --- a/src/serialport/qserialport_p.h +++ b/src/serialport/qserialport_p.h @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSERIALPORT_P_H #define QSERIALPORT_P_H @@ -55,14 +19,17 @@ #include "qserialport.h" -#include <private/qiodevice_p.h> #include <qdeadlinetimer.h> +#include <private/qiodevice_p.h> +#include <private/qproperty_p.h> + +#include <memory> + #if defined(Q_OS_WIN32) # include <qt_windows.h> #elif defined(Q_OS_UNIX) # include <QtCore/qlockfile.h> -# include <QtCore/qscopedpointer.h> # include <QtCore/qfileinfo.h> # include <QtCore/qstringlist.h> # include <limits.h> @@ -104,6 +71,7 @@ struct serial_struct { QT_BEGIN_NAMESPACE +class QWinOverlappedIoNotifier; class QTimer; class QSocketNotifier; @@ -114,7 +82,7 @@ QString serialPortLockFilePath(const QString &portName); class QSerialPortErrorInfo { public: - explicit QSerialPortErrorInfo(QSerialPort::SerialPortError newErrorCode = QSerialPort::UnknownError, + QSerialPortErrorInfo(QSerialPort::SerialPortError newErrorCode = QSerialPort::UnknownError, const QString &newErrorString = QString()); QSerialPort::SerialPortError errorCode = QSerialPort::UnknownError; QString errorString; @@ -122,8 +90,9 @@ public: class QSerialPortPrivate : public QIODevicePrivate { - Q_DECLARE_PUBLIC(QSerialPort) public: + Q_DECLARE_PUBLIC(QSerialPort) + QSerialPortPrivate(); bool open(QIODevice::OpenMode mode); @@ -164,16 +133,42 @@ public: static QList<qint32> standardBaudRates(); qint64 readBufferMaxSize = 0; - QSerialPort::SerialPortError error = QSerialPort::NoError; + + void setBindableError(QSerialPort::SerialPortError error) + { setError(error); } + Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSerialPortPrivate, QSerialPort::SerialPortError, error, + &QSerialPortPrivate::setBindableError, QSerialPort::NoError) + QString systemLocation; qint32 inputBaudRate = QSerialPort::Baud9600; qint32 outputBaudRate = QSerialPort::Baud9600; - QSerialPort::DataBits dataBits = QSerialPort::Data8; - QSerialPort::Parity parity = QSerialPort::NoParity; - QSerialPort::StopBits stopBits = QSerialPort::OneStop; - QSerialPort::FlowControl flowControl = QSerialPort::NoFlowControl; + + bool setBindableDataBits(QSerialPort::DataBits dataBits) + { return q_func()->setDataBits(dataBits); } + Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSerialPortPrivate, QSerialPort::DataBits, dataBits, + &QSerialPortPrivate::setBindableDataBits, QSerialPort::Data8) + + bool setBindableParity(QSerialPort::Parity parity) + { return q_func()->setParity(parity); } + Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSerialPortPrivate, QSerialPort::Parity, parity, + &QSerialPortPrivate::setBindableParity, QSerialPort::NoParity) + + bool setBindableStopBits(QSerialPort::StopBits stopBits) + { return q_func()->setStopBits(stopBits); } + Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSerialPortPrivate, QSerialPort::StopBits, stopBits, + &QSerialPortPrivate::setBindableStopBits, QSerialPort::OneStop) + + bool setBindableFlowControl(QSerialPort::FlowControl flowControl) + { return q_func()->setFlowControl(flowControl); } + Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSerialPortPrivate, QSerialPort::FlowControl, flowControl, + &QSerialPortPrivate::setBindableFlowControl, QSerialPort::NoFlowControl) + bool settingsRestoredOnClose = true; - bool isBreakEnabled = false; + + bool setBindableBreakEnabled(bool isBreakEnabled) + { return q_func()->setBreakEnabled(isBreakEnabled); } + Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QSerialPortPrivate, bool, isBreakEnabled, + &QSerialPortPrivate::setBindableBreakEnabled, false) bool startAsyncRead(); @@ -181,6 +176,7 @@ public: bool setDcb(DCB *dcb); bool getDcb(DCB *dcb); + OVERLAPPED *waitForNotified(QDeadlineTimer deadline); qint64 queuedBytesCount(QSerialPort::Direction direction) const; @@ -190,15 +186,10 @@ public: bool startAsyncCommunication(); bool _q_startAsyncWrite(); - void handleNotification(DWORD bytesTransferred, DWORD errorCode, - OVERLAPPED *overlapped); + void _q_notified(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped); void emitReadyRead(); - static void CALLBACK ioCompletionRoutine( - DWORD errorCode, DWORD bytesTransfered, - OVERLAPPED *overlappedBase); - DCB restoredDcb; COMMTIMEOUTS currentCommTimeouts; COMMTIMEOUTS restoredCommTimeouts; @@ -208,12 +199,11 @@ public: bool communicationStarted = false; bool writeStarted = false; bool readStarted = false; - qint64 writeBytesTransferred = 0; - qint64 readBytesTransferred = 0; + QWinOverlappedIoNotifier *notifier = nullptr; QTimer *startAsyncWriteTimer = nullptr; - class Overlapped *communicationCompletionOverlapped = nullptr; - class Overlapped *readCompletionOverlapped = nullptr; - class Overlapped *writeCompletionOverlapped = nullptr; + OVERLAPPED communicationOverlapped; + OVERLAPPED readCompletionOverlapped; + OVERLAPPED writeCompletionOverlapped; DWORD triggeredEventMask = 0; #elif defined(Q_OS_UNIX) @@ -262,7 +252,7 @@ public: qint64 pendingBytesWritten = 0; bool writeSequenceStarted = false; - QScopedPointer<QLockFile> lockFileScopedPointer; + std::unique_ptr<QLockFile> lockFileScopedPointer; #endif }; diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index 294782b..e0f2e79 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Copyright (C) 2012 Andre Hartmann <aha_1980@gmx.de> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// Copyright (C) 2012 Andre Hartmann <aha_1980@gmx.de> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qserialport_p.h" #include "qserialportinfo_p.h" @@ -316,7 +280,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) return false; } - QScopedPointer<QLockFile> newLockFileScopedPointer(new QLockFile(lockFilePath)); + auto newLockFileScopedPointer = std::make_unique<QLockFile>(lockFilePath); if (!newLockFileScopedPointer->tryLock()) { setError(QSerialPortErrorInfo(QSerialPort::PermissionError, QSerialPort::tr("Permission error while locking the device"))); @@ -349,7 +313,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) return false; } - lockFileScopedPointer.swap(newLockFileScopedPointer); + lockFileScopedPointer = std::move(newLockFileScopedPointer); return true; } diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index c0061fc..5e7e0eb 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -1,54 +1,49 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Copyright (C) 2012 Andre Hartmann <aha_1980@gmx.de> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// Copyright (C) 2012 Andre Hartmann <aha_1980@gmx.de> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qserialport_p.h" -#include "qtntdll_p.h" +#include "qwinoverlappedionotifier_p.h" #include <QtCore/qcoreevent.h> #include <QtCore/qelapsedtimer.h> +#include <QtCore/qlist.h> #include <QtCore/qmutex.h> #include <QtCore/qtimer.h> -#include <QtCore/qvector.h> #include <algorithm> +#ifndef CTL_CODE +# define CTL_CODE(DeviceType, Function, Method, Access) ( \ + ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ + ) +#endif + +#ifndef FILE_DEVICE_SERIAL_PORT +# define FILE_DEVICE_SERIAL_PORT 27 +#endif + +#ifndef METHOD_BUFFERED +# define METHOD_BUFFERED 0 +#endif + +#ifndef FILE_ANY_ACCESS +# define FILE_ANY_ACCESS 0x00000000 +#endif + +#ifndef IOCTL_SERIAL_GET_DTRRTS +# define IOCTL_SERIAL_GET_DTRRTS \ + CTL_CODE(FILE_DEVICE_SERIAL_PORT, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif + +#ifndef SERIAL_DTR_STATE +# define SERIAL_DTR_STATE 0x00000001 +#endif + +#ifndef SERIAL_RTS_STATE +# define SERIAL_RTS_STATE 0x00000002 +#endif + QT_BEGIN_NAMESPACE static inline void qt_set_common_props(DCB *dcb) @@ -143,117 +138,8 @@ static inline void qt_set_flowcontrol(DCB *dcb, QSerialPort::FlowControl flowcon } } -// Translate NT-callbacks to Win32 callbacks. -static VOID WINAPI qt_apc_routine( - PVOID context, - PIO_STATUS_BLOCK ioStatusBlock, - DWORD reserved) -{ - Q_UNUSED(reserved); - - const DWORD errorCode = ::RtlNtStatusToDosError(ioStatusBlock->Status); - const DWORD bytesTransfered = NT_SUCCESS(ioStatusBlock->Status) - ? DWORD(ioStatusBlock->Information) : 0; - const LPOVERLAPPED overlapped = CONTAINING_RECORD(ioStatusBlock, - OVERLAPPED, Internal); - - (reinterpret_cast<LPOVERLAPPED_COMPLETION_ROUTINE>(context)) - (errorCode, bytesTransfered, overlapped); -} - -// Alertable analog of DeviceIoControl function. -static BOOL qt_device_io_control_ex( - HANDLE deviceHandle, - DWORD ioControlCode, - LPVOID inputBuffer, - DWORD inputBufferSize, - LPVOID outputBuffer, - DWORD outputBufferSize, - LPOVERLAPPED overlapped, - LPOVERLAPPED_COMPLETION_ROUTINE completionRoutine) -{ - const auto ioStatusBlock = reinterpret_cast<PIO_STATUS_BLOCK>( - &overlapped->Internal); - ioStatusBlock->Status = STATUS_PENDING; - - const NTSTATUS status = ::NtDeviceIoControlFile( - deviceHandle, - nullptr, - qt_apc_routine, - reinterpret_cast<PVOID>(completionRoutine), - ioStatusBlock, - ioControlCode, - inputBuffer, - inputBufferSize, - outputBuffer, - outputBufferSize); - - if (!NT_SUCCESS(status)) { - ::SetLastError(::RtlNtStatusToDosError(status)); - return false; - } - - return true; -} - -// Alertable analog of WaitCommEvent function. -static BOOL qt_wait_comm_event_ex( - HANDLE deviceHandle, - LPDWORD eventsMask, - LPOVERLAPPED overlapped, - LPOVERLAPPED_COMPLETION_ROUTINE completionRoutine) -{ - return qt_device_io_control_ex( - deviceHandle, - IOCTL_SERIAL_WAIT_ON_MASK, - nullptr, - 0, - eventsMask, - sizeof(DWORD), - overlapped, - completionRoutine); -} - -struct RuntimeHelper -{ - QLibrary ntLibrary; - QBasicMutex mutex; -}; - -Q_GLOBAL_STATIC(RuntimeHelper, helper) - -class Overlapped final : public OVERLAPPED -{ - Q_DISABLE_COPY(Overlapped) -public: - explicit Overlapped(QSerialPortPrivate *d); - void clear(); - - QSerialPortPrivate *dptr = nullptr; -}; - -Overlapped::Overlapped(QSerialPortPrivate *d) - : dptr(d) -{ -} - -void Overlapped::clear() -{ - ::ZeroMemory(this, sizeof(OVERLAPPED)); -} - bool QSerialPortPrivate::open(QIODevice::OpenMode mode) { - { - QMutexLocker locker(&helper()->mutex); - static bool symbolsResolved = resolveNtdllSymbols(&helper()->ntLibrary); - if (!symbolsResolved) { - setError(QSerialPortErrorInfo(QSerialPort::OpenError, - helper()->ntLibrary.errorString())); - return false; - } - } - DWORD desiredAccess = 0; if (mode & QIODevice::ReadOnly) @@ -278,44 +164,17 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) void QSerialPortPrivate::close() { - delete startAsyncWriteTimer; - startAsyncWriteTimer = nullptr; + ::CancelIo(handle); - if (communicationStarted) { - communicationCompletionOverlapped->dptr = nullptr; - ::CancelIoEx(handle, communicationCompletionOverlapped); - // The object will be deleted in the I/O callback. - communicationCompletionOverlapped = nullptr; - communicationStarted = false; - } else { - delete communicationCompletionOverlapped; - communicationCompletionOverlapped = nullptr; - } + delete notifier; + notifier = nullptr; - if (readStarted) { - readCompletionOverlapped->dptr = nullptr; - ::CancelIoEx(handle, readCompletionOverlapped); - // The object will be deleted in the I/O callback. - readCompletionOverlapped = nullptr; - readStarted = false; - } else { - delete readCompletionOverlapped; - readCompletionOverlapped = nullptr; - }; - - if (writeStarted) { - writeCompletionOverlapped->dptr = nullptr; - ::CancelIoEx(handle, writeCompletionOverlapped); - // The object will be deleted in the I/O callback. - writeCompletionOverlapped = nullptr; - writeStarted = false; - } else { - delete writeCompletionOverlapped; - writeCompletionOverlapped = nullptr; - } + delete startAsyncWriteTimer; + startAsyncWriteTimer = nullptr; - readBytesTransferred = 0; - writeBytesTransferred = 0; + communicationStarted = false; + readStarted = false; + writeStarted = false; writeBuffer.clear(); if (settingsRestoredOnClose) { @@ -447,25 +306,30 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs) if (!writeStarted && !_q_startAsyncWrite()) return false; + const qint64 initialReadBufferSize = buffer.size(); + qint64 currentReadBufferSize = initialReadBufferSize; + QDeadlineTimer deadline(msecs); do { - if (readBytesTransferred <= 0) { - const qint64 remaining = deadline.remainingTime(); - const DWORD result = ::SleepEx( - remaining == -1 ? INFINITE : DWORD(remaining), - TRUE); - if (result != WAIT_IO_COMPLETION) - continue; - } + const OVERLAPPED *overlapped = waitForNotified(deadline); + if (!overlapped) + return false; - if (readBytesTransferred > 0) { - readBytesTransferred = 0; - return true; + if (overlapped == &readCompletionOverlapped) { + const qint64 readBytesForOneReadOperation = qint64(buffer.size()) - currentReadBufferSize; + if (readBytesForOneReadOperation == QSERIALPORT_BUFFERSIZE) { + currentReadBufferSize = buffer.size(); + } else if (readBytesForOneReadOperation == 0) { + if (initialReadBufferSize != currentReadBufferSize) + return true; + } else { + return true; + } } + } while (!deadline.hasExpired()); - setError(getSystemError(WAIT_TIMEOUT)); return false; } @@ -479,23 +343,15 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs) QDeadlineTimer deadline(msecs); - do { - if (writeBytesTransferred <= 0) { - const qint64 remaining = deadline.remainingTime(); - const DWORD result = ::SleepEx( - remaining == -1 ? INFINITE : DWORD(remaining), - TRUE); - if (result != WAIT_IO_COMPLETION) - continue; - } + for (;;) { + const OVERLAPPED *overlapped = waitForNotified(deadline); + if (!overlapped) + return false; - if (writeBytesTransferred > 0) { - writeBytesTransferred = 0; + if (overlapped == &writeCompletionOverlapped) return true; - } - } while (!deadline.hasExpired()); + } - setError(getSystemError(WAIT_TIMEOUT)); return false; } @@ -576,10 +432,6 @@ bool QSerialPortPrivate::completeAsyncCommunication(qint64 bytesTransferred) bool QSerialPortPrivate::completeAsyncRead(qint64 bytesTransferred) { - // Store the number of transferred bytes which are - // required only in waitForReadyRead() method. - readBytesTransferred = bytesTransferred; - if (bytesTransferred == qint64(-1)) { readStarted = false; return false; @@ -607,10 +459,6 @@ bool QSerialPortPrivate::completeAsyncWrite(qint64 bytesTransferred) { Q_Q(QSerialPort); - // Store the number of transferred bytes which are - // required only in waitForBytesWritten() method. - writeBytesTransferred = bytesTransferred; - if (writeStarted) { if (bytesTransferred == qint64(-1)) { writeChunkBuffer.clear(); @@ -631,16 +479,8 @@ bool QSerialPortPrivate::startAsyncCommunication() if (communicationStarted) return true; - if (!communicationCompletionOverlapped) - communicationCompletionOverlapped = new Overlapped(this); - - communicationCompletionOverlapped->clear(); - communicationStarted = true; - if (!::qt_wait_comm_event_ex(handle, - &triggeredEventMask, - communicationCompletionOverlapped, - ioCompletionRoutine)) { - communicationStarted = false; + ::ZeroMemory(&communicationOverlapped, sizeof(communicationOverlapped)); + if (!::WaitCommEvent(handle, &triggeredEventMask, &communicationOverlapped)) { QSerialPortErrorInfo error = getSystemError(); if (error.errorCode != QSerialPort::NoError) { if (error.errorCode == QSerialPort::PermissionError) @@ -649,6 +489,7 @@ bool QSerialPortPrivate::startAsyncCommunication() return false; } } + communicationStarted = true; return true; } @@ -670,27 +511,23 @@ bool QSerialPortPrivate::startAsyncRead() Q_ASSERT(int(bytesToRead) <= readChunkBuffer.size()); - if (!readCompletionOverlapped) - readCompletionOverlapped = new Overlapped(this); + ::ZeroMemory(&readCompletionOverlapped, sizeof(readCompletionOverlapped)); + if (::ReadFile(handle, readChunkBuffer.data(), bytesToRead, nullptr, &readCompletionOverlapped)) { + readStarted = true; + return true; + } - readCompletionOverlapped->clear(); - readStarted = true; - if (!::ReadFileEx(handle, - readChunkBuffer.data(), - bytesToRead, - readCompletionOverlapped, - ioCompletionRoutine)) { - readStarted = false; - QSerialPortErrorInfo error = getSystemError(); - if (error.errorCode != QSerialPort::NoError) { - if (error.errorCode == QSerialPort::PermissionError) - error.errorCode = QSerialPort::ResourceError; - if (error.errorCode != QSerialPort::ResourceError) - error.errorCode = QSerialPort::ReadError; - setError(error); - return false; - } + QSerialPortErrorInfo error = getSystemError(); + if (error.errorCode != QSerialPort::NoError) { + if (error.errorCode == QSerialPort::PermissionError) + error.errorCode = QSerialPort::ResourceError; + if (error.errorCode != QSerialPort::ResourceError) + error.errorCode = QSerialPort::ReadError; + setError(error); + return false; } + + readStarted = true; return true; } @@ -700,18 +537,10 @@ bool QSerialPortPrivate::_q_startAsyncWrite() return true; writeChunkBuffer = writeBuffer.read(); + ::ZeroMemory(&writeCompletionOverlapped, sizeof(writeCompletionOverlapped)); + if (!::WriteFile(handle, writeChunkBuffer.constData(), + writeChunkBuffer.size(), nullptr, &writeCompletionOverlapped)) { - if (!writeCompletionOverlapped) - writeCompletionOverlapped = new Overlapped(this); - - writeCompletionOverlapped->clear(); - writeStarted = true; - if (!::WriteFileEx(handle, - writeChunkBuffer.constData(), - writeChunkBuffer.size(), - writeCompletionOverlapped, - ioCompletionRoutine)) { - writeStarted = false; QSerialPortErrorInfo error = getSystemError(); if (error.errorCode != QSerialPort::NoError) { if (error.errorCode != QSerialPort::ResourceError) @@ -720,29 +549,25 @@ bool QSerialPortPrivate::_q_startAsyncWrite() return false; } } + + writeStarted = true; return true; } -void QSerialPortPrivate::handleNotification(DWORD bytesTransferred, DWORD errorCode, - OVERLAPPED *overlapped) +void QSerialPortPrivate::_q_notified(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped) { - // This occurred e.g. after calling the CloseHandle() function, - // just skip handling at all. - if (handle == INVALID_HANDLE_VALUE) - return; - const QSerialPortErrorInfo error = getSystemError(errorCode); if (error.errorCode != QSerialPort::NoError) { setError(error); return; } - if (overlapped == communicationCompletionOverlapped) - completeAsyncCommunication(bytesTransferred); - else if (overlapped == readCompletionOverlapped) - completeAsyncRead(bytesTransferred); - else if (overlapped == writeCompletionOverlapped) - completeAsyncWrite(bytesTransferred); + if (overlapped == &communicationOverlapped) + completeAsyncCommunication(numberOfBytes); + else if (overlapped == &readCompletionOverlapped) + completeAsyncRead(numberOfBytes); + else if (overlapped == &writeCompletionOverlapped) + completeAsyncWrite(numberOfBytes); else Q_ASSERT(!"Unknown OVERLAPPED activated"); } @@ -772,6 +597,16 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize) return maxSize; } +OVERLAPPED *QSerialPortPrivate::waitForNotified(QDeadlineTimer deadline) +{ + OVERLAPPED *overlapped = notifier->waitForAnyNotified(deadline); + if (!overlapped) { + setError(getSystemError(WAIT_TIMEOUT)); + return nullptr; + } + return overlapped; +} + qint64 QSerialPortPrivate::queuedBytesCount(QSerialPort::Direction direction) const { COMSTAT comstat; @@ -784,6 +619,8 @@ qint64 QSerialPortPrivate::queuedBytesCount(QSerialPort::Direction direction) co inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode) { + Q_Q(QSerialPort); + DCB dcb; if (!getDcb(&dcb)) return false; @@ -819,8 +656,17 @@ inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode) return false; } - if ((eventMask & EV_RXCHAR) && !startAsyncCommunication()) + notifier = new QWinOverlappedIoNotifier(q); + QObjectPrivate::connect(notifier, &QWinOverlappedIoNotifier::notified, + this, &QSerialPortPrivate::_q_notified); + notifier->setHandle(handle); + notifier->setEnabled(true); + + if ((eventMask & EV_RXCHAR) && !startAsyncCommunication()) { + delete notifier; + notifier = nullptr; return false; + } return true; } @@ -920,17 +766,4 @@ QSerialPort::Handle QSerialPort::handle() const return d->handle; } -void QSerialPortPrivate::ioCompletionRoutine( - DWORD errorCode, DWORD bytesTransfered, - OVERLAPPED *overlappedBase) -{ - const auto overlapped = static_cast<Overlapped *>(overlappedBase); - if (overlapped->dptr) { - overlapped->dptr->handleNotification(bytesTransfered, errorCode, - overlappedBase); - } else { - delete overlapped; - } -} - QT_END_NAMESPACE diff --git a/src/serialport/qserialportglobal.h b/src/serialport/qserialportglobal.h index f6c5803..8bfd299 100644 --- a/src/serialport/qserialportglobal.h +++ b/src/serialport/qserialportglobal.h @@ -1,61 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSERIALPORTGLOBAL_H #define QSERIALPORTGLOBAL_H #include <QtCore/qstring.h> #include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -#ifndef QT_STATIC -# if defined(QT_BUILD_SERIALPORT_LIB) -# define Q_SERIALPORT_EXPORT Q_DECL_EXPORT -# else -# define Q_SERIALPORT_EXPORT Q_DECL_IMPORT -# endif -#else -# define Q_SERIALPORT_EXPORT -#endif - -QT_END_NAMESPACE +#include <QtSerialPort/qtserialportexports.h> #endif // QSERIALPORTGLOBAL_H diff --git a/src/serialport/qserialportinfo.cpp b/src/serialport/qserialportinfo.cpp index 3bfa56c..be58f69 100644 --- a/src/serialport/qserialportinfo.cpp +++ b/src/serialport/qserialportinfo.cpp @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qserialportinfo.h" #include "qserialportinfo_p.h" @@ -46,6 +10,12 @@ QT_BEGIN_NAMESPACE +// We changed from QScopedPointer to std::unique_ptr, make sure it's +// binary compatible. The QScopedPointer had a non-default deleter, but +// the deleter just provides a static function to use for deletion so we don't +// include it in this template definition (the deleter-class was deleted). +static_assert(sizeof(std::unique_ptr<QSerialPortInfoPrivate>) + == sizeof(QScopedPointer<QSerialPortInfoPrivate>)); /*! \class QSerialPortInfo @@ -56,12 +26,20 @@ QT_BEGIN_NAMESPACE \inmodule QtSerialPort \since 5.1 - Use the static functions to generate a list of QSerialPortInfo - objects. Each QSerialPortInfo object in the list represents a single - serial port and can be queried for the port name, system location, - description, and manufacturer. The QSerialPortInfo class can also be - used as an input parameter for the setPort() method of the QSerialPort - class. + Use the static \l availablePorts() function to generate a list of + QSerialPortInfo objects. Each QSerialPortInfo object in the list represents + a single serial port and can be queried for the \l {portName}{port name}, + \l {systemLocation}{system location}, \l description, \l manufacturer, and + some other hardware parameters. The QSerialPortInfo class can also be + used as an input parameter for the \l {QSerialPort::}{setPort()} method of + the QSerialPort class. + + \section1 Example Usage + + The example code enumerates all available serial ports and prints their + parameters to console: + + \snippet doc_src_serialport.cpp enumerate_ports \sa QSerialPort */ @@ -255,33 +233,7 @@ bool QSerialPortInfo::hasProductIdentifier() const Returns whether this QSerialPortInfo object holds a serial port definition. - - \sa isBusy() -*/ - -#if QT_DEPRECATED_SINCE(5, 6) -/*! - \fn bool QSerialPortInfo::isBusy() const - \obsolete - - Returns \c true if serial port is busy; - otherwise returns \c false. - - \sa isNull() -*/ -#endif // QT_DEPRECATED_SINCE(5, 6) - -#if QT_DEPRECATED_SINCE(5, 2) -/*! - \fn bool QSerialPortInfo::isValid() const - \obsolete - - Returns \c true if serial port is present on system; - otherwise returns \c false. - - \sa isNull(), isBusy() */ -#endif // QT_DEPRECATED_SINCE(5, 2) /*! \fn QList<qint32> QSerialPortInfo::standardBaudRates() diff --git a/src/serialport/qserialportinfo.h b/src/serialport/qserialportinfo.h index e4c9288..d6c1e66 100644 --- a/src/serialport/qserialportinfo.h +++ b/src/serialport/qserialportinfo.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSERIALPORTINFO_H #define QSERIALPORTINFO_H @@ -50,7 +14,6 @@ QT_BEGIN_NAMESPACE class QSerialPort; class QSerialPortInfoPrivate; -class QSerialPortInfoPrivateDeleter; class Q_SERIALPORT_EXPORT QSerialPortInfo { @@ -78,12 +41,6 @@ public: bool hasProductIdentifier() const; bool isNull() const; -#if QT_DEPRECATED_SINCE(5, 6) - bool isBusy() const; -#endif -#if QT_DEPRECATED_SINCE(5, 2) - QT_DEPRECATED bool isValid() const; -#endif static QList<qint32> standardBaudRates(); static QList<QSerialPortInfo> availablePorts(); @@ -93,7 +50,7 @@ private: friend QList<QSerialPortInfo> availablePortsByUdev(bool &ok); friend QList<QSerialPortInfo> availablePortsBySysfs(bool &ok); friend QList<QSerialPortInfo> availablePortsByFiltersOfDevices(bool &ok); - QScopedPointer<QSerialPortInfoPrivate, QSerialPortInfoPrivateDeleter> d_ptr; + std::unique_ptr<QSerialPortInfoPrivate> d_ptr; }; inline bool QSerialPortInfo::isNull() const diff --git a/src/serialport/qserialportinfo_freebsd.cpp b/src/serialport/qserialportinfo_freebsd.cpp index f6d6ea6..5852cd7 100644 --- a/src/serialport/qserialportinfo_freebsd.cpp +++ b/src/serialport/qserialportinfo_freebsd.cpp @@ -1,48 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qserialportinfo.h" #include "qserialportinfo_p.h" #include "qserialport_p.h" #include <QtCore/qdatastream.h> -#include <QtCore/qvector.h> +#include <QtCore/qlist.h> #include <QtCore/qdir.h> #include <errno.h> @@ -109,23 +73,23 @@ struct NodeInfo QString value; }; -static QVector<int> mibFromName(const QString &name) +static QList<int> mibFromName(const QString &name) { size_t mibsize = 0; if (::sysctlnametomib(name.toLocal8Bit().constData(), nullptr, &mibsize) < 0 || mibsize == 0) { - return QVector<int>(); + return QList<int>(); } - QVector<int> mib(mibsize); + QList<int> mib(mibsize); if (::sysctlnametomib(name.toLocal8Bit().constData(), &mib[0], &mibsize) < 0) - return QVector<int>(); + return QList<int>(); return mib; } -static QVector<int> nextOid(const QVector<int> &previousOid) +static QList<int> nextOid(const QList<int> &previousOid) { - QVector<int> mib; + QList<int> mib; mib.append(0); // Magic undocumented code (CTL_UNSPEC ?) mib.append(2); // Magic undocumented code for (int code : previousOid) @@ -133,21 +97,21 @@ static QVector<int> nextOid(const QVector<int> &previousOid) size_t requiredLength = 0; if (::sysctl(&mib[0], mib.count(), nullptr, &requiredLength, nullptr, 0) < 0) - return QVector<int>(); + return QList<int>(); const size_t oidLength = requiredLength / sizeof(int); - QVector<int> oid(oidLength, 0); + QList<int> oid(oidLength, 0); if (::sysctl(&mib[0], mib.count(), &oid[0], &requiredLength, nullptr, 0) < 0) - return QVector<int>(); + return QList<int>(); if (previousOid.first() != oid.first()) - return QVector<int>(); + return QList<int>(); return oid; } -static NodeInfo nodeForOid(const QVector<int> &oid) +static NodeInfo nodeForOid(const QList<int> &oid) { - QVector<int> mib; + QList<int> mib; mib.append(0); // Magic undocumented code (CTL_UNSPEC ?) mib.append(1); // Magic undocumented code for (int code : oid) @@ -195,14 +159,14 @@ static NodeInfo nodeForOid(const QVector<int> &oid) return result; } -static QList<NodeInfo> enumerateDesiredNodes(const QVector<int> &mib) +static QList<NodeInfo> enumerateDesiredNodes(const QList<int> &mib) { QList<NodeInfo> nodes; - QVector<int> oid = mib; + QList<int> oid = mib; for (;;) { - const QVector<int> nextoid = nextOid(oid); + const QList<int> nextoid = nextOid(oid); if (nextoid.isEmpty()) break; @@ -222,7 +186,7 @@ static QList<NodeInfo> enumerateDesiredNodes(const QVector<int> &mib) QList<QSerialPortInfo> QSerialPortInfo::availablePorts() { - const QVector<int> mib = mibFromName(QLatin1String("dev")); + const QList<int> mib = mibFromName(QLatin1String("dev")); if (mib.isEmpty()) return QList<QSerialPortInfo>(); @@ -320,10 +284,10 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() QList<QSerialPortInfo> serialPortInfoList; - for (const QSerialPortInfo &cuaCandidate : qAsConst(cuaCandidates)) { + for (const QSerialPortInfo &cuaCandidate : std::as_const(cuaCandidates)) { const QString cuaPortName = cuaCandidate.portName(); const QString cuaToken = deviceProperty(cuaPortName, "cua"); - for (const QSerialPortInfo &ttyCandidate : qAsConst(ttyCandidates)) { + for (const QSerialPortInfo &ttyCandidate : std::as_const(ttyCandidates)) { const QString ttyPortName = ttyCandidate.portName(); const QString ttyToken = deviceProperty(ttyPortName, "tty"); if (cuaToken != ttyToken) @@ -337,37 +301,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() return serialPortInfoList; } -bool QSerialPortInfo::isBusy() const -{ - QString lockFilePath = serialPortLockFilePath(portName()); - if (lockFilePath.isEmpty()) - return false; - - QFile reader(lockFilePath); - if (!reader.open(QIODevice::ReadOnly)) - return false; - - QByteArray pidLine = reader.readLine(); - pidLine.chop(1); - if (pidLine.isEmpty()) - return false; - - qint64 pid = pidLine.toLongLong(); - - if (pid && (::kill(pid, 0) == -1) && (errno == ESRCH)) - return false; // PID doesn't exist anymore - - return true; -} - -#if QT_DEPRECATED_SINCE(5, 2) -bool QSerialPortInfo::isValid() const -{ - QFile f(systemLocation()); - return f.exists(); -} -#endif // QT_DEPRECATED_SINCE(5, 2) - QString QSerialPortInfoPrivate::portNameToSystemLocation(const QString &source) { return (source.startsWith(QLatin1Char('/')) diff --git a/src/serialport/qserialportinfo_osx.cpp b/src/serialport/qserialportinfo_osx.cpp index 2e46397..203b084 100644 --- a/src/serialport/qserialportinfo_osx.cpp +++ b/src/serialport/qserialportinfo_osx.cpp @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qserialportinfo.h" #include "qserialportinfo_p.h" @@ -230,39 +194,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() return serialPortInfoList; } -#if QT_DEPRECATED_SINCE(5, 6) -bool QSerialPortInfo::isBusy() const -{ - QString lockFilePath = serialPortLockFilePath(portName()); - if (lockFilePath.isEmpty()) - return false; - - QFile reader(lockFilePath); - if (!reader.open(QIODevice::ReadOnly)) - return false; - - QByteArray pidLine = reader.readLine(); - pidLine.chop(1); - if (pidLine.isEmpty()) - return false; - - qint64 pid = pidLine.toLongLong(); - - if (pid && (::kill(pid, 0) == -1) && (errno == ESRCH)) - return false; // PID doesn't exist anymore - - return true; -} -#endif // QT_DEPRECATED_SINCE(5, 6) - -#if QT_DEPRECATED_SINCE(5, 2) -bool QSerialPortInfo::isValid() const -{ - QFile f(systemLocation()); - return f.exists(); -} -#endif // QT_DEPRECATED_SINCE(5, 2) - QString QSerialPortInfoPrivate::portNameToSystemLocation(const QString &source) { return (source.startsWith(QLatin1Char('/')) diff --git a/src/serialport/qserialportinfo_p.h b/src/serialport/qserialportinfo_p.h index 405cc41..1a949f0 100644 --- a/src/serialport/qserialportinfo_p.h +++ b/src/serialport/qserialportinfo_p.h @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2017 Sergey Belyashov <Sergey.Belyashov@gmail.com> +// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSERIALPORTINFO_P_H #define QSERIALPORTINFO_P_H @@ -54,6 +18,7 @@ // #include <QtCore/qstring.h> +#include <QtCore/private/qglobal_p.h> QT_BEGIN_NAMESPACE @@ -76,14 +41,6 @@ public: bool hasProductIdentifier = false; }; -class QSerialPortInfoPrivateDeleter -{ -public: - static void cleanup(QSerialPortInfoPrivate *p) { - delete p; - } -}; - QT_END_NAMESPACE #endif // QSERIALPORTINFO_P_H diff --git a/src/serialport/qserialportinfo_unix.cpp b/src/serialport/qserialportinfo_unix.cpp index 105d10a..4f9304b 100644 --- a/src/serialport/qserialportinfo_unix.cpp +++ b/src/serialport/qserialportinfo_unix.cpp @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qserialportinfo.h" #include "qserialportinfo_p.h" @@ -46,10 +10,11 @@ #include <QtCore/qlockfile.h> #include <QtCore/qfile.h> #include <QtCore/qdir.h> -#include <QtCore/qscopedpointer.h> #include <private/qcore_unix_p.h> +#include <memory> + #include <errno.h> #include <sys/types.h> // kill #include <signal.h> // kill @@ -151,13 +116,13 @@ static bool isValidSerial8250(const QString &systemLocation) return false; } -static bool isRfcommDevice(const QString &portName) +static bool isRfcommDevice(QStringView portName) { if (!portName.startsWith(QLatin1String("rfcomm"))) return false; bool ok; - const int portNumber = portName.midRef(6).toInt(&ok); + const int portNumber = portName.mid(6).toInt(&ok); if (!ok || (portNumber < 0) || (portNumber > 255)) return false; return true; @@ -313,29 +278,22 @@ QList<QSerialPortInfo> availablePortsBySysfs(bool &ok) return serialPortInfoList; } -struct ScopedPointerUdevDeleter -{ - static inline void cleanup(struct ::udev *pointer) +struct udev_deleter { + void operator()(struct ::udev *pointer) const { ::udev_unref(pointer); } -}; - -struct ScopedPointerUdevEnumeratorDeleter -{ - static inline void cleanup(struct ::udev_enumerate *pointer) + void operator()(struct ::udev_enumerate *pointer) const { ::udev_enumerate_unref(pointer); } -}; - -struct ScopedPointerUdevDeviceDeleter -{ - static inline void cleanup(struct ::udev_device *pointer) + void operator()(struct ::udev_device *pointer) const { ::udev_device_unref(pointer); } }; +template <typename T> +using udev_ptr = std::unique_ptr<T, udev_deleter>; #ifndef LINK_LIBUDEV Q_GLOBAL_STATIC(QLibrary, udevLibrary) @@ -396,21 +354,20 @@ QList<QSerialPortInfo> availablePortsByUdev(bool &ok) return QList<QSerialPortInfo>(); #endif - QScopedPointer<struct ::udev, ScopedPointerUdevDeleter> udev(::udev_new()); + const udev_ptr<struct ::udev> udev(::udev_new()); if (!udev) return QList<QSerialPortInfo>(); - QScopedPointer<udev_enumerate, ScopedPointerUdevEnumeratorDeleter> - enumerate(::udev_enumerate_new(udev.data())); + const udev_ptr<udev_enumerate> enumerate(::udev_enumerate_new(udev.get())); if (!enumerate) return QList<QSerialPortInfo>(); - ::udev_enumerate_add_match_subsystem(enumerate.data(), "tty"); - ::udev_enumerate_scan_devices(enumerate.data()); + ::udev_enumerate_add_match_subsystem(enumerate.get(), "tty"); + ::udev_enumerate_scan_devices(enumerate.get()); - udev_list_entry *devices = ::udev_enumerate_get_list_entry(enumerate.data()); + udev_list_entry *devices = ::udev_enumerate_get_list_entry(enumerate.get()); QList<QSerialPortInfo> serialPortInfoList; udev_list_entry *dev_list_entry; @@ -418,29 +375,29 @@ QList<QSerialPortInfo> availablePortsByUdev(bool &ok) ok = true; - QScopedPointer<udev_device, ScopedPointerUdevDeviceDeleter> + const udev_ptr<udev_device> dev(::udev_device_new_from_syspath( - udev.data(), ::udev_list_entry_get_name(dev_list_entry))); + udev.get(), ::udev_list_entry_get_name(dev_list_entry))); if (!dev) return serialPortInfoList; QSerialPortInfoPrivate priv; - priv.device = deviceLocation(dev.data()); - priv.portName = deviceName(dev.data()); + priv.device = deviceLocation(dev.get()); + priv.portName = deviceName(dev.get()); - udev_device *parentdev = ::udev_device_get_parent(dev.data()); + udev_device *parentdev = ::udev_device_get_parent(dev.get()); if (parentdev) { const QString driverName = deviceDriver(parentdev); if (isSerial8250Driver(driverName) && !isValidSerial8250(priv.device)) continue; - priv.description = deviceDescription(dev.data()); - priv.manufacturer = deviceManufacturer(dev.data()); - priv.serialNumber = deviceSerialNumber(dev.data()); - priv.vendorIdentifier = deviceVendorIdentifier(dev.data(), priv.hasVendorIdentifier); - priv.productIdentifier = deviceProductIdentifier(dev.data(), priv.hasProductIdentifier); + priv.description = deviceDescription(dev.get()); + priv.manufacturer = deviceManufacturer(dev.get()); + priv.serialNumber = deviceSerialNumber(dev.get()); + priv.vendorIdentifier = deviceVendorIdentifier(dev.get(), priv.hasVendorIdentifier); + priv.productIdentifier = deviceProductIdentifier(dev.get(), priv.hasProductIdentifier); } else { if (!isRfcommDevice(priv.portName) && !isVirtualNullModemDevice(priv.portName) @@ -472,39 +429,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() return serialPortInfoList; } -#if QT_DEPRECATED_SINCE(5, 6) -bool QSerialPortInfo::isBusy() const -{ - QString lockFilePath = serialPortLockFilePath(portName()); - if (lockFilePath.isEmpty()) - return false; - - QFile reader(lockFilePath); - if (!reader.open(QIODevice::ReadOnly)) - return false; - - QByteArray pidLine = reader.readLine(); - pidLine.chop(1); - if (pidLine.isEmpty()) - return false; - - qint64 pid = pidLine.toLongLong(); - - if (pid && (::kill(pid, 0) == -1) && (errno == ESRCH)) - return false; // PID doesn't exist anymore - - return true; -} -#endif // QT_DEPRECATED_SINCE(5, 6) - -#if QT_DEPRECATED_SINCE(5, 2) -bool QSerialPortInfo::isValid() const -{ - QFile f(systemLocation()); - return f.exists(); -} -#endif // QT_DEPRECATED_SINCE(5, 2) - QString QSerialPortInfoPrivate::portNameToSystemLocation(const QString &source) { return (source.startsWith(QLatin1Char('/')) diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index 1bab3e9..30159f1 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> -** Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> -** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> +// Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com> +// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qserialportinfo.h" #include "qserialportinfo_p.h" @@ -347,38 +311,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() return serialPortInfoList; } -#if QT_DEPRECATED_SINCE(5, 6) -bool QSerialPortInfo::isBusy() const -{ - const HANDLE handle = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation().utf16()), - GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); - - if (handle == INVALID_HANDLE_VALUE) { - if (::GetLastError() == ERROR_ACCESS_DENIED) - return true; - } else { - ::CloseHandle(handle); - } - return false; -} -#endif // QT_DEPRECATED_SINCE(5, 6) - -#if QT_DEPRECATED_SINCE(5, 2) -bool QSerialPortInfo::isValid() const -{ - const HANDLE handle = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation().utf16()), - GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); - - if (handle == INVALID_HANDLE_VALUE) { - if (::GetLastError() != ERROR_ACCESS_DENIED) - return false; - } else { - ::CloseHandle(handle); - } - return true; -} -#endif // QT_DEPRECATED_SINCE(5, 2) - QString QSerialPortInfoPrivate::portNameToSystemLocation(const QString &source) { return source.startsWith(QLatin1String("COM")) diff --git a/src/serialport/qt_cmdline.cmake b/src/serialport/qt_cmdline.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/serialport/qt_cmdline.cmake diff --git a/src/serialport/qtntdll_p.h b/src/serialport/qtntdll_p.h deleted file mode 100644 index 2e57201..0000000 --- a/src/serialport/qtntdll_p.h +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTNTDLL_P_H -#define QTNTDLL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qlibrary.h> -#include <QtCore/qstring.h> -#include <QtCore/qdebug.h> - -#include <qt_windows.h> - -// Internal control codes. - -#ifndef CTL_CODE -# define CTL_CODE(DeviceType, Function, Method, Access) ( \ - ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ - ) -#endif - -#ifndef FILE_DEVICE_SERIAL_PORT -# define FILE_DEVICE_SERIAL_PORT 27 -#endif - -#ifndef METHOD_BUFFERED -# define METHOD_BUFFERED 0 -#endif - -#ifndef FILE_ANY_ACCESS -# define FILE_ANY_ACCESS 0x00000000 -#endif - -#ifndef IOCTL_SERIAL_GET_DTRRTS -# define IOCTL_SERIAL_GET_DTRRTS \ - CTL_CODE(FILE_DEVICE_SERIAL_PORT, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) -#endif - -#ifndef SERIAL_DTR_STATE -# define SERIAL_DTR_STATE 0x00000001 -#endif - -#ifndef SERIAL_RTS_STATE -# define SERIAL_RTS_STATE 0x00000002 -#endif - -#ifndef IOCTL_SERIAL_WAIT_ON_MASK -# define IOCTL_SERIAL_WAIT_ON_MASK \ - CTL_CODE(FILE_DEVICE_SERIAL_PORT, 18, METHOD_BUFFERED, FILE_ANY_ACCESS) -#endif - -// Internal NT-based data types. - -#ifndef NT_SUCCESS -#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) -#endif - -typedef struct _IO_STATUS_BLOCK { - union { - NTSTATUS Status; - PVOID Pointer; - } DUMMYUNIONNAME; - - ULONG_PTR Information; -} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; - -typedef VOID (WINAPI *PIO_APC_ROUTINE) ( - PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG Reserved - ); - -// Resolving macros. - -#define GENERATE_SYMBOL_VARIABLE(returnType, symbolName, ...) \ - typedef returnType (WINAPI *fp_##symbolName)(__VA_ARGS__); \ - static fp_##symbolName symbolName; - -#define RESOLVE_SYMBOL(symbolName) \ - symbolName = reinterpret_cast<fp_##symbolName>(resolveNtdllSymbol(ntLibrary, #symbolName)); \ - if (!symbolName) \ - return false; - -GENERATE_SYMBOL_VARIABLE(ULONG, RtlNtStatusToDosError, NTSTATUS) -GENERATE_SYMBOL_VARIABLE(NTSTATUS, NtDeviceIoControlFile, HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, ULONG, PVOID, ULONG, PVOID, ULONG) - -inline QFunctionPointer resolveNtdllSymbol(QLibrary *ntLibrary, const char *symbolName) -{ - QFunctionPointer symbolFunctionPointer = ntLibrary->resolve(symbolName); - if (!symbolFunctionPointer) - qWarning("Failed to resolve the symbol: %s", symbolName); - - return symbolFunctionPointer; -} - -inline bool resolveNtdllSymbols(QLibrary *ntLibrary) -{ - if (!ntLibrary->isLoaded()) { - ntLibrary->setFileName(QStringLiteral("ntdll")); - if (!ntLibrary->load()) { - qWarning("Failed to load the library: %s", qPrintable(ntLibrary->fileName())); - return false; - } - } - - RESOLVE_SYMBOL(RtlNtStatusToDosError) - RESOLVE_SYMBOL(NtDeviceIoControlFile) - - return true; -} - -#endif // QTNTDLL_P_H diff --git a/src/serialport/qtudev_p.h b/src/serialport/qtudev_p.h index af2dab2..311fa75 100644 --- a/src/serialport/qtudev_p.h +++ b/src/serialport/qtudev_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTUDEV_P_H #define QTUDEV_P_H @@ -60,6 +24,7 @@ extern "C" #include <QtCore/qlibrary.h> #include <QtCore/qstring.h> #include <QtCore/qdebug.h> +#include <QtCore/private/qglobal_p.h> #define GENERATE_SYMBOL_VARIABLE(returnType, symbolName, ...) \ typedef returnType (*fp_##symbolName)(__VA_ARGS__); \ diff --git a/src/serialport/qwinoverlappedionotifier.cpp b/src/serialport/qwinoverlappedionotifier.cpp index f29bae0..3e85fd8 100644 --- a/src/serialport/qwinoverlappedionotifier.cpp +++ b/src/serialport/qwinoverlappedionotifier.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qwinoverlappedionotifier_p.h" #include <qdebug.h> @@ -129,6 +93,7 @@ public: HANDLE hSemaphore = nullptr; HANDLE hResultsMutex = nullptr; QAtomicInt waiting; + QAtomicInt signalSent; QQueue<IOResult> results; }; @@ -200,7 +165,7 @@ public: using QThread::isRunning; protected: - void run() + void run() override { DWORD dwBytesRead = 0; ULONG_PTR pulCompletionKey = 0; @@ -313,13 +278,13 @@ OVERLAPPED *QWinOverlappedIoNotifierPrivate::waitForAnyNotified(QDeadlineTimer d return 0; } - DWORD msecs = deadline.remainingTime(); + qint64 msecs = deadline.remainingTime(); if (msecs == 0) iocp->drainQueue(); if (msecs == -1) msecs = INFINITE; - const DWORD wfso = WaitForSingleObject(hSemaphore, msecs); + const DWORD wfso = WaitForSingleObject(hSemaphore, DWORD(msecs)); switch (wfso) { case WAIT_OBJECT_0: return dispatchNextIoResult(); @@ -395,16 +360,45 @@ void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCod Q_Q(QWinOverlappedIoNotifier); WaitForSingleObject(hResultsMutex, INFINITE); results.enqueue(IOResult(numberOfBytes, errorCode, overlapped)); - ReleaseMutex(hResultsMutex); ReleaseSemaphore(hSemaphore, 1, NULL); - if (!waiting) + ReleaseMutex(hResultsMutex); + // Do not send a signal if we didn't process the previous one. + // This is done to prevent soft memory leaks when working in a completely + // synchronous way. + if (!waiting && !signalSent.loadAcquire()) { + signalSent.storeRelease(1); emit q->_q_notify(); + } } void QWinOverlappedIoNotifierPrivate::_q_notified() { - if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) - dispatchNextIoResult(); + Q_Q(QWinOverlappedIoNotifier); + signalSent.storeRelease(0); // signal processed - ready for a new one + if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) { + // As we do not queue signals anymore, we need to process the whole + // queue at once. + WaitForSingleObject(hResultsMutex, INFINITE); + QQueue<IOResult> values; + results.swap(values); + // Decreasing the semaphore count to keep it in sync with the number + // of messages in queue. As ReleaseSemaphore does not accept negative + // values, this is sort of a recommended way to go: + // https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasesemaphore#remarks + int numToDecrease = values.size() - 1; + while (numToDecrease > 0) { + WaitForSingleObject(hSemaphore, 0); + --numToDecrease; + } + ReleaseMutex(hResultsMutex); + // 'q' can go out of scope if the user decides to close the serial port + // while processing some answer. So we need to guard against that. + QPointer<QWinOverlappedIoNotifier> qptr(q); + while (!values.empty() && qptr) { + IOResult ioresult = values.dequeue(); + emit qptr->notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped); + } + } } OVERLAPPED *QWinOverlappedIoNotifierPrivate::dispatchNextIoResult() diff --git a/src/serialport/qwinoverlappedionotifier_p.h b/src/serialport/qwinoverlappedionotifier_p.h new file mode 100644 index 0000000..45d252e --- /dev/null +++ b/src/serialport/qwinoverlappedionotifier_p.h @@ -0,0 +1,55 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QWINOVERLAPPEDIONOTIFIER_P_H +#define QWINOVERLAPPEDIONOTIFIER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/private/qglobal_p.h> +#include <qobject.h> +#include <qdeadlinetimer.h> + +typedef struct _OVERLAPPED OVERLAPPED; + +QT_BEGIN_NAMESPACE + +class QWinOverlappedIoNotifierPrivate; + +class QWinOverlappedIoNotifier : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(QWinOverlappedIoNotifier) + Q_DECLARE_PRIVATE(QWinOverlappedIoNotifier) + Q_PRIVATE_SLOT(d_func(), void _q_notified()) + friend class QWinIoCompletionPort; +public: + QWinOverlappedIoNotifier(QObject *parent = 0); + ~QWinOverlappedIoNotifier(); + + void setHandle(Qt::HANDLE h); + Qt::HANDLE handle() const; + + void setEnabled(bool enabled); + OVERLAPPED *waitForAnyNotified(QDeadlineTimer deadline); + bool waitForNotified(QDeadlineTimer deadline, OVERLAPPED *overlapped); + +Q_SIGNALS: + void notified(quint32 numberOfBytes, quint32 errorCode, OVERLAPPED *overlapped); +#if !defined(Q_QDOC) + void _q_notify(); +#endif +}; + +QT_END_NAMESPACE + +#endif // QWINOVERLAPPEDIONOTIFIER_P_H diff --git a/src/serialport/serialport-lib.pri b/src/serialport/serialport-lib.pri deleted file mode 100644 index b9b3c83..0000000 --- a/src/serialport/serialport-lib.pri +++ /dev/null @@ -1,51 +0,0 @@ -INCLUDEPATH += $$PWD - -unix:qtConfig(libudev) { - DEFINES += LINK_LIBUDEV - INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV - LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV -} - -PUBLIC_HEADERS += \ - $$PWD/qserialportglobal.h \ - $$PWD/qserialport.h \ - $$PWD/qserialportinfo.h - -PRIVATE_HEADERS += \ - $$PWD/qserialport_p.h \ - $$PWD/qserialportinfo_p.h - -SOURCES += \ - $$PWD/qserialport.cpp \ - $$PWD/qserialportinfo.cpp - -win32 { - SOURCES += \ - $$PWD/qserialport_win.cpp \ - $$PWD/qserialportinfo_win.cpp \ - - PRIVATE_HEADERS += \ - $$PWD/qtntdll_p.h - - LIBS_PRIVATE += -lsetupapi -ladvapi32 -} - -unix { - SOURCES += \ - $$PWD/qserialport_unix.cpp - - osx { - SOURCES += \ - $$PWD/qserialportinfo_osx.cpp - - LIBS_PRIVATE += -framework IOKit -framework CoreFoundation - } else:freebsd { - SOURCES += \ - $$PWD/qserialportinfo_freebsd.cpp - } else { - SOURCES += \ - $$PWD/qserialportinfo_unix.cpp - } -} - -HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS diff --git a/src/serialport/serialport.pro b/src/serialport/serialport.pro deleted file mode 100644 index 194958a..0000000 --- a/src/serialport/serialport.pro +++ /dev/null @@ -1,12 +0,0 @@ -TARGET = QtSerialPort -QT = core-private - -QMAKE_DOCS = $$PWD/doc/qtserialport.qdocconf - -config_ntddmodm: DEFINES += QT_NO_REDEFINE_GUID_DEVINTERFACE_MODEM - -include($$PWD/serialport-lib.pri) - -load(qt_module) - -PRECOMPILED_HEADER = diff --git a/src/src.pro b/src/src.pro deleted file mode 100644 index 1426d64..0000000 --- a/src/src.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS = serialport |