summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/serialport/blockingmaster/dialog.cpp12
-rw-r--r--examples/serialport/blockingslave/dialog.cpp23
-rw-r--r--examples/serialport/creaderasync/serialportreader.cpp7
-rw-r--r--examples/serialport/cwriterasync/serialportwriter.cpp7
-rw-r--r--examples/serialport/master/dialog.cpp9
-rw-r--r--examples/serialport/slave/dialog.cpp22
-rw-r--r--examples/serialport/terminal/mainwindow.cpp22
-rw-r--r--examples/serialport/terminal/settingsdialog.cpp16
-rw-r--r--qtserialport.pro1
-rw-r--r--src/serialport/qserialport.cpp92
-rw-r--r--src/serialport/qserialport.h20
-rw-r--r--src/serialport/qserialport_p.h33
-rw-r--r--src/serialport/qserialport_unix.cpp463
-rw-r--r--src/serialport/qserialport_win.cpp216
-rw-r--r--src/serialport/qserialport_wince.cpp71
-rw-r--r--src/serialport/qserialportinfo_unix.cpp20
-rw-r--r--tests/auto/qserialport/tst_qserialport.cpp395
18 files changed, 808 insertions, 623 deletions
diff --git a/.qmake.conf b/.qmake.conf
index e543981..66a0241 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,3 +1,3 @@
load(qt_build_config)
-MODULE_VERSION = 5.5.1
+MODULE_VERSION = 5.6.0
diff --git a/examples/serialport/blockingmaster/dialog.cpp b/examples/serialport/blockingmaster/dialog.cpp
index 6355429..86020a1 100644
--- a/examples/serialport/blockingmaster/dialog.cpp
+++ b/examples/serialport/blockingmaster/dialog.cpp
@@ -78,14 +78,10 @@ Dialog::Dialog(QWidget *parent)
setWindowTitle(tr("Blocking Master"));
serialPortComboBox->setFocus();
- connect(runButton, SIGNAL(clicked()),
- this, SLOT(transaction()));
- connect(&thread, SIGNAL(response(QString)),
- this, SLOT(showResponse(QString)));
- connect(&thread, SIGNAL(error(QString)),
- this, SLOT(processError(QString)));
- connect(&thread, SIGNAL(timeout(QString)),
- this, SLOT(processTimeout(QString)));
+ connect(runButton, &QPushButton::clicked, this, &Dialog::transaction);
+ connect(&thread, &MasterThread::response, this, &Dialog::showResponse);
+ connect(&thread, &MasterThread::error, this, &Dialog::processError);
+ connect(&thread, &MasterThread::timeout, this, &Dialog::processTimeout);
}
void Dialog::transaction()
diff --git a/examples/serialport/blockingslave/dialog.cpp b/examples/serialport/blockingslave/dialog.cpp
index 9933e05..78c2ec0 100644
--- a/examples/serialport/blockingslave/dialog.cpp
+++ b/examples/serialport/blockingslave/dialog.cpp
@@ -78,21 +78,16 @@ Dialog::Dialog(QWidget *parent)
setWindowTitle(tr("Blocking Slave"));
serialPortComboBox->setFocus();
- connect(runButton, SIGNAL(clicked()),
- this, SLOT(startSlave()));
- connect(&thread, SIGNAL(request(QString)),
- this, SLOT(showRequest(QString)));
- connect(&thread, SIGNAL(error(QString)),
- this, SLOT(processError(QString)));
- connect(&thread, SIGNAL(timeout(QString)),
- this, SLOT(processTimeout(QString)));
+ connect(runButton, &QPushButton::clicked, this, &Dialog::startSlave);
+ connect(&thread, &SlaveThread::request, this,&Dialog::showRequest);
+ connect(&thread, &SlaveThread::error, this, &Dialog::processError);
+ connect(&thread, &SlaveThread::timeout, this, &Dialog::processTimeout);
- connect(serialPortComboBox, SIGNAL(currentIndexChanged(QString)),
- this, SLOT(activateRunButton()));
- connect(waitRequestSpinBox, SIGNAL(valueChanged(int)),
- this, SLOT(activateRunButton()));
- connect(responseLineEdit, SIGNAL(textChanged(QString)),
- this, SLOT(activateRunButton()));
+ connect(serialPortComboBox, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
+ this, &Dialog::activateRunButton);
+ connect(waitRequestSpinBox, static_cast<void (QSpinBox::*)(const QString &)>(&QSpinBox::valueChanged),
+ this, &Dialog::activateRunButton);
+ connect(responseLineEdit, &QLineEdit::textChanged, this, &Dialog::activateRunButton);
}
void Dialog::startSlave()
diff --git a/examples/serialport/creaderasync/serialportreader.cpp b/examples/serialport/creaderasync/serialportreader.cpp
index 815ff8c..5188c69 100644
--- a/examples/serialport/creaderasync/serialportreader.cpp
+++ b/examples/serialport/creaderasync/serialportreader.cpp
@@ -42,9 +42,10 @@ SerialPortReader::SerialPortReader(QSerialPort *serialPort, QObject *parent)
, m_serialPort(serialPort)
, m_standardOutput(stdout)
{
- connect(m_serialPort, SIGNAL(readyRead()), SLOT(handleReadyRead()));
- connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), SLOT(handleError(QSerialPort::SerialPortError)));
- connect(&m_timer, SIGNAL(timeout()), SLOT(handleTimeout()));
+ connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortReader::handleReadyRead);
+ connect(m_serialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
+ this, &SerialPortReader::handleError);
+ connect(&m_timer, &QTimer::timeout, this, &SerialPortReader::handleTimeout);
m_timer.start(5000);
}
diff --git a/examples/serialport/cwriterasync/serialportwriter.cpp b/examples/serialport/cwriterasync/serialportwriter.cpp
index b50b353..4b22259 100644
--- a/examples/serialport/cwriterasync/serialportwriter.cpp
+++ b/examples/serialport/cwriterasync/serialportwriter.cpp
@@ -44,9 +44,10 @@ SerialPortWriter::SerialPortWriter(QSerialPort *serialPort, QObject *parent)
, m_bytesWritten(0)
{
m_timer.setSingleShot(true);
- connect(m_serialPort, SIGNAL(bytesWritten(qint64)), SLOT(handleBytesWritten(qint64)));
- connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), SLOT(handleError(QSerialPort::SerialPortError)));
- connect(&m_timer, SIGNAL(timeout()), SLOT(handleTimeout()));
+ connect(m_serialPort, &QSerialPort::bytesWritten, this, &SerialPortWriter::handleBytesWritten);
+ connect(m_serialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
+ this, &SerialPortWriter::handleError);
+ connect(&m_timer, &QTimer::timeout, this, &SerialPortWriter::handleTimeout);
}
SerialPortWriter::~SerialPortWriter()
diff --git a/examples/serialport/master/dialog.cpp b/examples/serialport/master/dialog.cpp
index c292b66..847635a 100644
--- a/examples/serialport/master/dialog.cpp
+++ b/examples/serialport/master/dialog.cpp
@@ -80,12 +80,9 @@ Dialog::Dialog(QWidget *parent)
timer.setSingleShot(true);
- connect(runButton, SIGNAL(clicked()),
- this, SLOT(sendRequest()));
- connect(&serial, SIGNAL(readyRead()),
- this, SLOT(readResponse()));
- connect(&timer, SIGNAL(timeout()),
- this, SLOT(processTimeout()));
+ connect(runButton, &QPushButton::clicked, this, &Dialog::sendRequest);
+ connect(&serial, &QSerialPort::readyRead, this, &Dialog::readResponse);
+ connect(&timer, &QTimer::timeout, this, &Dialog::processTimeout);
}
void Dialog::sendRequest()
diff --git a/examples/serialport/slave/dialog.cpp b/examples/serialport/slave/dialog.cpp
index 34118de..2d5d81d 100644
--- a/examples/serialport/slave/dialog.cpp
+++ b/examples/serialport/slave/dialog.cpp
@@ -80,19 +80,15 @@ Dialog::Dialog(QWidget *parent)
timer.setSingleShot(true);
- connect(runButton, SIGNAL(clicked()),
- this, SLOT(startSlave()));
- connect(&serial, SIGNAL(readyRead()),
- this, SLOT(readRequest()));
- connect(&timer, SIGNAL(timeout()),
- this, SLOT(processTimeout()));
-
- connect(serialPortComboBox, SIGNAL(currentIndexChanged(QString)),
- this, SLOT(activateRunButton()));
- connect(waitRequestSpinBox, SIGNAL(valueChanged(int)),
- this, SLOT(activateRunButton()));
- connect(responseLineEdit, SIGNAL(textChanged(QString)),
- this, SLOT(activateRunButton()));
+ connect(runButton, &QPushButton::clicked, this, &Dialog::startSlave);
+ connect(&serial, &QSerialPort::readyRead, this, &Dialog::readRequest);
+ connect(&timer, &QTimer::timeout, this, &Dialog::processTimeout);
+
+ connect(serialPortComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, &Dialog::activateRunButton);
+ connect(waitRequestSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ this, &Dialog::activateRunButton);
+ connect(responseLineEdit, &QLineEdit::textChanged, this, &Dialog::activateRunButton);
}
void Dialog::startSlave()
diff --git a/examples/serialport/terminal/mainwindow.cpp b/examples/serialport/terminal/mainwindow.cpp
index 3630b1f..b26b884 100644
--- a/examples/serialport/terminal/mainwindow.cpp
+++ b/examples/serialport/terminal/mainwindow.cpp
@@ -66,13 +66,13 @@ MainWindow::MainWindow(QWidget *parent) :
initActionsConnections();
- connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this,
- SLOT(handleError(QSerialPort::SerialPortError)));
+ connect(serial, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
+ this, &MainWindow::handleError);
//! [2]
- connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));
+ connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData);
//! [2]
- connect(console, SIGNAL(getData(QByteArray)), this, SLOT(writeData(QByteArray)));
+ connect(console, &Console::getData, this, &MainWindow::writeData);
//! [3]
}
//! [3]
@@ -158,13 +158,13 @@ void MainWindow::handleError(QSerialPort::SerialPortError error)
void MainWindow::initActionsConnections()
{
- connect(ui->actionConnect, SIGNAL(triggered()), this, SLOT(openSerialPort()));
- connect(ui->actionDisconnect, SIGNAL(triggered()), this, SLOT(closeSerialPort()));
- connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(close()));
- connect(ui->actionConfigure, SIGNAL(triggered()), settings, SLOT(show()));
- connect(ui->actionClear, SIGNAL(triggered()), console, SLOT(clear()));
- connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));
- connect(ui->actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ connect(ui->actionConnect, &QAction::triggered, this, &MainWindow::openSerialPort);
+ connect(ui->actionDisconnect, &QAction::triggered, this, &MainWindow::closeSerialPort);
+ connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::close);
+ connect(ui->actionConfigure, &QAction::triggered, settings, &MainWindow::show);
+ connect(ui->actionClear, &QAction::triggered, console, &Console::clear);
+ connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::about);
+ connect(ui->actionAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt);
}
void MainWindow::showStatusMessage(const QString &message)
diff --git a/examples/serialport/terminal/settingsdialog.cpp b/examples/serialport/terminal/settingsdialog.cpp
index 900d2fe..cd7211d 100644
--- a/examples/serialport/terminal/settingsdialog.cpp
+++ b/examples/serialport/terminal/settingsdialog.cpp
@@ -53,14 +53,14 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
ui->baudRateBox->setInsertPolicy(QComboBox::NoInsert);
- connect(ui->applyButton, SIGNAL(clicked()),
- this, SLOT(apply()));
- connect(ui->serialPortInfoListBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(showPortInfo(int)));
- connect(ui->baudRateBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(checkCustomBaudRatePolicy(int)));
- connect(ui->serialPortInfoListBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(checkCustomDevicePathPolicy(int)));
+ connect(ui->applyButton, &QPushButton::clicked,
+ this, &SettingsDialog::apply);
+ connect(ui->serialPortInfoListBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, &SettingsDialog::showPortInfo);
+ connect(ui->baudRateBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, &SettingsDialog::checkCustomBaudRatePolicy);
+ connect(ui->serialPortInfoListBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, &SettingsDialog::checkCustomDevicePathPolicy);
fillPortsParameters();
fillPortsInfo();
diff --git a/qtserialport.pro b/qtserialport.pro
index b3ebb8b..b8e7231 100644
--- a/qtserialport.pro
+++ b/qtserialport.pro
@@ -4,5 +4,6 @@ lessThan(QT_MAJOR_VERSION, 5) {
}
requires(!winrt)
+requires(!ios)
load(qt_parts)
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp
index 956c899..369be62 100644
--- a/src/serialport/qserialport.cpp
+++ b/src/serialport/qserialport.cpp
@@ -44,6 +44,42 @@
QT_BEGIN_NAMESPACE
+QSerialPortErrorInfo::QSerialPortErrorInfo(QSerialPort::SerialPortError newErrorCode,
+ const QString &newErrorString)
+ : errorCode(newErrorCode)
+ , errorString(newErrorString)
+{
+ if (errorString.isNull()) {
+ switch (errorCode) {
+ case QSerialPort::NoError:
+ errorString = QSerialPort::tr("No error");
+ break;
+ case QSerialPort::OpenError:
+ errorString = QSerialPort::tr("Device is already open");
+ break;
+ case QSerialPort::NotOpenError:
+ errorString = QSerialPort::tr("Device is not open");
+ break;
+ case QSerialPort::TimeoutError:
+ errorString = QSerialPort::tr("Operation timed out");
+ break;
+ case QSerialPort::ReadError:
+ errorString = QSerialPort::tr("Error reading from device");
+ break;
+ case QSerialPort::WriteError:
+ errorString = QSerialPort::tr("Error writing to device");
+ break;
+ case QSerialPort::ResourceError:
+ errorString = QSerialPort::tr("Device disappeared from the system");
+ break;
+ default:
+ // an empty string will be interpreted as "Unknown error"
+ // from the QIODevice::errorString()
+ break;
+ }
+ }
+}
+
QSerialPortPrivate::QSerialPortPrivate()
: readBufferMaxSize(0)
, writeBuffer(InitialBufferSize)
@@ -54,19 +90,17 @@ QSerialPortPrivate::QSerialPortPrivate()
, parity(QSerialPort::NoParity)
, stopBits(QSerialPort::OneStop)
, flowControl(QSerialPort::NoFlowControl)
- , policy(QSerialPort::IgnorePolicy)
#if QT_DEPRECATED_SINCE(5,3)
, settingsRestoredOnClose(true)
#endif
, isBreakEnabled(false)
#if defined(Q_OS_WINCE)
, handle(INVALID_HANDLE_VALUE)
- , parityErrorOccurred(false)
, eventNotifier(0)
#elif defined(Q_OS_WIN32)
, handle(INVALID_HANDLE_VALUE)
- , parityErrorOccurred(false)
, readChunkBuffer(ReadChunkSize, 0)
+ , communicationStarted(false)
, writeStarted(false)
, readStarted(false)
, notifier(0)
@@ -176,7 +210,7 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo)
used in non-GUI threads, to avoid freezing the user interface.
For more details about these approaches, refer to the
- \l {Examples}{example} applications.
+ \l {Qt Serial Port Examples}{example} applications.
The QSerialPort class can also be used with QTextStream and QDataStream's
stream operators (operator<<() and operator>>()). There is one issue to be
@@ -371,13 +405,16 @@ void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo)
QtSerialPort 5.2.
\value ParityError Parity error detected by the hardware while
- reading data.
+ 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.
+ 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.
+ 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.
@@ -521,7 +558,7 @@ bool QSerialPort::open(OpenMode mode)
Q_D(QSerialPort);
if (isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::OpenError, tr("Device is already open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::OpenError));
return false;
}
@@ -561,7 +598,7 @@ void QSerialPort::close()
{
Q_D(QSerialPort);
if (!isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError, tr("Device is not open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
return;
}
@@ -874,7 +911,7 @@ bool QSerialPort::setDataTerminalReady(bool set)
Q_D(QSerialPort);
if (!isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError, tr("Device is not open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
qWarning("%s: device not open", Q_FUNC_INFO);
return false;
}
@@ -921,7 +958,7 @@ bool QSerialPort::setRequestToSend(bool set)
Q_D(QSerialPort);
if (!isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError, tr("Device is not open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
qWarning("%s: device not open", Q_FUNC_INFO);
return false;
}
@@ -971,7 +1008,7 @@ QSerialPort::PinoutSignals QSerialPort::pinoutSignals()
Q_D(QSerialPort);
if (!isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError, tr("Device is not open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
qWarning("%s: device not open", Q_FUNC_INFO);
return QSerialPort::NoSignal;
}
@@ -1001,7 +1038,7 @@ bool QSerialPort::flush()
Q_D(QSerialPort);
if (!isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError, tr("Device is not open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
qWarning("%s: device not open", Q_FUNC_INFO);
return false;
}
@@ -1023,7 +1060,7 @@ bool QSerialPort::clear(Directions directions)
Q_D(QSerialPort);
if (!isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError, tr("Device is not open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
qWarning("%s: device not open", Q_FUNC_INFO);
return false;
}
@@ -1085,24 +1122,23 @@ bool QSerialPort::setDataErrorPolicy(DataErrorPolicy policy)
Q_D(QSerialPort);
if (!isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError, tr("Device is not open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
qWarning("%s: device not open", Q_FUNC_INFO);
return false;
}
- const bool ret = d->policy == policy || d->setDataErrorPolicy(policy);
- if (ret && (d->policy != policy)) {
- d->policy = policy;
- emit dataErrorPolicyChanged(d->policy);
+ if (policy != QSerialPort::IgnorePolicy) {
+ d->setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError,
+ tr("The device supports only the ignoring policy")));
+ return false;
}
- return ret;
+ return true;
}
QSerialPort::DataErrorPolicy QSerialPort::dataErrorPolicy() const
{
- Q_D(const QSerialPort);
- return d->policy;
+ return QSerialPort::IgnorePolicy;
}
#endif // QT_DEPRECATED_SINCE(5, 2)
@@ -1311,7 +1347,7 @@ bool QSerialPort::sendBreak(int duration)
Q_D(QSerialPort);
if (!isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError, tr("Device is not open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
qWarning("%s: device not open", Q_FUNC_INFO);
return false;
}
@@ -1341,7 +1377,7 @@ bool QSerialPort::setBreakEnabled(bool set)
Q_D(QSerialPort);
if (!isOpen()) {
- d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError, tr("Device is not open")));
+ d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
qWarning("%s: device not open", Q_FUNC_INFO);
return false;
}
@@ -1373,7 +1409,7 @@ qint64 QSerialPort::readData(char *data, qint64 maxSize)
Q_UNUSED(data);
Q_UNUSED(maxSize);
-#ifdef Q_OS_WIN32
+#if defined(Q_OS_WIN32)
// We need try to start async reading to read a remainder from a driver's queue
// in case we have a limited read buffer size. Because the read notification can
// be stalled since Windows do not re-triggered an EV_RXCHAR event if a driver's
@@ -1381,6 +1417,12 @@ qint64 QSerialPort::readData(char *data, qint64 maxSize)
Q_D(QSerialPort);
if (d->readBufferMaxSize || d->flowControl == QSerialPort::HardwareControl)
d->startAsyncRead();
+#elif defined(Q_OS_UNIX)
+ // We need try to re-trigger the read notification to read a remainder from a
+ // driver's queue in case we have a limited read buffer size.
+ Q_D(QSerialPort);
+ if (d->readBufferMaxSize && !d->isReadNotificationEnabled())
+ d->setReadNotificationEnabled(true);
#endif
// return 0 indicating there may be more data in the future
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h
index 36ae788..a19e1bf 100644
--- a/src/serialport/qserialport.h
+++ b/src/serialport/qserialport.h
@@ -65,9 +65,6 @@ class Q_SERIALPORT_EXPORT QSerialPort : public QIODevice
#endif
Q_PROPERTY(bool breakEnabled READ isBreakEnabled WRITE setBreakEnabled NOTIFY breakEnabledChanged)
- Q_ENUMS(BaudRate DataBits Parity StopBits FlowControl DataErrorPolicy SerialPortError)
- Q_FLAGS(Directions PinoutSignals)
-
#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
typedef void* Handle;
#else
@@ -81,6 +78,7 @@ public:
Output = 2,
AllDirections = Input | Output
};
+ Q_FLAG(Direction)
Q_DECLARE_FLAGS(Directions, Direction)
enum BaudRate {
@@ -94,6 +92,7 @@ public:
Baud115200 = 115200,
UnknownBaud = -1
};
+ Q_ENUM(BaudRate)
enum DataBits {
Data5 = 5,
@@ -102,6 +101,7 @@ public:
Data8 = 8,
UnknownDataBits = -1
};
+ Q_ENUM(DataBits)
enum Parity {
NoParity = 0,
@@ -111,6 +111,7 @@ public:
MarkParity = 5,
UnknownParity = -1
};
+ Q_ENUM(Parity)
enum StopBits {
OneStop = 1,
@@ -118,6 +119,7 @@ public:
TwoStop = 2,
UnknownStopBits = -1
};
+ Q_ENUM(StopBits)
enum FlowControl {
NoFlowControl,
@@ -125,6 +127,7 @@ public:
SoftwareControl,
UnknownFlowControl = -1
};
+ Q_ENUM(FlowControl)
enum PinoutSignal {
NoSignal = 0x00,
@@ -139,6 +142,7 @@ public:
SecondaryTransmittedDataSignal = 0x100,
SecondaryReceivedDataSignal = 0x200
};
+ Q_FLAG(PinoutSignal)
Q_DECLARE_FLAGS(PinoutSignals, PinoutSignal)
#if QT_DEPRECATED_SINCE(5, 2)
@@ -161,6 +165,7 @@ public:
StopReceivingPolicy,
UnknownPolicy = -1
};
+ Q_ENUM(DataErrorPolicy)
#endif
enum SerialPortError {
@@ -179,6 +184,15 @@ public:
TimeoutError,
NotOpenError
};
+ Q_ENUM(SerialPortError)
+
+#if QT_DEPRECATED_SINCE(5, 6)
+#if defined(_MSC_VER)
+#pragma deprecated(ParityError)
+#pragma deprecated(FramingError)
+#pragma deprecated(BreakConditionError)
+#endif
+#endif
explicit QSerialPort(QObject *parent = Q_NULLPTR);
explicit QSerialPort(const QString &name, QObject *parent = Q_NULLPTR);
diff --git a/src/serialport/qserialport_p.h b/src/serialport/qserialport_p.h
index 571b0de..d2527e3 100644
--- a/src/serialport/qserialport_p.h
+++ b/src/serialport/qserialport_p.h
@@ -109,12 +109,8 @@ QString serialPortLockFilePath(const QString &portName);
class QSerialPortErrorInfo
{
public:
- explicit QSerialPortErrorInfo(QSerialPort::SerialPortError errorCode = QSerialPort::UnknownError,
- const QString &errorString = QString())
- : errorCode(errorCode)
- , errorString(errorString)
- {
- }
+ explicit QSerialPortErrorInfo(QSerialPort::SerialPortError newErrorCode = QSerialPort::UnknownError,
+ const QString &newErrorString = QString());
QSerialPort::SerialPortError errorCode;
QString errorString;
};
@@ -155,7 +151,6 @@ public:
bool setParity(QSerialPort::Parity parity);
bool setStopBits(QSerialPort::StopBits stopBits);
bool setFlowControl(QSerialPort::FlowControl flowControl);
- bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy);
QSerialPortErrorInfo getSystemError(int systemErrorCode = -1) const;
@@ -181,7 +176,6 @@ public:
QSerialPort::Parity parity;
QSerialPort::StopBits stopBits;
QSerialPort::FlowControl flowControl;
- QSerialPort::DataErrorPolicy policy;
bool settingsRestoredOnClose;
bool isBreakEnabled;
@@ -194,7 +188,6 @@ public:
bool waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs);
- void processIoErrors(bool error);
bool notifyRead();
bool notifyWrite();
@@ -204,7 +197,6 @@ public:
COMMTIMEOUTS currentCommTimeouts;
COMMTIMEOUTS restoredCommTimeouts;
HANDLE handle;
- bool parityErrorOccurred;
QThread *eventNotifier;
QMutex settingsChangeMutex;
@@ -212,9 +204,9 @@ public:
#elif defined(Q_OS_WIN32)
bool initialize();
- bool updateDcb();
+ bool setDcb(DCB *dcb);
+ bool getDcb(DCB *dcb);
bool updateCommTimeouts();
- void handleLineStatusErrors();
OVERLAPPED *waitForNotified(int msecs);
bool completeAsyncCommunication(qint64 bytesTransferred);
@@ -226,16 +218,14 @@ public:
bool _q_startAsyncWrite();
void _q_notified(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped);
- bool emulateErrorPolicy();
void emitReadyRead();
- DCB currentDcb;
DCB restoredDcb;
COMMTIMEOUTS currentCommTimeouts;
COMMTIMEOUTS restoredCommTimeouts;
HANDLE handle;
- bool parityErrorOccurred;
QByteArray readChunkBuffer;
+ bool communicationStarted;
bool writeStarted;
bool readStarted;
QWinOverlappedIoNotifier *notifier;
@@ -250,14 +240,11 @@ public:
#elif defined(Q_OS_UNIX)
bool initialize(QIODevice::OpenMode mode);
- bool updateTermios();
+ bool setTermios(const termios *tio);
+ bool getTermios(termios *tio);
- QSerialPortErrorInfo setBaudRate_helper(qint32 baudRate,
- QSerialPort::Directions directions);
- QSerialPortErrorInfo setCustomBaudRate(qint32 baudRate,
- QSerialPort::Directions directions);
- QSerialPortErrorInfo setStandardBaudRate(qint32 baudRate,
- QSerialPort::Directions directions);
+ bool setCustomBaudRate(qint32 baudRate, QSerialPort::Directions directions);
+ bool setStandardBaudRate(qint32 baudRate, QSerialPort::Directions directions);
bool isReadNotificationEnabled() const;
void setReadNotificationEnabled(bool enable);
@@ -274,13 +261,11 @@ public:
#ifndef CMSPAR
qint64 writePerChar(const char *data, qint64 maxSize);
#endif
- qint64 readPerChar(char *data, qint64 maxSize);
bool readNotification();
bool startAsyncWrite();
bool completeAsyncWrite();
- struct termios currentTermios;
struct termios restoredTermios;
int descriptor;
diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp
index 612d84a..c243319 100644
--- a/src/serialport/qserialport_unix.cpp
+++ b/src/serialport/qserialport_unix.cpp
@@ -52,6 +52,33 @@
#define CRTSCTS (IHFLOW | OHFLOW)
#endif
+#ifdef Q_OS_LINUX
+
+struct termios2 {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[19]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
+#ifndef TCGETS2
+#define TCGETS2 _IOR('T', 0x2A, struct termios2)
+#endif
+
+#ifndef TCSETS2
+#define TCSETS2 _IOW('T', 0x2B, struct termios2)
+#endif
+
+#ifndef BOTHER
+#define BOTHER 0010000
+#endif
+
+#endif
+
#include <private/qcore_unix_p.h>
#include <QtCore/qelapsedtimer.h>
@@ -409,121 +436,151 @@ bool QSerialPortPrivate::setBaudRate()
&& setBaudRate(outputBaudRate, QSerialPort::Output));
}
-QSerialPortErrorInfo
-QSerialPortPrivate::setBaudRate_helper(qint32 baudRate,
- QSerialPort::Directions directions)
+bool QSerialPortPrivate::setStandardBaudRate(qint32 baudRate, QSerialPort::Directions directions)
{
- if ((directions & QSerialPort::Input) && ::cfsetispeed(&currentTermios, baudRate) < 0)
- return getSystemError();
-
- if ((directions & QSerialPort::Output) && ::cfsetospeed(&currentTermios, baudRate) < 0)
- return getSystemError();
-
- return QSerialPortErrorInfo(QSerialPort::NoError);
-}
+#ifdef Q_OS_LINUX
+ // try to clear custom baud rate, using termios v2
+ struct termios2 tio2;
+ if (::ioctl(descriptor, TCGETS2, &tio2) != -1) {
+ if (tio2.c_cflag & BOTHER) {
+ tio2.c_cflag &= ~BOTHER;
+ tio2.c_cflag |= CBAUD;
+ ::ioctl(descriptor, TCSETS2, &tio2);
+ }
+ }
-#if defined(Q_OS_LINUX)
+ // try to clear custom baud rate, using serial_struct (old way)
+ struct serial_struct serial;
+ ::memset(&serial, 0, sizeof(serial));
+ if (::ioctl(descriptor, TIOCGSERIAL, &serial) != -1) {
+ if (serial.flags & ASYNC_SPD_CUST) {
+ serial.flags &= ~ASYNC_SPD_CUST;
+ serial.custom_divisor = 0;
+ // we don't check on errors because a driver can has not this feature
+ ::ioctl(descriptor, TIOCSSERIAL, &serial);
+ }
+ }
+#endif
-QSerialPortErrorInfo
-QSerialPortPrivate::setStandardBaudRate(qint32 baudRate, QSerialPort::Directions directions)
-{
- struct serial_struct currentSerialInfo;
+ termios tio;
+ if (!getTermios(&tio))
+ return false;
- ::memset(&currentSerialInfo, 0, sizeof(currentSerialInfo));
+ if ((directions & QSerialPort::Input) && ::cfsetispeed(&tio, baudRate) < 0) {
+ setError(getSystemError());
+ return false;
+ }
- if ((::ioctl(descriptor, TIOCGSERIAL, &currentSerialInfo) != -1)
- && (currentSerialInfo.flags & ASYNC_SPD_CUST)) {
- currentSerialInfo.flags &= ~ASYNC_SPD_CUST;
- currentSerialInfo.custom_divisor = 0;
- if (::ioctl(descriptor, TIOCSSERIAL, &currentSerialInfo) == -1)
- return getSystemError();
+ if ((directions & QSerialPort::Output) && ::cfsetospeed(&tio, baudRate) < 0) {
+ setError(getSystemError());
+ return false;
}
- return setBaudRate_helper(baudRate, directions);
+ return setTermios(&tio);
}
-#else
+#if defined(Q_OS_LINUX)
-QSerialPortErrorInfo
-QSerialPortPrivate::setStandardBaudRate(qint32 baudRate, QSerialPort::Directions directions)
+bool QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions directions)
{
- return setBaudRate_helper(baudRate, directions);
-}
+ if (directions != QSerialPort::AllDirections) {
+ setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError,
+ QSerialPort::tr("Cannot set custom speed for one direction")));
+ return false;
+ }
-#endif
+ struct termios2 tio2;
-#if defined(Q_OS_LINUX)
+ if (::ioctl(descriptor, TCGETS2, &tio2) != -1) {
+ tio2.c_cflag &= ~CBAUD;
+ tio2.c_cflag |= BOTHER;
-QSerialPortErrorInfo
-QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions directions)
-{
- Q_UNUSED(directions);
+ tio2.c_ispeed = baudRate;
+ tio2.c_ospeed = baudRate;
- struct serial_struct currentSerialInfo;
+ if (::ioctl(descriptor, TCSETS2, &tio2) != -1
+ && ::ioctl(descriptor, TCGETS2, &tio2) != -1) {
+ return true;
+ }
+ }
- ::memset(&currentSerialInfo, 0, sizeof(currentSerialInfo));
+ struct serial_struct serial;
- if (::ioctl(descriptor, TIOCGSERIAL, &currentSerialInfo) == -1)
- return getSystemError();
+ if (::ioctl(descriptor, TIOCGSERIAL, &serial) == -1) {
+ setError(getSystemError());
+ return false;
+ }
- currentSerialInfo.flags &= ~ASYNC_SPD_MASK;
- currentSerialInfo.flags |= (ASYNC_SPD_CUST /* | ASYNC_LOW_LATENCY*/);
- currentSerialInfo.custom_divisor = currentSerialInfo.baud_base / baudRate;
+ serial.flags &= ~ASYNC_SPD_MASK;
+ serial.flags |= (ASYNC_SPD_CUST /* | ASYNC_LOW_LATENCY*/);
+ serial.custom_divisor = serial.baud_base / baudRate;
- if (currentSerialInfo.custom_divisor == 0)
- return QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError, QSerialPort::tr("No suitable custom baud rate divisor"));
+ if (serial.custom_divisor == 0) {
+ setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError,
+ QSerialPort::tr("No suitable custom baud rate divisor")));
+ return false;
+ }
- if (currentSerialInfo.custom_divisor * baudRate != currentSerialInfo.baud_base) {
+ if (serial.custom_divisor * baudRate != serial.baud_base) {
qWarning("Baud rate of serial port %s is set to %d instead of %d: divisor %f unsupported",
qPrintable(systemLocation),
- currentSerialInfo.baud_base / currentSerialInfo.custom_divisor,
- baudRate, (float)currentSerialInfo.baud_base / baudRate);
+ serial.baud_base / serial.custom_divisor,
+ baudRate, (float)serial.baud_base / baudRate);
}
- if (::ioctl(descriptor, TIOCSSERIAL, &currentSerialInfo) == -1)
- return getSystemError();
+ if (::ioctl(descriptor, TIOCSSERIAL, &serial) == -1) {
+ setError(getSystemError());
+ return false;
+ }
- return setBaudRate_helper(B38400, directions);
+ return setStandardBaudRate(B38400, directions);
}
#elif defined(Q_OS_MAC)
-QSerialPortErrorInfo
-QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions directions)
+bool QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions directions)
{
- Q_UNUSED(directions);
+ if (directions != QSerialPort::AllDirections) {
+ setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError,
+ QSerialPort::tr("Cannot set custom speed for one direction")));
+ return false;
+ }
#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
- if (::ioctl(descriptor, IOSSIOSPEED, &baudRate) == -1)
- return getSystemError();
+ if (::ioctl(descriptor, IOSSIOSPEED, &baudRate) == -1) {
+ setError(getSystemError());
+ return false;
+ }
- return QSerialPortErrorInfo(QSerialPort::NoError);
+ return true;
+#else
+ setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError,
+ QSerialPort::tr("Custom baud rate is not supported")));
+ return false;
#endif
-
- return QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError, QSerialPort::tr("Custom baud rate is not supported"));
}
#elif defined(Q_OS_QNX)
-QSerialPortErrorInfo
-QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions directions)
+bool QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions directions)
{
// On QNX, the values of the 'Bxxxx' constants are set to 'xxxx' (i.e.
// B115200 is defined to '115200'), which means that literal values can be
// passed to cfsetispeed/cfsetospeed, including custom values, provided
// that the underlying hardware supports them.
- return setBaudRate_helper(baudRate, directions);
+ return setStandardBaudRate(baudRate, directions);
}
#else
-QSerialPortErrorInfo
-QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions directions)
+bool QSerialPortPrivate::setCustomBaudRate(qint32 baudRate, QSerialPort::Directions directions)
{
Q_UNUSED(baudRate);
Q_UNUSED(directions);
- return QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError);
+ setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError,
+ QSerialPort::tr("Custom baud rate is not supported")));
+ return false;
}
#endif
@@ -537,147 +594,124 @@ bool QSerialPortPrivate::setBaudRate(qint32 baudRate, QSerialPort::Directions di
const qint32 unixBaudRate = QSerialPortPrivate::settingFromBaudRate(baudRate);
- const QSerialPortErrorInfo error = (unixBaudRate > 0)
- ? setStandardBaudRate(unixBaudRate, directions)
- : setCustomBaudRate(baudRate, directions);
-
- if (error.errorCode == QSerialPort::NoError)
- return updateTermios();
-
- setError(error);
- return false;
+ return (unixBaudRate > 0)
+ ? setStandardBaudRate(unixBaudRate, directions)
+ : setCustomBaudRate(baudRate, directions);
}
bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits)
{
- currentTermios.c_cflag &= ~CSIZE;
+ termios tio;
+ if (!getTermios(&tio))
+ return false;
+
+ tio.c_cflag &= ~CSIZE;
switch (dataBits) {
case QSerialPort::Data5:
- currentTermios.c_cflag |= CS5;
+ tio.c_cflag |= CS5;
break;
case QSerialPort::Data6:
- currentTermios.c_cflag |= CS6;
+ tio.c_cflag |= CS6;
break;
case QSerialPort::Data7:
- currentTermios.c_cflag |= CS7;
+ tio.c_cflag |= CS7;
break;
case QSerialPort::Data8:
- currentTermios.c_cflag |= CS8;
+ tio.c_cflag |= CS8;
break;
default:
- currentTermios.c_cflag |= CS8;
+ tio.c_cflag |= CS8;
break;
}
- return updateTermios();
+ return setTermios(&tio);
}
bool QSerialPortPrivate::setParity(QSerialPort::Parity parity)
{
- currentTermios.c_iflag &= ~(PARMRK | INPCK);
- currentTermios.c_iflag |= IGNPAR;
+ termios tio;
+ if (!getTermios(&tio))
+ return false;
+
+ tio.c_iflag &= ~(PARMRK | INPCK);
+ tio.c_iflag |= IGNPAR;
switch (parity) {
#ifdef CMSPAR
// Here Installation parity only for GNU/Linux where the macro CMSPAR.
case QSerialPort::SpaceParity:
- currentTermios.c_cflag &= ~PARODD;
- currentTermios.c_cflag |= PARENB | CMSPAR;
+ tio.c_cflag &= ~PARODD;
+ tio.c_cflag |= PARENB | CMSPAR;
break;
case QSerialPort::MarkParity:
- currentTermios.c_cflag |= PARENB | CMSPAR | PARODD;
+ tio.c_cflag |= PARENB | CMSPAR | PARODD;
break;
#endif
case QSerialPort::NoParity:
- currentTermios.c_cflag &= ~PARENB;
+ tio.c_cflag &= ~PARENB;
break;
case QSerialPort::EvenParity:
- currentTermios.c_cflag &= ~PARODD;
- currentTermios.c_cflag |= PARENB;
+ tio.c_cflag &= ~PARODD;
+ tio.c_cflag |= PARENB;
break;
case QSerialPort::OddParity:
- currentTermios.c_cflag |= PARENB | PARODD;
+ tio.c_cflag |= PARENB | PARODD;
break;
default:
- currentTermios.c_cflag |= PARENB;
- currentTermios.c_iflag |= PARMRK | INPCK;
- currentTermios.c_iflag &= ~IGNPAR;
+ tio.c_cflag |= PARENB;
+ tio.c_iflag |= PARMRK | INPCK;
+ tio.c_iflag &= ~IGNPAR;
break;
}
- return updateTermios();
+ return setTermios(&tio);
}
bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits)
{
+ termios tio;
+ if (!getTermios(&tio))
+ return false;
+
switch (stopBits) {
case QSerialPort::OneStop:
- currentTermios.c_cflag &= ~CSTOPB;
+ tio.c_cflag &= ~CSTOPB;
break;
case QSerialPort::TwoStop:
- currentTermios.c_cflag |= CSTOPB;
+ tio.c_cflag |= CSTOPB;
break;
default:
- currentTermios.c_cflag &= ~CSTOPB;
+ tio.c_cflag &= ~CSTOPB;
break;
}
- return updateTermios();
+ return setTermios(&tio);
}
bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flowControl)
{
+ termios tio;
+ if (!getTermios(&tio))
+ return false;
+
switch (flowControl) {
case QSerialPort::NoFlowControl:
- currentTermios.c_cflag &= ~CRTSCTS;
- currentTermios.c_iflag &= ~(IXON | IXOFF | IXANY);
+ tio.c_cflag &= ~CRTSCTS;
+ tio.c_iflag &= ~(IXON | IXOFF | IXANY);
break;
case QSerialPort::HardwareControl:
- currentTermios.c_cflag |= CRTSCTS;
- currentTermios.c_iflag &= ~(IXON | IXOFF | IXANY);
+ tio.c_cflag |= CRTSCTS;
+ tio.c_iflag &= ~(IXON | IXOFF | IXANY);
break;
case QSerialPort::SoftwareControl:
- currentTermios.c_cflag &= ~CRTSCTS;
- currentTermios.c_iflag |= IXON | IXOFF | IXANY;
+ tio.c_cflag &= ~CRTSCTS;
+ tio.c_iflag |= IXON | IXOFF | IXANY;
break;
default:
- currentTermios.c_cflag &= ~CRTSCTS;
- currentTermios.c_iflag &= ~(IXON | IXOFF | IXANY);
+ tio.c_cflag &= ~CRTSCTS;
+ tio.c_iflag &= ~(IXON | IXOFF | IXANY);
break;
}
- return updateTermios();
-}
-
-bool QSerialPortPrivate::setDataErrorPolicy(QSerialPort::DataErrorPolicy policy)
-{
- tcflag_t parmrkMask = PARMRK;
-#ifndef CMSPAR
- // in space/mark parity emulation also used PARMRK flag
- if (parity == QSerialPort::SpaceParity
- || parity == QSerialPort::MarkParity) {
- parmrkMask = 0;
- }
-#endif //CMSPAR
- switch (policy) {
- case QSerialPort::SkipPolicy:
- currentTermios.c_iflag &= ~parmrkMask;
- currentTermios.c_iflag |= IGNPAR | INPCK;
- break;
- case QSerialPort::PassZeroPolicy:
- currentTermios.c_iflag &= ~(IGNPAR | parmrkMask);
- currentTermios.c_iflag |= INPCK;
- break;
- case QSerialPort::IgnorePolicy:
- currentTermios.c_iflag &= ~INPCK;
- break;
- case QSerialPort::StopReceivingPolicy:
- currentTermios.c_iflag &= ~IGNPAR;
- currentTermios.c_iflag |= parmrkMask | INPCK;
- break;
- default:
- currentTermios.c_iflag &= ~INPCK;
- break;
- }
- return updateTermios();
+ return setTermios(&tio);
}
bool QSerialPortPrivate::readNotification()
@@ -686,13 +720,14 @@ bool QSerialPortPrivate::readNotification()
// Always buffered, read data from the port into the read buffer
qint64 newBytes = buffer.size();
- qint64 bytesToRead = policy == QSerialPort::IgnorePolicy ? ReadChunkSize : 1;
+ qint64 bytesToRead = ReadChunkSize;
if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - buffer.size())) {
bytesToRead = readBufferMaxSize - buffer.size();
if (bytesToRead == 0) {
// Buffer is full. User must read data from the buffer
// before we can read more from the port.
+ setReadNotificationEnabled(false);
return false;
}
}
@@ -785,29 +820,28 @@ inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode)
setError(getSystemError());
#endif
- if (::tcgetattr(descriptor, &restoredTermios) == -1) {
- setError(getSystemError());
+ termios tio;
+ if (!getTermios(&tio))
return false;
- }
- currentTermios = restoredTermios;
+ restoredTermios = tio;
#ifdef Q_OS_SOLARIS
- currentTermios.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
- currentTermios.c_oflag &= ~OPOST;
- currentTermios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
- currentTermios.c_cflag &= ~(CSIZE|PARENB);
- currentTermios.c_cflag |= CS8;
+ tio.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ tio.c_oflag &= ~OPOST;
+ tio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ tio.c_cflag &= ~(CSIZE|PARENB);
+ tio.c_cflag |= CS8;
#else
- ::cfmakeraw(&currentTermios);
+ ::cfmakeraw(&tio);
#endif
- currentTermios.c_cflag |= CLOCAL;
- currentTermios.c_cc[VTIME] = 0;
- currentTermios.c_cc[VMIN] = 0;
+ tio.c_cflag |= CLOCAL;
+ tio.c_cc[VTIME] = 0;
+ tio.c_cc[VMIN] = 0;
if (mode & QIODevice::ReadOnly)
- currentTermios.c_cflag |= CREAD;
+ tio.c_cflag |= CREAD;
- if (!updateTermios())
+ if (!setTermios(&tio))
return false;
if (mode & QIODevice::ReadOnly)
@@ -824,9 +858,19 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
return maxSize;
}
-bool QSerialPortPrivate::updateTermios()
+bool QSerialPortPrivate::setTermios(const termios *tio)
{
- if (::tcsetattr(descriptor, TCSANOW, &currentTermios) == -1) {
+ if (::tcsetattr(descriptor, TCSANOW, tio) == -1) {
+ setError(getSystemError());
+ return false;
+ }
+ return true;
+}
+
+bool QSerialPortPrivate::getTermios(termios *tio)
+{
+ ::memset(tio, 0, sizeof(termios));
+ if (::tcgetattr(descriptor, tio) == -1) {
setError(getSystemError());
return false;
}
@@ -958,7 +1002,7 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
return false;
}
if (ret == 0) {
- setError(QSerialPortErrorInfo(QSerialPort::TimeoutError, QSerialPort::tr("Operation timed out")));
+ setError(QSerialPortErrorInfo(QSerialPort::TimeoutError));
return false;
}
@@ -969,20 +1013,7 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
qint64 QSerialPortPrivate::readFromPort(char *data, qint64 maxSize)
{
- qint64 bytesRead = 0;
-#if defined(CMSPAR)
- if (parity == QSerialPort::NoParity
- || policy != QSerialPort::StopReceivingPolicy) {
-#else
- if (parity != QSerialPort::MarkParity
- && parity != QSerialPort::SpaceParity) {
-#endif
- bytesRead = qt_safe_read(descriptor, data, maxSize);
- } else {// Perform parity emulation.
- bytesRead = readPerChar(data, maxSize);
- }
-
- return bytesRead;
+ return qt_safe_read(descriptor, data, maxSize);
}
qint64 QSerialPortPrivate::writeToPort(const char *data, qint64 maxSize)
@@ -1002,6 +1033,8 @@ qint64 QSerialPortPrivate::writeToPort(const char *data, qint64 maxSize)
return bytesWritten;
}
+#ifndef CMSPAR
+
static inline bool evenParity(quint8 c)
{
c ^= c >> 4; //(c7 ^ c3)(c6 ^ c2)(c5 ^ c1)(c4 ^ c0)
@@ -1010,10 +1043,12 @@ static inline bool evenParity(quint8 c)
return c & 1; //(c7 ^ c3)(c5 ^ c1)(c6 ^ c2)(c4 ^ c0)
}
-#ifndef CMSPAR
-
qint64 QSerialPortPrivate::writePerChar(const char *data, qint64 maxSize)
{
+ termios tio;
+ if (!getTermios(&tio))
+ return -1;
+
qint64 ret = 0;
quint8 const charMask = (0xFF >> (8 - dataBits));
@@ -1022,11 +1057,11 @@ qint64 QSerialPortPrivate::writePerChar(const char *data, qint64 maxSize)
bool par = evenParity(*data & charMask);
// False if need EVEN, true if need ODD.
par ^= parity == QSerialPort::MarkParity;
- if (par ^ (currentTermios.c_cflag & PARODD)) { // Need switch parity mode?
- currentTermios.c_cflag ^= PARODD;
- flush(); //force sending already buffered data, because updateTermios() cleares buffers
+ if (par ^ (tio.c_cflag & PARODD)) { // Need switch parity mode?
+ tio.c_cflag ^= PARODD;
+ flush(); //force sending already buffered data, because setTermios(&tio); cleares buffers
//todo: add receiving buffered data!!!
- if (!updateTermios())
+ if (!setTermios(&tio))
break;
}
@@ -1043,78 +1078,6 @@ qint64 QSerialPortPrivate::writePerChar(const char *data, qint64 maxSize)
#endif //CMSPAR
-qint64 QSerialPortPrivate::readPerChar(char *data, qint64 maxSize)
-{
- qint64 ret = 0;
- quint8 const charMask = (0xFF >> (8 - dataBits));
-
- // 0 - prefix not started,
- // 1 - received 0xFF,
- // 2 - received 0xFF and 0x00
- int prefix = 0;
- while (ret < maxSize) {
-
- qint64 r = qt_safe_read(descriptor, data, 1);
- if (r < 0) {
- if (errno == EAGAIN) // It is ok for nonblocking mode.
- break;
- return -1;
- }
- if (r == 0)
- break;
-
- bool par = true;
- switch (prefix) {
- case 2: // Previously received both 0377 and 0.
- par = false;
- prefix = 0;
- break;
- case 1: // Previously received 0377.
- if (*data == '\0') {
- ++prefix;
- continue;
- }
- prefix = 0;
- break;
- default:
- if (*data == '\377') {
- prefix = 1;
- continue;
- }
- break;
- }
- // Now: par contains parity ok or error, *data contains received character
- par ^= evenParity(*data & charMask); //par contains parity bit value for EVEN mode
- par ^= (currentTermios.c_cflag & PARODD); //par contains parity bit value for current mode
- if (par ^ (parity == QSerialPort::SpaceParity)) { //if parity error
- switch (policy) {
- case QSerialPort::SkipPolicy:
- continue; //ignore received character
- case QSerialPort::StopReceivingPolicy: {
- if (parity != QSerialPort::NoParity)
- setError(QSerialPortErrorInfo(QSerialPort::ParityError, QSerialPort::tr("Parity error detected while reading")));
- else if (*data == '\0')
- setError(QSerialPortErrorInfo(QSerialPort::BreakConditionError, QSerialPort::tr("Break condition detected while reading")));
- else
- setError(QSerialPortErrorInfo(QSerialPort::FramingError, QSerialPort::tr("Framing error detected while reading")));
- return ++ret; //abort receiving
- }
- break;
- case QSerialPort::UnknownPolicy:
- // Unknown error policy is used! Falling back to PassZeroPolicy
- case QSerialPort::PassZeroPolicy:
- *data = '\0'; //replace received character by zero
- break;
- case QSerialPort::IgnorePolicy:
- break; //ignore error and pass received character
- }
- }
- ++data;
- ++ret;
- }
- return ret;
-}
-
typedef QMap<qint32, qint32> BaudRateMap;
// The OS specific defines can be found in termios.h
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 6c99491..39d7e33 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -78,7 +78,7 @@ QT_BEGIN_NAMESPACE
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
DWORD desiredAccess = 0;
- originalEventMask = EV_ERR;
+ originalEventMask = 0;
if (mode & QIODevice::ReadOnly) {
desiredAccess |= GENERIC_READ;
@@ -117,13 +117,12 @@ void QSerialPortPrivate::close()
startAsyncWriteTimer = Q_NULLPTR;
}
+ communicationStarted = false;
readStarted = false;
writeStarted = false;
writeBuffer.clear();
actualBytesToWrite = 0;
- parityErrorOccurred = false;
-
if (settingsRestoredOnClose) {
if (!::SetCommState(handle, &restoredDcb))
setError(getSystemError());
@@ -180,8 +179,12 @@ bool QSerialPortPrivate::setDataTerminalReady(bool set)
return false;
}
- currentDcb.fDtrControl = set ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE;
- return true;
+ DCB dcb;
+ if (!getDcb(&dcb))
+ return false;
+
+ dcb.fDtrControl = set ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE;
+ return setDcb(&dcb);
}
bool QSerialPortPrivate::setRequestToSend(bool set)
@@ -312,98 +315,113 @@ bool QSerialPortPrivate::setBaudRate(qint32 baudRate, QSerialPort::Directions di
setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError, QSerialPort::tr("Custom baud rate direction is unsupported")));
return false;
}
- currentDcb.BaudRate = baudRate;
- return updateDcb();
+
+ DCB dcb;
+ if (!getDcb(&dcb))
+ return false;
+
+ dcb.BaudRate = baudRate;
+ return setDcb(&dcb);
}
bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits)
{
- currentDcb.ByteSize = dataBits;
- return updateDcb();
+ DCB dcb;
+ if (!getDcb(&dcb))
+ return false;
+
+ dcb.ByteSize = dataBits;
+ return setDcb(&dcb);
}
bool QSerialPortPrivate::setParity(QSerialPort::Parity parity)
{
- currentDcb.fParity = TRUE;
+ DCB dcb;
+ if (!getDcb(&dcb))
+ return false;
+
+ dcb.fParity = TRUE;
switch (parity) {
case QSerialPort::NoParity:
- currentDcb.Parity = NOPARITY;
- currentDcb.fParity = FALSE;
+ dcb.Parity = NOPARITY;
+ dcb.fParity = FALSE;
break;
case QSerialPort::OddParity:
- currentDcb.Parity = ODDPARITY;
+ dcb.Parity = ODDPARITY;
break;
case QSerialPort::EvenParity:
- currentDcb.Parity = EVENPARITY;
+ dcb.Parity = EVENPARITY;
break;
case QSerialPort::MarkParity:
- currentDcb.Parity = MARKPARITY;
+ dcb.Parity = MARKPARITY;
break;
case QSerialPort::SpaceParity:
- currentDcb.Parity = SPACEPARITY;
+ dcb.Parity = SPACEPARITY;
break;
default:
- currentDcb.Parity = NOPARITY;
- currentDcb.fParity = FALSE;
+ dcb.Parity = NOPARITY;
+ dcb.fParity = FALSE;
break;
}
- return updateDcb();
+ return setDcb(&dcb);
}
bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits)
{
+ DCB dcb;
+ if (!getDcb(&dcb))
+ return false;
+
switch (stopBits) {
case QSerialPort::OneStop:
- currentDcb.StopBits = ONESTOPBIT;
+ dcb.StopBits = ONESTOPBIT;
break;
case QSerialPort::OneAndHalfStop:
- currentDcb.StopBits = ONE5STOPBITS;
+ dcb.StopBits = ONE5STOPBITS;
break;
case QSerialPort::TwoStop:
- currentDcb.StopBits = TWOSTOPBITS;
+ dcb.StopBits = TWOSTOPBITS;
break;
default:
- currentDcb.StopBits = ONESTOPBIT;
+ dcb.StopBits = ONESTOPBIT;
break;
}
- return updateDcb();
+ return setDcb(&dcb);
}
bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flowControl)
{
- currentDcb.fInX = FALSE;
- currentDcb.fOutX = FALSE;
- currentDcb.fOutxCtsFlow = FALSE;
- currentDcb.fRtsControl = RTS_CONTROL_DISABLE;
+ DCB dcb;
+ if (!getDcb(&dcb))
+ return false;
+
+ dcb.fInX = FALSE;
+ dcb.fOutX = FALSE;
+ dcb.fOutxCtsFlow = FALSE;
+ dcb.fRtsControl = RTS_CONTROL_DISABLE;
switch (flowControl) {
case QSerialPort::NoFlowControl:
break;
case QSerialPort::SoftwareControl:
- currentDcb.fInX = TRUE;
- currentDcb.fOutX = TRUE;
+ dcb.fInX = TRUE;
+ dcb.fOutX = TRUE;
break;
case QSerialPort::HardwareControl:
- currentDcb.fOutxCtsFlow = TRUE;
- currentDcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
+ dcb.fOutxCtsFlow = TRUE;
+ dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
break;
default:
break;
}
- return updateDcb();
-}
-
-bool QSerialPortPrivate::setDataErrorPolicy(QSerialPort::DataErrorPolicy policy)
-{
- policy = policy;
- return true;
+ return setDcb(&dcb);
}
bool QSerialPortPrivate::completeAsyncCommunication(qint64 bytesTransferred)
{
+ communicationStarted = false;
+
if (bytesTransferred == qint64(-1))
return false;
- if (EV_ERR & triggeredEventMask)
- handleLineStatusErrors();
return startAsyncRead();
}
@@ -422,12 +440,12 @@ bool QSerialPortPrivate::completeAsyncRead(qint64 bytesTransferred)
readStarted = false;
bool result = true;
- if ((bytesTransferred == ReadChunkSize) && (policy == QSerialPort::IgnorePolicy))
+ if (bytesTransferred == ReadChunkSize)
result = startAsyncRead();
else if (readBufferMaxSize == 0 || readBufferMaxSize > buffer.size())
result = startAsyncCommunication();
- if ((bytesTransferred > 0) && !emulateErrorPolicy())
+ if (bytesTransferred > 0)
emitReadyRead();
return result;
@@ -453,6 +471,9 @@ bool QSerialPortPrivate::completeAsyncWrite(qint64 bytesTransferred)
bool QSerialPortPrivate::startAsyncCommunication()
{
+ if (communicationStarted)
+ return true;
+
::ZeroMemory(&communicationOverlapped, sizeof(communicationOverlapped));
if (!::WaitCommEvent(handle, &triggeredEventMask, &communicationOverlapped)) {
QSerialPortErrorInfo error = getSystemError();
@@ -463,6 +484,7 @@ bool QSerialPortPrivate::startAsyncCommunication()
return false;
}
}
+ communicationStarted = true;
return true;
}
@@ -471,7 +493,7 @@ bool QSerialPortPrivate::startAsyncRead()
if (readStarted)
return true;
- DWORD bytesToRead = policy == QSerialPort::IgnorePolicy ? ReadChunkSize : 1;
+ DWORD bytesToRead = ReadChunkSize;
if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - buffer.size())) {
bytesToRead = readBufferMaxSize - buffer.size();
@@ -544,34 +566,6 @@ void QSerialPortPrivate::_q_notified(DWORD numberOfBytes, DWORD errorCode, OVERL
Q_ASSERT(!"Unknown OVERLAPPED activated");
}
-bool QSerialPortPrivate::emulateErrorPolicy()
-{
- if (!parityErrorOccurred)
- return false;
-
- parityErrorOccurred = false;
-
- switch (policy) {
- case QSerialPort::SkipPolicy:
- buffer.getChar();
- break;
- case QSerialPort::PassZeroPolicy:
- buffer.getChar();
- buffer.ungetChar('\0');
- emitReadyRead();
- break;
- case QSerialPort::IgnorePolicy:
- return false;
- case QSerialPort::StopReceivingPolicy:
- emitReadyRead();
- break;
- default:
- return false;
- }
-
- return true;
-}
-
void QSerialPortPrivate::emitReadyRead()
{
Q_Q(QSerialPort);
@@ -589,7 +583,7 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
if (!writeBuffer.isEmpty() && !writeStarted) {
if (!startAsyncWriteTimer) {
startAsyncWriteTimer = new QTimer(q);
- q->connect(startAsyncWriteTimer, SIGNAL(timeout()), q, SLOT(_q_startAsyncWrite()));
+ QObjectPrivate::connect(startAsyncWriteTimer, &QTimer::timeout, this, &QSerialPortPrivate::_q_startAsyncWrite);
startAsyncWriteTimer->setSingleShot(true);
}
startAsyncWriteTimer->start(0);
@@ -597,26 +591,6 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
return maxSize;
}
-void QSerialPortPrivate::handleLineStatusErrors()
-{
- DWORD errors = 0;
- if (!::ClearCommError(handle, &errors, Q_NULLPTR)) {
- setError(getSystemError());
- return;
- }
-
- if (errors & CE_FRAME) {
- setError(QSerialPortErrorInfo(QSerialPort::FramingError, QSerialPort::tr("Framing error detected while reading")));
- } else if (errors & CE_RXPARITY) {
- setError(QSerialPortErrorInfo(QSerialPort::ParityError, QSerialPort::tr("ParityError error detected while reading")));
- parityErrorOccurred = true;
- } else if (errors & CE_BREAK) {
- setError(QSerialPortErrorInfo(QSerialPort::BreakConditionError, QSerialPort::tr("Break condition detected while reading")));
- } else {
- setError(QSerialPortErrorInfo(QSerialPort::UnknownError, QSerialPort::tr("Unknown streaming error")));
- }
-}
-
OVERLAPPED *QSerialPortPrivate::waitForNotified(int msecs)
{
OVERLAPPED *overlapped = notifier->waitForAnyNotified(msecs);
@@ -631,28 +605,25 @@ inline bool QSerialPortPrivate::initialize()
{
Q_Q(QSerialPort);
- ::ZeroMemory(&restoredDcb, sizeof(restoredDcb));
- restoredDcb.DCBlength = sizeof(restoredDcb);
-
- if (!::GetCommState(handle, &restoredDcb)) {
- setError(getSystemError());
+ DCB dcb;
+ if (!getDcb(&dcb))
return false;
- }
- currentDcb = restoredDcb;
- currentDcb.fBinary = TRUE;
- currentDcb.fInX = FALSE;
- currentDcb.fOutX = FALSE;
- currentDcb.fAbortOnError = FALSE;
- currentDcb.fNull = FALSE;
- currentDcb.fErrorChar = FALSE;
+ restoredDcb = dcb;
- if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
- currentDcb.fDtrControl = DTR_CONTROL_DISABLE;
+ dcb.fBinary = TRUE;
+ dcb.fInX = FALSE;
+ dcb.fOutX = FALSE;
+ dcb.fAbortOnError = FALSE;
+ dcb.fNull = FALSE;
+ dcb.fErrorChar = FALSE;
- currentDcb.BaudRate = inputBaudRate;
+ if (dcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
+ dcb.fDtrControl = DTR_CONTROL_DISABLE;
- if (!updateDcb())
+ dcb.BaudRate = inputBaudRate;
+
+ if (!setDcb(&dcb))
return false;
if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) {
@@ -672,20 +643,32 @@ inline bool QSerialPortPrivate::initialize()
}
notifier = new QWinOverlappedIoNotifier(q);
- q->connect(notifier, SIGNAL(notified(quint32, quint32, OVERLAPPED*)),
- q, SLOT(_q_notified(quint32, quint32, OVERLAPPED*)));
+ QObjectPrivate::connect(notifier, &QWinOverlappedIoNotifier::notified,
+ this, &QSerialPortPrivate::_q_notified);
notifier->setHandle(handle);
notifier->setEnabled(true);
- if (!startAsyncCommunication())
+ if ((originalEventMask & EV_RXCHAR) && !startAsyncCommunication())
return false;
return true;
}
-bool QSerialPortPrivate::updateDcb()
+bool QSerialPortPrivate::setDcb(DCB *dcb)
{
- if (!::SetCommState(handle, &currentDcb)) {
+ if (!::SetCommState(handle, dcb)) {
+ setError(getSystemError());
+ return false;
+ }
+ return true;
+}
+
+bool QSerialPortPrivate::getDcb(DCB *dcb)
+{
+ ::ZeroMemory(dcb, sizeof(DCB));
+ dcb->DCBlength = sizeof(DCB);
+
+ if (!::GetCommState(handle, dcb)) {
setError(getSystemError());
return false;
}
@@ -722,6 +705,9 @@ QSerialPortErrorInfo QSerialPortPrivate::getSystemError(int systemErrorCode) con
case ERROR_FILE_NOT_FOUND:
error.errorCode = QSerialPort::DeviceNotFoundError;
break;
+ case ERROR_PATH_NOT_FOUND:
+ error.errorCode = QSerialPort::DeviceNotFoundError;
+ break;
case ERROR_INVALID_NAME:
error.errorCode = QSerialPort::DeviceNotFoundError;
break;
diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp
index ac67e45..18dd15d 100644
--- a/src/serialport/qserialport_wince.cpp
+++ b/src/serialport/qserialport_wince.cpp
@@ -84,7 +84,7 @@ signals:
public:
CommEventNotifier(DWORD mask, QSerialPortPrivate *d, QObject *parent)
: QThread(parent), dptr(d) {
- connect(this, SIGNAL(eventMask(quint32)), this, SLOT(processNotification(quint32)));
+ connect(this, &CommEventNotifier::eventMask, this, &CommEventNotifier::processNotification);
::SetCommMask(dptr->handle, mask);
}
@@ -119,8 +119,6 @@ private slots:
error = true;
}
- if (error || (EV_ERR & eventMask))
- dptr->processIoErrors(error);
if (EV_RXCHAR & eventMask)
dptr->notifyRead();
if (EV_TXEMPTY & eventMask)
@@ -156,7 +154,7 @@ public:
protected:
void run() {
QTimer timer;
- QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(processTimeout()), Qt::DirectConnection);
+ QObject::connect(&timer, &QTimer::timeout, this, &WaitCommEventBreaker::processTimeout, Qt::DirectConnection);
timer.start(timeout);
exec();
worked = true;
@@ -179,7 +177,7 @@ private:
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
DWORD desiredAccess = 0;
- DWORD eventMask = EV_ERR;
+ DWORD eventMask = 0;
if (mode & QIODevice::ReadOnly) {
desiredAccess |= GENERIC_READ;
@@ -463,17 +461,11 @@ bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flowControl)
return updateDcb();
}
-bool QSerialPortPrivate::setDataErrorPolicy(QSerialPort::DataErrorPolicy policy)
-{
- policy = policy;
- return true;
-}
-
bool QSerialPortPrivate::notifyRead()
{
Q_Q(QSerialPort);
- DWORD bytesToRead = (policy == QSerialPort::IgnorePolicy) ? ReadChunkSize : 1;
+ DWORD bytesToRead = ReadChunkSize;
if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - buffer.size())) {
bytesToRead = readBufferMaxSize - buffer.size();
@@ -491,33 +483,12 @@ bool QSerialPortPrivate::notifyRead()
if (!sucessResult) {
buffer.chop(bytesToRead);
- setError(QSerialPortErrorInfo(QSerialPort::ReadError, QSerialPort::tr("Error reading from device")));
+ setError(QSerialPortErrorInfo(QSerialPort::ReadError));
return false;
}
buffer.chop(bytesToRead - qMax(readBytes, DWORD(0)));
- // Process emulate policy.
- if ((policy != QSerialPort::IgnorePolicy) && parityErrorOccurred) {
-
- parityErrorOccurred = false;
-
- switch (policy) {
- case QSerialPort::SkipPolicy:
- buffer.getChar();
- return true;
- case QSerialPort::PassZeroPolicy:
- buffer.getChar();
- buffer.ungetChar('\0');
- break;
- case QSerialPort::StopReceivingPolicy:
- // FIXME: Maybe need disable read notifier?
- break;
- default:
- break;
- }
- }
-
if (readBytes > 0)
emit q->readyRead();
@@ -534,7 +505,7 @@ bool QSerialPortPrivate::notifyWrite()
DWORD bytesWritten = 0;
if (!::WriteFile(handle, ptr, nextSize, &bytesWritten, Q_NULLPTR)) {
- setError(QSerialPortErrorInfo(QSerialPort::WriteError, QSerialPort::tr("Error writing to device")));
+ setError(QSerialPortErrorInfo(QSerialPort::WriteError));
return false;
}
@@ -554,31 +525,6 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
return maxSize;
}
-void QSerialPortPrivate::processIoErrors(bool hasError)
-{
- if (hasError) {
- setError(QSerialPortErrorInfo(QSerialPort::ResourceError, QSerialPort::tr("Device disappeared from the system")));
- return;
- }
-
- DWORD errors = 0;
- if (!::ClearCommError(handle, &errors, Q_NULLPTR)) {
- setError(getSystemError());
- return;
- }
-
- if (errors & CE_FRAME) {
- setError(QSerialPortErrorInfo(QSerialPort::FramingError, QSerialPort::tr("Framing error detected while reading")));
- } else if (errors & CE_RXPARITY) {
- setError(QSerialPortErrorInfo(QSerialPort::ParityError, QSerialPort::tr("ParityError error detected while reading")));
- parityErrorOccurred = true;
- } else if (errors & CE_BREAK) {
- setError(QSerialPortErrorInfo(QSerialPort::BreakConditionError, QSerialPort::tr("Break condition detected while reading")));
- } else {
- setError(QSerialPortErrorInfo(QSerialPort::UnknownError, QSerialPort::tr("Unknown streaming error")));
- }
-}
-
inline bool QSerialPortPrivate::initialize(DWORD eventMask)
{
Q_Q(QSerialPort);
@@ -670,6 +616,9 @@ QSerialPortErrorInfo QSerialPortPrivate::getSystemError(int systemErrorCode) con
case ERROR_FILE_NOT_FOUND:
error.errorCode = QSerialPort::DeviceNotFoundError;
break;
+ case ERROR_PATH_NOT_FOUND:
+ error.errorCode = QSerialPort::DeviceNotFoundError;
+ break;
case ERROR_INVALID_NAME:
error.errorCode = QSerialPort::DeviceNotFoundError;
break;
@@ -708,7 +657,7 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
breaker.stop();
if (breaker.isWorked()) {
- setError(QSerialPortErrorInfo(QSerialPort::TimeoutError, QSerialPort::tr("Operation timed out")));
+ setError(QSerialPortErrorInfo(QSerialPort::TimeoutError));
} else {
if (checkRead) {
Q_ASSERT(selectForRead);
diff --git a/src/serialport/qserialportinfo_unix.cpp b/src/serialport/qserialportinfo_unix.cpp
index f3f5a27..f52516f 100644
--- a/src/serialport/qserialportinfo_unix.cpp
+++ b/src/serialport/qserialportinfo_unix.cpp
@@ -75,7 +75,8 @@ static QStringList filteredDeviceFilePaths()
<< QStringLiteral("ttymxc*") // Motorola IMX serial ports (i.e. Freescale i.MX).
<< QStringLiteral("ttyAMA*") // AMBA serial device for embedded platform on ARM (i.e. Raspberry Pi).
<< QStringLiteral("rfcomm*") // Bluetooth serial device.
- << QStringLiteral("ircomm*"); // IrDA serial device.
+ << QStringLiteral("ircomm*") // IrDA serial device.
+ << QStringLiteral("tnt*"); // Virtual tty0tty serial device.
#elif defined(Q_OS_FREEBSD)
<< QStringLiteral("cu*");
#elif defined(Q_OS_QNX)
@@ -436,6 +437,15 @@ static bool isRfcommDevice(const QString &portName)
return true;
}
+// provided by the tty0tty driver
+static bool isVirtualNullModemDevice(const QString &portName)
+{
+ if (!portName.startsWith(QLatin1String("tnt")))
+ return false;
+
+ return true;
+}
+
static QString ueventProperty(const QDir &targetDir, const QByteArray &pattern)
{
QFile f(QFileInfo(targetDir, QStringLiteral("uevent")).absoluteFilePath());
@@ -530,8 +540,10 @@ QList<QSerialPortInfo> availablePortsBySysfs(bool &ok)
const QString driverName = deviceDriver(targetDir);
if (driverName.isEmpty()) {
- if (!isRfcommDevice(priv.portName))
+ if (!isRfcommDevice(priv.portName)
+ && !isVirtualNullModemDevice(priv.portName)) {
continue;
+ }
}
priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(priv.portName);
@@ -700,8 +712,10 @@ QList<QSerialPortInfo> availablePortsByUdev(bool &ok)
priv.vendorIdentifier = deviceVendorIdentifier(dev.data(), priv.hasVendorIdentifier);
priv.productIdentifier = deviceProductIdentifier(dev.data(), priv.hasProductIdentifier);
} else {
- if (!isRfcommDevice(priv.portName))
+ if (!isRfcommDevice(priv.portName)
+ && !isVirtualNullModemDevice(priv.portName)) {
continue;
+ }
}
serialPortInfoList.append(priv);
diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp
index c5c9113..3a62bfa 100644
--- a/tests/auto/qserialport/tst_qserialport.cpp
+++ b/tests/auto/qserialport/tst_qserialport.cpp
@@ -38,6 +38,11 @@
#include <QThread>
Q_DECLARE_METATYPE(QSerialPort::SerialPortError);
+Q_DECLARE_METATYPE(QSerialPort::BaudRate);
+Q_DECLARE_METATYPE(QSerialPort::DataBits);
+Q_DECLARE_METATYPE(QSerialPort::Parity);
+Q_DECLARE_METATYPE(QSerialPort::StopBits);
+Q_DECLARE_METATYPE(QSerialPort::FlowControl);
Q_DECLARE_METATYPE(QIODevice::OpenMode);
Q_DECLARE_METATYPE(QIODevice::OpenModeFlag);
Q_DECLARE_METATYPE(Qt::ConnectionType);
@@ -85,6 +90,17 @@ private slots:
void openNotExisting_data();
void openNotExisting();
+ void baudRate_data();
+ void baudRate();
+ void dataBits_data();
+ void dataBits();
+ void parity_data();
+ void parity();
+ void stopBits_data();
+ void stopBits();
+ void flowControl_data();
+ void flowControl();
+
void flush();
void doubleFlush();
@@ -104,21 +120,24 @@ private slots:
void asynchronousWriteByTimer_data();
void asynchronousWriteByTimer();
-#ifdef Q_OS_WIN
+ void asyncReadWithLimitedReadBufferSize();
+
void readBufferOverflow();
void readAfterInputClear();
void synchronousReadWriteAfterAsynchronousReadWrite();
-#endif
void controlBreak();
+ void clearAfterOpen();
+
+ void readWriteWithDifferentBaudRate_data();
+ void readWriteWithDifferentBaudRate();
+
protected slots:
void handleBytesWrittenAndExitLoopSlot(qint64 bytesWritten);
void handleBytesWrittenAndExitLoopSlot2(qint64 bytesWritten);
private:
- void clearReceiver(const QString &customReceiverName = QString());
-
QString m_senderPortName;
QString m_receiverPortName;
QStringList m_availablePortNames;
@@ -137,24 +156,6 @@ tst_QSerialPort::tst_QSerialPort()
{
}
-// This method is a workaround for the "com0com" virtual serial port
-// driver or for the SOCAT utility. The problem is that the close/clear
-// methods have no effect on sender serial port. If any data didn't manage
-// to be transferred before closing, then this data will continue to be
-// transferred at next opening of sender port.
-// Thus, this behavior influences other tests and leads to the wrong results
-// (e.g. the receiver port on other test can receive some data which are
-// not expected). It is recommended to use this method for cleaning of
-// read FIFO of receiver for those tests in which reception of data is
-// required.
-void tst_QSerialPort::clearReceiver(const QString &customReceiverName)
-{
- QSerialPort receiver(customReceiverName.isEmpty()
- ? m_receiverPortName : customReceiverName);
- if (receiver.open(QIODevice::ReadOnly))
- enterLoopMsecs(100);
-}
-
void tst_QSerialPort::initTestCase()
{
m_senderPortName = QString::fromLocal8Bit(qgetenv("QTEST_SERIALPORT_SENDER"));
@@ -271,7 +272,7 @@ void tst_QSerialPort::openExisting()
foreach (const QString &serialPortName, m_availablePortNames) {
QSerialPort serialPort(serialPortName);
- QSignalSpy errorSpy(&serialPort, SIGNAL(error(QSerialPort::SerialPortError)));
+ QSignalSpy errorSpy(&serialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error));
QVERIFY(errorSpy.isValid());
QCOMPARE(serialPort.portName(), serialPortName);
@@ -303,7 +304,7 @@ void tst_QSerialPort::openNotExisting()
QSerialPort serialPort(serialPortName);
- QSignalSpy errorSpy(&serialPort, SIGNAL(error(QSerialPort::SerialPortError)));
+ QSignalSpy errorSpy(&serialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error));
QVERIFY(errorSpy.isValid());
QCOMPARE(serialPort.portName(), serialPortName);
@@ -315,6 +316,163 @@ void tst_QSerialPort::openNotExisting()
//QCOMPARE(qvariant_cast<QSerialPort::SerialPortError>(errorSpy.at(0).at(0)), errorCode);
}
+void tst_QSerialPort::baudRate_data()
+{
+ QTest::addColumn<qint32>("baudrate");
+ QTest::newRow("Baud1200") << static_cast<qint32>(QSerialPort::Baud1200);
+ QTest::newRow("Baud2400") << static_cast<qint32>(QSerialPort::Baud2400);
+ QTest::newRow("Baud4800") << static_cast<qint32>(QSerialPort::Baud4800);
+ QTest::newRow("Baud9600") << static_cast<qint32>(QSerialPort::Baud9600);
+ QTest::newRow("Baud19200") << static_cast<qint32>(QSerialPort::Baud19200);
+ QTest::newRow("Baud38400") << static_cast<qint32>(QSerialPort::Baud38400);
+ QTest::newRow("Baud57600") << static_cast<qint32>(QSerialPort::Baud57600);
+ QTest::newRow("Baud115200") << static_cast<qint32>(QSerialPort::Baud115200);
+
+ QTest::newRow("31250") << 31250; // custom baudrate (MIDI)
+}
+
+void tst_QSerialPort::baudRate()
+{
+ QFETCH(qint32, baudrate);
+
+ {
+ // setup before opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.setBaudRate(baudrate));
+ QCOMPARE(serialPort.baudRate(), baudrate);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ }
+
+ {
+ // setup after opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ QVERIFY(serialPort.setBaudRate(baudrate));
+ QCOMPARE(serialPort.baudRate(), baudrate);
+ }
+}
+
+void tst_QSerialPort::dataBits_data()
+{
+ QTest::addColumn<QSerialPort::DataBits>("databits");
+ QTest::newRow("Data5") << QSerialPort::Data5;
+ QTest::newRow("Data6") << QSerialPort::Data6;
+ QTest::newRow("Data7") << QSerialPort::Data7;
+ QTest::newRow("Data8") << QSerialPort::Data8;
+}
+
+void tst_QSerialPort::dataBits()
+{
+ QFETCH(QSerialPort::DataBits, databits);
+
+ {
+ // setup before opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.setDataBits(databits));
+ QCOMPARE(serialPort.dataBits(), databits);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ }
+
+ {
+ // setup after opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ QVERIFY(serialPort.setDataBits(databits));
+ QCOMPARE(serialPort.dataBits(), databits);
+ }
+}
+
+void tst_QSerialPort::parity_data()
+{
+ QTest::addColumn<QSerialPort::Parity>("parity");
+ QTest::newRow("NoParity") << QSerialPort::NoParity;
+ QTest::newRow("EvenParity") << QSerialPort::EvenParity;
+ QTest::newRow("OddParity") << QSerialPort::OddParity;
+ QTest::newRow("SpaceParity") << QSerialPort::SpaceParity;
+ QTest::newRow("MarkParity") << QSerialPort::MarkParity;
+}
+
+void tst_QSerialPort::parity()
+{
+ QFETCH(QSerialPort::Parity, parity);
+
+ {
+ // setup before opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.setParity(parity));
+ QCOMPARE(serialPort.parity(), parity);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ }
+
+ {
+ // setup after opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ QVERIFY(serialPort.setParity(parity));
+ QCOMPARE(serialPort.parity(), parity);
+ }
+}
+
+void tst_QSerialPort::stopBits_data()
+{
+ QTest::addColumn<QSerialPort::StopBits>("stopbits");
+ QTest::newRow("OneStop") << QSerialPort::OneStop;
+#ifdef Q_OS_WIN
+ QTest::newRow("OneAndHalfStop") << QSerialPort::OneAndHalfStop;
+#endif
+ QTest::newRow("TwoStop") << QSerialPort::TwoStop;
+}
+
+void tst_QSerialPort::stopBits()
+{
+ QFETCH(QSerialPort::StopBits, stopbits);
+
+ {
+ // setup before opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.setStopBits(stopbits));
+ QCOMPARE(serialPort.stopBits(), stopbits);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ }
+
+ {
+ // setup after opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ QVERIFY(serialPort.setStopBits(stopbits));
+ QCOMPARE(serialPort.stopBits(), stopbits);
+ }
+}
+
+void tst_QSerialPort::flowControl_data()
+{
+ QTest::addColumn<QSerialPort::FlowControl>("flowcontrol");
+ QTest::newRow("NoFlowControl") << QSerialPort::NoFlowControl;
+ QTest::newRow("HardwareControl") << QSerialPort::HardwareControl;
+ QTest::newRow("SoftwareControl") << QSerialPort::SoftwareControl;
+}
+
+void tst_QSerialPort::flowControl()
+{
+ QFETCH(QSerialPort::FlowControl, flowcontrol);
+
+ {
+ // setup before opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.setFlowControl(flowcontrol));
+ QCOMPARE(serialPort.flowControl(), flowcontrol);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ }
+
+ {
+ // setup after opening
+ QSerialPort serialPort(m_senderPortName);
+ QVERIFY(serialPort.open(QIODevice::ReadWrite));
+ QVERIFY(serialPort.setFlowControl(flowcontrol));
+ QCOMPARE(serialPort.flowControl(), flowcontrol);
+ }
+}
+
void tst_QSerialPort::handleBytesWrittenAndExitLoopSlot(qint64 bytesWritten)
{
QCOMPARE(bytesWritten, qint64(alphabetArray.size() + newlineArray.size()));
@@ -332,8 +490,8 @@ void tst_QSerialPort::flush()
QVERIFY(dummySerialPort.open(QIODevice::ReadOnly));
QSerialPort serialPort(m_senderPortName);
- connect(&serialPort, SIGNAL(bytesWritten(qint64)), this, SLOT(handleBytesWrittenAndExitLoopSlot(qint64)));
- QSignalSpy bytesWrittenSpy(&serialPort, SIGNAL(bytesWritten(qint64)));
+ connect(&serialPort, &QSerialPort::bytesWritten, this, &tst_QSerialPort::handleBytesWrittenAndExitLoopSlot);
+ QSignalSpy bytesWrittenSpy(&serialPort, &QSerialPort::bytesWritten);
QVERIFY(serialPort.open(QIODevice::WriteOnly));
serialPort.write(alphabetArray + newlineArray);
@@ -367,8 +525,8 @@ void tst_QSerialPort::doubleFlush()
QVERIFY(dummySerialPort.open(QIODevice::ReadOnly));
QSerialPort serialPort(m_senderPortName);
- connect(&serialPort, SIGNAL(bytesWritten(qint64)), this, SLOT(handleBytesWrittenAndExitLoopSlot2(qint64)));
- QSignalSpy bytesWrittenSpy(&serialPort, SIGNAL(bytesWritten(qint64)));
+ connect(&serialPort, &QSerialPort::bytesWritten, this, &tst_QSerialPort::handleBytesWrittenAndExitLoopSlot2);
+ QSignalSpy bytesWrittenSpy(&serialPort, &QSerialPort::bytesWritten);
QVERIFY(serialPort.open(QIODevice::WriteOnly));
serialPort.write(alphabetArray);
@@ -401,12 +559,9 @@ void tst_QSerialPort::waitForBytesWritten()
void tst_QSerialPort::waitForReadyReadWithTimeout()
{
- clearReceiver();
-#ifdef Q_OS_WIN
// the dummy device on other side also has to be open
QSerialPort dummySerialPort(m_senderPortName);
QVERIFY(dummySerialPort.open(QIODevice::WriteOnly));
-#endif
QSerialPort receiverSerialPort(m_receiverPortName);
QVERIFY(receiverSerialPort.open(QIODevice::ReadOnly));
@@ -417,17 +572,13 @@ void tst_QSerialPort::waitForReadyReadWithTimeout()
void tst_QSerialPort::waitForReadyReadWithOneByte()
{
-#ifdef Q_OS_WIN
- clearReceiver();
-#endif
-
const qint64 oneByte = 1;
const int waitMsecs = 50;
QSerialPort senderSerialPort(m_senderPortName);
QVERIFY(senderSerialPort.open(QIODevice::WriteOnly));
QSerialPort receiverSerialPort(m_receiverPortName);
- QSignalSpy readyReadSpy(&receiverSerialPort, SIGNAL(readyRead()));
+ QSignalSpy readyReadSpy(&receiverSerialPort, &QSerialPort::readyRead);
QVERIFY(readyReadSpy.isValid());
QVERIFY(receiverSerialPort.open(QIODevice::ReadOnly));
QCOMPARE(senderSerialPort.write(alphabetArray.constData(), oneByte), oneByte);
@@ -440,16 +591,12 @@ void tst_QSerialPort::waitForReadyReadWithOneByte()
void tst_QSerialPort::waitForReadyReadWithAlphabet()
{
-#ifdef Q_OS_WIN
- clearReceiver();
-#endif
-
const int waitMsecs = 50;
QSerialPort senderSerialPort(m_senderPortName);
QVERIFY(senderSerialPort.open(QIODevice::WriteOnly));
QSerialPort receiverSerialPort(m_receiverPortName);
- QSignalSpy readyReadSpy(&receiverSerialPort, SIGNAL(readyRead()));
+ QSignalSpy readyReadSpy(&receiverSerialPort, &QSerialPort::readyRead);
QVERIFY(readyReadSpy.isValid());
QVERIFY(receiverSerialPort.open(QIODevice::ReadOnly));
QCOMPARE(senderSerialPort.write(alphabetArray), qint64(alphabetArray.size()));
@@ -465,11 +612,6 @@ void tst_QSerialPort::waitForReadyReadWithAlphabet()
void tst_QSerialPort::twoStageSynchronousLoopback()
{
-#ifdef Q_OS_WIN
- clearReceiver();
- clearReceiver(m_senderPortName);
-#endif
-
QSerialPort senderPort(m_senderPortName);
QVERIFY(senderPort.open(QSerialPort::ReadWrite));
@@ -508,10 +650,6 @@ void tst_QSerialPort::twoStageSynchronousLoopback()
void tst_QSerialPort::synchronousReadWrite()
{
-#ifdef Q_OS_WIN
- clearReceiver();
-#endif
-
QSerialPort senderPort(m_senderPortName);
QVERIFY(senderPort.open(QSerialPort::WriteOnly));
@@ -539,7 +677,7 @@ public:
explicit AsyncReader(QSerialPort &port, Qt::ConnectionType connectionType, int expectedBytesCount)
: serialPort(port), expectedBytesCount(expectedBytesCount)
{
- connect(&serialPort, SIGNAL(readyRead()), this, SLOT(receive()), connectionType);
+ connect(&serialPort, &QSerialPort::readyRead, this, &AsyncReader::receive, connectionType);
}
private slots:
@@ -565,7 +703,7 @@ public:
{
writeBuffer.setData(dataToWrite);
writeBuffer.open(QIODevice::ReadOnly);
- connect(&serialPort, SIGNAL(bytesWritten(qint64)), this, SLOT(send()), connectionType);
+ connect(&serialPort, &QSerialPort::bytesWritten, this, &AsyncWriterByBytesWritten::send, connectionType);
send();
}
@@ -595,10 +733,6 @@ void tst_QSerialPort::asynchronousWriteByBytesWritten_data()
void tst_QSerialPort::asynchronousWriteByBytesWritten()
{
-#ifdef Q_OS_WIN
- clearReceiver();
-#endif
-
QFETCH(Qt::ConnectionType, readConnectionType);
QFETCH(Qt::ConnectionType, writeConnectionType);
@@ -626,7 +760,7 @@ public:
{
writeBuffer.setData(dataToWrite);
writeBuffer.open(QIODevice::ReadOnly);
- connect(&timer, SIGNAL(timeout()), this, SLOT(send()), connectionType);
+ connect(&timer, &QTimer::timeout, this, &AsyncWriterByTimer::send, connectionType);
timer.start(0);
}
@@ -659,10 +793,6 @@ void tst_QSerialPort::asynchronousWriteByTimer_data()
void tst_QSerialPort::asynchronousWriteByTimer()
{
-#ifdef Q_OS_WIN
- clearReceiver();
-#endif
-
QFETCH(Qt::ConnectionType, readConnectionType);
QFETCH(Qt::ConnectionType, writeConnectionType);
@@ -680,11 +810,51 @@ void tst_QSerialPort::asynchronousWriteByTimer()
QCOMPARE(receiverPort.readAll(), alphabetArray);
}
-#ifdef Q_OS_WIN
-void tst_QSerialPort::readBufferOverflow()
+class AsyncReader2 : public QObject
+{
+ Q_OBJECT
+public:
+ explicit AsyncReader2(QSerialPort &port, const QByteArray &expectedData)
+ : serialPort(port), expectedData(expectedData)
+ {
+ connect(&serialPort, &QSerialPort::readyRead, this, &AsyncReader2::receive);
+ }
+
+private slots:
+ void receive()
+ {
+ receivedData.append(serialPort.readAll());
+ if (receivedData == expectedData)
+ tst_QSerialPort::exitLoop();
+ }
+
+private:
+ QSerialPort &serialPort;
+ const QByteArray expectedData;
+ QByteArray receivedData;
+};
+
+void tst_QSerialPort::asyncReadWithLimitedReadBufferSize()
{
- clearReceiver();
+ QSerialPort senderPort(m_senderPortName);
+ QVERIFY(senderPort.open(QSerialPort::WriteOnly));
+
+ QSerialPort receiverPort(m_receiverPortName);
+ QVERIFY(receiverPort.open(QSerialPort::ReadOnly));
+
+ receiverPort.setReadBufferSize(1);
+ QCOMPARE(receiverPort.readBufferSize(), qint64(1));
+ AsyncReader2 reader(receiverPort, alphabetArray);
+
+ QCOMPARE(senderPort.write(alphabetArray), qint64(alphabetArray.size()));
+
+ enterLoop(1);
+ QVERIFY2(!timeout(), "Timed out when waiting for the read or write.");
+}
+
+void tst_QSerialPort::readBufferOverflow()
+{
QSerialPort senderPort(m_senderPortName);
QVERIFY(senderPort.open(QSerialPort::WriteOnly));
@@ -712,8 +882,6 @@ void tst_QSerialPort::readBufferOverflow()
void tst_QSerialPort::readAfterInputClear()
{
- clearReceiver();
-
QSerialPort senderPort(m_senderPortName);
QVERIFY(senderPort.open(QSerialPort::WriteOnly));
@@ -843,7 +1011,7 @@ void tst_QSerialPort::synchronousReadWriteAfterAsynchronousReadWrite()
QMetaObject::invokeMethod(slave, "open", Qt::QueuedConnection);
- tst_QSerialPort::enterLoopMsecs(500);
+ tst_QSerialPort::enterLoopMsecs(2000);
thread.quit();
thread.wait();
@@ -851,8 +1019,6 @@ void tst_QSerialPort::synchronousReadWriteAfterAsynchronousReadWrite()
QVERIFY2(!timeout(), "Timed out when testing of transactions.");
}
-#endif
-
class BreakReader : public QObject
{
Q_OBJECT
@@ -860,7 +1026,7 @@ public:
explicit BreakReader(QSerialPort &port)
: serialPort(port)
{
- connect(&serialPort, SIGNAL(readyRead()), this, SLOT(receive()));
+ connect(&serialPort, &QSerialPort::readyRead, this, &BreakReader::receive);
}
private slots:
@@ -875,15 +1041,11 @@ private:
void tst_QSerialPort::controlBreak()
{
-#ifdef Q_OS_WIN
- clearReceiver();
-#endif
-
QSerialPort senderPort(m_senderPortName);
QVERIFY(senderPort.open(QSerialPort::WriteOnly));
QCOMPARE(senderPort.isBreakEnabled(), false);
- QSignalSpy breakSpy(&senderPort, SIGNAL(breakEnabledChanged(bool)));
+ QSignalSpy breakSpy(&senderPort, &QSerialPort::breakEnabledChanged);
QVERIFY(breakSpy.isValid());
QSerialPort receiverPort(m_receiverPortName);
@@ -910,5 +1072,88 @@ void tst_QSerialPort::controlBreak()
QCOMPARE(qvariant_cast<bool>(breakSpy.at(1).at(0)), false);
}
+void tst_QSerialPort::clearAfterOpen()
+{
+ QSerialPort senderPort(m_senderPortName);
+ QVERIFY(senderPort.open(QSerialPort::ReadWrite));
+ QCOMPARE(senderPort.error(), QSerialPort::NoError);
+ QVERIFY(senderPort.clear());
+ QCOMPARE(senderPort.error(), QSerialPort::NoError);
+}
+
+void tst_QSerialPort::readWriteWithDifferentBaudRate_data()
+{
+ QTest::addColumn<int>("senderBaudRate");
+ QTest::addColumn<int>("receiverBaudRate");
+ QTest::addColumn<bool>("expectedResult");
+
+ QTest::newRow("9600, 9600") << 9600 << 9600 << true;
+ QTest::newRow("115200, 115200") << 115200 << 115200 << true;
+ QTest::newRow("9600, 115200") << 9600 << 115200 << false;
+
+ QTest::newRow("31250, 31250") << 31250 << 31250 << true; // custom baudrate (MIDI)
+ QTest::newRow("31250, 115200") << 31250 << 115200 << false;
+
+#ifdef Q_OS_LINUX
+ QTest::newRow("14400, 14400") << 14400 << 14400 << true; // custom baudrate for Linux
+ QTest::newRow("14400, 115200") << 14400 << 115200 << false;
+#endif
+}
+
+void tst_QSerialPort::readWriteWithDifferentBaudRate()
+{
+ QFETCH(int, senderBaudRate);
+ QFETCH(int, receiverBaudRate);
+ QFETCH(bool, expectedResult);
+
+ {
+ // setup before opening
+ QSerialPort senderSerialPort(m_senderPortName);
+ QVERIFY(senderSerialPort.setBaudRate(senderBaudRate));
+ QCOMPARE(senderSerialPort.baudRate(), senderBaudRate);
+ QVERIFY(senderSerialPort.open(QSerialPort::ReadWrite));
+ QSerialPort receiverSerialPort(m_receiverPortName);
+ QVERIFY(receiverSerialPort.setBaudRate(receiverBaudRate));
+ QCOMPARE(receiverSerialPort.baudRate(), receiverBaudRate);
+ QVERIFY(receiverSerialPort.open(QSerialPort::ReadWrite));
+
+ QCOMPARE(senderSerialPort.write(alphabetArray), qint64(alphabetArray.size()));
+ QVERIFY(senderSerialPort.waitForBytesWritten(500));
+
+ do {
+ QVERIFY(receiverSerialPort.waitForReadyRead(500));
+ } while (receiverSerialPort.bytesAvailable() < alphabetArray.size());
+
+ if (expectedResult)
+ QVERIFY(receiverSerialPort.readAll() == alphabetArray);
+ else
+ QVERIFY(receiverSerialPort.readAll() != alphabetArray);
+ }
+
+ {
+ // setup after opening
+ QSerialPort senderSerialPort(m_senderPortName);
+ QVERIFY(senderSerialPort.open(QSerialPort::ReadWrite));
+ QVERIFY(senderSerialPort.setBaudRate(senderBaudRate));
+ QCOMPARE(senderSerialPort.baudRate(), senderBaudRate);
+ QSerialPort receiverSerialPort(m_receiverPortName);
+ QVERIFY(receiverSerialPort.open(QSerialPort::ReadWrite));
+ QVERIFY(receiverSerialPort.setBaudRate(receiverBaudRate));
+ QCOMPARE(receiverSerialPort.baudRate(), receiverBaudRate);
+
+ QCOMPARE(senderSerialPort.write(alphabetArray), qint64(alphabetArray.size()));
+ QVERIFY(senderSerialPort.waitForBytesWritten(500));
+
+ do {
+ QVERIFY(receiverSerialPort.waitForReadyRead(500));
+ } while (receiverSerialPort.bytesAvailable() < alphabetArray.size());
+
+ if (expectedResult)
+ QVERIFY(receiverSerialPort.readAll() == alphabetArray);
+ else
+ QVERIFY(receiverSerialPort.readAll() != alphabetArray);
+ }
+}
+
QTEST_MAIN(tst_QSerialPort)
#include "tst_qserialport.moc"