summaryrefslogtreecommitdiff
path: root/src/serialport
diff options
context:
space:
mode:
Diffstat (limited to 'src/serialport')
-rw-r--r--src/serialport/qserialport.cpp81
-rw-r--r--src/serialport/qserialport.h23
-rw-r--r--src/serialport/qserialport_symbian.cpp26
-rw-r--r--src/serialport/qserialport_symbian_p.h3
-rw-r--r--src/serialport/qserialport_unix.cpp51
-rw-r--r--src/serialport/qserialport_unix_p.h3
-rw-r--r--src/serialport/qserialport_win.cpp480
-rw-r--r--src/serialport/qserialport_win_p.h29
-rw-r--r--src/serialport/qserialport_wince.cpp29
-rw-r--r--src/serialport/qserialportglobal.h4
-rw-r--r--src/serialport/qserialportinfo.cpp1
-rw-r--r--src/serialport/qserialportinfo.h7
-rw-r--r--src/serialport/qserialportinfo_mac.cpp3
-rw-r--r--src/serialport/qserialportinfo_symbian.cpp21
-rw-r--r--src/serialport/qserialportinfo_unix.cpp150
-rw-r--r--src/serialport/qserialportinfo_win.cpp57
-rw-r--r--src/serialport/qserialportinfo_wince.cpp3
-rw-r--r--src/serialport/qtudev_p.h2
-rw-r--r--src/serialport/serialport-lib.pri2
19 files changed, 408 insertions, 567 deletions
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp
index 7c332cc..5d9442e 100644
--- a/src/serialport/qserialport.cpp
+++ b/src/serialport/qserialport.cpp
@@ -70,10 +70,10 @@ QSerialPortPrivateData::QSerialPortPrivateData(QSerialPort *q)
, error(QSerialPort::NoError)
, inputBaudRate(0)
, outputBaudRate(0)
- , dataBits(QSerialPort::UnknownDataBits)
- , parity(QSerialPort::UnknownParity)
- , stopBits(QSerialPort::UnknownStopBits)
- , flow(QSerialPort::UnknownFlowControl)
+ , dataBits(QSerialPort::Data8)
+ , parity(QSerialPort::NoParity)
+ , stopBits(QSerialPort::OneStop)
+ , flow(QSerialPort::NoFlowControl)
, policy(QSerialPort::IgnorePolicy)
, settingsRestoredOnClose(true)
, q_ptr(q)
@@ -198,7 +198,9 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
\value Baud38400 38400 baud.
\value Baud57600 57600 baud.
\value Baud115200 115200 baud.
- \value UnknownBaud Unknown 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
*/
@@ -208,11 +210,21 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
This enum describes the number of data bits used.
- \value Data5 Five bits.
- \value Data6 Six bits.
- \value Data7 Seven bits
- \value Data8 Eight bits.
- \value UnknownDataBits Unknown number of bits.
+ \value Data5 The number of data bits in each character is 5. It
+ is used for Baudot code. It generally only makes
+ sense with older equipments such as teleprinters.
+ \value Data6 The number of data bits in each character is 6. It
+ is rarely used.
+ \value Data7 The number of data bits in each character is 7. It
+ is used for true ASCII. It generally only makes
+ sense with older equipments such as teleprinters.
+ \value Data8 The number of data bits in each character is 8. It
+ is used for most kinds of data, as this size matches
+ the size of a byte. It is almost universally used in
+ 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
*/
@@ -222,12 +234,23 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
This enum describes the parity scheme used.
- \value NoParity No parity.
- \value EvenParity Even parity.
- \value OddParity Odd parity.
- \value SpaceParity Space parity.
- \value MarkParity Mark parity.
- \value UnknownParity Unknown parity.
+ \value NoParity No parity bit it sent. This is the most common
+ parity setting. Error detection is handled by the
+ communication protocol.
+ \value EvenParity The number of 1 bits in each character, including
+ the parity bit, is always even.
+ \value OddParity The number of 1 bits in each character, including
+ the parity bit, is always odd. It ensures that at
+ least one state transition occurs in each character.
+ \value SpaceParity Space parity. The parity bit is sent in the space
+ signal condition. It does not provide error
+ detection information.
+ \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
*/
@@ -238,9 +261,11 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
This enum describes the number of stop bits used.
\value OneStop 1 stop bit.
- \value OneAndHalfStop 1.5 stop bits.
+ \value OneAndHalfStop 1.5 stop bits. This is only for Windows platform.
\value TwoStop 2 stop bits.
- \value UnknownStopBits Unknown number of stop bit.
+ \value UnknownStopBits Unknown number of stop bit. 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
*/
@@ -253,7 +278,9 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
\value NoFlowControl No flow control.
\value HardwareControl Hardware flow control (RTS/CTS).
\value SoftwareControl Software flow control (XON/XOFF).
- \value UnknownFlowControl Unknown flow control.
+ \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
*/
@@ -274,7 +301,6 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
\value ClearToSendSignal CTS (Clear To Send).
\value SecondaryTransmittedDataSignal STD (Secondary Transmitted Data).
\value SecondaryReceivedDataSignal SRD (Secondary Received Data).
- \value UnknownSignal Unknown line state. This value was introduced in QtSerialPort 5.2.
\sa pinoutSignals(), QSerialPort::dataTerminalReady,
QSerialPort::requestToSend
@@ -621,7 +647,7 @@ qint32 QSerialPort::baudRate(Directions directions) const
Q_D(const QSerialPort);
if (directions == QSerialPort::AllDirections)
return d->inputBaudRate == d->outputBaudRate ?
- d->inputBaudRate : QSerialPort::UnknownBaud;
+ d->inputBaudRate : -1;
return directions & QSerialPort::Input ? d->inputBaudRate : d->outputBaudRate;
}
@@ -953,8 +979,7 @@ bool QSerialPort::isRequestToSend()
operating systems cannot provide proper notifications about the changes.
\note The serial port has to be open before trying to get the pinout
- signals; otherwise returns UnknownSignal and sets the NotOpenError error
- code.
+ signals; otherwise returns NoSignal and sets the NotOpenError error code.
\sa isDataTerminalReady(), isRequestToSend, setDataTerminalReady(),
setRequestToSend()
@@ -966,7 +991,7 @@ QSerialPort::PinoutSignals QSerialPort::pinoutSignals()
if (!isOpen()) {
setError(QSerialPort::NotOpenError);
qWarning("%s: device not open", Q_FUNC_INFO);
- return QSerialPort::UnknownSignal;
+ return QSerialPort::NoSignal;
}
return d->pinoutSignals();
@@ -1053,7 +1078,7 @@ bool QSerialPort::clear(Directions directions)
bool QSerialPort::atEnd() const
{
Q_D(const QSerialPort);
- return QIODevice::atEnd() && (!isOpen() || (d->bytesAvailable() == 0));
+ return QIODevice::atEnd() && (!isOpen() || (d->readBuffer.size() == 0));
}
/*!
@@ -1201,7 +1226,7 @@ bool QSerialPort::isSequential() const
qint64 QSerialPort::bytesAvailable() const
{
Q_D(const QSerialPort);
- return d->bytesAvailable() + QIODevice::bytesAvailable();
+ return d->readBuffer.size() + QIODevice::bytesAvailable();
}
/*!
@@ -1230,7 +1255,7 @@ qint64 QSerialPort::bytesToWrite() const
bool QSerialPort::canReadLine() const
{
Q_D(const QSerialPort);
- const bool hasLine = (d->bytesAvailable() > 0) && d->readBuffer.canReadLine();
+ const bool hasLine = (d->readBuffer.size() > 0) && d->readBuffer.canReadLine();
return hasLine || QIODevice::canReadLine();
}
@@ -1333,7 +1358,7 @@ bool QSerialPort::setBreakEnabled(bool set)
qint64 QSerialPort::readData(char *data, qint64 maxSize)
{
Q_D(QSerialPort);
- return d->readFromBuffer(data, maxSize);
+ return d->readBuffer.read(data, maxSize);
}
/*!
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h
index ada19fb..c07af91 100644
--- a/src/serialport/qserialport.h
+++ b/src/serialport/qserialport.h
@@ -47,10 +47,6 @@
#include <QtSerialPort/qserialportglobal.h>
-#ifndef QT_DEPRECATED_SINCE
-#define QT_DEPRECATED_SINCE(major, minor) 1
-#endif
-
QT_BEGIN_NAMESPACE
class QSerialPortInfo;
@@ -135,6 +131,16 @@ public:
UnknownFlowControl = -1
};
+#if QT_DEPRECATED_SINCE(5, 2)
+#if defined _MSC_VER
+#pragma deprecated(UnknownBaud)
+#pragma deprecated(UnknownDataBits)
+#pragma deprecated(UnknownParity)
+#pragma deprecated(UnknownStopBits)
+#pragma deprecated(UnknownFlowControl)
+#endif
+#endif
+
enum PinoutSignal {
NoSignal = 0x00,
TransmittedDataSignal = 0x01,
@@ -146,8 +152,7 @@ public:
RequestToSendSignal = 0x40,
ClearToSendSignal = 0x80,
SecondaryTransmittedDataSignal = 0x100,
- SecondaryReceivedDataSignal = 0x200,
- UnknownSignal = -1
+ SecondaryReceivedDataSignal = 0x200
};
Q_DECLARE_FLAGS(PinoutSignals, PinoutSignal)
@@ -269,6 +274,12 @@ private:
QSerialPortPrivate * const d_ptr;
Q_DISABLE_COPY(QSerialPort)
+
+#if defined (Q_OS_WIN32) || defined(Q_OS_WIN64)
+ Q_PRIVATE_SLOT(d_func(), void _q_canCompleteCommunication())
+ Q_PRIVATE_SLOT(d_func(), void _q_canCompleteRead())
+ Q_PRIVATE_SLOT(d_func(), void _q_canCompleteWrite())
+#endif
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QSerialPort::Directions)
diff --git a/src/serialport/qserialport_symbian.cpp b/src/serialport/qserialport_symbian.cpp
index d905db1..6047793 100644
--- a/src/serialport/qserialport_symbian.cpp
+++ b/src/serialport/qserialport_symbian.cpp
@@ -248,17 +248,6 @@ qint64 QSerialPortPrivate::systemOutputQueueSize () const
return 0;
}
-qint64 QSerialPortPrivate::bytesAvailable() const
-{
- return readBuffer.size();
-}
-
-qint64 QSerialPortPrivate::readFromBuffer(char *data, qint64 maxSize)
-{
- // TODO: Implement me
- return -1;
-}
-
qint64 QSerialPortPrivate::writeToBuffer(const char *data, qint64 maxSize)
{
// TODO: Implement me
@@ -433,7 +422,8 @@ void QSerialPortPrivate::detectDefaultSettings()
dataBits = QSerialPort::Data8;
break;
default:
- dataBits = QSerialPort::UnknownDataBits;
+ qWarning("%s: Unexpected data bits settings", Q_FUNC_INFO);
+ dataBits = QSerialPort::Data8;
break;
}
@@ -455,7 +445,8 @@ void QSerialPortPrivate::detectDefaultSettings()
parity = QSerialPort::SpaceParity;
break;
default:
- parity = QSerialPort::UnknownParity;
+ qWarning("%s: Unexpected parity settings", Q_FUNC_INFO);
+ parity = QSerialPort::NoParity;
break;
}
@@ -468,7 +459,8 @@ void QSerialPortPrivate::detectDefaultSettings()
stopBits = QSerialPort::TwoStop;
break;
default:
- stopBits = QSerialPort::UnknownStopBits;
+ qWarning("%s: Unexpected stop bits settings", Q_FUNC_INFO);
+ stopBits = QSerialPort::OneStop;
break;
}
@@ -481,8 +473,10 @@ void QSerialPortPrivate::detectDefaultSettings()
flow = QSerialPort::HardwareControl;
else if (currentSettings().iHandshake & KConfigFailDSR)
flow = QSerialPort::NoFlowControl;
- else
- flow = QSerialPort::UnknownFlowControl;
+ else {
+ qWarning("%s: Unexpected flow control settings", Q_FUNC_INFO);
+ flow = QSerialPort::NoFlowControl;
+ }
}
QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
diff --git a/src/serialport/qserialport_symbian_p.h b/src/serialport/qserialport_symbian_p.h
index c56ddae..253aa11 100644
--- a/src/serialport/qserialport_symbian_p.h
+++ b/src/serialport/qserialport_symbian_p.h
@@ -72,9 +72,6 @@ public:
qint64 systemInputQueueSize () const;
qint64 systemOutputQueueSize () const;
- qint64 bytesAvailable() const;
-
- qint64 readFromBuffer(char *data, qint64 maxSize);
qint64 writeToBuffer(const char *data, qint64 maxSize);
bool waitForReadyRead(int msec);
diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp
index 8b3d94b..51bb01e 100644
--- a/src/serialport/qserialport_unix.cpp
+++ b/src/serialport/qserialport_unix.cpp
@@ -305,7 +305,7 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals()
if (::ioctl(descriptor, TIOCMGET, &arg) == -1) {
q->setError(decodeSystemError());
- return QSerialPort::UnknownSignal;
+ return QSerialPort::NoSignal;
}
QSerialPort::PinoutSignals ret = QSerialPort::NoSignal;
@@ -414,46 +414,6 @@ qint64 QSerialPortPrivate::systemOutputQueueSize () const
return nbytes;
}
-qint64 QSerialPortPrivate::bytesAvailable() const
-{
- return readBuffer.size();
-}
-
-qint64 QSerialPortPrivate::readFromBuffer(char *data, qint64 maxSize)
-{
- if (readBuffer.isEmpty())
- return 0;
-
- if (maxSize == 1) {
- *data = readBuffer.getChar();
- if (readBuffer.isEmpty())
- setReadNotificationEnabled(true);
- return 1;
- }
-
- const qint64 bytesToRead = qMin(qint64(readBuffer.size()), maxSize);
- qint64 readSoFar = 0;
- while (readSoFar < bytesToRead) {
- const char *ptr = readBuffer.readPointer();
- const int bytesToReadFromThisBlock = qMin(int(bytesToRead - readSoFar),
- readBuffer.nextDataBlockSize());
- ::memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
- readSoFar += bytesToReadFromThisBlock;
- readBuffer.free(bytesToReadFromThisBlock);
- }
-
- if (!isReadNotificationEnabled())
- setReadNotificationEnabled(true);
-
- if (readSoFar > 0) {
- if (readBuffer.isEmpty())
- setReadNotificationEnabled(true);
- return readSoFar;
- }
-
- return readSoFar;
-}
-
qint64 QSerialPortPrivate::writeToBuffer(const char *data, qint64 maxSize)
{
char *ptr = writeBuffer.reserve(maxSize);
@@ -921,7 +881,8 @@ void QSerialPortPrivate::detectDefaultSettings()
dataBits = QSerialPort::Data8;
break;
default:
- dataBits = QSerialPort::UnknownDataBits;
+ qWarning("%s: Unexpected data bits settings", Q_FUNC_INFO);
+ dataBits = QSerialPort::Data8;
break;
}
@@ -953,8 +914,10 @@ void QSerialPortPrivate::detectDefaultSettings()
flow = QSerialPort::SoftwareControl;
else if ((currentTermios.c_cflag & CRTSCTS) && (!(currentTermios.c_iflag & (IXON | IXOFF | IXANY))))
flow = QSerialPort::HardwareControl;
- else
- flow = QSerialPort::UnknownFlowControl;
+ else {
+ qWarning("%s: Unexpected flow control settings", Q_FUNC_INFO);
+ flow = QSerialPort::NoFlowControl;
+ }
}
QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
diff --git a/src/serialport/qserialport_unix_p.h b/src/serialport/qserialport_unix_p.h
index 15bb5f8..7c2b771 100644
--- a/src/serialport/qserialport_unix_p.h
+++ b/src/serialport/qserialport_unix_p.h
@@ -111,9 +111,6 @@ public:
qint64 systemInputQueueSize () const;
qint64 systemOutputQueueSize () const;
- qint64 bytesAvailable() const;
-
- qint64 readFromBuffer(char *data, qint64 maxSize);
qint64 writeToBuffer(const char *data, qint64 maxSize);
bool waitForReadyRead(int msecs);
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 80cba34..506dc94 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -88,167 +88,55 @@ QT_BEGIN_NAMESPACE
#ifndef Q_OS_WINCE
-class AbstractOverlappedEventNotifier : public QWinEventNotifier
+static void initializeOverlappedStructure(OVERLAPPED &overlapped)
{
- Q_OBJECT
-public:
- enum Type { CommEvent, ReadCompletionEvent, WriteCompletionEvent };
-
- AbstractOverlappedEventNotifier(QSerialPortPrivate *d, Type type, bool manual, QObject *parent)
- : QWinEventNotifier(parent), dptr(d), t(type) {
- ::ZeroMemory(&o, sizeof(o));
- o.hEvent = ::CreateEvent(NULL, manual, FALSE, NULL);
- if (!o.hEvent) {
- dptr->setError(dptr->decodeSystemError());
- } else {
- setHandle(o.hEvent);
- dptr->notifiers[o.hEvent] = this;
- }
- }
-
- virtual bool processCompletionRoutine() = 0;
-
- virtual ~AbstractOverlappedEventNotifier() {
- setEnabled(false);
- if (!::CloseHandle(o.hEvent))
- dptr->setError(dptr->decodeSystemError());
- }
-
- Type type() const { return t; }
- OVERLAPPED *overlappedPointer() { return &o; }
-
-protected:
- bool event(QEvent *e) Q_DECL_OVERRIDE {
- const bool ret = QWinEventNotifier::event(e);
- if (e->type() == QEvent::WinEventAct)
- processCompletionRoutine();
- return ret;
- }
-
- QSerialPortPrivate *dptr;
- Type t;
- OVERLAPPED o;
-};
-
-class CommOverlappedEventNotifier : public AbstractOverlappedEventNotifier
-{
- Q_OBJECT
-public:
- CommOverlappedEventNotifier(QSerialPortPrivate *d, DWORD eventMask, QObject *parent)
- : AbstractOverlappedEventNotifier(d, CommEvent, false, parent)
- , originalEventMask(eventMask), triggeredEventMask(0) {
- if (!::SetCommMask(dptr->descriptor, originalEventMask))
- dptr->setError(dptr->decodeSystemError());
- else
- startWaitCommEvent();
- }
-
- void startWaitCommEvent() {
- if (!::WaitCommEvent(dptr->descriptor, &triggeredEventMask, &o)) {
- const QSerialPort::SerialPortError error = dptr->decodeSystemError();
- if (error != QSerialPort::NoError) {
- dptr->setError(dptr->decodeSystemError());
- return;
- }
- }
- }
-
- bool processCompletionRoutine() Q_DECL_OVERRIDE {
- DWORD numberOfBytesTransferred = 0;
-
- if (!::GetOverlappedResult(dptr->descriptor, &o, &numberOfBytesTransferred, FALSE))
- dptr->setError(dptr->decodeSystemError());
-
- bool error = false;
-
- // Check for unexpected event. This event triggered when pulled previously
- // opened device from the system, when opened as for not to read and not to
- // write options and so forth.
- if (triggeredEventMask == 0)
- error = true;
-
- // Workaround for standard CDC ACM serial ports, for which triggered an
- // unexpected event EV_TXEMPTY at data transmission.
- if ((originalEventMask & triggeredEventMask) == 0) {
- if ((triggeredEventMask & EV_TXEMPTY) == 0)
- error = true;
- }
-
- // Start processing a caught error.
- if (error || (EV_ERR & triggeredEventMask))
- dptr->processIoErrors(error);
-
- if (!error)
- dptr->startAsyncRead();
-
- return !error;
- }
-
-private:
- DWORD originalEventMask;
- DWORD triggeredEventMask;
-};
-
-class ReadOverlappedCompletionNotifier : public AbstractOverlappedEventNotifier
-{
- Q_OBJECT
-public:
- ReadOverlappedCompletionNotifier(QSerialPortPrivate *d, QObject *parent)
- : AbstractOverlappedEventNotifier(d, ReadCompletionEvent, false, parent) {}
-
- bool processCompletionRoutine() Q_DECL_OVERRIDE {
- DWORD numberOfBytesTransferred = 0;
- if (!::GetOverlappedResult(dptr->descriptor, &o, &numberOfBytesTransferred, FALSE))
- dptr->setError(dptr->decodeSystemError());
-
- dptr->completeAsyncRead(numberOfBytesTransferred);
-
- // start async read for possible remainder into driver queue
- if ((numberOfBytesTransferred > 0) && (dptr->policy == QSerialPort::IgnorePolicy)) {
- dptr->startAsyncRead();
- } else { // driver queue is emplty, so startup wait comm event
- CommOverlappedEventNotifier *n =
- qobject_cast<CommOverlappedEventNotifier *>(dptr->lookupCommEventNotifier());
- if (n)
- n->startWaitCommEvent();
- }
-
- return true;
- }
-};
-
-class WriteOverlappedCompletionNotifier : public AbstractOverlappedEventNotifier
-{
- Q_OBJECT
-public:
- WriteOverlappedCompletionNotifier(QSerialPortPrivate *d, QObject *parent)
- : AbstractOverlappedEventNotifier(d, WriteCompletionEvent, false, parent) {}
-
- bool processCompletionRoutine() Q_DECL_OVERRIDE {
- setEnabled(false);
- DWORD numberOfBytesTransferred = 0;
- if (!::GetOverlappedResult(dptr->descriptor, &o, &numberOfBytesTransferred, FALSE)) {
- numberOfBytesTransferred = 0;
- dptr->setError(dptr->decodeSystemError());
- }
-
- dptr->completeAsyncWrite(numberOfBytesTransferred);
- return true;
- }
-};
-
-#include "qserialport_win.moc"
+ overlapped.Internal = 0;
+ overlapped.InternalHigh = 0;
+ overlapped.Offset = 0;
+ overlapped.OffsetHigh = 0;
+}
QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
: QSerialPortPrivateData(q)
, descriptor(INVALID_HANDLE_VALUE)
, parityErrorOccurred(false)
- , actualReadBufferSize(0)
+ , readChunkBuffer(ReadChunkSize, 0)
, actualWriteBufferSize(0)
, acyncWritePosition(0)
, readyReadEmitted(0)
, writeSequenceStarted(false)
+ , communicationNotifier(new QWinEventNotifier(q))
+ , readCompletionNotifier(new QWinEventNotifier(q))
+ , writeCompletionNotifier(new QWinEventNotifier(q))
+ , originalEventMask(0)
+ , triggeredEventMask(0)
{
+ ::ZeroMemory(&communicationOverlapped, sizeof(communicationOverlapped));
+ communicationOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!communicationOverlapped.hEvent)
+ q->setError(decodeSystemError());
+ else {
+ communicationNotifier->setHandle(communicationOverlapped.hEvent);
+ q->connect(communicationNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_canCompleteCommunication()));
+ }
+
+ ::ZeroMemory(&readCompletionOverlapped, sizeof(readCompletionOverlapped));
+ readCompletionOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!readCompletionOverlapped.hEvent)
+ q->setError(decodeSystemError());
+ else {
+ readCompletionNotifier->setHandle(readCompletionOverlapped.hEvent);
+ q->connect(readCompletionNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_canCompleteRead()));
+ }
+
+ ::ZeroMemory(&writeCompletionOverlapped, sizeof(writeCompletionOverlapped));
+ writeCompletionOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!writeCompletionOverlapped.hEvent)
+ q->setError(decodeSystemError());
+ else {
+ writeCompletionNotifier->setHandle(writeCompletionOverlapped.hEvent);
+ q->connect(writeCompletionNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_canCompleteWrite()));
+ }
}
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
@@ -256,7 +144,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
Q_Q(QSerialPort);
DWORD desiredAccess = 0;
- DWORD originalEventMask = EV_ERR;
+ originalEventMask = EV_ERR;
if (mode & QIODevice::ReadOnly) {
desiredAccess |= GENERIC_READ;
@@ -300,13 +188,27 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
if (!updateCommTimeouts())
return false;
- if (originalEventMask & EV_RXCHAR) {
- QWinEventNotifier *n = new ReadOverlappedCompletionNotifier(this, q);
- n->setEnabled(true);
+ if (mode & QIODevice::ReadOnly)
+ readCompletionNotifier->setEnabled(true);
+
+ if (mode & QIODevice::WriteOnly)
+ writeCompletionNotifier->setEnabled(true);
+
+ if (!::SetCommMask(descriptor, originalEventMask)) {
+ q->setError(decodeSystemError());
+ return false;
+ }
+
+ initializeOverlappedStructure(communicationOverlapped);
+ if (!::WaitCommEvent(descriptor, &triggeredEventMask, &communicationOverlapped)) {
+ const QSerialPort::SerialPortError error = decodeSystemError();
+ if (error != QSerialPort::NoError) {
+ q->setError(decodeSystemError());
+ return false;
+ }
}
- QWinEventNotifier *n = new CommOverlappedEventNotifier(this, originalEventMask, q);
- n->setEnabled(true);
+ communicationNotifier->setEnabled(true);
detectDefaultSettings();
return true;
@@ -319,11 +221,11 @@ void QSerialPortPrivate::close()
if (!::CancelIo(descriptor))
q->setError(decodeSystemError());
- qDeleteAll(notifiers);
- notifiers.clear();
+ readCompletionNotifier->setEnabled(false);
+ writeCompletionNotifier->setEnabled(false);
+ communicationNotifier->setEnabled(false);
readBuffer.clear();
- actualReadBufferSize = 0;
writeSequenceStarted = false;
writeBuffer.clear();
@@ -356,7 +258,7 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals()
if (!::GetCommModemStatus(descriptor, &modemStat)) {
q->setError(decodeSystemError());
- return QSerialPort::UnknownSignal;
+ return QSerialPort::NoSignal;
}
QSerialPort::PinoutSignals ret = QSerialPort::NoSignal;
@@ -405,10 +307,8 @@ bool QSerialPortPrivate::flush()
bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
{
DWORD flags = 0;
- if (directions & QSerialPort::Input) {
+ if (directions & QSerialPort::Input)
flags |= PURGE_RXABORT | PURGE_RXCLEAR;
- actualReadBufferSize = 0;
- }
if (directions & QSerialPort::Output) {
flags |= PURGE_TXABORT | PURGE_TXCLEAR;
actualWriteBufferSize = 0;
@@ -466,38 +366,6 @@ qint64 QSerialPortPrivate::systemOutputQueueSize ()
#ifndef Q_OS_WINCE
-qint64 QSerialPortPrivate::bytesAvailable() const
-{
- return actualReadBufferSize;
-}
-
-qint64 QSerialPortPrivate::readFromBuffer(char *data, qint64 maxSize)
-{
- if (actualReadBufferSize == 0)
- return 0;
-
- qint64 readSoFar = -1;
- if (maxSize == 1 && actualReadBufferSize > 0) {
- *data = readBuffer.getChar();
- actualReadBufferSize--;
- readSoFar = 1;
- } else {
- const qint64 bytesToRead = qMin(qint64(actualReadBufferSize), maxSize);
- readSoFar = 0;
- while (readSoFar < bytesToRead) {
- const char *ptr = readBuffer.readPointer();
- const int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
- qint64(readBuffer.nextDataBlockSize()));
- ::memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
- readSoFar += bytesToReadFromThisBlock;
- readBuffer.free(bytesToReadFromThisBlock);
- actualReadBufferSize -= bytesToReadFromThisBlock;
- }
- }
-
- return readSoFar;
-}
-
qint64 QSerialPortPrivate::writeToBuffer(const char *data, qint64 maxSize)
{
char *ptr = writeBuffer.reserve(maxSize);
@@ -524,28 +392,28 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
do {
bool timedOut = false;
- AbstractOverlappedEventNotifier *n = 0;
+ HANDLE triggeredEvent = 0;
- if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &n) || !n) {
+ if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &triggeredEvent) || !triggeredEvent) {
// This is occur timeout or another error
if (!timedOut)
q->setError(decodeSystemError());
return false;
}
- switch (n->type()) {
- case AbstractOverlappedEventNotifier::CommEvent:
- if (!n->processCompletionRoutine())
+ if (triggeredEvent == communicationOverlapped.hEvent) {
+ _q_canCompleteCommunication();
+ if (error != QSerialPort::NoError)
return false;
- break;
- case AbstractOverlappedEventNotifier::ReadCompletionEvent:
- return n->processCompletionRoutine();
- case AbstractOverlappedEventNotifier::WriteCompletionEvent:
- n->processCompletionRoutine();
- break;
- default: // newer called
+ } else if (triggeredEvent == readCompletionOverlapped.hEvent) {
+ _q_canCompleteRead();
+ return error == QSerialPort::NoError;
+ } else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
+ _q_canCompleteWrite();
+ } else {
return false;
}
+
} while (msecs == -1 || timeoutValue(msecs, stopWatch.elapsed()) > 0);
return false;
@@ -563,25 +431,25 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs)
forever {
bool timedOut = false;
- AbstractOverlappedEventNotifier *n = 0;
+ HANDLE triggeredEvent = 0;
- if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &n) || !n) {
+ if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &triggeredEvent) || !triggeredEvent) {
if (!timedOut)
q->setError(decodeSystemError());
return false;
}
- switch (n->type()) {
- case AbstractOverlappedEventNotifier::CommEvent:
- // do nothing, jump to ReadCompletionEvent case
- case AbstractOverlappedEventNotifier::ReadCompletionEvent:
- n->processCompletionRoutine();
- break;
- case AbstractOverlappedEventNotifier::WriteCompletionEvent:
- return n->processCompletionRoutine();
- default: // newer called
+ if (triggeredEvent == communicationOverlapped.hEvent) {
+ _q_canCompleteRead();
+ } else if (triggeredEvent == readCompletionOverlapped.hEvent) {
+ _q_canCompleteRead();
+ } else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
+ _q_canCompleteWrite();
+ return error == QSerialPort::NoError;
+ } else {
return false;
}
+
}
return false;
@@ -685,6 +553,75 @@ bool QSerialPortPrivate::setDataErrorPolicy(QSerialPort::DataErrorPolicy policy)
#ifndef Q_OS_WINCE
+void QSerialPortPrivate::_q_canCompleteCommunication()
+{
+ Q_Q(QSerialPort);
+
+ DWORD numberOfBytesTransferred = 0;
+
+ if (!::GetOverlappedResult(descriptor, &communicationOverlapped, &numberOfBytesTransferred, FALSE))
+ q->setError(decodeSystemError());
+
+ bool error = false;
+
+ // Check for unexpected event. This event triggered when pulled previously
+ // opened device from the system, when opened as for not to read and not to
+ // write options and so forth.
+ if (triggeredEventMask == 0)
+ error = true;
+
+ // Workaround for standard CDC ACM serial ports, for which triggered an
+ // unexpected event EV_TXEMPTY at data transmission.
+ if ((originalEventMask & triggeredEventMask) == 0) {
+ if ((triggeredEventMask & EV_TXEMPTY) == 0)
+ error = true;
+ }
+
+ // Start processing a caught error.
+ if (error || (EV_ERR & triggeredEventMask))
+ processIoErrors(error);
+
+ if (!error)
+ startAsyncRead();
+}
+
+void QSerialPortPrivate::_q_canCompleteRead()
+{
+ Q_Q(QSerialPort);
+
+ DWORD numberOfBytesTransferred = 0;
+ if (!::GetOverlappedResult(descriptor, &readCompletionOverlapped, &numberOfBytesTransferred, FALSE))
+ q->setError(decodeSystemError());
+
+ completeAsyncRead(numberOfBytesTransferred);
+
+ // start async read for possible remainder into driver queue
+ if ((numberOfBytesTransferred > 0) && (policy == QSerialPort::IgnorePolicy)) {
+ startAsyncRead();
+ } else { // driver queue is emplty, so startup wait comm event
+ initializeOverlappedStructure(communicationOverlapped);
+ if (!::WaitCommEvent(descriptor, &triggeredEventMask, &communicationOverlapped)) {
+ const QSerialPort::SerialPortError error = decodeSystemError();
+ if (error != QSerialPort::NoError) {
+ q->setError(decodeSystemError());
+ }
+ }
+ }
+}
+
+void QSerialPortPrivate::_q_canCompleteWrite()
+{
+ Q_Q(QSerialPort);
+
+ DWORD numberOfBytesTransferred = 0;
+ if (!::GetOverlappedResult(descriptor, &writeCompletionOverlapped, &numberOfBytesTransferred, FALSE)) {
+ numberOfBytesTransferred = 0;
+ q->setError(decodeSystemError());
+ }
+
+ completeAsyncWrite(numberOfBytesTransferred);
+}
+
bool QSerialPortPrivate::startAsyncRead()
{
Q_Q(QSerialPort);
@@ -700,15 +637,8 @@ bool QSerialPortPrivate::startAsyncRead()
}
}
- AbstractOverlappedEventNotifier *n = lookupReadCompletionNotifier();
- if (!n) {
- q->setError(QSerialPort::ResourceError);
- return false;
- }
-
- char *ptr = readBuffer.reserve(bytesToRead);
-
- if (::ReadFile(descriptor, ptr, bytesToRead, NULL, n->overlappedPointer()))
+ initializeOverlappedStructure(readCompletionOverlapped);
+ if (::ReadFile(descriptor, readChunkBuffer.data(), bytesToRead, NULL, &readCompletionOverlapped))
return true;
QSerialPort::SerialPortError error = decodeSystemError();
@@ -717,7 +647,6 @@ bool QSerialPortPrivate::startAsyncRead()
error = QSerialPort::ReadError;
q->setError(error);
- readBuffer.truncate(actualReadBufferSize);
return false;
}
@@ -740,15 +669,8 @@ bool QSerialPortPrivate::startAsyncWrite(int maxSize)
writeSequenceStarted = true;
- AbstractOverlappedEventNotifier *n = lookupFreeWriteCompletionNotifier();
- if (!n) {
- q->setError(QSerialPort::ResourceError);
- return false;
- }
-
- n->setEnabled(true);
-
- if (::WriteFile(descriptor, ptr, nextSize, NULL, n->overlappedPointer()))
+ initializeOverlappedStructure(writeCompletionOverlapped);
+ if (::WriteFile(descriptor, ptr, nextSize, NULL, &writeCompletionOverlapped))
return true;
QSerialPort::SerialPortError error = decodeSystemError();
@@ -800,11 +722,10 @@ void QSerialPortPrivate::completeAsyncRead(DWORD numberOfBytes)
{
Q_Q(QSerialPort);
- actualReadBufferSize += qint64(numberOfBytes);
- readBuffer.truncate(actualReadBufferSize);
-
if (numberOfBytes > 0) {
+ readBuffer.append(readChunkBuffer.left(numberOfBytes));
+
// Process emulate policy.
if ((policy != QSerialPort::IgnorePolicy) && parityErrorOccurred) {
@@ -854,39 +775,6 @@ void QSerialPortPrivate::completeAsyncWrite(DWORD numberOfBytes)
startAsyncWrite(WriteChunkSize);
}
-AbstractOverlappedEventNotifier *QSerialPortPrivate::lookupFreeWriteCompletionNotifier()
-{
- Q_Q(QSerialPort);
-
- // find first free not running write notifier
- foreach (AbstractOverlappedEventNotifier *n, notifiers) {
- if ((n->type() == AbstractOverlappedEventNotifier::WriteCompletionEvent)
- && !n->isEnabled()) {
- return n;
- }
- }
- // if all write notifiers in use, then create new write notifier
- return new WriteOverlappedCompletionNotifier(this, q);
-}
-
-AbstractOverlappedEventNotifier *QSerialPortPrivate::lookupCommEventNotifier()
-{
- foreach (AbstractOverlappedEventNotifier *n, notifiers) {
- if (n->type() == AbstractOverlappedEventNotifier::CommEvent)
- return n;
- }
- return 0;
-}
-
-AbstractOverlappedEventNotifier *QSerialPortPrivate::lookupReadCompletionNotifier()
-{
- foreach (AbstractOverlappedEventNotifier *n, notifiers) {
- if (n->type() == AbstractOverlappedEventNotifier::ReadCompletionEvent)
- return n;
- }
- return 0;
-}
-
bool QSerialPortPrivate::updateDcb()
{
Q_Q(QSerialPort);
@@ -932,7 +820,8 @@ void QSerialPortPrivate::detectDefaultSettings()
dataBits = QSerialPort::Data8;
break;
default:
- dataBits = QSerialPort::UnknownDataBits;
+ qWarning("%s: Unexpected data bits settings", Q_FUNC_INFO);
+ dataBits = QSerialPort::Data8;
break;
}
@@ -947,8 +836,10 @@ void QSerialPortPrivate::detectDefaultSettings()
parity = QSerialPort::EvenParity;
else if ((currentDcb.Parity == ODDPARITY) && currentDcb.fParity)
parity = QSerialPort::OddParity;
- else
- parity = QSerialPort::UnknownParity;
+ else {
+ qWarning("%s: Unexpected parity settings", Q_FUNC_INFO);
+ parity = QSerialPort::NoParity;
+ }
// Detect stopbits.
switch (currentDcb.StopBits) {
@@ -962,7 +853,8 @@ void QSerialPortPrivate::detectDefaultSettings()
stopBits = QSerialPort::TwoStop;
break;
default:
- stopBits = QSerialPort::UnknownStopBits;
+ qWarning("%s: Unexpected stop bits settings", Q_FUNC_INFO);
+ stopBits = QSerialPort::OneStop;
break;
}
@@ -976,8 +868,10 @@ void QSerialPortPrivate::detectDefaultSettings()
} else if (currentDcb.fOutxCtsFlow && (currentDcb.fRtsControl == RTS_CONTROL_HANDSHAKE)
&& !currentDcb.fInX && !currentDcb.fOutX) {
flow = QSerialPort::HardwareControl;
- } else
- flow = QSerialPort::UnknownFlowControl;
+ } else {
+ qWarning("%s: Unexpected flow control settings", Q_FUNC_INFO);
+ flow = QSerialPort::NoFlowControl;
+ }
}
QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
@@ -1017,14 +911,17 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
#ifndef Q_OS_WINCE
-bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut,
- AbstractOverlappedEventNotifier **triggeredNotifier)
+bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut, HANDLE *triggeredEvent)
{
Q_Q(QSerialPort);
Q_ASSERT(timedOut);
- QVector<HANDLE> handles = notifiers.keys().toVector();
+ QVector<HANDLE> handles = QVector<HANDLE>()
+ << communicationOverlapped.hEvent
+ << readCompletionOverlapped.hEvent
+ << writeCompletionOverlapped.hEvent;
+
DWORD waitResult = ::WaitForMultipleObjects(handles.count(),
handles.constData(),
FALSE, // wait any event
@@ -1038,8 +935,7 @@ bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut,
if (waitResult >= DWORD(WAIT_OBJECT_0 + handles.count()))
return false;
- HANDLE h = handles.at(waitResult - WAIT_OBJECT_0);
- *triggeredNotifier = notifiers.value(h);
+ *triggeredEvent = handles.at(waitResult - WAIT_OBJECT_0);
return true;
}
@@ -1155,21 +1051,7 @@ qint32 QSerialPortPrivate::settingFromBaudRate(qint32 baudRate)
QList<qint32> QSerialPortPrivate::standardBaudRates()
{
- QList<qint32> ret;
- const QList<qint32> baudRatePairs = standardBaudRatePairList();
-
- foreach (qint32 baudRatePair, baudRatePairs) {
- ret.append(baudRatePair);
- }
-
- return ret;
-}
-
-void QSerialPortPrivate::setError(QSerialPort::SerialPortError serialPortError, const QString &errorString)
-{
- Q_Q(QSerialPort);
-
- q->setError(serialPortError, errorString);
+ return standardBaudRatePairList();
}
QSerialPort::Handle QSerialPort::handle() const
diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h
index 414f026..059be87 100644
--- a/src/serialport/qserialport_win_p.h
+++ b/src/serialport/qserialport_win_p.h
@@ -57,10 +57,6 @@ QT_BEGIN_NAMESPACE
class QThread;
#endif
-#ifndef Q_OS_WINCE
-class AbstractOverlappedEventNotifier;
-#endif
-
class QSerialPortPrivate : public QSerialPortPrivateData
{
Q_DECLARE_PUBLIC(QSerialPort)
@@ -85,9 +81,6 @@ public:
qint64 systemInputQueueSize ();
qint64 systemOutputQueueSize ();
- qint64 bytesAvailable() const;
-
- qint64 readFromBuffer(char *data, qint64 maxSize);
qint64 writeToBuffer(const char *data, qint64 maxSize);
bool waitForReadyRead(int msec);
@@ -101,16 +94,16 @@ public:
bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy);
void processIoErrors(bool error);
- void setError(QSerialPort::SerialPortError error, const QString &errorString = QString());
QSerialPort::SerialPortError decodeSystemError() const;
#ifndef Q_OS_WINCE
+ void _q_canCompleteCommunication();
+ void _q_canCompleteRead();
+ void _q_canCompleteWrite();
+
bool startAsyncRead();
bool startAsyncWrite(int maxSize = INT_MAX);
void completeAsyncRead(DWORD numberOfBytes);
void completeAsyncWrite(DWORD numberOfBytes);
- AbstractOverlappedEventNotifier *lookupFreeWriteCompletionNotifier();
- AbstractOverlappedEventNotifier *lookupCommEventNotifier();
- AbstractOverlappedEventNotifier *lookupReadCompletionNotifier();
#else
bool notifyRead();
bool notifyWrite(int maxSize = INT_MAX);
@@ -132,12 +125,19 @@ public:
bool parityErrorOccurred;
#ifndef Q_OS_WINCE
- QHash<HANDLE, AbstractOverlappedEventNotifier *> notifiers;
- qint64 actualReadBufferSize;
+ QByteArray readChunkBuffer;
qint64 actualWriteBufferSize;
qint64 acyncWritePosition;
bool readyReadEmitted;
bool writeSequenceStarted;
+ QWinEventNotifier *communicationNotifier;
+ QWinEventNotifier *readCompletionNotifier;
+ QWinEventNotifier *writeCompletionNotifier;
+ OVERLAPPED communicationOverlapped;
+ OVERLAPPED readCompletionOverlapped;
+ OVERLAPPED writeCompletionOverlapped;
+ DWORD originalEventMask;
+ DWORD triggeredEventMask;
#else
QThread *eventNotifier;
QMutex settingsChangeMutex;
@@ -150,8 +150,7 @@ private:
void detectDefaultSettings();
#ifndef Q_OS_WINCE
- bool waitAnyEvent(int msecs, bool *timedOut,
- AbstractOverlappedEventNotifier **triggeredNotifier);
+ bool waitAnyEvent(int msecs, bool *timedOut, HANDLE *triggeredEvent);
#else
bool waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp
index 21bea1e..2983071 100644
--- a/src/serialport/qserialport_wince.cpp
+++ b/src/serialport/qserialport_wince.cpp
@@ -253,35 +253,6 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
return ::PurgeComm(descriptor, flags);
}
-qint64 QSerialPortPrivate::bytesAvailable() const
-{
- return readBuffer.size();
-}
-
-qint64 QSerialPortPrivate::readFromBuffer(char *data, qint64 maxSize)
-{
- if (readBuffer.isEmpty())
- return 0;
-
- if (maxSize == 1) {
- *data = readBuffer.getChar();
- return 1;
- }
-
- const qint64 bytesToRead = qMin(qint64(readBuffer.size()), maxSize);
- qint64 readSoFar = 0;
- while (readSoFar < bytesToRead) {
- const char *ptr = readBuffer.readPointer();
- const int bytesToReadFromThisBlock = qMin(int(bytesToRead - readSoFar),
- readBuffer.nextDataBlockSize());
- ::memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
- readSoFar += bytesToReadFromThisBlock;
- readBuffer.free(bytesToReadFromThisBlock);
- }
-
- return readSoFar;
-}
-
qint64 QSerialPortPrivate::writeToBuffer(const char *data, qint64 maxSize)
{
char *ptr = writeBuffer.reserve(maxSize);
diff --git a/src/serialport/qserialportglobal.h b/src/serialport/qserialportglobal.h
index 09ba0df..d17ce6b 100644
--- a/src/serialport/qserialportglobal.h
+++ b/src/serialport/qserialportglobal.h
@@ -59,6 +59,10 @@ QT_BEGIN_NAMESPACE
#endif
// These macros have been available only since Qt 5.0
+#ifndef QT_DEPRECATED_SINCE
+#define QT_DEPRECATED_SINCE(major, minor) 1
+#endif
+
#ifndef Q_DECL_OVERRIDE
#define Q_DECL_OVERRIDE
#endif
diff --git a/src/serialport/qserialportinfo.cpp b/src/serialport/qserialportinfo.cpp
index 78ef694..5172e60 100644
--- a/src/serialport/qserialportinfo.cpp
+++ b/src/serialport/qserialportinfo.cpp
@@ -258,6 +258,7 @@ bool QSerialPortInfo::hasProductIdentifier() const
/*!
\fn bool QSerialPortInfo::isValid() const
+ \obsolete
Returns true if serial port is present on system;
otherwise returns false.
diff --git a/src/serialport/qserialportinfo.h b/src/serialport/qserialportinfo.h
index 51f3b10..8320fc5 100644
--- a/src/serialport/qserialportinfo.h
+++ b/src/serialport/qserialportinfo.h
@@ -80,12 +80,17 @@ public:
bool isNull() const;
bool isBusy() const;
- bool isValid() const;
+#if QT_DEPRECATED_SINCE(5, 2)
+ QT_DEPRECATED bool isValid() const;
+#endif
static QList<qint32> standardBaudRates();
static QList<QSerialPortInfo> availablePorts();
private:
+ friend QList<QSerialPortInfo> availablePortsByUdev();
+ friend QList<QSerialPortInfo> availablePortsBySysfs();
+ friend QList<QSerialPortInfo> availablePortsByFiltersOfDevices();
QScopedPointer<QSerialPortInfoPrivate, QSerialPortInfoPrivateDeleter> d_ptr;
};
diff --git a/src/serialport/qserialportinfo_mac.cpp b/src/serialport/qserialportinfo_mac.cpp
index af57598..c69a4a3 100644
--- a/src/serialport/qserialportinfo_mac.cpp
+++ b/src/serialport/qserialportinfo_mac.cpp
@@ -97,7 +97,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
io_registry_entry_t entry = service;
- // Find MacOSX-specific properties names.
do {
if (!device) {
@@ -184,7 +183,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
}
- // If all matching properties is found, then force break loop.
if (matchingPropertiesCounter == propertyCount)
break;
@@ -194,7 +192,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
(void) ::IOObjectRelease(entry);
- // Convert from MacOSX-specific properties to Qt4-specific.
if (matchingPropertiesCounter > 0) {
QSerialPortInfo serialPortInfo;
diff --git a/src/serialport/qserialportinfo_symbian.cpp b/src/serialport/qserialportinfo_symbian.cpp
index 5512048..cae00e9 100644
--- a/src/serialport/qserialportinfo_symbian.cpp
+++ b/src/serialport/qserialportinfo_symbian.cpp
@@ -46,7 +46,6 @@
#include "qserialport_symbian_p.h"
#include <e32base.h>
-//#include <e32test.h>
#include <c32comm.h>
#include <f32file.h>
@@ -54,23 +53,19 @@
QT_BEGIN_NAMESPACE
-// Physical device driver.
#ifdef __WINS__
_LIT(KPddName, "ECDRV");
-#else // defined (__EPOC32__)
+#else
_LIT(KPddName, "EUART");
#endif
-// Logical native device driver.
_LIT(KLddName,"ECOMM");
-// Modules names.
_LIT(KRS232ModuleName , "ECUART");
_LIT(KBluetoothModuleName , "BTCOMM");
_LIT(KInfraRedModuleName , "IRCOMM");
_LIT(KACMModuleName, "ECACM");
-// Return false on error load.
static bool loadDevices()
{
TInt r = KErrNone;
@@ -84,16 +79,16 @@ static bool loadDevices()
r = User::LoadPhysicalDevice(KPddName);
if (r != KErrNone && r != KErrAlreadyExists)
- return false; //User::Leave(r);
+ return false;
r = User::LoadLogicalDevice(KLddName);
if (r != KErrNone && r != KErrAlreadyExists)
- return false; //User::Leave(r);
+ return false;
#ifndef __WINS__
r = StartC32();
if (r != KErrNone && r != KErrAlreadyExists)
- return false; //User::Leave(r);
+ return false;
#endif
return true;
@@ -109,14 +104,13 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
RCommServ server;
TInt r = server.Connect();
if (r != KErrNone)
- return serialPortInfoList; //User::LeaveIfError(r);
+ return serialPortInfoList;
- TSerialInfo nativeSerialInfo; // Native Symbian OS port info class.
+ TSerialInfo nativeSerialInfo;
QString s("%1::%2");
// FIXME: Get info about RS232 ports.
r = server.LoadCommModule(KRS232ModuleName);
- //User::LeaveIfError(r);
if (r == KErrNone) {
r = server.GetPortInfo(KRS232ModuleName, nativeSerialInfo);
if (r == KErrNone) {
@@ -138,7 +132,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
// FIXME: Get info about Bluetooth ports.
r = server.LoadCommModule(KBluetoothModuleName);
- //User::LeaveIfError(r);
if (r == KErrNone) {
r = server.GetPortInfo(KBluetoothModuleName, nativeSerialInfo);
if (r == KErrNone) {
@@ -160,7 +153,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
// FIXME: Get info about InfraRed ports.
r = server.LoadCommModule(KInfraRedModuleName);
- //User::LeaveIfError(r);
if (r == KErrNone) {
r = server.GetPortInfo(KInfraRedModuleName, nativeSerialInfo);
if (r == KErrNone) {
@@ -182,7 +174,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
// FIXME: Get info about ACM ports.
r = server.LoadCommModule(KACMModuleName);
- //User::LeaveIfError(r);
if (r == KErrNone) {
r = server.GetPortInfo(KACMModuleName, nativeSerialInfo);
if (r == KErrNone) {
diff --git a/src/serialport/qserialportinfo_unix.cpp b/src/serialport/qserialportinfo_unix.cpp
index 9b3bf94..4433a4e 100644
--- a/src/serialport/qserialportinfo_unix.cpp
+++ b/src/serialport/qserialportinfo_unix.cpp
@@ -47,29 +47,23 @@
#include <QtCore/qlockfile.h>
#include <QtCore/qfile.h>
+#include <QtCore/qdir.h>
#ifndef Q_OS_MAC
-#if defined(LINK_LIBUDEV) || defined(LOAD_LIBUDEV)
#include "qtudev_p.h"
-#else
-#include <QtCore/qdir.h>
-#include <QtCore/qstringlist.h>
-#endif
-#endif // Q_OS_MAC
+#endif
QT_BEGIN_NAMESPACE
#ifndef Q_OS_MAC
-#if !defined(LINK_LIBUDEV) && !defined(LOAD_LIBUDEV)
-
-static inline const QStringList& filtersOfDevices()
+static QStringList filteredDeviceFilePaths()
{
static const QStringList deviceFileNameFilterList = QStringList()
-# ifdef Q_OS_LINUX
+#ifdef Q_OS_LINUX
<< QStringLiteral("ttyS*") // Standard UART 8250 and etc.
<< QStringLiteral("ttyO*") // OMAP UART 8250 and etc.
<< QStringLiteral("ttyUSB*") // Usb/serial converters PL2303 and etc.
@@ -80,22 +74,17 @@ static inline const QStringList& filtersOfDevices()
<< QStringLiteral("ttyAMA*") // AMBA serial device for embedded platform on ARM (i.e. Raspberry Pi).
<< QStringLiteral("rfcomm*") // Bluetooth serial device.
<< QStringLiteral("ircomm*"); // IrDA serial device.
-# elif defined (Q_OS_FREEBSD)
+#elif defined (Q_OS_FREEBSD)
<< QStringLiteral("cu*");
-# else
- ; // Here for other *nix OS.
-# endif
-
- return deviceFileNameFilterList;
-}
+#else
+ ;
+#endif
-static QStringList filteredDeviceFilePaths()
-{
QStringList result;
QDir deviceDir(QStringLiteral("/dev"));
if (deviceDir.exists()) {
- deviceDir.setNameFilters(filtersOfDevices());
+ deviceDir.setNameFilters(deviceFileNameFilterList);
deviceDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks);
QStringList deviceFilePaths;
foreach (const QFileInfo &deviceFileInfo, deviceDir.entryInfoList()) {
@@ -110,13 +99,23 @@ static QStringList filteredDeviceFilePaths()
return result;
}
-QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
+QList<QSerialPortInfo> availablePortsByFiltersOfDevices()
{
QList<QSerialPortInfo> serialPortInfoList;
-#ifndef Q_OS_LINUX
- static const bool sysfsEnabled = false;
-#else
+ foreach (const QString &deviceFilePath, filteredDeviceFilePaths()) {
+ QSerialPortInfo serialPortInfo;
+ serialPortInfo.d_ptr->device = deviceFilePath;
+ serialPortInfo.d_ptr->portName = QSerialPortPrivate::portNameFromSystemLocation(deviceFilePath);
+ serialPortInfoList.append(serialPortInfo);
+ }
+
+ return serialPortInfoList;
+}
+
+QList<QSerialPortInfo> availablePortsBySysfs()
+{
+ QList<QSerialPortInfo> serialPortInfoList;
QDir ttySysClassDir(QStringLiteral("/sys/class/tty"));
const bool sysfsEnabled = ttySysClassDir.exists() && ttySysClassDir.isReadable();
@@ -131,16 +130,12 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
if (lastIndexOfSlash == -1)
continue;
- bool canAppendToList = true;
QSerialPortInfo serialPortInfo;
if (targetPath.contains(QStringLiteral("pnp"))) {
- // TODO: Implement me.
+ // TODO: Obtain more information
} else if (targetPath.contains(QStringLiteral("platform"))) {
- // Platform 'pseudo' bus for legacy device.
- // Skip this devices because this type of subsystem does
- // not include a real physical serial device.
- canAppendToList = false;
+ continue;
} else if (targetPath.contains(QStringLiteral("usb"))) {
QDir targetDir(targetPath);
@@ -185,26 +180,14 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
}
} while (targetDir.cdUp());
+ } else if (targetPath.contains(QStringLiteral("pci"))) {
+ // TODO: Obtain more information about the device
} else {
- // unknown types of devices
- canAppendToList = false;
- }
-
- if (canAppendToList) {
- serialPortInfo.d_ptr->portName = targetPath.mid(lastIndexOfSlash + 1);
- serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(serialPortInfo.d_ptr->portName);
- serialPortInfoList.append(serialPortInfo);
+ continue;
}
- }
- }
-#endif
-
- if (!sysfsEnabled) {
- foreach (const QString &deviceFilePath, filteredDeviceFilePaths()) {
- QSerialPortInfo serialPortInfo;
- serialPortInfo.d_ptr->device = deviceFilePath;
- serialPortInfo.d_ptr->portName = QSerialPortPrivate::portNameFromSystemLocation(deviceFilePath);
+ serialPortInfo.d_ptr->portName = targetPath.mid(lastIndexOfSlash + 1);
+ serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(serialPortInfo.d_ptr->portName);
serialPortInfoList.append(serialPortInfo);
}
}
@@ -212,18 +195,15 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
return serialPortInfoList;
}
-#else
-
-QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
+QList<QSerialPortInfo> availablePortsByUdev()
{
-#ifdef LOAD_LIBUDEV
+#ifndef LINK_LIBUDEV
static bool symbolsResolved = resolveSymbols();
if (!symbolsResolved)
return QList<QSerialPortInfo>();
#endif
QList<QSerialPortInfo> serialPortInfoList;
- // White list for devices without a parent
static const QString rfcommDeviceName(QStringLiteral("rfcomm"));
struct ::udev *udev = ::udev_new();
@@ -256,15 +236,12 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
struct ::udev_device *parentdev = ::udev_device_get_parent(dev);
- bool canAppendToList = true;
-
if (parentdev) {
QString subsys = QString::fromLatin1(::udev_device_get_subsystem(parentdev));
if (subsys == QStringLiteral("usb-serial")
- || subsys == QStringLiteral("usb")) { // USB bus type
- // Append this devices and try get additional information about them.
+ || subsys == QStringLiteral("usb")) {
serialPortInfo.d_ptr->description = QString::fromLatin1(::udev_device_get_property_value(dev,
"ID_MODEL")).replace(QLatin1Char('_'), QLatin1Char(' '));
serialPortInfo.d_ptr->manufacturer = QString::fromLatin1(::udev_device_get_property_value(dev,
@@ -278,39 +255,28 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
QString::fromLatin1(::udev_device_get_property_value(dev,
"ID_MODEL_ID")).toInt(&serialPortInfo.d_ptr->hasProductIdentifier, 16);
- } else if (subsys == QStringLiteral("pnp")) { // PNP bus type
- // Append this device.
- // FIXME: How to get additional information about serial devices
- // with this subsystem?
- } else if (subsys == QStringLiteral("platform")) { // Platform 'pseudo' bus for legacy device.
- // Skip this devices because this type of subsystem does
- // not include a real physical serial device.
- canAppendToList = false;
- } else { // Others types of subsystems.
- // Append this devices because we believe that any other types of
- // subsystems provide a real serial devices. For example, for devices
- // such as ttyGSx, its driver provide an empty subsystem name, but it
- // devices is a real physical serial devices.
- // FIXME: How to get additional information about serial devices
- // with this subsystems?
+ } else if (subsys == QStringLiteral("pnp")) {
+ // TODO: Obtain more information
+ } else if (subsys == QStringLiteral("platform")) {
+ continue;
+ } else if (subsys == QStringLiteral("pci")) {
+ // TODO: Obtain more information about the device
+ } else {
+ // FIXME: Obtain more information
}
- } else { // Devices without a parent
- if (serialPortInfo.d_ptr->portName.startsWith(rfcommDeviceName)) { // Bluetooth device
+ } else {
+ if (serialPortInfo.d_ptr->portName.startsWith(rfcommDeviceName)) {
bool ok;
- // Check for an unsigned decimal integer at the end of the device name: "rfcomm0", "rfcomm15"
- // devices with negative and invalid numbers in the name are rejected
int portNumber = serialPortInfo.d_ptr->portName.mid(rfcommDeviceName.length()).toInt(&ok);
- if (!ok || (portNumber < 0) || (portNumber > 255)) {
- canAppendToList = false;
- }
+ if (!ok || (portNumber < 0) || (portNumber > 255))
+ continue;
} else {
- canAppendToList = false;
+ continue;
}
}
- if (canAppendToList)
- serialPortInfoList.append(serialPortInfo);
+ serialPortInfoList.append(serialPortInfo);
::udev_device_unref(dev);
}
@@ -326,11 +292,29 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
return serialPortInfoList;
}
+QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
+{
+ QList<QSerialPortInfo> serialPortInfoList;
+ // TODO: Remove this condition once the udev runtime symbol resolution crash
+ // is fixed for Qt 4.
+#if defined(LINK_LIBUDEV) || (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+ serialPortInfoList = availablePortsByUdev();
#endif
-#endif // Q_OS_MAC
+#ifdef Q_OS_LINUX
+ if (serialPortInfoList.isEmpty())
+ serialPortInfoList = availablePortsBySysfs();
+ else
+ return serialPortInfoList;
+#endif
-// common part
+ if (serialPortInfoList.isEmpty())
+ serialPortInfoList = availablePortsByFiltersOfDevices();
+
+ return serialPortInfoList;
+}
+
+#endif
QList<qint32> QSerialPortInfo::standardBaudRates()
{
diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp
index 7eec46a..51f529e 100644
--- a/src/serialport/qserialportinfo_win.cpp
+++ b/src/serialport/qserialportinfo_win.cpp
@@ -52,24 +52,28 @@
#include <QtCore/qvariant.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/quuid.h>
+#include <QtCore/qpair.h>
QT_BEGIN_NAMESPACE
#ifndef Q_OS_WINCE
-static const GUID guidsArray[] =
+typedef QPair<QUuid, DWORD> GuidFlagsPair;
+
+static inline const QList<GuidFlagsPair>& guidFlagsPairs()
{
- // Windows Ports Class GUID
- { 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },
- // Virtual Ports Class GUID (i.e. com0com and etc)
- { 0xDF799E12, 0x3C56, 0x421B, { 0xB2, 0x98, 0xB6, 0xD3, 0x64, 0x2B, 0xC8, 0x78 } },
- // Windows Modems Class GUID
- { 0x4D36E96D, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },
- // Eltima Virtual Serial Port Driver v4 GUID
- { 0xCC0EF009, 0xB820, 0x42F4, { 0x95, 0xA9, 0x9B, 0xFA, 0x6A, 0x5A, 0xB7, 0xAB } },
- // Advanced Virtual COM Port GUID
- { 0x9341CD95, 0x4371, 0x4A37, { 0xA5, 0xAF, 0xFD, 0xB0, 0xA9, 0xD1, 0x96, 0x31 } },
-};
+ static const QList<GuidFlagsPair> guidFlagsPairList = QList<GuidFlagsPair>()
+ // Standard Setup Ports Class GUID
+ << qMakePair(QUuid(0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18), DWORD(DIGCF_PRESENT))
+ // Standard Setup Modems Class GUID
+ << qMakePair(QUuid(0x4D36E96D, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18), DWORD(DIGCF_PRESENT))
+ // Standard Serial Port Device Interface Class GUID
+ << qMakePair(QUuid(0x86E0D1E0, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73), DWORD(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE))
+ // Standard Modem Device Interface Class GUID
+ << qMakePair(QUuid(0x2C7089AA, 0x2E0E, 0x11D1, 0xB1, 0x14, 0x00, 0xC0, 0x4F, 0xC2, 0xAA, 0xE4), DWORD(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+ return guidFlagsPairList;
+}
static QVariant deviceRegistryProperty(HDEVINFO deviceInfoSet,
PSP_DEVINFO_DATA deviceInfoData,
@@ -157,6 +161,23 @@ static QString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInf
return QString::fromWCharArray(((const wchar_t *)data.constData()));
}
+class SerialPortNameEqualFunctor
+{
+public:
+ explicit SerialPortNameEqualFunctor(const QString &serialPortName)
+ : m_serialPortName(serialPortName)
+ {
+ }
+
+ bool operator() (const QSerialPortInfo &serialPortInfo) const
+ {
+ return serialPortInfo.portName() == m_serialPortName;
+ }
+
+private:
+ const QString &m_serialPortName;
+};
+
QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
{
static const QString usbVendorIdentifierPrefix(QStringLiteral("VID_"));
@@ -168,10 +189,9 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
static const int productIdentifierSize = 4;
QList<QSerialPortInfo> serialPortInfoList;
- static const int guidCount = sizeof(guidsArray)/sizeof(guidsArray[0]);
- for (int i = 0; i < guidCount; ++i) {
- const HDEVINFO deviceInfoSet = ::SetupDiGetClassDevs(&guidsArray[i], NULL, 0, DIGCF_PRESENT);
+ foreach (const GuidFlagsPair &uniquePair, guidFlagsPairs()) {
+ const HDEVINFO deviceInfoSet = ::SetupDiGetClassDevs(reinterpret_cast<const GUID *>(&uniquePair.first), NULL, 0, uniquePair.second);
if (deviceInfoSet == INVALID_HANDLE_VALUE)
return serialPortInfoList;
@@ -187,6 +207,11 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
if (s.isEmpty() || s.contains(QStringLiteral("LPT")))
continue;
+ if (std::find_if(serialPortInfoList.begin(), serialPortInfoList.end(),
+ SerialPortNameEqualFunctor(s)) != serialPortInfoList.end()) {
+ continue;
+ }
+
serialPortInfo.d_ptr->portName = s;
serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(s);
serialPortInfo.d_ptr->description =
@@ -227,8 +252,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
#endif
-// common part
-
QList<qint32> QSerialPortInfo::standardBaudRates()
{
return QSerialPortPrivate::standardBaudRates();
diff --git a/src/serialport/qserialportinfo_wince.cpp b/src/serialport/qserialportinfo_wince.cpp
index 0d0fd0d..27ecb28 100644
--- a/src/serialport/qserialportinfo_wince.cpp
+++ b/src/serialport/qserialportinfo_wince.cpp
@@ -119,9 +119,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
serialPortInfo.d_ptr->description = findDescription(HKEY_LOCAL_MACHINE,
QString::fromWCharArray(di.szDeviceKey));
- // Get manufacturer, vendor identifier, product identifier are not
- // possible.
-
serialPortInfoList.append(serialPortInfo);
} while (::FindNextDevice(hSearch, &di));
diff --git a/src/serialport/qtudev_p.h b/src/serialport/qtudev_p.h
index 457c3f0..1187165 100644
--- a/src/serialport/qtudev_p.h
+++ b/src/serialport/qtudev_p.h
@@ -47,7 +47,7 @@ extern "C"
{
#include <libudev.h>
}
-#elif defined(LOAD_LIBUDEV)
+#else
#include <QtCore/qlibrary.h>
#include <QtCore/qstring.h>
#include <QtCore/qdebug.h>
diff --git a/src/serialport/serialport-lib.pri b/src/serialport/serialport-lib.pri
index 7ad55f8..4c7e732 100644
--- a/src/serialport/serialport-lib.pri
+++ b/src/serialport/serialport-lib.pri
@@ -1,6 +1,6 @@
INCLUDEPATH += $$PWD
-!contains(DEFINES, LOAD_LIBUDEV): unix {
+unix {
greaterThan(QT_MAJOR_VERSION, 4) {
contains(QT_CONFIG, libudev) {
DEFINES += LINK_LIBUDEV