summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-12-12 18:30:35 +0100
committerLiang Qi <liang.qi@qt.io>2016-12-12 18:33:32 +0100
commit55632d600076aa934663598ddb462ae122958685 (patch)
tree19a54c0c8ac4cab1e29e85827d893df817473e9b
parentbd1fb0a6aa2a7522fe2d1b0c21e3523eb75231d5 (diff)
parentbb999860c46757d9afd6c36fdba11ebe96caccc1 (diff)
Merge remote-tracking branch 'origin/5.8' into dev
Conflicts: examples/serialbus/can/mainwindow.cpp Change-Id: I8d821a832bc5bf966230b4f66f0113929b3114dc
-rw-r--r--.gitignore1
-rw-r--r--config.tests/language/language.pro9
-rw-r--r--config.tests/language/main.cpp122
-rw-r--r--config.tests/socketcan/socketcan.pro2
-rw-r--r--config.tests/socketcan_fd/socketcan_fd.pro2
-rw-r--r--configure.json5
-rw-r--r--dist/changes-5.7.133
-rw-r--r--examples/serialbus/can/mainwindow.cpp31
-rw-r--r--examples/serialbus/can/mainwindow.ui15
-rw-r--r--qtserialbus.pro12
-rw-r--r--src/plugins/canbus/canbus.pro4
-rw-r--r--src/plugins/canbus/peakcan/main.cpp2
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp5
-rw-r--r--src/plugins/canbus/tinycan/main.cpp2
-rw-r--r--src/serialbus/configure.json53
-rw-r--r--src/serialbus/doc/qtserialbus.qdocconf1
-rw-r--r--src/serialbus/doc/src/peakcan.qdoc6
-rw-r--r--src/serialbus/doc/src/socketcan.qdoc14
-rw-r--r--src/serialbus/doc/src/tinycan.qdoc6
-rw-r--r--src/serialbus/doc/src/vectorcan.qdoc4
-rw-r--r--src/serialbus/qcanbus.cpp6
-rw-r--r--src/serialbus/qcanbusdevice.cpp48
-rw-r--r--src/serialbus/qcanbusfactory.cpp4
-rw-r--r--src/serialbus/qcanbusframe.cpp100
-rw-r--r--src/serialbus/qcanbusframe.h85
-rw-r--r--src/serialbus/qmodbusclient.cpp2
-rw-r--r--src/serialbus/qmodbusdataunit.cpp4
-rw-r--r--src/serialbus/qmodbusdevice.cpp2
-rw-r--r--src/serialbus/qmodbusdeviceidentification.cpp2
-rw-r--r--src/serialbus/qmodbuspdu.cpp16
-rw-r--r--src/serialbus/qmodbuspdu.h4
-rw-r--r--src/serialbus/qmodbusreply.cpp2
-rw-r--r--src/serialbus/qmodbusrtuserialmaster.cpp7
-rw-r--r--src/serialbus/qmodbusrtuserialmaster_p.h5
-rw-r--r--src/serialbus/qmodbusrtuserialslave.cpp2
-rw-r--r--src/serialbus/qmodbusserver.cpp2
-rw-r--r--src/serialbus/qmodbustcpclient.cpp2
-rw-r--r--src/serialbus/qmodbustcpserver.cpp2
-rw-r--r--src/tools/canbusutil/canbusutil.cpp42
-rw-r--r--src/tools/canbusutil/canbusutil.h9
-rw-r--r--src/tools/canbusutil/main.cpp5
-rw-r--r--src/tools/canbusutil/readtask.cpp30
-rw-r--r--src/tools/canbusutil/readtask.h2
-rw-r--r--sync.profile5
-rw-r--r--tests/auto/qcanbusframe/tst_qcanbusframe.cpp129
-rw-r--r--tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp19
46 files changed, 486 insertions, 379 deletions
diff --git a/.gitignore b/.gitignore
index 9bc1090..98ece5a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,7 @@ tests/auto/qmodbusserver/tst_qmodbusserver
*.ipch
*_wrapper.bat
*_wrapper.sh
+qtserialbus-config.pri
# Visual Studio generated files
*.ib_pdb_index
diff --git a/config.tests/language/language.pro b/config.tests/language/language.pro
deleted file mode 100644
index 908d781..0000000
--- a/config.tests/language/language.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-TEMPLATE = app
-
-CONFIG += qt
-CONFIG += c++11
-CONFIG += console
-
-QT = core
-
-SOURCES += main.cpp
diff --git a/config.tests/language/main.cpp b/config.tests/language/main.cpp
deleted file mode 100644
index 1d6732b..0000000
--- a/config.tests/language/main.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtSerialBus module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
-
-#include <memory>
-#include <type_traits>
-
-struct Base
-{
- virtual void overrideMe() = 0;
-};
-
-struct Test : public Base
-{
- // strongly typed enums
- enum struct Enum : char {
- EnumA, EnumB
- };
-
- Test() = default; // defaulted and
- Test(const Test&) = delete; // deleted ctors
-
- explicit Test(int i)
- : Test(0, i) { }
- Test(int a, int i)
- : m_intA(a), m_intI(i) {}
-
- // std::is_same
- template <typename T, typename ... Ts> struct IsType { enum { value = false }; };
- template <typename T, typename T1, typename ... Ts> struct IsType<T, T1, Ts...> {
- enum { value = std::is_same<T, T1>::value || IsType<T, Ts...>::value };
- };
-
- // std::is_pod
- template <typename T> void test(T) const {
- static_assert(std::is_pod<T>::value, "Only POD supported.");
- static_assert(IsType<T, int>::value, "Only int supported.");
- }
-
- // variadics
- template <typename ... Args>
- void setValues(Args ... values)
- {
- const int size = sizeof...(Args);
- int tmp[size] = { (test(values), void(), '0')... };
- (void) (tmp);
- }
-
- // override keyword
- void overrideMe() override {}
-
- // const and constexpr
- Q_DECL_CONSTEXPR qint64 first() const Q_DECL_NOTHROW { return m_intA; }
- Q_DECL_RELAXED_CONSTEXPR void setFirst(int a) Q_DECL_NOTHROW { m_intA = a; }
-
- // non-static data member initializers
- int m_intA = 0;
- int m_intI = 0;
-};
-
-using func = int (*) (int, int);
-int total(int a, int i) { return a + i; }
-
-int main(int /*argc*/, char** /*argv*/)
-{
- // nullptr
- Test *t = nullptr;
- Test stackT(155);
- t = &stackT;
-
- // variadics
- t->setValues(1, 2, 3, 4, 5);
-
- // lambda and auto
- auto m = [](int a, int b) -> int {
- return a * b;
- };
-
- // decltype
- decltype(m) multiply = m;
- multiply(t->m_intA, t->m_intI);
-
- // alias templates
- func f = total;
- f(t->m_intA, t->m_intI);
-
- return 0;
-}
diff --git a/config.tests/socketcan/socketcan.pro b/config.tests/socketcan/socketcan.pro
index 104ea1e..3f6c643 100644
--- a/config.tests/socketcan/socketcan.pro
+++ b/config.tests/socketcan/socketcan.pro
@@ -1,4 +1,2 @@
-TEMPLATE = app
-
SOURCES += main.cpp
diff --git a/config.tests/socketcan_fd/socketcan_fd.pro b/config.tests/socketcan_fd/socketcan_fd.pro
index 104ea1e..3f6c643 100644
--- a/config.tests/socketcan_fd/socketcan_fd.pro
+++ b/config.tests/socketcan_fd/socketcan_fd.pro
@@ -1,4 +1,2 @@
-TEMPLATE = app
-
SOURCES += main.cpp
diff --git a/configure.json b/configure.json
new file mode 100644
index 0000000..c43610f
--- /dev/null
+++ b/configure.json
@@ -0,0 +1,5 @@
+{
+ "subconfigs": [
+ "src/serialbus"
+ ]
+}
diff --git a/dist/changes-5.7.1 b/dist/changes-5.7.1
new file mode 100644
index 0000000..bcbac29
--- /dev/null
+++ b/dist/changes-5.7.1
@@ -0,0 +1,33 @@
+Qt 5.7.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.7.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+http://doc.qt.io/qt-5/index.html
+
+The Qt version 5.7 series is binary compatible with the 5.6.x series.
+Applications compiled for 5.6 will continue to run with 5.7.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+QtSerialBus
+---------
+
+ - Build system improvements
+ - Documentation improvements
+ - Several fixes to CAN-Examples
+ - Several PeakCAN and SocketCAN implementation improvements
+ - Expand license scope from "Qt GUI Toolkit" to "Qt Toolkit"
+
+ - QTBUG-53171: CAN: Fix displaying extended identifiers below 0x800
+ - QTBUG-53171: CAN: Fix displaying data bytes for remote request frames
+ - QTBUG-53767: Fix Modbus timeout on Windows.
+ - QTBUG-53277: Make adueditor compile on platforms with QT_NO_CLIPBOARD
+ - QTBUG-56009: Fix ModbusRtuSerialMaster stack overflow on close
diff --git a/examples/serialbus/can/mainwindow.cpp b/examples/serialbus/can/mainwindow.cpp
index 135faf1..ac24f43 100644
--- a/examples/serialbus/can/mainwindow.cpp
+++ b/examples/serialbus/can/mainwindow.cpp
@@ -42,15 +42,12 @@
#include "ui_mainwindow.h"
#include "connectdialog.h"
-#include <QCanBusFrame>
#include <QCanBus>
+#include <QCanBusFrame>
#include <QCloseEvent>
+#include <QtDebug>
#include <QTimer>
-#include <QtCore/qbytearray.h>
-#include <QtCore/qvariant.h>
-#include <QtCore/qdebug.h>
-
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
m_ui(new Ui::MainWindow)
@@ -94,6 +91,7 @@ void MainWindow::initActionsConnections()
connect(m_ui->actionDisconnect, &QAction::triggered, this, &MainWindow::disconnectDevice);
connect(m_ui->actionQuit, &QAction::triggered, this, &QWidget::close);
connect(m_ui->actionAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt);
+ connect(m_ui->actionClearLog, &QAction::triggered, m_ui->receivedMessagesEdit, &QTextEdit::clear);
}
void MainWindow::receiveError(QCanBusDevice::CanBusError error) const
@@ -191,19 +189,21 @@ void MainWindow::checkMessages()
if (!m_canDevice)
return;
- const QCanBusFrame frame = m_canDevice->readFrame();
+ while (m_canDevice->framesAvailable()) {
+ const QCanBusFrame frame = m_canDevice->readFrame();
- QString view;
- if (frame.frameType() == QCanBusFrame::ErrorFrame)
- view = m_canDevice->interpretErrorFrame(frame);
- else
- view = frame.toString();
+ QString view;
+ if (frame.frameType() == QCanBusFrame::ErrorFrame)
+ view = m_canDevice->interpretErrorFrame(frame);
+ else
+ view = frame.toString();
- const QString time = QString::fromLatin1("%1.%2 ")
- .arg(frame.timeStamp().seconds(), 10, 10, QLatin1Char(' '))
- .arg(frame.timeStamp().microSeconds() / 100, 4, 10, QLatin1Char('0'));
+ const QString time = QString::fromLatin1("%1.%2 ")
+ .arg(frame.timeStamp().seconds(), 10, 10, QLatin1Char(' '))
+ .arg(frame.timeStamp().microSeconds() / 100, 4, 10, QLatin1Char('0'));
- m_ui->receivedMessagesEdit->append(time + view);
+ m_ui->receivedMessagesEdit->append(time + view);
+ }
}
static QByteArray dataFromHex(const QString &hex)
@@ -231,6 +231,7 @@ void MainWindow::sendMessage() const
frame.setFrameId(id);
frame.setExtendedFrameFormat(m_ui->effBox->checkState());
+ frame.setFlexibleDataRateFormat(m_ui->fdBox->checkState());
if (m_ui->remoteFrame->isChecked())
frame.setFrameType(QCanBusFrame::RemoteRequestFrame);
diff --git a/examples/serialbus/can/mainwindow.ui b/examples/serialbus/can/mainwindow.ui
index 4a3fcf9..38e1157 100644
--- a/examples/serialbus/can/mainwindow.ui
+++ b/examples/serialbus/can/mainwindow.ui
@@ -143,7 +143,7 @@ Otherwise, the standard format with 11 bit idenfier is used.</string>
<enum>QFrame::StyledPanel</enum>
</property>
<property name="text">
- <string>Timestamp CAN-ID DLC Data</string>
+ <string>Timestamp CAN-ID DLC Data</string>
</property>
</widget>
</item>
@@ -190,6 +190,8 @@ Otherwise, the standard format with 11 bit idenfier is used.</string>
<addaction name="actionConnect"/>
<addaction name="actionDisconnect"/>
<addaction name="separator"/>
+ <addaction name="actionClearLog"/>
+ <addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuHelp">
@@ -210,6 +212,8 @@ Otherwise, the standard format with 11 bit idenfier is used.</string>
</attribute>
<addaction name="actionConnect"/>
<addaction name="actionDisconnect"/>
+ <addaction name="separator"/>
+ <addaction name="actionClearLog"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionConnect">
@@ -244,6 +248,15 @@ Otherwise, the standard format with 11 bit idenfier is used.</string>
<string>&amp;About Qt</string>
</property>
</action>
+ <action name="actionClearLog">
+ <property name="icon">
+ <iconset resource="can.qrc">
+ <normaloff>:/images/clear.png</normaloff>:/images/clear.png</iconset>
+ </property>
+ <property name="text">
+ <string>Clear &amp;Log</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
diff --git a/qtserialbus.pro b/qtserialbus.pro
index d0e94f7..469da33 100644
--- a/qtserialbus.pro
+++ b/qtserialbus.pro
@@ -4,16 +4,4 @@ lessThan(QT_MAJOR_VERSION, 5) {
message("Cannot build current QtSerialBus sources with Qt version $${QT_VERSION}.")
}
-load(configure)
-qtCompileTest(language)
-qtCompileTest(socketcan)
-qtCompileTest(socketcan_fd)
load(qt_parts)
-
-requires(config_language) # enforce defined set of C++11
-!config_language:warning("Cannot compile the module with your compiler, missing C++11 language features.")
-
-linux {
- !config_socketcan:warning("You need linux/can.h and linux/can/raw.h linux headers for socketCAN support, disabling it")
- !config_socketcan_fd:warning("Newer kernel needed for flexible data-rate frame support 'canfd_frame'")
-}
diff --git a/src/plugins/canbus/canbus.pro b/src/plugins/canbus/canbus.pro
index a2e5304..0304dcc 100644
--- a/src/plugins/canbus/canbus.pro
+++ b/src/plugins/canbus/canbus.pro
@@ -1,6 +1,8 @@
TEMPLATE = subdirs
-config_socketcan {
+include($$OUT_PWD/../../serialbus/qtserialbus-config.pri)
+QT_FOR_CONFIG += serialbus-private
+qtConfig(socketcan) {
SUBDIRS += socketcan
}
diff --git a/src/plugins/canbus/peakcan/main.cpp b/src/plugins/canbus/peakcan/main.cpp
index d4886a9..00b4d36 100644
--- a/src/plugins/canbus/peakcan/main.cpp
+++ b/src/plugins/canbus/peakcan/main.cpp
@@ -55,7 +55,7 @@ public:
{
QString errorReason;
if (!PeakCanBackend::canCreate(&errorReason)) {
- qWarning("%s", qUtf8Printable(errorReason));
+ qWarning("%ls", qUtf16Printable(errorReason));
if (errorMessage)
*errorMessage = errorReason;
return nullptr;
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index c9781d1..8974279 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.cpp
+++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp
@@ -368,7 +368,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
qWarning() << QString("payload (%1 bytes) is too large for chosen frame size of "
"maximal %2 bytes. Frame is discarded.").
arg(payloadSize).arg(canFdOptionEnabled ? CANFD_MAX_DLEN : CAN_MAX_DLEN);
- if (!canFdOptionEnabled && payloadSize <= CANFD_MAX_DLEN)
+ if (!canFdOptionEnabled && newData.hasFlexibleDataRateFormat())
setError(tr("Sending CAN FD frame although CAN FD option not enabled."),
QCanBusDevice::WriteError);
else
@@ -378,7 +378,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
}
qint64 bytesWritten = 0;
- if (canFdOptionEnabled) {
+ if (newData.hasFlexibleDataRateFormat()) {
canfd_frame frame;
frame.len = newData.payload().size();
frame.can_id = canId;
@@ -600,6 +600,7 @@ void SocketCanBackend::readSocket()
const QCanBusFrame::TimeStamp stamp(timeStamp.tv_sec, timeStamp.tv_usec);
QCanBusFrame bufferedFrame;
bufferedFrame.setTimeStamp(stamp);
+ bufferedFrame.setFlexibleDataRateFormat(bytesReceived == CANFD_MTU);
bufferedFrame.setExtendedFrameFormat(frame.can_id & CAN_EFF_FLAG);
Q_ASSERT(frame.len <= CANFD_MAX_DLEN);
diff --git a/src/plugins/canbus/tinycan/main.cpp b/src/plugins/canbus/tinycan/main.cpp
index 5bce912..fe988ba 100644
--- a/src/plugins/canbus/tinycan/main.cpp
+++ b/src/plugins/canbus/tinycan/main.cpp
@@ -55,7 +55,7 @@ public:
{
QString errorReason;
if (!TinyCanBackend::canCreate(&errorReason)) {
- qWarning("%s", qUtf8Printable(errorReason));
+ qWarning("%ls", qUtf16Printable(errorReason));
if (errorMessage)
*errorMessage = errorReason;
return nullptr;
diff --git a/src/serialbus/configure.json b/src/serialbus/configure.json
new file mode 100644
index 0000000..d640f57
--- /dev/null
+++ b/src/serialbus/configure.json
@@ -0,0 +1,53 @@
+{
+ "module": "serialbus",
+ "testDir": "../../config.tests",
+
+ "tests": {
+ "socketcan": {
+ "label": "Socket CAN",
+ "type": "compile",
+ "test": "socketcan"
+ },
+ "socketcan_fd": {
+ "label": "Socket CAN FD",
+ "type": "compile",
+ "test": "socketcan_fd"
+ }
+ },
+
+ "features": {
+ "socketcan": {
+ "label": "Socket CAN",
+ "condition": "config.linux && tests.socketcan",
+ "output": [ "privateFeature" ]
+ },
+ "socketcan_fd": {
+ "label": "Socket CAN FD",
+ "condition": "config.linux && features.socketcan && tests.socketcan_fd",
+ "output": [ "privateFeature"]
+ }
+ },
+
+ "report": [
+ {
+ "type": "note",
+ "condition": "config.linux && !features.socketcan",
+ "message": "QtSerialBus: Cannot find linux/can.h and linux/can/raw.h Linux headers for socketCAN support."
+ },
+ {
+ "type": "note",
+ "condition": "config.linux && features.socketcan && !features.socketcan_fd",
+ "message": "QtSerialBus: Newer kernel needed for flexible data-rate frame support (canfd_frame)."
+ }
+ ],
+
+ "summary": [
+ {
+ "section": "Qt SerialBus",
+ "entries": [
+ "socketcan",
+ "socketcan_fd"
+ ]
+ }
+ ]
+}
diff --git a/src/serialbus/doc/qtserialbus.qdocconf b/src/serialbus/doc/qtserialbus.qdocconf
index d80d953..c84064c 100644
--- a/src/serialbus/doc/qtserialbus.qdocconf
+++ b/src/serialbus/doc/qtserialbus.qdocconf
@@ -43,4 +43,3 @@ imagedirs += images
navigation.landingpage = "Qt Serial Bus"
navigation.cppclassespage = "Qt Serial Bus C++ Classes"
-navigation.homepage = "Qt Documentation (Technology Preview)"
diff --git a/src/serialbus/doc/src/peakcan.qdoc b/src/serialbus/doc/src/peakcan.qdoc
index 504c234..d47d776 100644
--- a/src/serialbus/doc/src/peakcan.qdoc
+++ b/src/serialbus/doc/src/peakcan.qdoc
@@ -70,11 +70,11 @@
\endcode
The reading can be done using the \l {QCanBusDevice::}{readFrame()} method. The
- \l {QCanBusDevice::}{framesReceived()} signal is emitted when a new frame is available
- for reading:
+ \l {QCanBusDevice::}{framesReceived()} signal is emitted when at least one new frame
+ is available for reading:
\code
- QCanBusFrame frame = device->readFrame();
+ QCanBusFrame frame = device->readFrame();
\endcode
PeakCAN supports the following configurations that can be controlled through
diff --git a/src/serialbus/doc/src/socketcan.qdoc b/src/serialbus/doc/src/socketcan.qdoc
index e60f51b..b5d7db6 100644
--- a/src/serialbus/doc/src/socketcan.qdoc
+++ b/src/serialbus/doc/src/socketcan.qdoc
@@ -111,11 +111,11 @@
\endcode
The reading can be done using the \l {QCanBusDevice::}{readFrame()} method. The
- \l {QCanBusDevice::}{framesReceived()} signal is emitted when a new frame is available
- for reading:
+ \l {QCanBusDevice::}{framesReceived()} signal is emitted when at least one new frame
+ is available for reading:
\code
- QCanBusFrame frame = device->readFrame();
+ QCanBusFrame frame = device->readFrame();
\endcode
SocketCAN supports the following configurations that can be controlled through
@@ -128,10 +128,14 @@
\row
\li QCanBusDevice::LoopbackKey
\li To meet the multiple-user needs, the local loopback is enabled by default.
+ This means, whenever a CAN frame is transmitted on the CAN bus, a local
+ echo of this frame is sent to all applications connected to this CAN device.
\row
\li QCanBusDevice::ReceiveOwnKey
\li The reception of the CAN frames on the same socket that was sending the CAN frame
- is disabled by default.
+ is disabled by default. When enabling this option, all CAN frames sent to the CAN
+ bus immediately appear in the receive buffer. This can be used to check if sending
+ was successful.
\row
\li QCanBusDevice::ErrorFilterKey
\li A CAN interface driver can generate so called \e {Error Message Frames} that can
@@ -151,7 +155,7 @@
\row
\li QCanBusDevice::CanFdKey
\li This configuration option determines whether CANFD frames may be sent or received.
- By default, this option is disabled. It controls controls the CAN_RAW_FD_FRAMES
+ By default, this option is disabled. It controls the CAN_RAW_FD_FRAMES
option of the CAN socket.
\endtable
diff --git a/src/serialbus/doc/src/tinycan.qdoc b/src/serialbus/doc/src/tinycan.qdoc
index af35464..a504198 100644
--- a/src/serialbus/doc/src/tinycan.qdoc
+++ b/src/serialbus/doc/src/tinycan.qdoc
@@ -70,11 +70,11 @@
\endcode
The reading can be done using the \l {QCanBusDevice::}{readFrame()} method. The
- \l {QCanBusDevice::}{framesReceived()} signal is emitted when new frames are available
- for reading:
+ \l {QCanBusDevice::}{framesReceived()} signal is emitted when at least one new frame
+ is available for reading:
\code
- QCanBusFrame frame = device->readFrame();
+ QCanBusFrame frame = device->readFrame();
\endcode
TinyCAN supports the following configurations that can be controlled through
diff --git a/src/serialbus/doc/src/vectorcan.qdoc b/src/serialbus/doc/src/vectorcan.qdoc
index b4dbb52..8163207 100644
--- a/src/serialbus/doc/src/vectorcan.qdoc
+++ b/src/serialbus/doc/src/vectorcan.qdoc
@@ -71,8 +71,8 @@
\endcode
The reading can be done using the \l {QCanBusDevice::}{readFrame()} method. The
- \l {QCanBusDevice::}{framesReceived()} signal is emitted when a new frame is available
- for reading:
+ \l {QCanBusDevice::}{framesReceived()} signal is emitted when at least one new frame
+ is available for reading:
\code
QCanBusFrame frame = device->readFrame();
diff --git a/src/serialbus/qcanbus.cpp b/src/serialbus/qcanbus.cpp
index 207cd2b..3e1704c 100644
--- a/src/serialbus/qcanbus.cpp
+++ b/src/serialbus/qcanbus.cpp
@@ -87,7 +87,7 @@ static void loadPlugins()
/*!
\class QCanBus
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QCanBus class handles registration and creation of bus plugins.
@@ -107,8 +107,6 @@ QCanBus *QCanBus::instance()
}
/*!
- \since 5.8
-
Returns a list of identifiers for all loaded plugins.
*/
QStringList QCanBus::plugins() const
@@ -125,8 +123,6 @@ static void setErrorMessage(QString *result, const QString &message)
}
/*!
- \since 5.8
-
Creates a CAN bus device. \a plugin is the name of the plugin as returned by the \l plugins()
method. \a interfaceName is the CAN bus interface name. In case of failure, the optional
parameter \a errorMessage returns a textual error description.
diff --git a/src/serialbus/qcanbusdevice.cpp b/src/serialbus/qcanbusdevice.cpp
index f5e6809..c80753a 100644
--- a/src/serialbus/qcanbusdevice.cpp
+++ b/src/serialbus/qcanbusdevice.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QCanBusDevice
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QCanBusDevice class is the interface class for CAN bus.
@@ -94,15 +94,17 @@ QT_BEGIN_NAMESPACE
\value ErrorFilterKey This key defines the type of error that should be
forwarded via the current connection. The associated
value should be of type \l QCanBusFrame::FrameErrors.
- \value LoopbackKey This key defines whether the CAN bus device should
- operate in loopback mode. The expected value for this
- key is \c bool.
- \value ReceiveOwnKey This key defines whether this CAN device can send messages.
+ \value LoopbackKey This key defines whether the CAN bus device should operate in loopback
+ mode. Loopback means, whenever a CAN frame is transmitted on the CAN
+ bus, a local echo of this frame is sent to all applications connected to
+ this CAN device. The expected value for this key is \c bool.
+ \value ReceiveOwnKey This key defines whether this CAN device receives its own send frames.
+ This can be used to check if the transmission was successful.
The expected value for this key is \c bool.
\value BitRateKey This key defines the bitrate in bits per second.
\value CanFdKey This key defines whether sending and receiving of CAN FD frames
should be enabled. The expected value for this key is \c bool.
- \value UserKey This key defines the range where custom keys start. It's most
+ \value UserKey This key defines the range where custom keys start. Its most
common purpose is to permit platform-specific configuration
options.
@@ -112,12 +114,12 @@ QT_BEGIN_NAMESPACE
/*!
\class QCanBusDevice::Filter
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
- \brief The QCanBusDevice::Filter struct defines a filter for CAN bus messages.
+ \brief The QCanBusDevice::Filter struct defines a filter for CAN bus frames.
A list of QCanBusDevice::Filter instances is passed to
- \l QCanBusDevice::setConfigurationParameter() to enable filtering. If a received CAN message
+ \l QCanBusDevice::setConfigurationParameter() to enable filtering. If a received CAN frame
matches at least one of the filters in the list, the QCanBusDevice will accept it.
The example below demonstrates how to use the struct:
@@ -128,20 +130,20 @@ QT_BEGIN_NAMESPACE
/*!
\enum QCanBusDevice::Filter::FormatFilter
This enum describes the format pattern, which is used to filter incoming
- CAN bus messages.
+ CAN bus frames.
- \value MatchBaseFormat The CAN bus message must use the base message format
+ \value MatchBaseFormat The CAN bus frame must use the base frame format
(11 bit identifier).
- \value MatchExtendedFormat The CAN bus message must use the extended message format
+ \value MatchExtendedFormat The CAN bus frame must use the extended frame format
(29 bit identifier).
- \value MatchBaseAndExtendedFormat The CAN bus message can have a base or an extended
- message format.
+ \value MatchBaseAndExtendedFormat The CAN bus frame can have a base or an extended
+ frame format.
*/
/*!
\variable QCanBusDevice::Filter::frameId
- \brief the frame id used to filter the incoming messages.
+ \brief The frame id used to filter the incoming frames.
The frameId is used in conjunction with \a frameIdMask.
The matching is successful if the following evaluates to \c true:
@@ -158,7 +160,7 @@ QT_BEGIN_NAMESPACE
/*!
\variable QCanBusDevice::Filter::frameIdMask
- \brief the bit mask that is applied to the frame id of the filter and the received message.
+ \brief The bit mask that is applied to the frame id of the filter and the received frame.
The two frame ids are matching if the following evaluates to \c true:
@@ -174,9 +176,9 @@ QT_BEGIN_NAMESPACE
/*!
\variable QCanBusDevice::Filter::type
- \brief the type of the message to be filtered.
+ \brief The type of the frame to be filtered.
- Any CAN bus message type can be matched by setting this variable
+ Any CAN bus frame type can be matched by setting this variable
to \l QCanBusFrame::InvalidFrame. The filter object is invalid if
type is equal to \l QCanBusFrame::UnknownFrame.
@@ -188,7 +190,7 @@ QT_BEGIN_NAMESPACE
/*!
\variable QCanBusDevice::Filter::format
- \brief the message format of the matching CAN bus message.
+ \brief The frame format of the matching CAN bus frame.
By default this field is set to \l QCanBusDevice::Filter::MatchBaseAndExtendedFormat.
*/
@@ -386,8 +388,6 @@ QString QCanBusDevice::errorString() const
}
/*!
- \fn qint64 QCanBusDevice::framesAvailable() const
-
Returns the number of available frames. If no frames are available,
this function returns 0.
@@ -399,8 +399,6 @@ qint64 QCanBusDevice::framesAvailable() const
}
/*!
- \fn qint64 QCanBusDevice::framesToWrite() const
-
Returns the number of frames waiting to be written.
\sa writeFrame()
@@ -427,7 +425,6 @@ qint64 QCanBusDevice::framesToWrite() const
or \l errorOccurred() signals.
\sa waitForFramesReceived()
- \since 5.8
*/
bool QCanBusDevice::waitForFramesWritten(int msecs)
{
@@ -481,7 +478,6 @@ bool QCanBusDevice::waitForFramesWritten(int msecs)
or \l errorOccurred() signals.
\sa waitForFramesWritten()
- \since 5.8
*/
bool QCanBusDevice::waitForFramesReceived(int msecs)
{
@@ -598,7 +594,7 @@ QCanBusFrame QCanBusDevice::readFrame()
As per CAN bus specification, frames of type
\l {QCanBusFrame::RemoteRequestFrame} {remote transfer request (RTR)}
- do not have a payload but require a size larger than zero. This size indicates
+ do not have a payload, but a length from 0 to 8 (including). This length indicates
the expected response payload length from the remote party. Therefore when sending a RTR frame using
this function it may still be required to set an arbitrary payload on \a frame. The length of
the arbitrary payload is what is set as size expectation for the RTR frame.
diff --git a/src/serialbus/qcanbusfactory.cpp b/src/serialbus/qcanbusfactory.cpp
index 7fdbcca..b3df416 100644
--- a/src/serialbus/qcanbusfactory.cpp
+++ b/src/serialbus/qcanbusfactory.cpp
@@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QCanBusFactory
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QCanBusFactory class is a factory class used as the
plugin interface for CAN bus plugins.
@@ -59,8 +59,6 @@ QT_BEGIN_NAMESPACE
\a errorMessage contains an error description in case of failure.
If the factory cannot create a plugin, it returns \c nullptr.
-
- \since 5.8
*/
/*!
diff --git a/src/serialbus/qcanbusframe.cpp b/src/serialbus/qcanbusframe.cpp
index 34a6aa9..db17e1d 100644
--- a/src/serialbus/qcanbusframe.cpp
+++ b/src/serialbus/qcanbusframe.cpp
@@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QCanBusFrame
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief QCanBusFrame is a container class representing a single CAN frame.
@@ -55,14 +55,12 @@ QT_BEGIN_NAMESPACE
/*!
\fn QCanBusFrame::QCanBusFrame(QCanBusFrame::FrameType type = DataFrame)
- \since 5.8
Constructs a CAN frame of the specified \a type.
*/
/*!
\fn QCanBusFrame::QCanBusFrame(quint32 identifier, const QByteArray &data)
- \since 5.8
Constructs a CAN frame using \a identifier as the frame identifier and \a data as the payload.
*/
@@ -72,7 +70,9 @@ QT_BEGIN_NAMESPACE
Returns \c false if the \l frameType() is \l InvalidFrame,
the \l hasExtendedFrameFormat() is not set although \l frameId() is longer than 11 bit or
- the payload is longer than the maximal permitted payload length of 64 byte.
+ the payload is longer than the maximal permitted payload length of 64 byte if \e {Flexible
+ Data-Rate} mode is enabled or 8 byte if it is disabled. If \l frameType() is \l RemoteRequestFrame
+ and the \e {Flexible Data-Rate} mode is enabled at the same time \c false is also returned.
Otherwise this function returns \c true.
*/
@@ -91,7 +91,8 @@ QT_BEGIN_NAMESPACE
\fn QCanBusFrame::setPayload(const QByteArray &data)
Sets \a data as the payload for the CAN frame. The maximum size of payload is 8 bytes, which can
- be extended up to 64 bytes by supporting \e {Flexible Data-Rate}. Flexible Data-Rate has to be
+ be extended up to 64 bytes by supporting \e {Flexible Data-Rate}. If \a data contains more than
+ 8 byte the \e {Flexible Data-Rate} flag is automatically set. Flexible Data-Rate has to be
enabled on the \l QCanBusDevice by setting the \l QCanBusDevice::CanFdKey.
Frames of type \l RemoteRequestFrame (RTR) do not have a payload. However they have to
@@ -105,13 +106,11 @@ QT_BEGIN_NAMESPACE
frame.setPayload(QByteArray(expectedResponseLength, 0));
\endcode
-
- \sa payload()
+ \sa payload(), hasFlexibleDataRateFormat()
*/
/*!
\fn QCanBusFrame::setTimeStamp(TimeStamp ts)
- \since 5.8
Sets \a ts as the timestamp for the CAN frame. Usually, this function is not needed, because the
timestamp is created during the read operation and not needed during the write operation.
@@ -235,9 +234,28 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn bool QCanBusFrame::hasFlexibleDataRateFormat() const
+
+ Returns \c true if the CAN frame uses \e {Flexible Data-Rate} which allows up to 64 data bytes,
+ otherwise \c false, implying at most 8 byte of payload.
+
+ \sa setFlexibleDataRateFormat(), payload()
+*/
+
+/*!
+ \fn void QCanBusFrame::setFlexibleDataRateFormat(bool isFlexibleData)
+
+ Sets the \e {Flexible Data-Rate} flag to \a isFlexibleData. Those frames can be sent using
+ a higher speed on supporting controllers. Additionally the payload length limit is raised to
+ 64 byte.
+
+ \sa hasFlexibleDataRateFormat()
+*/
+
+/*!
\class QCanBusFrame::TimeStamp
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The TimeStamp class provides timestamp information with microsecond precision.
*/
@@ -253,11 +271,10 @@ QT_BEGIN_NAMESPACE
/*!
\fn static TimeStamp TimeStamp::fromMicroSeconds(qint64 usec)
- \since 5.8
Constructs a normalized TimeStamp from microseconds \a usec.
- The created TimeStamp is normalized, i.e. microsconds greater 1000000 are converted
+ The created TimeStamp is normalized, i.e. microseconds greater 1000000 are converted
to seconds.
*/
@@ -274,8 +291,6 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QString QCanBusFrame::toString() const
-
Returns the CAN frame as a formatted string.
The output contains the CAN identfier in hexadecimal format, right
@@ -288,16 +303,54 @@ QT_BEGIN_NAMESPACE
Typical outputs are:
\code
- (Error) - error frame
- 7FF [1] 01 - data frame with standard identifier
- 1FFFFFFF [8] 01 23 45 67 89 AB CD EF - data frame with extended identifier
- 400 [10] 01 23 45 67 ... EF 01 23 - CAN FD frame
- 123 [5] Remote Request - remote frame with standard identifier
- 00000234 [0] Remote Request - remote frame with extended identifier
+ (Error) - error frame
+ 7FF [1] 01 - data frame with standard identifier
+ 1FFFFFFF [8] 01 23 45 67 89 AB CD EF - data frame with extended identifier
+ 400 [10] 01 23 45 67 ... EF 01 23 - CAN FD frame
+ 123 [5] Remote Request - remote frame with standard identifier
+ 00000234 [0] Remote Request - remote frame with extended identifier
\endcode
-
- \since 5.8
*/
+QString QCanBusFrame::toString() const
+{
+ const FrameType type = frameType();
+
+ switch (type) {
+ case InvalidFrame:
+ return QStringLiteral("(Invalid)");
+ case ErrorFrame:
+ return QStringLiteral("(Error)");
+ case UnknownFrame:
+ return QStringLiteral("(Unknown)");
+ default:
+ break;
+ }
+
+ const char *idFormat = hasExtendedFrameFormat() ? "%08X" : " %03X";
+ const char *dlcFormat = hasFlexibleDataRateFormat() ? " [%02d]" : " [%d]";
+ QString result;
+ result.append(QString::asprintf(idFormat, static_cast<uint>(frameId())));
+ result.append(QString::asprintf(dlcFormat, payload().size()));
+
+ if (type == RemoteRequestFrame) {
+ result.append(QLatin1String(" Remote Request"));
+ } else {
+ const QByteArray data = payload().toHex().toUpper();
+ const int length = data.size();
+ if (length) {
+ const QLatin1String l1(data.data(), length);
+
+ result.append(QLatin1Char(' '));
+
+ for (int i = 0; i < length; i += 2) {
+ result.append(QLatin1Char(' '));
+ result.append(l1.mid(i, 2));
+ }
+ }
+ }
+
+ return result;
+}
#ifndef QT_NO_DATASTREAM
@@ -312,6 +365,7 @@ QDataStream &operator<<(QDataStream &out, const QCanBusFrame &frame)
out << static_cast<quint8>(frame.frameType());
out << static_cast<quint8>(frame.version);
out << frame.hasExtendedFrameFormat();
+ out << frame.hasFlexibleDataRateFormat();
out << frame.payload();
const QCanBusFrame::TimeStamp stamp = frame.timeStamp();
out << stamp.seconds();
@@ -330,11 +384,12 @@ QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame)
quint8 frameType;
quint8 version;
bool extendedFrameFormat;
+ bool flexibleDataRate;
QByteArray payload;
qint64 seconds;
qint64 microSeconds;
- in >> frameId >> frameType >> version >> extendedFrameFormat
+ in >> frameId >> frameType >> version >> extendedFrameFormat >> flexibleDataRate
>> payload >> seconds >> microSeconds;
frame.setFrameId(frameId);
@@ -342,6 +397,7 @@ QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame)
frame.setFrameType(static_cast<QCanBusFrame::FrameType>(frameType));
frame.setExtendedFrameFormat(extendedFrameFormat);
+ frame.setFlexibleDataRateFormat(flexibleDataRate);
frame.setPayload(payload);
frame.setTimeStamp(QCanBusFrame::TimeStamp(seconds, microSeconds));
diff --git a/src/serialbus/qcanbusframe.h b/src/serialbus/qcanbusframe.h
index e6f4d28..486d996 100644
--- a/src/serialbus/qcanbusframe.h
+++ b/src/serialbus/qcanbusframe.h
@@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE
class QDataStream;
-class QCanBusFrame
+class Q_SERIALBUS_EXPORT QCanBusFrame
{
public:
class TimeStamp {
@@ -73,10 +73,12 @@ public:
};
explicit QCanBusFrame(FrameType type = DataFrame) Q_DECL_NOTHROW :
- canId(0x0),
isExtendedFrame(0x0),
- version(0x0)
+ version(0x0),
+ isFlexibleDataRate(0x0)
{
+ memset(reserved, 0, sizeof(reserved));
+ setFrameId(0x0);
setFrameType(type);
}
@@ -99,14 +101,14 @@ public:
Q_FLAGS(FrameErrors)
explicit QCanBusFrame(quint32 identifier, const QByteArray &data) :
- canId(identifier & 0x1FFFFFFFU),
format(DataFrame),
- isExtendedFrame((identifier & 0x1FFFF800U) ? 0x1 : 0x0),
+ isExtendedFrame(0x0),
version(0x0),
+ isFlexibleDataRate(data.length() > 8 ? 0x1 : 0x0),
load(data)
{
- Q_UNUSED(extra);
- Q_UNUSED(reserved);
+ memset(reserved, 0, sizeof(reserved));
+ setFrameId(identifier);
}
bool isValid() const Q_DECL_NOTHROW
@@ -118,10 +120,20 @@ public:
if (!isExtendedFrame && (canId & 0x1FFFF800U))
return false;
- // maximum permitted payload size in CAN FD
- if (load.length() > 64)
+ if (!isValidFrameId)
return false;
+ // maximum permitted payload size in CAN or CAN FD
+ if (isFlexibleDataRate) {
+ if (load.length() > 64)
+ return false;
+ if (format == RemoteRequestFrame)
+ return false;
+ } else {
+ if (load.length() > 8)
+ return false;
+ }
+
return true;
}
@@ -168,11 +180,22 @@ public:
}
void setFrameId(quint32 newFrameId)
{
- canId = (newFrameId & 0x1FFFFFFFU);
- setExtendedFrameFormat(isExtendedFrame || (newFrameId & 0x1FFFF800U));
+ if (newFrameId < 0x20000000U) {
+ isValidFrameId = true;
+ canId = newFrameId;
+ setExtendedFrameFormat(isExtendedFrame || (newFrameId & 0x1FFFF800U));
+ } else {
+ isValidFrameId = false;
+ canId = 0;
+ }
}
- void setPayload(const QByteArray &data) { load = data; }
+ void setPayload(const QByteArray &data)
+ {
+ load = data;
+ if (data.length() > 8)
+ isFlexibleDataRate = 0x1;
+ }
void setTimeStamp(TimeStamp ts) Q_DECL_NOTHROW { stamp = ts; }
QByteArray payload() const { return load; }
@@ -192,37 +215,12 @@ public:
canId = (e & AnyError);
}
- QString toString() const
- {
- const FrameType type = frameType();
-
- if (type == InvalidFrame)
- return QStringLiteral("(Invalid)");
-
- if (type == ErrorFrame)
- return QStringLiteral("(Error)");
-
- if (type == UnknownFrame)
- return QStringLiteral("(Unknown)");
-
- const char *idFormat = hasExtendedFrameFormat() ? "%08X" : " %03X";
- const char *dlcFormat = payload().size() < 10 ? " [%d]" : " [%d]";
- QString result;
- result.append(QString::asprintf(idFormat, static_cast<uint>(frameId())));
- result.append(QString::asprintf(dlcFormat, payload().size()));
+ QString toString() const;
- if (type == RemoteRequestFrame) {
- result.append(QLatin1String(" Remote Request"));
- } else {
- const QByteArray data = payload().toHex().toUpper();
- const QLatin1String l1(data.data(), data.size());
- for (int i = 0, e = data.size(); i < e; i += 2) {
- result.append(QLatin1Char(' '));
- result.append(l1.mid(i, 2));
- }
- }
-
- return result;
+ bool hasFlexibleDataRateFormat() const Q_DECL_NOTHROW { return (isFlexibleDataRate & 0x1); }
+ void setFlexibleDataRateFormat(bool isFlexibleData) Q_DECL_NOTHROW
+ {
+ isFlexibleDataRate = (isFlexibleData & 0x1);
}
#ifndef QT_NO_DATASTREAM
@@ -236,7 +234,8 @@ private:
quint8 isExtendedFrame:1;
quint8 version:5;
- quint8 extra: 2; // unused
+ quint8 isValidFrameId:1;
+ quint8 isFlexibleDataRate:1;
// reserved for future use
quint8 reserved[3];
diff --git a/src/serialbus/qmodbusclient.cpp b/src/serialbus/qmodbusclient.cpp
index a54f739..fcbad8b 100644
--- a/src/serialbus/qmodbusclient.cpp
+++ b/src/serialbus/qmodbusclient.cpp
@@ -50,7 +50,7 @@ Q_DECLARE_LOGGING_CATEGORY(QT_MODBUS)
/*!
\class QModbusClient
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QModbusClient class is the interface to send Modbus requests.
diff --git a/src/serialbus/qmodbusdataunit.cpp b/src/serialbus/qmodbusdataunit.cpp
index de06bc2..0f8821f 100644
--- a/src/serialbus/qmodbusdataunit.cpp
+++ b/src/serialbus/qmodbusdataunit.cpp
@@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QModbusDataUnit
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief QModbusDataUnit is a container class representing single bit and
\c 16 bit word entries in the Modbus register.
@@ -206,7 +206,7 @@ QT_BEGIN_NAMESPACE
/*!
\typedef QModbusDataUnitMap
\relates QModbusDataUnit
- \since 5.6
+ \since 5.8
Synonym for QMap<QModbusDataUnit::RegisterType, QModbusDataUnit>.
*/
diff --git a/src/serialbus/qmodbusdevice.cpp b/src/serialbus/qmodbusdevice.cpp
index 0eecac7..08718d6 100644
--- a/src/serialbus/qmodbusdevice.cpp
+++ b/src/serialbus/qmodbusdevice.cpp
@@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QModbusDevice
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QModbusDevice class is the base class for Modbus classes, \l QModbusServer
and \l QModbusClient.
diff --git a/src/serialbus/qmodbusdeviceidentification.cpp b/src/serialbus/qmodbusdeviceidentification.cpp
index 5ae3f54..3aa54fb 100644
--- a/src/serialbus/qmodbusdeviceidentification.cpp
+++ b/src/serialbus/qmodbusdeviceidentification.cpp
@@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QModbusDeviceIdentification
\inmodule QtSerialBus
- \since 5.7
+ \since 5.8
\brief The QModbusDeviceIdentification is a container class representing
the physical and functional description of a Modbus server.
diff --git a/src/serialbus/qmodbuspdu.cpp b/src/serialbus/qmodbuspdu.cpp
index d6e1ef9..32a3b43 100644
--- a/src/serialbus/qmodbuspdu.cpp
+++ b/src/serialbus/qmodbuspdu.cpp
@@ -184,7 +184,7 @@ static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type typ
/*!
\class QModbusPdu
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief QModbusPdu is a abstract container class containing the function code and
payload that is stored inside a Modbus ADU.
@@ -464,7 +464,7 @@ QDataStream &operator<<(QDataStream &stream, const QModbusPdu &pdu)
/*!
\class QModbusRequest
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief QModbusRequest is a container class containing the function code and payload that is
stored inside a Modbus ADU.
@@ -555,18 +555,18 @@ int QModbusRequest::calculateDataSize(const QModbusRequest &request)
case QModbusPdu::WriteMultipleCoils:
minimum -= 1; // first payload payload byte
if (request.dataSize() >= minimum)
- size = minimum + request.data()[minimum - 1] /*byte count*/;
+ size = minimum + quint8(request.data()[minimum - 1]) /*byte count*/;
break;
case QModbusPdu::WriteMultipleRegisters:
case QModbusPdu::ReadWriteMultipleRegisters:
minimum -= 2; // first 2 payload payload bytes
if (request.dataSize() >= minimum)
- size = minimum + request.data()[minimum - 1] /*byte count*/;
+ size = minimum + quint8(request.data()[minimum - 1]) /*byte count*/;
break;
case QModbusPdu::ReadFileRecord:
case QModbusPdu::WriteFileRecord:
if (request.dataSize() >= 1)
- size = 1 /*byte count*/ + request.data()[0] /*actual bytes*/;
+ size = 1 /*byte count*/ + quint8(request.data()[0]) /*actual bytes*/;
break;
case QModbusPdu::EncapsulatedInterfaceTransport: {
if (request.dataSize() < minimum)
@@ -618,7 +618,7 @@ QDataStream &operator>>(QDataStream &stream, QModbusRequest &pdu)
/*!
\class QModbusResponse
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief QModbusResponse is a container class containing the function code and payload that is
stored inside a Modbus ADU.
@@ -710,7 +710,7 @@ int QModbusResponse::calculateDataSize(const QModbusResponse &response)
case QModbusResponse::ReadWriteMultipleRegisters:
case QModbusResponse::ReportServerId:
if (response.dataSize() >= 1)
- size = 1 /*byte count*/ + response.data()[0] /*actual bytes*/;
+ size = 1 /*byte count*/ + quint8(response.data()[0]) /*actual bytes*/;
break;
case QModbusResponse::ReadFifoQueue: {
if (response.dataSize() >= 2) {
@@ -796,7 +796,7 @@ QDataStream &operator>>(QDataStream &stream, QModbusResponse &pdu)
/*!
\class QModbusExceptionResponse
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief QModbusExceptionResponse is a container class containing the function and error code
inside a Modbus ADU.
diff --git a/src/serialbus/qmodbuspdu.h b/src/serialbus/qmodbuspdu.h
index 1255593..65a3247 100644
--- a/src/serialbus/qmodbuspdu.h
+++ b/src/serialbus/qmodbuspdu.h
@@ -208,6 +208,8 @@ public:
{}
};
Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &stream, QModbusRequest &pdu);
+inline QDataStream &operator<<(QDataStream &stream, const QModbusRequest &pdu)
+{ return stream << static_cast<const QModbusPdu &>(pdu); }
class QModbusResponse : public QModbusPdu
{
@@ -250,6 +252,8 @@ public:
void setExceptionCode(ExceptionCode ec) { QModbusPdu::encodeData(quint8(ec)); }
};
Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &stream, QModbusResponse &pdu);
+inline QDataStream &operator<<(QDataStream &stream, const QModbusResponse &pdu)
+{ return stream << static_cast<const QModbusPdu &>(pdu); }
Q_DECLARE_TYPEINFO(QModbusPdu, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QModbusPdu::ExceptionCode, Q_PRIMITIVE_TYPE);
diff --git a/src/serialbus/qmodbusreply.cpp b/src/serialbus/qmodbusreply.cpp
index 2a8ee19..f88a3bd 100644
--- a/src/serialbus/qmodbusreply.cpp
+++ b/src/serialbus/qmodbusreply.cpp
@@ -58,7 +58,7 @@ public:
/*!
\class QModbusReply
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QModbusReply class contains the data for a request sent with
a \l QModbusClient derived class.
diff --git a/src/serialbus/qmodbusrtuserialmaster.cpp b/src/serialbus/qmodbusrtuserialmaster.cpp
index 331e0ee..5a9555e 100644
--- a/src/serialbus/qmodbusrtuserialmaster.cpp
+++ b/src/serialbus/qmodbusrtuserialmaster.cpp
@@ -144,10 +144,15 @@ bool QModbusRtuSerialMaster::open()
*/
void QModbusRtuSerialMaster::close()
{
- if (state() == QModbusDevice::UnconnectedState)
+ if (state() == QModbusDevice::UnconnectedState ||
+ state() == QModbusDevice::ClosingState) {
return;
+ }
+
+ setState(QModbusDevice::ClosingState);
Q_D(QModbusRtuSerialMaster);
+
if (d->m_serialPort->isOpen())
d->m_serialPort->close();
diff --git a/src/serialbus/qmodbusrtuserialmaster_p.h b/src/serialbus/qmodbusrtuserialmaster_p.h
index e7e9a92..c698ebc 100644
--- a/src/serialbus/qmodbusrtuserialmaster_p.h
+++ b/src/serialbus/qmodbusrtuserialmaster_p.h
@@ -216,8 +216,9 @@ public:
QObject::connect(m_serialPort, &QSerialPort::aboutToClose, q, [this]() {
Q_Q(QModbusRtuSerialMaster);
- if (q->state() != QModbusDevice::ClosingState)
- q->close();
+ Q_UNUSED(q); // To avoid unused variable warning in release mode
+ Q_ASSERT(q->state() == QModbusDevice::ClosingState);
+
m_sendTimer.stop();
m_responseTimer.stop();
});
diff --git a/src/serialbus/qmodbusrtuserialslave.cpp b/src/serialbus/qmodbusrtuserialslave.cpp
index 644ad07..87698d3 100644
--- a/src/serialbus/qmodbusrtuserialslave.cpp
+++ b/src/serialbus/qmodbusrtuserialslave.cpp
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QModbusRtuSerialSlave
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QModbusRtuSerialSlave class represents a Modbus server
that uses a serial port for its communication with the Modbus client.
diff --git a/src/serialbus/qmodbusserver.cpp b/src/serialbus/qmodbusserver.cpp
index ffb673a..1a16347 100644
--- a/src/serialbus/qmodbusserver.cpp
+++ b/src/serialbus/qmodbusserver.cpp
@@ -53,7 +53,7 @@ Q_DECLARE_LOGGING_CATEGORY(QT_MODBUS)
/*!
\class QModbusServer
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QModbusServer class is the interface to receive and process Modbus requests.
diff --git a/src/serialbus/qmodbustcpclient.cpp b/src/serialbus/qmodbustcpclient.cpp
index 94fa174..a34c241 100644
--- a/src/serialbus/qmodbustcpclient.cpp
+++ b/src/serialbus/qmodbustcpclient.cpp
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QModbusTcpClient
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QModbusTcpClient class is the interface class for Modbus TCP client device.
diff --git a/src/serialbus/qmodbustcpserver.cpp b/src/serialbus/qmodbustcpserver.cpp
index 0f9aff2..07a3363 100644
--- a/src/serialbus/qmodbustcpserver.cpp
+++ b/src/serialbus/qmodbustcpserver.cpp
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QModbusTcpServer
\inmodule QtSerialBus
- \since 5.6
+ \since 5.8
\brief The QModbusTcpServer class represents a Modbus server that uses a
TCP server for its communication with the Modbus client.
diff --git a/src/tools/canbusutil/canbusutil.cpp b/src/tools/canbusutil/canbusutil.cpp
index 80ea5e3..d614583 100644
--- a/src/tools/canbusutil/canbusutil.cpp
+++ b/src/tools/canbusutil/canbusutil.cpp
@@ -45,6 +45,11 @@ CanBusUtil::CanBusUtil(QTextStream &output, QCoreApplication &app, QObject *pare
{
}
+void CanBusUtil::setShowTimeStamp(bool showTimeStamp)
+{
+ m_readTask->setShowTimeStamp(showTimeStamp);
+}
+
bool CanBusUtil::start(const QString &pluginName, const QString &deviceName, const QString &data)
{
if (!m_canBus) {
@@ -74,7 +79,6 @@ bool CanBusUtil::start(const QString &pluginName, const QString &deviceName, con
void CanBusUtil::printPlugins()
{
const QStringList plugins = m_canBus->plugins();
- m_output << "Plugins: " << endl;
for (int i = 0; i < plugins.size(); i++)
m_output << plugins.at(i) << endl;
}
@@ -93,25 +97,21 @@ bool CanBusUtil::parseDataField(qint32 &id, QString &payload)
return true;
}
-bool CanBusUtil::parsePayloadField(QString payload, bool &rtrFrame,
- bool &fdFrame, QByteArray &bytes)
+bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame)
{
- fdFrame = false;
- rtrFrame = false;
-
if (!payload.isEmpty() && payload.at(0).toUpper() == 'R') {
- rtrFrame = true;
bool validPayloadLength = false;
- if (fdFrame) {
- m_output << "CAN FD RTR data frames are not valid." << endl;
- } else if (payload.size() == 1) { // payload = "R"
+
+ frame->setFrameType(QCanBusFrame::RemoteRequestFrame);
+
+ if (payload.size() == 1) { // payload = "R"
validPayloadLength = true;
} else if (payload.size() > 1) { // payload = "R8"
payload = payload.mid(1);
int rtrFrameLength = payload.toInt(&validPayloadLength);
if (validPayloadLength && rtrFrameLength >= 0 && rtrFrameLength <= 8) {
- bytes = QByteArray(rtrFrameLength, 0);
+ frame->setPayload(QByteArray(rtrFrameLength, 0));
} else if (validPayloadLength) {
m_output << "The length must be between 0 and 8 (including)." << endl;
validPayloadLength = false;
@@ -124,7 +124,7 @@ bool CanBusUtil::parsePayloadField(QString payload, bool &rtrFrame,
return validPayloadLength;
} else if (!payload.isEmpty() && payload.at(0) == '#') {
- fdFrame = true;
+ frame->setFlexibleDataRateFormat(true);
payload = payload.mid(1);
}
@@ -139,14 +139,16 @@ bool CanBusUtil::parsePayloadField(QString payload, bool &rtrFrame,
return false;
}
- bytes = QByteArray::fromHex(payload.toLatin1());
+ QByteArray bytes = QByteArray::fromHex(payload.toLatin1());
- const int maxSize = fdFrame ? 64 : 8;
+ const int maxSize = frame->hasFlexibleDataRateFormat() ? 64 : 8;
if (bytes.size() > maxSize) {
m_output << "Warning: Truncating payload at max. size of " << maxSize << " bytes." << endl;
bytes.truncate(maxSize);
}
+ frame->setPayload(bytes);
+
return true;
}
@@ -154,6 +156,7 @@ bool CanBusUtil::connectCanDevice()
{
if (!m_canBus->plugins().contains(m_pluginName)) {
m_output << "Could not find suitable plugin." << endl;
+ m_output << "Available plugins:" << endl;
printPlugins();
return false;
}
@@ -176,15 +179,12 @@ bool CanBusUtil::sendData()
{
qint32 id;
QString payload;
- bool rtrFrame;
- bool fdFrame;
- QByteArray bytes;
QCanBusFrame frame;
if (parseDataField(id, payload) == false)
return false;
- if (parsePayloadField(payload, rtrFrame, fdFrame, bytes) == false)
+ if (setFrameFromPayload(payload, &frame) == false)
return false;
if (id < 0 || id > 0x1FFFFFFF) { // 29 bits
@@ -192,13 +192,9 @@ bool CanBusUtil::sendData()
m_output << "Warning! Id does not fit into Extended Frame Format, setting id to: " << id << endl;
}
- if (rtrFrame)
- frame.setFrameType(QCanBusFrame::RemoteRequestFrame);
-
- frame.setPayload(bytes);
frame.setFrameId(id);
- if (fdFrame)
+ if (frame.hasFlexibleDataRateFormat())
m_canDevice->setConfigurationParameter(QCanBusDevice::CanFdKey, true);
return m_canDevice->writeFrame(frame);
diff --git a/src/tools/canbusutil/canbusutil.h b/src/tools/canbusutil/canbusutil.h
index 8737c30..e17fe7b 100644
--- a/src/tools/canbusutil/canbusutil.h
+++ b/src/tools/canbusutil/canbusutil.h
@@ -44,18 +44,25 @@
#include "readtask.h"
+QT_BEGIN_NAMESPACE
+
+class QCanBusFrame;
+
+QT_END_NAMESPACE
+
class CanBusUtil : public QObject
{
Q_OBJECT
public:
explicit CanBusUtil(QTextStream &output, QCoreApplication &app, QObject *parent = nullptr);
+ void setShowTimeStamp(bool showTimeStamp);
bool start(const QString &pluginName, const QString &deviceName, const QString &data = QString());
void printPlugins();
private:
bool parseDataField(qint32 &id, QString &payload);
- bool parsePayloadField(QString payload, bool &rtrFrame, bool &fdFrame, QByteArray &bytes);
+ bool setFrameFromPayload(QString payload, QCanBusFrame *frame);
bool connectCanDevice();
bool startListeningOnCanDevice();
bool sendData();
diff --git a/src/tools/canbusutil/main.cpp b/src/tools/canbusutil/main.cpp
index d75a16a..c760c31 100644
--- a/src/tools/canbusutil/main.cpp
+++ b/src/tools/canbusutil/main.cpp
@@ -90,6 +90,10 @@ int main(int argc, char *argv[])
CanBusUtil::tr("List all available plugins."));
parser.addOption(listOption);
+ const QCommandLineOption showTimeStampOption({"t", "timestamp"},
+ CanBusUtil::tr("Show timestamp for each received message."));
+ parser.addOption(showTimeStampOption);
+
parser.process(app);
if (parser.isSet(listOption)) {
@@ -107,6 +111,7 @@ int main(int argc, char *argv[])
return 1;
}
+ util.setShowTimeStamp(parser.isSet(showTimeStampOption));
if (!util.start(args[0], args[1], data))
return -1;
diff --git a/src/tools/canbusutil/readtask.cpp b/src/tools/canbusutil/readtask.cpp
index 6c09e02..90858c2 100644
--- a/src/tools/canbusutil/readtask.cpp
+++ b/src/tools/canbusutil/readtask.cpp
@@ -36,12 +36,15 @@
#include "readtask.h"
-using namespace std;
-
ReadTask::ReadTask(QTextStream &output, QObject *parent)
: QObject(parent),
output(output) { }
+void ReadTask::setShowTimeStamp(bool showTimeStamp)
+{
+ m_showTimeStamp = showTimeStamp;
+}
+
void ReadTask::checkMessages() {
auto canDevice = qobject_cast<QCanBusDevice *>(QObject::sender());
if (canDevice == nullptr) {
@@ -49,15 +52,24 @@ void ReadTask::checkMessages() {
return;
}
- const QCanBusFrame frame = canDevice->readFrame();
+ while (canDevice->framesAvailable()) {
+ const QCanBusFrame frame = canDevice->readFrame();
- QString view;
- if (frame.frameType() == QCanBusFrame::ErrorFrame)
- view = canDevice->interpretErrorFrame(frame);
- else
- view = frame.toString();
+ QString view;
- output << view << endl;
+ if (m_showTimeStamp) {
+ view = QString::fromLatin1("%1.%2 ")
+ .arg(frame.timeStamp().seconds(), 10, 10, QLatin1Char(' '))
+ .arg(frame.timeStamp().microSeconds() / 100, 4, 10, QLatin1Char('0'));
+ }
+
+ if (frame.frameType() == QCanBusFrame::ErrorFrame)
+ view += canDevice->interpretErrorFrame(frame);
+ else
+ view += frame.toString();
+
+ output << view << endl;
+ }
}
void ReadTask::receiveError(QCanBusDevice::CanBusError /*error*/) {
diff --git a/src/tools/canbusutil/readtask.h b/src/tools/canbusutil/readtask.h
index a59f218..7f7613b 100644
--- a/src/tools/canbusutil/readtask.h
+++ b/src/tools/canbusutil/readtask.h
@@ -46,6 +46,7 @@ class ReadTask : public QObject
Q_OBJECT
public:
explicit ReadTask(QTextStream &output, QObject *parent = nullptr);
+ void setShowTimeStamp(bool showStamp);
signals:
void sigTermSignal();
@@ -56,6 +57,7 @@ public slots:
private:
QTextStream &output;
+ bool m_showTimeStamp = false;
};
#endif // READTASK_H
diff --git a/sync.profile b/sync.profile
index 57da4d8..e7125c6 100644
--- a/sync.profile
+++ b/sync.profile
@@ -1,8 +1,3 @@
%modules = (
"QtSerialBus" => "$basedir/src/serialbus",
);
-
-%dependencies = (
- "qtbase" => "",
- "qtserialport" => "",
-);
diff --git a/tests/auto/qcanbusframe/tst_qcanbusframe.cpp b/tests/auto/qcanbusframe/tst_qcanbusframe.cpp
index 3a199ec..78f35da 100644
--- a/tests/auto/qcanbusframe/tst_qcanbusframe.cpp
+++ b/tests/auto/qcanbusframe/tst_qcanbusframe.cpp
@@ -70,31 +70,39 @@ void tst_QCanBusFrame::constructors()
QCanBusFrame frame1;
QCanBusFrame frame2(123, "tst");
QCanBusFrame frame3(123456, "tst");
+ QCanBusFrame frame4(1234, "tst tst tst");
QCanBusFrame::TimeStamp timeStamp1;
QCanBusFrame::TimeStamp timeStamp2(5, 5);
QVERIFY(frame1.payload().isEmpty());
QVERIFY(!frame1.frameId());
+ QVERIFY(!frame1.hasFlexibleDataRateFormat());
+ QVERIFY(!frame1.hasExtendedFrameFormat());
+ QCOMPARE(frame1.frameType(), QCanBusFrame::DataFrame);
QVERIFY(!frame2.payload().isEmpty());
QVERIFY(frame2.frameId());
+ QVERIFY(!frame2.hasFlexibleDataRateFormat());
+ QVERIFY(!frame2.hasExtendedFrameFormat());
+ QCOMPARE(frame2.frameType(), QCanBusFrame::DataFrame);
QVERIFY(!frame3.payload().isEmpty());
QVERIFY(frame3.frameId());
+ QVERIFY(!frame3.hasFlexibleDataRateFormat());
+ QVERIFY(frame3.hasExtendedFrameFormat());
+ QCOMPARE(frame3.frameType(), QCanBusFrame::DataFrame);
+
+ QVERIFY(!frame4.payload().isEmpty());
+ QVERIFY(frame4.frameId());
+ QVERIFY(frame4.hasFlexibleDataRateFormat());
+ QVERIFY(!frame4.hasExtendedFrameFormat());
+ QCOMPARE(frame4.frameType(), QCanBusFrame::DataFrame);
QVERIFY(!timeStamp1.seconds());
QVERIFY(!timeStamp1.microSeconds());
QVERIFY(timeStamp2.seconds());
QVERIFY(timeStamp2.microSeconds());
-
- QVERIFY(frame1.hasExtendedFrameFormat() == false);
- QVERIFY(frame2.hasExtendedFrameFormat() == false);
- QVERIFY(frame3.hasExtendedFrameFormat() == true);
-
- QCOMPARE(frame1.frameType(), QCanBusFrame::DataFrame);
- QCOMPARE(frame2.frameType(), QCanBusFrame::DataFrame);
- QCOMPARE(frame3.frameType(), QCanBusFrame::DataFrame);
}
void tst_QCanBusFrame::id()
@@ -104,22 +112,32 @@ void tst_QCanBusFrame::id()
frame.setExtendedFrameFormat(false);
frame.setFrameId(2047u);
QCOMPARE(frame.frameId(), 2047u);
- QVERIFY(frame.hasExtendedFrameFormat() == false);
+ QVERIFY(frame.isValid());
+ QVERIFY(!frame.hasExtendedFrameFormat());
// id > 2^11 -> extended format
frame.setExtendedFrameFormat(false);
frame.setFrameId(2048u);
QCOMPARE(frame.frameId(), 2048u);
- QVERIFY(frame.hasExtendedFrameFormat() == true);
+ QVERIFY(frame.isValid());
+ QVERIFY(frame.hasExtendedFrameFormat());
// id < 2^11 -> no extended format
frame.setExtendedFrameFormat(false);
frame.setFrameId(512u);
QCOMPARE(frame.frameId(), 512u);
- QVERIFY(frame.hasExtendedFrameFormat() == false);
+ QVERIFY(frame.isValid());
+ QVERIFY(!frame.hasExtendedFrameFormat());
// id < 2^11 -> keep extended format
frame.setExtendedFrameFormat(true);
frame.setFrameId(512u);
QCOMPARE(frame.frameId(), 512u);
- QVERIFY(frame.hasExtendedFrameFormat() == true);
+ QVERIFY(frame.isValid());
+ QVERIFY(frame.hasExtendedFrameFormat());
+ // id >= 2^29 -> invalid
+ frame.setExtendedFrameFormat(false);
+ frame.setFrameId(536870912u);
+ QCOMPARE(frame.frameId(), 0u);
+ QVERIFY(!frame.isValid());
+ QVERIFY(!frame.hasExtendedFrameFormat());
}
void tst_QCanBusFrame::payload()
@@ -128,6 +146,15 @@ void tst_QCanBusFrame::payload()
QVERIFY(frame.payload().isEmpty());
frame.setPayload("test");
QCOMPARE(frame.payload().data(), "test");
+ QVERIFY(!frame.hasFlexibleDataRateFormat());
+ // setting long payload should automatically set hasFlexibleDataRateFormat()
+ frame.setPayload("testtesttest");
+ QCOMPARE(frame.payload().data(), "testtesttest");
+ QVERIFY(frame.hasFlexibleDataRateFormat());
+ // setting short payload should not change hasFlexibleDataRateFormat()
+ frame.setPayload("test");
+ QCOMPARE(frame.payload().data(), "test");
+ QVERIFY(frame.hasFlexibleDataRateFormat());
}
void tst_QCanBusFrame::timeStamp()
@@ -160,40 +187,53 @@ void tst_QCanBusFrame::tst_isValid_data()
QTest::addColumn<QByteArray>("payload");
QTest::addColumn<uint>("id");
QTest::addColumn<bool>("extended");
+ QTest::addColumn<bool>("flexibleData");
QTest::newRow("invalid frame")
<< QCanBusFrame::InvalidFrame << false
- << QByteArray() << 0u << false;
+ << QByteArray() << 0u << false << false;
QTest::newRow("data frame")
<< QCanBusFrame::DataFrame << true
- << QByteArray() << 0u << false;
+ << QByteArray() << 0u << false << false;
QTest::newRow("error frame")
<< QCanBusFrame::ErrorFrame << true
- << QByteArray() << 0u << false;
+ << QByteArray() << 0u << false << false;
QTest::newRow("remote request frame")
<< QCanBusFrame::RemoteRequestFrame << true
- << QByteArray() << 0u << false;
+ << QByteArray() << 0u << false << false;
+ QTest::newRow("remote request CAN FD frame")
+ << QCanBusFrame::RemoteRequestFrame << false
+ << QByteArray() << 0u << false << true;
QTest::newRow("unknown frame")
<< QCanBusFrame::UnknownFrame << true
- << QByteArray() << 0u << false;
+ << QByteArray() << 0u << false << false;
QTest::newRow("data frame CAN max payload")
<< QCanBusFrame::DataFrame << true
- << QByteArray(8, 0) << 0u << false;
+ << QByteArray(8, 0) << 0u << false << false;
QTest::newRow("data frame CAN FD max payload")
<< QCanBusFrame::DataFrame << true
- << QByteArray(64, 0) << 0u << false;
+ << QByteArray(64, 0) << 0u << false << true;
QTest::newRow("data frame CAN too much payload")
<< QCanBusFrame::DataFrame << false
- << QByteArray(65, 0) << 0u << false;
+ << QByteArray(65, 0) << 0u << false << false;
QTest::newRow("data frame short id")
<< QCanBusFrame::DataFrame << true
- << QByteArray(8, 0) << (1u << 11) - 1 << false;
+ << QByteArray(8, 0) << (1u << 11) - 1 << false << false;
QTest::newRow("data frame long id")
<< QCanBusFrame::DataFrame << true
- << QByteArray(8, 0) << (1u << 11) << true;
+ << QByteArray(8, 0) << (1u << 11) << true << false;
QTest::newRow("data frame bad long id")
<< QCanBusFrame::DataFrame << false
- << QByteArray(8, 0) << (1u << 11) << false;
+ << QByteArray(8, 0) << (1u << 11) << false << false;
+ QTest::newRow("data frame CAN too long payload")
+ << QCanBusFrame::DataFrame << false
+ << QByteArray(9, 0) << 512u << false << false;
+ QTest::newRow("data frame CAN FD long payload")
+ << QCanBusFrame::DataFrame << true
+ << QByteArray(9, 0) << 512u << false << true;
+ QTest::newRow("data frame CAN FD too long payload")
+ << QCanBusFrame::DataFrame << false
+ << QByteArray(65, 0) << 512u << false << true;
}
void tst_QCanBusFrame::tst_isValid()
@@ -203,16 +243,19 @@ void tst_QCanBusFrame::tst_isValid()
QFETCH(QByteArray, payload);
QFETCH(uint, id);
QFETCH(bool, extended);
+ QFETCH(bool, flexibleData);
QCanBusFrame frame(frameType);
frame.setPayload(payload);
frame.setFrameId(id);
frame.setExtendedFrameFormat(extended);
+ frame.setFlexibleDataRateFormat(flexibleData);
QCOMPARE(frame.isValid(), isValid);
QCOMPARE(frame.frameType(), frameType);
QCOMPARE(frame.payload(), payload);
QCOMPARE(frame.frameId(), id);
QCOMPARE(frame.hasExtendedFrameFormat(), extended);
+ QCOMPARE(frame.hasFlexibleDataRateFormat(), flexibleData);
frame.setFrameType(QCanBusFrame::InvalidFrame);
QCOMPARE(frame.isValid(), false);
@@ -242,39 +285,39 @@ void tst_QCanBusFrame::tst_toString_data()
QTest::newRow("remote request frame")
<< QCanBusFrame::RemoteRequestFrame << 0x123u << false
<< QByteArray::fromHex("01") // fake data to get a DLC > 0
- << QString(" 123 [1] Remote Request");
+ << QString(" 123 [1] Remote Request");
QTest::newRow("data frame min std id")
<< QCanBusFrame::DataFrame << 0x0u << false
<< QByteArray()
- << QString(" 000 [0]");
+ << QString(" 000 [0]");
QTest::newRow("data frame max std id")
<< QCanBusFrame::DataFrame << 0x7FFu << false
<< QByteArray()
- << QString(" 7FF [0]");
+ << QString(" 7FF [0]");
QTest::newRow("data frame min ext id")
<< QCanBusFrame::DataFrame << 0x0u << true
<< QByteArray()
- << QString("00000000 [0]");
+ << QString("00000000 [0]");
QTest::newRow("data frame max ext id")
<< QCanBusFrame::DataFrame << 0x1FFFFFFFu << true
<< QByteArray()
- << QString("1FFFFFFF [0]");
+ << QString("1FFFFFFF [0]");
QTest::newRow("data frame minimal size")
<< QCanBusFrame::DataFrame << 0x7FFu << false
<< QByteArray::fromHex("01")
- << QString(" 7FF [1] 01");
+ << QString(" 7FF [1] 01");
QTest::newRow("data frame maximal size")
<< QCanBusFrame::DataFrame << 0x1FFFFFFFu << true
<< QByteArray::fromHex("0123456789ABCDEF")
- << QString("1FFFFFFF [8] 01 23 45 67 89 AB CD EF");
+ << QString("1FFFFFFF [8] 01 23 45 67 89 AB CD EF");
QTest::newRow("short data frame FD")
<< QCanBusFrame::DataFrame << 0x123u << false
<< QByteArray::fromHex("001122334455667788")
- << QString(" 123 [9] 00 11 22 33 44 55 66 77 88");
+ << QString(" 123 [09] 00 11 22 33 44 55 66 77 88");
QTest::newRow("long data frame FD")
<< QCanBusFrame::DataFrame << 0x123u << false
<< QByteArray::fromHex("00112233445566778899")
- << QString(" 123 [10] 00 11 22 33 44 55 66 77 88 99");
+ << QString(" 123 [10] 00 11 22 33 44 55 66 77 88 99");
}
void tst_QCanBusFrame::tst_toString()
@@ -302,30 +345,34 @@ void tst_QCanBusFrame::streaming_data()
QTest::addColumn<qint64>("seconds");
QTest::addColumn<qint64>("microSeconds");
QTest::addColumn<bool>("isExtended");
+ QTest::addColumn<bool>("isFlexibleDataRate");
QTest::addColumn<QCanBusFrame::FrameType>("frameType");
QTest::newRow("emptyFrame") << quint32(0) << QByteArray()
<< qint64(0) << qint64(0)
- << false << QCanBusFrame::DataFrame;
+ << false << false << QCanBusFrame::DataFrame;
QTest::newRow("fullFrame1") << quint32(123) << QByteArray("abcde1")
<< qint64(456) << qint64(784)
- << true << QCanBusFrame::DataFrame;
+ << true << false << QCanBusFrame::DataFrame;
QTest::newRow("fullFrame2") << quint32(123) << QByteArray("abcde2")
<< qint64(457) << qint64(785)
- << false << QCanBusFrame::DataFrame;
+ << false << false << QCanBusFrame::DataFrame;
+ QTest::newRow("fullFrameFD") << quint32(123) << QByteArray("abcdfd")
+ << qint64(457) << qint64(785)
+ << false << true << QCanBusFrame::DataFrame;
QTest::newRow("fullFrame3") << quint32(123) << QByteArray("abcde3")
<< qint64(458) << qint64(786)
- << true << QCanBusFrame::RemoteRequestFrame;
+ << true << false << QCanBusFrame::RemoteRequestFrame;
QTest::newRow("fullFrame4") << quint32(123) << QByteArray("abcde4")
<< qint64(459) << qint64(787)
- << false << QCanBusFrame::RemoteRequestFrame;
+ << false << false << QCanBusFrame::RemoteRequestFrame;
QTest::newRow("fullFrame5") << quint32(123) << QByteArray("abcde5")
<< qint64(460) << qint64(789)
- << true << QCanBusFrame::ErrorFrame;
+ << true << false << QCanBusFrame::ErrorFrame;
QTest::newRow("fullFrame6") << quint32(123) << QByteArray("abcde6")
<< qint64(453) << qint64(788)
- << false << QCanBusFrame::ErrorFrame;
+ << false << false << QCanBusFrame::ErrorFrame;
}
void tst_QCanBusFrame::streaming()
@@ -335,6 +382,7 @@ void tst_QCanBusFrame::streaming()
QFETCH(qint64, seconds);
QFETCH(qint64, microSeconds);
QFETCH(bool, isExtended);
+ QFETCH(bool, isFlexibleDataRate);
QFETCH(QCanBusFrame::FrameType, frameType);
QCanBusFrame originalFrame(frameId, payload);
@@ -342,6 +390,7 @@ void tst_QCanBusFrame::streaming()
originalFrame.setTimeStamp(originalStamp);
originalFrame.setExtendedFrameFormat(isExtended);
+ originalFrame.setFlexibleDataRateFormat(isFlexibleDataRate);
originalFrame.setFrameType(frameType);
QByteArray buffer;
@@ -362,6 +411,8 @@ void tst_QCanBusFrame::streaming()
QCOMPARE(restoredFrame.frameType(), originalFrame.frameType());
QCOMPARE(restoredFrame.hasExtendedFrameFormat(),
originalFrame.hasExtendedFrameFormat());
+ QCOMPARE(restoredFrame.hasFlexibleDataRateFormat(),
+ originalFrame.hasFlexibleDataRateFormat());
}
void tst_QCanBusFrame::tst_error()
diff --git a/tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp b/tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp
index 592a14e..4472131 100644
--- a/tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp
+++ b/tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp
@@ -844,6 +844,25 @@ private slots:
});
QCOMPARE(QModbusRequest::calculateDataSize(request), 27);
}
+
+ void testCalculateLongDataSize()
+ {
+ QByteArray longData = QByteArray(128, ' ');
+ longData[0] = longData.size();
+ const QModbusResponse response(QModbusResponse::ReadCoils, longData);
+ QCOMPARE(QModbusResponse::calculateDataSize(response), 1 + longData.size());
+
+ const QModbusRequest wfrRequest(QModbusPdu::WriteFileRecord, longData);
+ QCOMPARE(QModbusRequest::calculateDataSize(wfrRequest), 1 + longData.size());
+
+ longData = QByteArray(4 + 128, ' ');
+ longData[4] = char(128);
+ const QModbusRequest wmcRequest(QModbusPdu::WriteMultipleCoils, longData);
+ QCOMPARE(QModbusRequest::calculateDataSize(wmcRequest), 1 + longData.size());
+
+ const QModbusRequest wmrRequest(QModbusPdu::WriteMultipleRegisters, longData);
+ QCOMPARE(QModbusRequest::calculateDataSize(wmrRequest), 1 + longData.size());
+ }
};
QTEST_MAIN(tst_QModbusPdu)