summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarsten Heimrich <karsten.heimrich@qt.io>2021-06-21 16:00:07 +0200
committerKarsten Heimrich <karsten.heimrich@qt.io>2021-10-19 10:14:24 +0200
commit4ff9993d9f2e991f2da1885a694d4f3a61c9af73 (patch)
tree8d78943470ac8e93913c118bb6dbeac716b0f303
parent2b90577da89a3b63714b6f560646db9724515f56 (diff)
downloadqtserialport-4ff9993d9f2e991f2da1885a694d4f3a61c9af73.tar.gz
Revert "QSerialPort: Port to alertable I/O functions on Windows"
This reverts commit a0faf986fccdce1d36f3308dc520cdac001f5264. Part of chain revert to go back to QWinOverlappedIoNotifier. Fixes: QTBUG-93865 Change-Id: Id4b6516282f35ccb3e81f20893872b4d1bcd3e05 Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
-rw-r--r--src/serialport/CMakeLists.txt3
-rw-r--r--src/serialport/qserialport.h1
-rw-r--r--src/serialport/qserialport_p.h18
-rw-r--r--src/serialport/qserialport_win.cpp361
-rw-r--r--src/serialport/qtntdll_p.h158
-rw-r--r--src/serialport/qwinoverlappedionotifier_p.h91
6 files changed, 216 insertions, 416 deletions
diff --git a/src/serialport/CMakeLists.txt b/src/serialport/CMakeLists.txt
index 25558ea..8c7863a 100644
--- a/src/serialport/CMakeLists.txt
+++ b/src/serialport/CMakeLists.txt
@@ -38,7 +38,8 @@ qt_internal_extend_target(SerialPort CONDITION WIN32
SOURCES
qserialport_win.cpp
qserialportinfo_win.cpp
- qtntdll_p.h
+ qwinoverlappedionotifier.cpp
+ qwinoverlappedionotifier_p.h
LIBRARIES
advapi32
setupapi
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h
index 8ef0f6b..0170c28 100644
--- a/src/serialport/qserialport.h
+++ b/src/serialport/qserialport.h
@@ -244,6 +244,7 @@ private:
#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 a9c08e9..a24ed0b 100644
--- a/src/serialport/qserialport_p.h
+++ b/src/serialport/qserialport_p.h
@@ -106,6 +106,7 @@ struct serial_struct {
QT_BEGIN_NAMESPACE
+class QWinOverlappedIoNotifier;
class QTimer;
class QSocketNotifier;
@@ -209,6 +210,7 @@ public:
bool setDcb(DCB *dcb);
bool getDcb(DCB *dcb);
+ OVERLAPPED *waitForNotified(QDeadlineTimer deadline);
qint64 queuedBytesCount(QSerialPort::Direction direction) const;
@@ -218,15 +220,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;
@@ -236,12 +233,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)
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 387c4f0..ad3a113 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include "qserialport_p.h"
-#include "qtntdll_p.h"
+#include "qwinoverlappedionotifier_p.h"
#include <QtCore/qcoreevent.h>
#include <QtCore/qelapsedtimer.h>
@@ -49,6 +49,37 @@
#include <QtCore/qtimer.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 +174,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 = resolveSymbols(&helper()->ntLibrary);
- if (!symbolsResolved) {
- setError(QSerialPortErrorInfo(QSerialPort::OpenError,
- helper()->ntLibrary.errorString()));
- return false;
- }
- }
-
DWORD desiredAccess = 0;
if (mode & QIODevice::ReadOnly)
@@ -278,44 +200,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 +342,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 +379,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 +468,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 +495,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 +515,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 +525,7 @@ bool QSerialPortPrivate::startAsyncCommunication()
return false;
}
}
+ communicationStarted = true;
return true;
}
@@ -670,27 +547,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 +573,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 +585,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 +633,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 +655,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 +692,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 +802,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/qtntdll_p.h b/src/serialport/qtntdll_p.h
deleted file mode 100644
index a8cdaf6..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>(resolveSymbol(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 resolveSymbol(QLibrary *ntLibrary, const char *symbolName)
-{
- QFunctionPointer symbolFunctionPointer = ntLibrary->resolve(symbolName);
- if (!symbolFunctionPointer)
- qWarning("Failed to resolve the symbol: %s", symbolName);
-
- return symbolFunctionPointer;
-}
-
-inline bool resolveSymbols(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/qwinoverlappedionotifier_p.h b/src/serialport/qwinoverlappedionotifier_p.h
new file mode 100644
index 0000000..9ee998b
--- /dev/null
+++ b/src/serialport/qwinoverlappedionotifier_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#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