summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/plugins/CMakeLists.txt1
-rw-r--r--src/plugins/canbus/CMakeLists.txt18
-rw-r--r--src/plugins/canbus/canbus.pro18
-rw-r--r--src/plugins/canbus/passthrucan/CMakeLists.txt19
-rw-r--r--src/plugins/canbus/passthrucan/j2534passthru.cpp37
-rw-r--r--src/plugins/canbus/passthrucan/j2534passthru.h37
-rw-r--r--src/plugins/canbus/passthrucan/main.cpp43
-rw-r--r--src/plugins/canbus/passthrucan/passthrucan.pro20
-rw-r--r--src/plugins/canbus/passthrucan/passthrucanbackend.cpp67
-rw-r--r--src/plugins/canbus/passthrucan/passthrucanbackend.h46
-rw-r--r--src/plugins/canbus/passthrucan/passthrucanio.cpp49
-rw-r--r--src/plugins/canbus/passthrucan/passthrucanio.h44
-rw-r--r--src/plugins/canbus/peakcan/CMakeLists.txt19
-rw-r--r--src/plugins/canbus/peakcan/main.cpp43
-rw-r--r--src/plugins/canbus/peakcan/peakcan.pro18
-rw-r--r--src/plugins/canbus/peakcan/peakcan_symbols_p.h83
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend.cpp237
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend.h60
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend_p.h41
-rw-r--r--src/plugins/canbus/socketcan/CMakeLists.txt19
-rw-r--r--src/plugins/canbus/socketcan/libsocketcan.cpp47
-rw-r--r--src/plugins/canbus/socketcan/libsocketcan.h37
-rw-r--r--src/plugins/canbus/socketcan/main.cpp41
-rw-r--r--src/plugins/canbus/socketcan/socketcan.pro18
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp130
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.h74
-rw-r--r--src/plugins/canbus/systeccan/CMakeLists.txt19
-rw-r--r--src/plugins/canbus/systeccan/main.cpp41
-rw-r--r--src/plugins/canbus/systeccan/systeccan.pro18
-rw-r--r--src/plugins/canbus/systeccan/systeccan_symbols_p.h40
-rw-r--r--src/plugins/canbus/systeccan/systeccanbackend.cpp98
-rw-r--r--src/plugins/canbus/systeccan/systeccanbackend.h47
-rw-r--r--src/plugins/canbus/systeccan/systeccanbackend_p.h43
-rw-r--r--src/plugins/canbus/tinycan/CMakeLists.txt19
-rw-r--r--src/plugins/canbus/tinycan/main.cpp43
-rw-r--r--src/plugins/canbus/tinycan/tinycan.pro17
-rw-r--r--src/plugins/canbus/tinycan/tinycan_symbols_p.h39
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend.cpp106
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend.h51
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend_p.h41
-rw-r--r--src/plugins/canbus/vectorcan/CMakeLists.txt19
-rw-r--r--src/plugins/canbus/vectorcan/main.cpp41
-rw-r--r--src/plugins/canbus/vectorcan/vectorcan.pro18
-rw-r--r--src/plugins/canbus/vectorcan/vectorcan_symbols_p.h162
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend.cpp477
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend.h50
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend_p.h44
-rw-r--r--src/plugins/canbus/virtualcan/CMakeLists.txt18
-rw-r--r--src/plugins/canbus/virtualcan/main.cpp41
-rw-r--r--src/plugins/canbus/virtualcan/virtualcan.pro16
-rw-r--r--src/plugins/canbus/virtualcan/virtualcanbackend.cpp74
-rw-r--r--src/plugins/canbus/virtualcan/virtualcanbackend.h46
-rw-r--r--src/plugins/plugins.pro3
-rw-r--r--src/serialbus/CMakeLists.txt62
-rw-r--r--src/serialbus/configure.cmake57
-rw-r--r--src/serialbus/configure.json60
-rw-r--r--src/serialbus/doc/images/can-example.pngbin16453 -> 56571 bytes
-rw-r--r--src/serialbus/doc/images/canbus_signals_be.pngbin0 -> 12420 bytes
-rw-r--r--src/serialbus/doc/images/canbus_signals_le.pngbin0 -> 12385 bytes
-rw-r--r--src/serialbus/doc/qtserialbus.qdocconf9
-rw-r--r--src/serialbus/doc/snippets/snippetmain.cpp51
-rw-r--r--src/serialbus/doc/snippets/snippets.pro7
-rw-r--r--src/serialbus/doc/src/examples/can.qdoc76
-rw-r--r--src/serialbus/doc/src/examples/qtserialbus-examples.qdoc29
-rw-r--r--src/serialbus/doc/src/external-resources.qdoc12
-rw-r--r--src/serialbus/doc/src/passthrucan.qdoc30
-rw-r--r--src/serialbus/doc/src/peakcan.qdoc46
-rw-r--r--src/serialbus/doc/src/qt6-changes.qdoc64
-rw-r--r--src/serialbus/doc/src/qtcanbus-backends.qdoc47
-rw-r--r--src/serialbus/doc/src/qtmodbus-backends.qdoc35
-rw-r--r--src/serialbus/doc/src/qtserialbus-index.qdoc56
-rw-r--r--src/serialbus/doc/src/qtserialbus-module-cpp.qdoc40
-rw-r--r--src/serialbus/doc/src/qtserialbus-module-use.qdocinc15
-rw-r--r--src/serialbus/doc/src/socketcan.qdoc28
-rw-r--r--src/serialbus/doc/src/systeccan.qdoc30
-rw-r--r--src/serialbus/doc/src/tinycan.qdoc28
-rw-r--r--src/serialbus/doc/src/vectorcan.qdoc37
-rw-r--r--src/serialbus/doc/src/virtualcan.qdoc28
-rw-r--r--src/serialbus/qcanbus.cpp83
-rw-r--r--src/serialbus/qcanbus.h38
-rw-r--r--src/serialbus/qcanbusdevice.cpp166
-rw-r--r--src/serialbus/qcanbusdevice.h83
-rw-r--r--src/serialbus/qcanbusdevice_p.h45
-rw-r--r--src/serialbus/qcanbusdeviceinfo.cpp74
-rw-r--r--src/serialbus/qcanbusdeviceinfo.h45
-rw-r--r--src/serialbus/qcanbusdeviceinfo_p.h40
-rw-r--r--src/serialbus/qcanbusfactory.cpp77
-rw-r--r--src/serialbus/qcanbusfactory.h54
-rw-r--r--src/serialbus/qcanbusframe.cpp107
-rw-r--r--src/serialbus/qcanbusframe.h99
-rw-r--r--src/serialbus/qcancommondefinitions.cpp134
-rw-r--r--src/serialbus/qcancommondefinitions.h63
-rw-r--r--src/serialbus/qcandbcfileparser.cpp1161
-rw-r--r--src/serialbus/qcandbcfileparser.h61
-rw-r--r--src/serialbus/qcandbcfileparser_p.h63
-rw-r--r--src/serialbus/qcanframeprocessor.cpp1191
-rw-r--r--src/serialbus/qcanframeprocessor.h67
-rw-r--r--src/serialbus/qcanframeprocessor_p.h54
-rw-r--r--src/serialbus/qcanmessagedescription.cpp355
-rw-r--r--src/serialbus/qcanmessagedescription.h80
-rw-r--r--src/serialbus/qcanmessagedescription_p.h39
-rw-r--r--src/serialbus/qcansignaldescription.cpp847
-rw-r--r--src/serialbus/qcansignaldescription.h135
-rw-r--r--src/serialbus/qcansignaldescription_p.h62
-rw-r--r--src/serialbus/qcanuniqueiddescription.cpp210
-rw-r--r--src/serialbus/qcanuniqueiddescription.h57
-rw-r--r--src/serialbus/qcanuniqueiddescription_p.h37
-rw-r--r--src/serialbus/qmodbus_symbols_p.h37
-rw-r--r--src/serialbus/qmodbusadu_p.h38
-rw-r--r--src/serialbus/qmodbusclient.cpp95
-rw-r--r--src/serialbus/qmodbusclient.h38
-rw-r--r--src/serialbus/qmodbusclient_p.h40
-rw-r--r--src/serialbus/qmodbuscommevent_p.h46
-rw-r--r--src/serialbus/qmodbusdataunit.cpp51
-rw-r--r--src/serialbus/qmodbusdataunit.h66
-rw-r--r--src/serialbus/qmodbusdevice.cpp79
-rw-r--r--src/serialbus/qmodbusdevice.h57
-rw-r--r--src/serialbus/qmodbusdevice_p.h63
-rw-r--r--src/serialbus/qmodbusdeviceidentification.cpp37
-rw-r--r--src/serialbus/qmodbusdeviceidentification.h39
-rw-r--r--src/serialbus/qmodbuspdu.cpp183
-rw-r--r--src/serialbus/qmodbuspdu.h110
-rw-r--r--src/serialbus/qmodbusreply.cpp86
-rw-r--r--src/serialbus/qmodbusreply.h42
-rw-r--r--src/serialbus/qmodbusrtuserialclient.cpp (renamed from src/serialbus/qmodbusrtuserialmaster.cpp)91
-rw-r--r--src/serialbus/qmodbusrtuserialclient.h49
-rw-r--r--src/serialbus/qmodbusrtuserialclient_p.h (renamed from src/serialbus/qmodbusrtuserialmaster_p.h)97
-rw-r--r--src/serialbus/qmodbusrtuserialmaster.h70
-rw-r--r--src/serialbus/qmodbusrtuserialserver.cpp160
-rw-r--r--src/serialbus/qmodbusrtuserialserver.h50
-rw-r--r--src/serialbus/qmodbusrtuserialserver_p.h (renamed from src/serialbus/qmodbusrtuserialslave_p.h)72
-rw-r--r--src/serialbus/qmodbusrtuserialslave.cpp163
-rw-r--r--src/serialbus/qmodbusrtuserialslave.h68
-rw-r--r--src/serialbus/qmodbusserver.cpp69
-rw-r--r--src/serialbus/qmodbusserver.h37
-rw-r--r--src/serialbus/qmodbusserver_p.h37
-rw-r--r--src/serialbus/qmodbustcpclient.cpp37
-rw-r--r--src/serialbus/qmodbustcpclient.h37
-rw-r--r--src/serialbus/qmodbustcpclient_p.h44
-rw-r--r--src/serialbus/qmodbustcpserver.cpp41
-rw-r--r--src/serialbus/qmodbustcpserver.h37
-rw-r--r--src/serialbus/qmodbustcpserver_p.h51
-rw-r--r--src/serialbus/qt_cmdline.cmake0
-rw-r--r--src/serialbus/qtserialbusglobal.h52
-rw-r--r--src/serialbus/serialbus.pro74
-rw-r--r--src/src.pro23
-rw-r--r--src/tools/CMakeLists.txt11
-rw-r--r--src/tools/canbusutil/CMakeLists.txt19
-rw-r--r--src/tools/canbusutil/canbusutil.cpp49
-rw-r--r--src/tools/canbusutil/canbusutil.h42
-rw-r--r--src/tools/canbusutil/canbusutil.pro14
-rw-r--r--src/tools/canbusutil/main.cpp42
-rw-r--r--src/tools/canbusutil/readtask.cpp37
-rw-r--r--src/tools/canbusutil/readtask.h37
-rw-r--r--src/tools/canbusutil/sigtermhandler.cpp37
-rw-r--r--src/tools/canbusutil/sigtermhandler.h37
-rw-r--r--src/tools/tools.pro3
158 files changed, 7170 insertions, 4901 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..b8c2545
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+add_subdirectory(serialbus)
+add_subdirectory(plugins)
+add_subdirectory(tools)
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
new file mode 100644
index 0000000..83a5822
--- /dev/null
+++ b/src/plugins/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(canbus)
diff --git a/src/plugins/canbus/CMakeLists.txt b/src/plugins/canbus/CMakeLists.txt
new file mode 100644
index 0000000..e86e0c6
--- /dev/null
+++ b/src/plugins/canbus/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+add_subdirectory(virtualcan)
+if(QT_FEATURE_socketcan)
+ add_subdirectory(socketcan)
+endif()
+if(QT_FEATURE_library)
+ add_subdirectory(passthrucan)
+ add_subdirectory(peakcan)
+ add_subdirectory(tinycan)
+endif()
+if(QT_FEATURE_library AND WIN32)
+ add_subdirectory(systeccan)
+endif()
+if(QT_FEATURE_library AND WIN32 AND NOT WINRT)
+ add_subdirectory(vectorcan)
+endif()
diff --git a/src/plugins/canbus/canbus.pro b/src/plugins/canbus/canbus.pro
deleted file mode 100644
index ab9755c..0000000
--- a/src/plugins/canbus/canbus.pro
+++ /dev/null
@@ -1,18 +0,0 @@
-TEMPLATE = subdirs
-
-include($$OUT_PWD/../../serialbus/qtserialbus-config.pri)
-QT_FOR_CONFIG += serialbus-private
-
-SUBDIRS += virtualcan
-
-qtConfig(socketcan) {
- SUBDIRS += socketcan
-}
-
-qtConfig(library) {
- SUBDIRS += passthrucan peakcan tinycan
- win32 {
- SUBDIRS += systeccan
- !winrt:SUBDIRS += vectorcan
- }
-}
diff --git a/src/plugins/canbus/passthrucan/CMakeLists.txt b/src/plugins/canbus/passthrucan/CMakeLists.txt
new file mode 100644
index 0000000..1884aed
--- /dev/null
+++ b/src/plugins/canbus/passthrucan/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## PassThruCanBusPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(PassThruCanBusPlugin
+ OUTPUT_NAME qtpassthrucanbus
+ PLUGIN_TYPE canbus
+ SOURCES
+ j2534passthru.cpp j2534passthru.h
+ main.cpp
+ passthrucanbackend.cpp passthrucanbackend.h
+ passthrucanio.cpp passthrucanio.h
+ LIBRARIES
+ Qt::Network
+ Qt::SerialBus
+)
diff --git a/src/plugins/canbus/passthrucan/j2534passthru.cpp b/src/plugins/canbus/passthrucan/j2534passthru.cpp
index 22bf996..e8967d7 100644
--- a/src/plugins/canbus/passthrucan/j2534passthru.cpp
+++ b/src/plugins/canbus/passthrucan/j2534passthru.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Ford Motor Company.
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Ford Motor Company.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "j2534passthru.h"
diff --git a/src/plugins/canbus/passthrucan/j2534passthru.h b/src/plugins/canbus/passthrucan/j2534passthru.h
index a9b88f4..b65534f 100644
--- a/src/plugins/canbus/passthrucan/j2534passthru.h
+++ b/src/plugins/canbus/passthrucan/j2534passthru.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Ford Motor Company.
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Ford Motor Company.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef PASSTHRUCAN_J2534PASSTHRU_H
#define PASSTHRUCAN_J2534PASSTHRU_H
diff --git a/src/plugins/canbus/passthrucan/main.cpp b/src/plugins/canbus/passthrucan/main.cpp
index 5017597..fe166fe 100644
--- a/src/plugins/canbus/passthrucan/main.cpp
+++ b/src/plugins/canbus/passthrucan/main.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Ford Motor Company.
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Ford Motor Company.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "passthrucanbackend.h"
@@ -42,17 +9,17 @@
QT_BEGIN_NAMESPACE
-class PassThruCanBusPlugin : public QObject, public QCanBusFactoryV2
+class PassThruCanBusPlugin : public QObject, public QCanBusFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QCanBusFactory" FILE "plugin.json")
- Q_INTERFACES(QCanBusFactoryV2)
+ Q_INTERFACES(QCanBusFactory)
public:
PassThruCanBusPlugin()
{
qRegisterMetaType<QCanBusDevice::CanBusError>();
- qRegisterMetaType<QVector<QCanBusFrame>>();
+ qRegisterMetaType<QList<QCanBusFrame>>();
}
QList<QCanBusDeviceInfo> availableDevices(QString *) const override
diff --git a/src/plugins/canbus/passthrucan/passthrucan.pro b/src/plugins/canbus/passthrucan/passthrucan.pro
deleted file mode 100644
index cb9bdc5..0000000
--- a/src/plugins/canbus/passthrucan/passthrucan.pro
+++ /dev/null
@@ -1,20 +0,0 @@
-QT = serialbus
-
-TARGET = qtpassthrucanbus
-
-SOURCES += \
- j2534passthru.cpp \
- main.cpp \
- passthrucanio.cpp \
- passthrucanbackend.cpp
-
-HEADERS += \
- j2534passthru.h \
- passthrucanio.h \
- passthrucanbackend.h
-
-DISTFILES = plugin.json
-
-PLUGIN_TYPE = canbus
-PLUGIN_CLASS_NAME = PassThruCanBusPlugin
-load(qt_plugin)
diff --git a/src/plugins/canbus/passthrucan/passthrucanbackend.cpp b/src/plugins/canbus/passthrucan/passthrucanbackend.cpp
index 2c18160..940913d 100644
--- a/src/plugins/canbus/passthrucan/passthrucanbackend.cpp
+++ b/src/plugins/canbus/passthrucan/passthrucanbackend.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Ford Motor Company.
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Ford Motor Company.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "passthrucanbackend.h"
#include "passthrucanio.h"
@@ -130,7 +97,7 @@ PassThruCanBackend::~PassThruCanBackend()
m_canIO->deleteLater();
}
-void PassThruCanBackend::setConfigurationParameter(int key, const QVariant &value)
+void PassThruCanBackend::setConfigurationParameter(ConfigurationKey key, const QVariant &value)
{
QCanBusDevice::setConfigurationParameter(key, value);
@@ -177,14 +144,18 @@ QList<QCanBusDeviceInfo> PassThruCanBackend::interfaces()
const QString name = canAdapterName(entries);
if (!name.isEmpty())
- list.append(createDeviceInfo(name));
-
+ list.append(createDeviceInfo(QStringLiteral("passthrucan"), name, false, false));
entries.endGroup();
}
#endif
return list;
}
+QCanBusDeviceInfo PassThruCanBackend::deviceInfo() const
+{
+ return createDeviceInfo(QStringLiteral("passthrucan"), m_deviceName, false, false);
+}
+
bool PassThruCanBackend::open()
{
if (Q_UNLIKELY(state() != ConnectingState)) {
@@ -200,7 +171,7 @@ bool PassThruCanBackend::open()
QByteArray subDev;
if (splitPos >= 0)
- subDev = m_deviceName.midRef(splitPos + 1).toLatin1();
+ subDev = QStringView{m_deviceName}.mid(splitPos + 1).toLatin1();
const QString library = libraryForAdapter(adapter);
if (library.isEmpty()) {
@@ -215,10 +186,9 @@ bool PassThruCanBackend::open()
}
m_ioThread.start();
- return QMetaObject::invokeMethod(m_canIO, "open", Qt::QueuedConnection,
- Q_ARG(QString, library),
- Q_ARG(QByteArray, subDev),
- Q_ARG(uint, bitRate));
+ return QMetaObject::invokeMethod(m_canIO, [this, library, subDev, bitRate] {
+ m_canIO->open(library, subDev, bitRate);
+ }, Qt::QueuedConnection);
}
void PassThruCanBackend::close()
@@ -227,7 +197,7 @@ void PassThruCanBackend::close()
qCCritical(QT_CANBUS_PLUGINS_PASSTHRU, "Unexpected state on close");
return;
}
- QMetaObject::invokeMethod(m_canIO, "close", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(m_canIO, &PassThruCanIO::close, Qt::QueuedConnection);
}
void PassThruCanBackend::ackOpenFinished(bool success)
@@ -250,7 +220,7 @@ void PassThruCanBackend::ackOpenFinished(bool success)
}
applyConfig(RawFilterKey, filters);
- QMetaObject::invokeMethod(m_canIO, "listen", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(m_canIO, &PassThruCanIO::listen, Qt::QueuedConnection);
setState(ConnectedState);
} else {
@@ -266,8 +236,9 @@ void PassThruCanBackend::ackCloseFinished()
setState(UnconnectedState);
}
-void PassThruCanBackend::applyConfig(int key, const QVariant &value)
+void PassThruCanBackend::applyConfig(QCanBusDevice::ConfigurationKey key, const QVariant &value)
{
- QMetaObject::invokeMethod(m_canIO, "applyConfig", Qt::QueuedConnection,
- Q_ARG(int, key), Q_ARG(QVariant, value));
+ QMetaObject::invokeMethod(m_canIO,
+ [this, key, value] { m_canIO->applyConfig(key, value); },
+ Qt::QueuedConnection);
}
diff --git a/src/plugins/canbus/passthrucan/passthrucanbackend.h b/src/plugins/canbus/passthrucan/passthrucanbackend.h
index 864d1b4..7f78036 100644
--- a/src/plugins/canbus/passthrucan/passthrucanbackend.h
+++ b/src/plugins/canbus/passthrucan/passthrucanbackend.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Ford Motor Company.
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Ford Motor Company.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef PASSTHRUCAN_PASSTHRUCANBACKEND_H
#define PASSTHRUCAN_PASSTHRUCANBACKEND_H
@@ -40,9 +7,9 @@
#include <QtSerialBus/qcanbusdevice.h>
#include <QtSerialBus/qcanbusframe.h>
+#include <QList>
#include <QString>
#include <QThread>
-#include <QVector>
QT_BEGIN_NAMESPACE
@@ -56,11 +23,12 @@ public:
explicit PassThruCanBackend(const QString &name, QObject *parent = nullptr);
virtual ~PassThruCanBackend();
- void setConfigurationParameter(int key, const QVariant &value) override;
+ void setConfigurationParameter(ConfigurationKey key, const QVariant &value) override;
bool writeFrame(const QCanBusFrame &frame) override;
QString interpretErrorFrame(const QCanBusFrame &errorFrame) override;
static QList<QCanBusDeviceInfo> interfaces();
+ QCanBusDeviceInfo deviceInfo() const override;
protected:
bool open() override;
@@ -69,7 +37,7 @@ protected:
private:
void ackOpenFinished(bool success);
void ackCloseFinished();
- void applyConfig(int key, const QVariant &value);
+ void applyConfig(QCanBusDevice::ConfigurationKey key, const QVariant &value);
QString m_deviceName;
QThread m_ioThread;
@@ -79,6 +47,6 @@ private:
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QCanBusDevice::CanBusError)
-Q_DECLARE_METATYPE(QVector<QCanBusFrame>)
+Q_DECLARE_METATYPE(QList<QCanBusFrame>)
#endif // PASSTHRUCAN_PASSTHRUCANBACKEND_H
diff --git a/src/plugins/canbus/passthrucan/passthrucanio.cpp b/src/plugins/canbus/passthrucan/passthrucanio.cpp
index dc3d2c7..4482aa1 100644
--- a/src/plugins/canbus/passthrucan/passthrucanio.cpp
+++ b/src/plugins/canbus/passthrucan/passthrucanio.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Ford Motor Company.
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Ford Motor Company.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "passthrucanio.h"
@@ -106,7 +73,7 @@ void PassThruCanIO::close()
emit closeFinished();
}
-void PassThruCanIO::applyConfig(int key, const QVariant &value)
+void PassThruCanIO::applyConfig(QCanBusDevice::ConfigurationKey key, const QVariant &value)
{
if (Q_UNLIKELY(!m_passThru)) {
qCCritical(QT_CANBUS_PLUGINS_PASSTHRU, "Pass-thru interface not open");
@@ -185,8 +152,8 @@ bool PassThruCanIO::setMessageFilters(const QList<QCanBusDevice::Filter> &filter
else
mask.setRxStatus({});
- qToBigEndian<quint32>(filter.frameId & filter.frameIdMask, pattern.data());
- qToBigEndian<quint32>(filter.frameIdMask, mask.data());
+ qToBigEndian<QCanBusFrame::FrameId>(filter.frameId & filter.frameIdMask, pattern.data());
+ qToBigEndian<QCanBusFrame::FrameId>(filter.frameIdMask, mask.data());
if (m_passThru->startMsgFilter(m_channelId, J2534::PassThru::PassFilter,
mask, pattern) != J2534::PassThru::NoError)
@@ -236,7 +203,7 @@ bool PassThruCanIO::writeMessages()
else
msg.setTxFlags({});
- qToBigEndian<quint32>(frame.frameId(), msg.data());
+ qToBigEndian<QCanBusFrame::FrameId>(frame.frameId(), msg.data());
std::memcpy(msg.data() + 4, payload.data(), payloadSize);
}
}
@@ -287,7 +254,7 @@ void PassThruCanIO::readMessages(bool writePending)
return;
}
const int numFrames = qMin<ulong>(m_ioBuffer.size(), numMsgs);
- QVector<QCanBusFrame> frames;
+ QList<QCanBusFrame> frames;
frames.reserve(numFrames);
for (int i = 0; i < numFrames; ++i) {
@@ -299,7 +266,7 @@ void PassThruCanIO::readMessages(bool writePending)
"Message with invalid size %lu received", msg.size());
continue;
}
- const quint32 msgId = qFromBigEndian<quint32>(msg.data());
+ const QCanBusFrame::FrameId msgId = qFromBigEndian<QCanBusFrame::FrameId>(msg.data());
const QByteArray payload (msg.data() + 4, msg.size() - 4);
QCanBusFrame frame (msgId, payload);
diff --git a/src/plugins/canbus/passthrucan/passthrucanio.h b/src/plugins/canbus/passthrucan/passthrucanio.h
index 071174c..a212b59 100644
--- a/src/plugins/canbus/passthrucan/passthrucanio.h
+++ b/src/plugins/canbus/passthrucan/passthrucanio.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Ford Motor Company.
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Ford Motor Company.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef PASSTHRUCAN_PASSTHRUCANIO_H
#define PASSTHRUCAN_PASSTHRUCANIO_H
@@ -48,7 +15,6 @@
#include <QString>
#include <QTimer>
#include <QVariant>
-#include <QVector>
QT_BEGIN_NAMESPACE
@@ -64,7 +30,7 @@ public:
Q_INVOKABLE void open(const QString &library, const QByteArray &subDev, uint bitRate);
Q_INVOKABLE void close();
- Q_INVOKABLE void applyConfig(int key, const QVariant &value);
+ Q_INVOKABLE void applyConfig(QCanBusDevice::ConfigurationKey key, const QVariant &value);
Q_INVOKABLE void listen();
// Internally locked; safe to call directly from any thread.
@@ -72,7 +38,7 @@ public:
Q_SIGNALS:
void errorOccurred(const QString &description, QCanBusDevice::CanBusError error);
- void messagesReceived(QVector<QCanBusFrame> frames);
+ void messagesReceived(QList<QCanBusFrame> frames);
void messagesSent(qint64 count);
void openFinished(bool success);
void closeFinished();
@@ -88,7 +54,7 @@ private:
J2534::PassThru::Handle m_deviceId = 0;
J2534::PassThru::Handle m_channelId = 0;
QTimer * m_idleNotifier = nullptr;
- QVector<J2534::Message> m_ioBuffer;
+ QList<J2534::Message> m_ioBuffer;
QMutex m_writeGuard;
QList<QCanBusFrame> m_writeQueue;
};
diff --git a/src/plugins/canbus/peakcan/CMakeLists.txt b/src/plugins/canbus/peakcan/CMakeLists.txt
new file mode 100644
index 0000000..0e4110c
--- /dev/null
+++ b/src/plugins/canbus/peakcan/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## PeakCanBusPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(PeakCanBusPlugin
+ OUTPUT_NAME qtpeakcanbus
+ PLUGIN_TYPE canbus
+ SOURCES
+ main.cpp
+ peakcan_symbols_p.h
+ peakcanbackend.cpp peakcanbackend.h peakcanbackend_p.h
+ LIBRARIES
+ Qt::Core
+ Qt::Network
+ Qt::SerialBus
+)
diff --git a/src/plugins/canbus/peakcan/main.cpp b/src/plugins/canbus/peakcan/main.cpp
index 8ab1b99..bff3261 100644
--- a/src/plugins/canbus/peakcan/main.cpp
+++ b/src/plugins/canbus/peakcan/main.cpp
@@ -1,39 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "peakcanbackend.h"
@@ -47,11 +14,11 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_PEAKCAN, "qt.canbus.plugins.peakcan")
-class PeakCanBusPlugin : public QObject, public QCanBusFactoryV2
+class PeakCanBusPlugin : public QObject, public QCanBusFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QCanBusFactory" FILE "plugin.json")
- Q_INTERFACES(QCanBusFactoryV2)
+ Q_INTERFACES(QCanBusFactory)
public:
QList<QCanBusDeviceInfo> availableDevices(QString *errorMessage) const override
diff --git a/src/plugins/canbus/peakcan/peakcan.pro b/src/plugins/canbus/peakcan/peakcan.pro
deleted file mode 100644
index d5b809c..0000000
--- a/src/plugins/canbus/peakcan/peakcan.pro
+++ /dev/null
@@ -1,18 +0,0 @@
-TARGET = qtpeakcanbus
-
-QT = core serialbus
-
-HEADERS += \
- peakcanbackend.h \
- peakcanbackend_p.h \
- peakcan_symbols_p.h
-
-SOURCES += \
- main.cpp \
- peakcanbackend.cpp
-
-DISTFILES = plugin.json
-
-PLUGIN_TYPE = canbus
-PLUGIN_CLASS_NAME = PeakCanBusPlugin
-load(qt_plugin)
diff --git a/src/plugins/canbus/peakcan/peakcan_symbols_p.h b/src/plugins/canbus/peakcan/peakcan_symbols_p.h
index 12de76f..bf786a3 100644
--- a/src/plugins/canbus/peakcan/peakcan_symbols_p.h
+++ b/src/plugins/canbus/peakcan/peakcan_symbols_p.h
@@ -1,39 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (c) 2020 Andre Hartmann <aha_1980@gmx.de>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef PEAKCAN_SYMBOLS_P_H
#define PEAKCAN_SYMBOLS_P_H
@@ -168,7 +136,7 @@
#define PCAN_PCC 0x06U // PCAN-PC Card
// PCAN parameters
-#define PCAN_DEVICE_NUMBER 0x01U // PCAN-USB device number parameter
+#define PCAN_DEVICE_ID 0x01U // Device identifier parameter
#define PCAN_5VOLTS_POWER 0x02U // PCAN-PC Card 5-Volt power parameter
#define PCAN_RECEIVE_EVENT 0x03U // PCAN receive event handler parameter
#define PCAN_MESSAGE_FILTER 0x04U // PCAN message filter parameter
@@ -197,6 +165,8 @@
#define PCAN_BUSSPEED_DATA 0x1BU // Configured CAN data speed as Bits per seconds
#define PCAN_IP_ADDRESS 0x1CU // Remote address of a LAN channel as string in IPv4 format
#define PCAN_LAN_SERVICE_STATUS 0x1DU // Status of the Virtual PCAN-Gateway Service
+#define PCAN_ATTACHED_CHANNELS_COUNT 0x2AU // Get the amount of PCAN channels attached to a system
+#define PCAN_ATTACHED_CHANNELS 0x2BU // Get information about PCAN channels attached to a system
#define FEATURE_FD_CAPABLE 0x01U // Device supports flexible data-rate (CAN-FD)
@@ -225,6 +195,10 @@
#define TRACE_FILE_TIME 0x04U // Includes the start time into the name of the trace file
#define TRACE_FILE_OVERWRITE 0x80U // Causes the overwriting of available traces (same name)
+// Other constants
+#define MAX_LENGTH_HARDWARE_NAME 33 // Maximum length of the name of a device: 32 characters + terminator
+#define MAX_LENGTH_VERSION_STRING 18 // Maximum length of a version string: 17 characters + terminator
+
// PCAN message types
#define PCAN_MESSAGE_STANDARD 0x00U // The PCAN message is a CAN Standard Frame (11-bit identifier)
#define PCAN_MESSAGE_RTR 0x01U // The PCAN message is a CAN Remote-Transfer-Request Frame
@@ -267,15 +241,8 @@
#define PCAN_TYPE_DNG_SJA_EPP 0x06U // PCAN-Dongle EPP SJA1000
// Type definitions
-#ifdef Q_OS_MACOS
-#define TPCANLong quint64
-#define TPCANLongToFrameID(a) static_cast<quint32>(a)
-#else
-#define TPCANLong quint32
-#define TPCANLongToFrameID(a) a
-#endif
#define TPCANHandle quint16 // Represents a PCAN hardware channel handle
-#define TPCANStatus TPCANLong // Represents a PCAN status/error code
+#define TPCANStatus quint32 // Represents a PCAN status/error code
#define TPCANParameter quint8 // Represents a PCAN parameter to be read or set
#define TPCANDevice quint8 // Represents a PCAN device
#define TPCANMessageType quint8 // Represents the type of a PCAN message
@@ -288,7 +255,7 @@
// Represents a PCAN message
typedef struct tagTPCANMsg
{
- TPCANLong ID; // 11/29-bit message identifier
+ quint32 ID; // 11/29-bit message identifier
TPCANMessageType MSGTYPE; // Type of the message
quint8 LEN; // Data Length Code of the message (0..8)
quint8 DATA[8]; // Data of the message (DATA[0]..DATA[7])
@@ -298,7 +265,7 @@ typedef struct tagTPCANMsg
// Total Microseconds = micros + 1000 * millis + 0xFFFFFFFF * 1000 * millis_overflow
typedef struct tagTPCANTimestamp
{
- TPCANLong millis; // Base-value: milliseconds: 0.. 2^32-1
+ quint32 millis; // Base-value: milliseconds: 0.. 2^32-1
quint16 millis_overflow; // Roll-arounds of millis
quint16 micros; // Microseconds: 0..999
} TPCANTimestamp;
@@ -306,12 +273,24 @@ typedef struct tagTPCANTimestamp
// Represents a PCAN message from a FD capable hardware
typedef struct tagTPCANMsgFD
{
- TPCANLong ID; // 11/29-bit message identifier
+ quint32 ID; // 11/29-bit message identifier
TPCANMessageType MSGTYPE; // Type of the message
quint8 DLC; // Data Length Code of the message (0..15)
quint8 DATA[64]; // Data of the message (DATA[0]..DATA[63])
} TPCANMsgFD;
+// Describes an available PCAN channel
+typedef struct tagTPCANChannelInformation
+{
+ TPCANHandle channel_handle; // PCAN channel handle
+ TPCANDevice device_type; // Kind of PCAN device
+ quint8 controller_number; // CAN-Controller number
+ quint32 device_features; // Device capabilities flag (see FEATURE_*)
+ char device_name[MAX_LENGTH_HARDWARE_NAME]; // Device name
+ quint32 device_id; // Device number
+ quint32 channel_condition; // Availability status of a PCAN-Channel
+} TPCANChannelInformation;
+
#define GENERATE_SYMBOL_VARIABLE(returnType, symbolName, ...) \
typedef returnType (DRV_CALLBACK_TYPE *fp_##symbolName)(__VA_ARGS__); \
static fp_##symbolName symbolName;
@@ -321,7 +300,7 @@ typedef struct tagTPCANMsgFD
if (!symbolName) \
return false;
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Initialize, TPCANHandle, TPCANBaudrate, TPCANType, TPCANLong, quint16)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Initialize, TPCANHandle, TPCANBaudrate, TPCANType, quint32, quint16)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_InitializeFD, TPCANHandle, TPCANBitrateFD)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Uninitialize, TPCANHandle)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Reset, TPCANHandle)
@@ -330,9 +309,9 @@ GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Read, TPCANHandle, TPCANMsg *, TPCANTi
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_ReadFD, TPCANHandle, TPCANMsgFD *, TPCANTimestampFD *)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Write, TPCANHandle, TPCANMsg *)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_WriteFD, TPCANHandle, TPCANMsgFD *)
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_FilterMessages, TPCANHandle, TPCANLong, TPCANLong, TPCANMode)
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetValue, TPCANHandle, TPCANParameter, void *, TPCANLong)
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_SetValue, TPCANHandle, TPCANParameter, void *, TPCANLong)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_FilterMessages, TPCANHandle, quint32, quint32, TPCANMode)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetValue, TPCANHandle, TPCANParameter, void *, quint32)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_SetValue, TPCANHandle, TPCANParameter, void *, quint32)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetErrorText, TPCANStatus, quint16, char *)
inline bool resolvePeakCanSymbols(QLibrary *pcanLibrary)
diff --git a/src/plugins/canbus/peakcan/peakcanbackend.cpp b/src/plugins/canbus/peakcan/peakcanbackend.cpp
index 5a17b22..6d8ce94 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend.cpp
+++ b/src/plugins/canbus/peakcan/peakcanbackend.cpp
@@ -1,39 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (c) 2020 Andre Hartmann <aha_1980@gmx.de>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "peakcanbackend.h"
#include "peakcanbackend_p.h"
@@ -46,6 +14,7 @@
#include <QtCore/qloggingcategory.h>
#include <algorithm>
+#include <vector>
#ifdef Q_OS_WIN32
# include <QtCore/qwineventnotifier.h>
@@ -64,7 +33,7 @@ Q_GLOBAL_STATIC(QLibrary, pcanLibrary)
bool PeakCanBackend::canCreate(QString *errorReason)
{
#ifdef LINK_LIBPCANBASIC
- return true;
+ Q_UNUSED(errorReason);
#else
static bool symbolsResolved = resolvePeakCanSymbols(pcanLibrary());
if (Q_UNLIKELY(!symbolsResolved)) {
@@ -73,8 +42,17 @@ bool PeakCanBackend::canCreate(QString *errorReason)
*errorReason = pcanLibrary()->errorString();
return false;
}
- return true;
#endif
+
+ char apiVersion[32];
+ TPCANStatus stat = CAN_GetValue(PCAN_NONEBUS, PCAN_API_VERSION, apiVersion, sizeof(apiVersion));
+ if (Q_UNLIKELY(stat != PCAN_ERROR_OK)) {
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot resolve PCAN-API version!");
+ return false;
+ }
+ qCInfo(QT_CANBUS_PLUGINS_PEAKCAN, "Using PCAN-API version: %s", apiVersion);
+
+ return true;
}
struct PcanChannel{
@@ -117,7 +95,7 @@ static const PcanChannel pcanChannels[] = {
{ "none", PCAN_NONEBUS }
};
-QList<QCanBusDeviceInfo> PeakCanBackend::interfaces()
+QList<QCanBusDeviceInfo> PeakCanBackend::interfacesByChannelCondition(Availability available)
{
QList<QCanBusDeviceInfo> result;
@@ -126,7 +104,7 @@ QList<QCanBusDeviceInfo> PeakCanBackend::interfaces()
const TPCANHandle index = pcanChannels[i].index;
const TPCANStatus stat = ::CAN_GetValue(index, PCAN_CHANNEL_CONDITION,
&value, sizeof(value));
- if ((stat == PCAN_ERROR_OK) && (value & PCAN_CHANNEL_AVAILABLE)) {
+ if ((stat == PCAN_ERROR_OK) && (value & uint(available))) {
const TPCANStatus fdStat = ::CAN_GetValue(index, PCAN_CHANNEL_FEATURES,
&value, sizeof(value));
const bool isFd = (fdStat == PCAN_ERROR_OK) && (value & FEATURE_FD_CAPABLE);
@@ -143,15 +121,115 @@ QList<QCanBusDeviceInfo> PeakCanBackend::interfaces()
if (chnStat != PCAN_ERROR_OK)
channel = 0;
- result.append(std::move(createDeviceInfo(QLatin1String(pcanChannels[i].name),
- QString(), QLatin1String(description),
- channel, false, isFd)));
+ QString alias;
+ quint32 deviceId = 0;
+ const TPCANStatus idStat = ::CAN_GetValue(index, PCAN_DEVICE_ID,
+ &deviceId, sizeof(deviceId));
+ if (idStat == PCAN_ERROR_OK)
+ alias = QString::number(deviceId);
+
+ result.append(QCanBusDevice::createDeviceInfo(QStringLiteral("peakcan"),
+ QLatin1String(pcanChannels[i].name),
+ QString(), QLatin1String(description),
+ alias, channel, false, isFd));
}
}
return result;
}
+static QString pcanChannelNameForIndex(uint index)
+{
+ const auto pcanChannel = std::find_if(std::begin(pcanChannels), std::end(pcanChannels),
+ [index](PcanChannel channel) {
+ return channel.index == index;
+ });
+ if (Q_LIKELY(pcanChannel != std::end(pcanChannels)))
+ return pcanChannel->name;
+
+ qWarning("%s: Cannot get channel name for index %u.", Q_FUNC_INFO, index);
+ return QStringLiteral("none");
+}
+
+QList<QCanBusDeviceInfo> PeakCanBackend::interfacesByAttachedChannels(Availability available, bool *ok)
+{
+ *ok = true;
+ quint32 count = 0;
+ const TPCANStatus countStat = ::CAN_GetValue(0, PCAN_ATTACHED_CHANNELS_COUNT,
+ &count, sizeof(count));
+ if (Q_UNLIKELY(countStat != PCAN_ERROR_OK)) {
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot query PCAN_ATTACHED_CHANNELS_COUNT.");
+ *ok = false;
+ return {};
+ }
+ if (count == 0)
+ return {};
+
+ std::vector<TPCANChannelInformation> infos(count);
+ const TPCANStatus infosStat = ::CAN_GetValue(0, PCAN_ATTACHED_CHANNELS, infos.data(),
+ quint32(infos.size() * sizeof(TPCANChannelInformation)));
+ if (Q_UNLIKELY(infosStat != PCAN_ERROR_OK)) {
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot query PCAN_ATTACHED_CHANNELS.");
+ *ok = false;
+ return {};
+ }
+
+ QList<QCanBusDeviceInfo> result;
+ for (quint32 i = 0; i < count; ++i) {
+ auto info = infos[i];
+ if (info.channel_condition & uint(available)) {
+ const QString name = pcanChannelNameForIndex(info.channel_handle);
+ const QString description = info.device_name;
+ const QString alias = QString::number(info.device_id);
+ const int channel = info.controller_number;
+ const bool isCanFd = (info.device_features & FEATURE_FD_CAPABLE);
+
+ result.append(createDeviceInfo(QStringLiteral("peakcan"), name, QString(),
+ description, alias,
+ channel, false, isCanFd));
+ }
+ }
+
+ return result;
+}
+
+QList<QCanBusDeviceInfo> PeakCanBackend::attachedInterfaces(Availability available)
+{
+#ifdef Q_OS_WIN
+ bool ok = false;
+ QList<QCanBusDeviceInfo> attachedChannelsResult = interfacesByAttachedChannels(available, &ok);
+ if (ok)
+ return attachedChannelsResult;
+#endif
+
+ QList<QCanBusDeviceInfo> result = interfacesByChannelCondition(available);
+ return result;
+}
+
+QList<QCanBusDeviceInfo> PeakCanBackend::interfaces()
+{
+ return attachedInterfaces(Availability::Available);
+}
+
+QCanBusDeviceInfo PeakCanBackend::deviceInfo() const
+{
+ const uint index = d_ptr->channelIndex;
+ const QString name = pcanChannelNameForIndex(index);
+ const QList<QCanBusDeviceInfo> availableDevices = attachedInterfaces(Availability::Occupied);
+
+ const auto deviceInfo = std::find_if(availableDevices.constBegin(),
+ availableDevices.constEnd(),
+ [name](const QCanBusDeviceInfo &info) {
+ return name == info.name();
+ });
+
+ if (Q_LIKELY(deviceInfo != availableDevices.constEnd()))
+ return *deviceInfo;
+
+ qWarning("%s: Cannot get device info for index %u.", Q_FUNC_INFO, index);
+ return QCanBusDevice::deviceInfo();
+}
+
#if defined(Q_OS_WIN32)
class PeakCanReadNotifier : public QWinEventNotifier
{
@@ -162,16 +240,10 @@ public:
, dptr(d)
{
setHandle(dptr->readHandle);
- }
-protected:
- bool event(QEvent *e) override
- {
- if (e->type() == QEvent::WinEventAct) {
+ connect(this, &QWinEventNotifier::activated, this, [this]() {
dptr->startRead();
- return true;
- }
- return QWinEventNotifier::event(e);
+ });
}
private:
@@ -344,7 +416,7 @@ bool PeakCanBackendPrivate::open()
if (readHandle == INVALID_HANDLE_VALUE) {
readHandle = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (Q_UNLIKELY(!readHandle)) {
- const QString errorString = qt_error_string(::GetLastError());
+ const QString errorString = qt_error_string(int(::GetLastError()));
qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot create receive event handler: %ls",
qUtf16Printable(errorString));
q->setError(errorString, QCanBusDevice::ConnectionError);
@@ -404,7 +476,7 @@ void PeakCanBackendPrivate::close()
#if defined(Q_OS_WIN32)
if (readHandle && (readHandle != INVALID_HANDLE_VALUE)) {
- const QString errorString = qt_error_string(::GetLastError());
+ const QString errorString = qt_error_string(int(::GetLastError()));
if (Q_UNLIKELY(!::CloseHandle(readHandle))) {
qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot close read handle: %ls",
qUtf16Printable(errorString));
@@ -419,7 +491,8 @@ void PeakCanBackendPrivate::close()
isOpen = false;
}
-bool PeakCanBackendPrivate::setConfigurationParameter(int key, const QVariant &value)
+bool PeakCanBackendPrivate::setConfigurationParameter(QCanBusDevice::ConfigurationKey key,
+ const QVariant &value)
{
Q_Q(PeakCanBackend);
@@ -557,14 +630,13 @@ void PeakCanBackendPrivate::startWrite()
const QCanBusFrame frame = q->dequeueOutgoingFrame();
const QByteArray payload = frame.payload();
+ const qsizetype payloadSize = payload.size();
TPCANStatus st = PCAN_ERROR_OK;
if (isFlexibleDatarateEnabled) {
- const int size = payload.size();
- TPCANMsgFD message;
- ::memset(&message, 0, sizeof(message));
+ TPCANMsgFD message = {};
message.ID = frame.frameId();
- message.DLC = sizeToDlc(size);
+ message.DLC = sizeToDlc(payloadSize);
message.MSGTYPE = frame.hasExtendedFrameFormat() ? PCAN_MESSAGE_EXTENDED
: PCAN_MESSAGE_STANDARD;
@@ -576,25 +648,23 @@ void PeakCanBackendPrivate::startWrite()
if (frame.frameType() == QCanBusFrame::RemoteRequestFrame)
message.MSGTYPE |= PCAN_MESSAGE_RTR; // we do not care about the payload
else
- ::memcpy(message.DATA, payload.constData(), sizeof(message.DATA));
+ ::memcpy(message.DATA, payload.constData(), payloadSize);
st = ::CAN_WriteFD(channelIndex, &message);
} else if (frame.hasFlexibleDataRateFormat()) {
const char errorString[] = "Cannot send CAN FD frame format as CAN FD is not enabled.";
qCWarning(QT_CANBUS_PLUGINS_PEAKCAN(), errorString);
q->setError(PeakCanBackend::tr(errorString), QCanBusDevice::WriteError);
} else {
- TPCANMsg message;
- ::memset(&message, 0, sizeof(message));
-
+ TPCANMsg message = {};
message.ID = frame.frameId();
- message.LEN = static_cast<quint8>(payload.size());
+ message.LEN = static_cast<quint8>(payloadSize);
message.MSGTYPE = frame.hasExtendedFrameFormat() ? PCAN_MESSAGE_EXTENDED
: PCAN_MESSAGE_STANDARD;
if (frame.frameType() == QCanBusFrame::RemoteRequestFrame)
message.MSGTYPE |= PCAN_MESSAGE_RTR; // we do not care about the payload
else
- ::memcpy(message.DATA, payload.constData(), sizeof(message.DATA));
+ ::memcpy(message.DATA, payload.constData(), payloadSize);
st = ::CAN_Write(channelIndex, &message);
}
@@ -615,14 +685,12 @@ void PeakCanBackendPrivate::startRead()
{
Q_Q(PeakCanBackend);
- QVector<QCanBusFrame> newFrames;
+ QList<QCanBusFrame> newFrames;
for (;;) {
if (isFlexibleDatarateEnabled) {
- TPCANMsgFD message;
- ::memset(&message, 0, sizeof(message));
- TPCANTimestampFD timestamp;
- ::memset(&timestamp, 0, sizeof(timestamp));
+ TPCANMsgFD message = {};
+ TPCANTimestampFD timestamp = {};
const TPCANStatus st = ::CAN_ReadFD(channelIndex, &message, &timestamp);
if (st != PCAN_ERROR_OK) {
@@ -637,8 +705,7 @@ void PeakCanBackendPrivate::startRead()
continue;
const int size = dlcToSize(static_cast<CanFrameDlc>(message.DLC));
- QCanBusFrame frame(TPCANLongToFrameID(message.ID),
- QByteArray(reinterpret_cast<const char *>(message.DATA), size));
+ QCanBusFrame frame(message.ID, QByteArray(reinterpret_cast<const char *>(message.DATA), size));
frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(static_cast<qint64>(timestamp)));
frame.setExtendedFrameFormat(message.MSGTYPE & PCAN_MESSAGE_EXTENDED);
frame.setFrameType((message.MSGTYPE & PCAN_MESSAGE_RTR)
@@ -649,10 +716,8 @@ void PeakCanBackendPrivate::startRead()
newFrames.append(std::move(frame));
} else {
- TPCANMsg message;
- ::memset(&message, 0, sizeof(message));
- TPCANTimestamp timestamp;
- ::memset(&timestamp, 0, sizeof(timestamp));
+ TPCANMsg message = {};
+ TPCANTimestamp timestamp = {};
const TPCANStatus st = ::CAN_Read(channelIndex, &message, &timestamp);
if (st != PCAN_ERROR_OK) {
@@ -667,9 +732,8 @@ void PeakCanBackendPrivate::startRead()
continue;
const int size = static_cast<int>(message.LEN);
- QCanBusFrame frame(TPCANLongToFrameID(message.ID),
- QByteArray(reinterpret_cast<const char *>(message.DATA), size));
- const quint64 millis = timestamp.millis + Q_UINT64_C(0xFFFFFFFF) * timestamp.millis_overflow;
+ QCanBusFrame frame(message.ID, QByteArray(reinterpret_cast<const char *>(message.DATA), size));
+ const quint64 millis = timestamp.millis + Q_UINT64_C(0x100000000) * timestamp.millis_overflow;
const quint64 micros = Q_UINT64_C(1000) * millis + timestamp.micros;
frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(static_cast<qint64>(micros)));
frame.setExtendedFrameFormat(message.MSGTYPE & PCAN_MESSAGE_EXTENDED);
@@ -717,12 +781,6 @@ PeakCanBackend::PeakCanBackend(const QString &name, QObject *parent)
d->setupChannel(name.toLatin1());
d->setupDefaultConfigurations();
-
- std::function<void()> f = std::bind(&PeakCanBackend::resetController, this);
- setResetControllerFunction(f);
-
- std::function<CanBusStatus()> g = std::bind(&PeakCanBackend::busStatus, this);
- setCanBusStatusGetter(g);
}
PeakCanBackend::~PeakCanBackend()
@@ -746,7 +804,7 @@ bool PeakCanBackend::open()
// Apply all stored configurations except bitrate, because
// the bitrate cannot be changed after opening the device
const auto keys = configurationKeys();
- for (int key : keys) {
+ for (ConfigurationKey key : keys) {
if (key == QCanBusDevice::BitRateKey || key == QCanBusDevice::DataBitRateKey)
continue;
const QVariant param = configurationParameter(key);
@@ -771,7 +829,7 @@ void PeakCanBackend::close()
setState(QCanBusDevice::UnconnectedState);
}
-void PeakCanBackend::setConfigurationParameter(int key, const QVariant &value)
+void PeakCanBackend::setConfigurationParameter(ConfigurationKey key, const QVariant &value)
{
Q_D(PeakCanBackend);
@@ -820,7 +878,12 @@ void PeakCanBackend::resetController()
open();
}
-QCanBusDevice::CanBusStatus PeakCanBackend::busStatus() const
+bool PeakCanBackend::hasBusStatus() const
+{
+ return true;
+}
+
+QCanBusDevice::CanBusStatus PeakCanBackend::busStatus()
{
const TPCANStatus status = ::CAN_GetStatus(d_ptr->channelIndex);
diff --git a/src/plugins/canbus/peakcan/peakcanbackend.h b/src/plugins/canbus/peakcan/peakcanbackend.h
index a9e108e..7e3acd4 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend.h
+++ b/src/plugins/canbus/peakcan/peakcanbackend.h
@@ -1,50 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef PEAKCANBACKEND_H
#define PEAKCANBACKEND_H
-#include <QtSerialBus/qcanbusframe.h>
#include <QtSerialBus/qcanbusdevice.h>
#include <QtSerialBus/qcanbusdeviceinfo.h>
+#include <QtSerialBus/qcanbusframe.h>
-#include <QtCore/qvariant.h>
-#include <QtCore/qvector.h>
#include <QtCore/qlist.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
@@ -62,7 +28,7 @@ public:
bool open() override;
void close() override;
- void setConfigurationParameter(int key, const QVariant &value) override;
+ void setConfigurationParameter(ConfigurationKey key, const QVariant &value) override;
bool writeFrame(const QCanBusFrame &newData) override;
@@ -71,9 +37,19 @@ public:
static bool canCreate(QString *errorReason);
static QList<QCanBusDeviceInfo> interfaces();
+ void resetController() override;
+ bool hasBusStatus() const override;
+ CanBusStatus busStatus() override;
+ QCanBusDeviceInfo deviceInfo() const override;
+
private:
- void resetController();
- CanBusStatus busStatus() const;
+ enum class Availability {
+ Available = 1U, // matches PCAN_CHANNEL_AVAILABLE
+ Occupied = 2U // matches PCAN_CHANNEL_OCCUPIED
+ };
+ static QList<QCanBusDeviceInfo> interfacesByChannelCondition(Availability available);
+ static QList<QCanBusDeviceInfo> interfacesByAttachedChannels(Availability available, bool *ok);
+ static QList<QCanBusDeviceInfo> attachedInterfaces(Availability available);
PeakCanBackendPrivate * const d_ptr;
};
diff --git a/src/plugins/canbus/peakcan/peakcanbackend_p.h b/src/plugins/canbus/peakcan/peakcanbackend_p.h
index 96d7ad3..866a39d 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend_p.h
+++ b/src/plugins/canbus/peakcan/peakcanbackend_p.h
@@ -1,39 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef PEAKCANBACKEND_P_H
#define PEAKCANBACKEND_P_H
@@ -72,7 +39,7 @@ public:
bool open();
void close();
- bool setConfigurationParameter(int key, const QVariant &value);
+ bool setConfigurationParameter(QCanBusDevice::ConfigurationKey key, const QVariant &value);
void setupChannel(const QByteArray &interfaceName);
void setupDefaultConfigurations();
QString systemErrorString(TPCANStatus errorCode);
diff --git a/src/plugins/canbus/socketcan/CMakeLists.txt b/src/plugins/canbus/socketcan/CMakeLists.txt
new file mode 100644
index 0000000..0ec3b64
--- /dev/null
+++ b/src/plugins/canbus/socketcan/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## SocketCanBusPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(SocketCanBusPlugin
+ OUTPUT_NAME qtsocketcanbus
+ PLUGIN_TYPE canbus
+ SOURCES
+ libsocketcan.cpp libsocketcan.h
+ main.cpp
+ socketcanbackend.cpp socketcanbackend.h
+ LIBRARIES
+ Qt::Core
+ Qt::Network
+ Qt::SerialBus
+)
diff --git a/src/plugins/canbus/socketcan/libsocketcan.cpp b/src/plugins/canbus/socketcan/libsocketcan.cpp
index c6144db..c469604 100644
--- a/src/plugins/canbus/socketcan/libsocketcan.cpp
+++ b/src/plugins/canbus/socketcan/libsocketcan.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "libsocketcan.h"
@@ -87,10 +54,14 @@ LibSocketCan::LibSocketCan(QString *errorString)
{
#if QT_CONFIG(library)
auto resolveSymbols = [](QLibrary *library) {
+ const QString libName = QStringLiteral("socketcan");
if (!library->isLoaded()) {
- library->setFileName(QStringLiteral("socketcan"));
- if (!library->load())
- return false;
+ library->setFileName(libName);
+ if (!library->load()) {
+ library->setFileNameAndVersion(libName, 2);
+ if (!library->load())
+ return false;
+ }
}
RESOLVE_SYMBOL(can_do_start);
diff --git a/src/plugins/canbus/socketcan/libsocketcan.h b/src/plugins/canbus/socketcan/libsocketcan.h
index b77afa1..1fa4175 100644
--- a/src/plugins/canbus/socketcan/libsocketcan.h
+++ b/src/plugins/canbus/socketcan/libsocketcan.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef LIBSOCKETCAN_H
#define LIBSOCKETCAN_H
diff --git a/src/plugins/canbus/socketcan/main.cpp b/src/plugins/canbus/socketcan/main.cpp
index 328db97..e833f6d 100644
--- a/src/plugins/canbus/socketcan/main.cpp
+++ b/src/plugins/canbus/socketcan/main.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "socketcanbackend.h"
@@ -47,11 +14,11 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_SOCKETCAN, "qt.canbus.plugins.socketcan")
//! [SocketCanFactory]
-class SocketCanBusPlugin : public QObject, public QCanBusFactoryV2
+class SocketCanBusPlugin : public QObject, public QCanBusFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QCanBusFactory" FILE "plugin.json")
- Q_INTERFACES(QCanBusFactoryV2)
+ Q_INTERFACES(QCanBusFactory)
public:
QList<QCanBusDeviceInfo> availableDevices(QString *errorMessage) const override
diff --git a/src/plugins/canbus/socketcan/socketcan.pro b/src/plugins/canbus/socketcan/socketcan.pro
deleted file mode 100644
index cd731fd..0000000
--- a/src/plugins/canbus/socketcan/socketcan.pro
+++ /dev/null
@@ -1,18 +0,0 @@
-TARGET = qtsocketcanbus
-
-QT = core serialbus
-
-HEADERS += \
- libsocketcan.h \
- socketcanbackend.h
-
-SOURCES += \
- libsocketcan.cpp \
- main.cpp \
- socketcanbackend.cpp
-
-DISTFILES = plugin.json
-
-PLUGIN_TYPE = canbus
-PLUGIN_CLASS_NAME = SocketCanBusPlugin
-load(qt_plugin)
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index 2ed1310..c89b9a4 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.cpp
+++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "socketcanbackend.h"
@@ -56,30 +23,6 @@
#include <sys/ioctl.h>
#include <sys/time.h>
-#ifndef CANFD_MTU
-// CAN FD support was added by Linux kernel 3.6
-// For prior kernels we redefine the missing defines here
-// they are taken from linux/can/raw.h & linux/can.h
-
-enum {
- CAN_RAW_FD_FRAMES = 5
-};
-
-#define CAN_MAX_DLEN 8
-#define CANFD_MAX_DLEN 64
-struct canfd_frame {
- canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
- __u8 len; /* frame payload length in byte */
- __u8 flags; /* additional flags for CAN FD */
- __u8 __res0; /* reserved / padding */
- __u8 __res1; /* reserved / padding */
- __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
-};
-#define CAN_MTU (sizeof(struct can_frame))
-#define CANFD_MTU (sizeof(struct canfd_frame))
-
-#endif
-
#ifndef CANFD_BRS
# define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
#endif
@@ -151,6 +94,18 @@ static int deviceChannel(const QString &canDevice)
return content.toInt(nullptr, 0);
}
+QCanBusDeviceInfo SocketCanBackend::socketCanDeviceInfo(const QString &deviceName)
+{
+ const QString serial; // exists for code readability purposes only
+ const QString alias; // exists for code readability purposes only
+ const QString description = deviceDescription(deviceName);
+ const int channel = deviceChannel(deviceName);
+ return createDeviceInfo(QStringLiteral("socketcan"), deviceName,
+ serial, description,
+ alias, channel, isVirtual(deviceName),
+ isFlexibleDataRateCapable(deviceName));
+}
+
QList<QCanBusDeviceInfo> SocketCanBackend::interfaces()
{
QList<QCanBusDeviceInfo> result;
@@ -167,12 +122,7 @@ QList<QCanBusDeviceInfo> SocketCanBackend::interfaces()
if (!(flags(deviceName) & DeviceIsActive))
continue;
- const QString serial;
- const QString description = deviceDescription(deviceName);
- const int channel = deviceChannel(deviceName);
- result.append(std::move(createDeviceInfo(deviceName, serial, description,
- channel, isVirtual(deviceName),
- isFlexibleDataRateCapable(deviceName))));
+ result.append(socketCanDeviceInfo(deviceName));
}
std::sort(result.begin(), result.end(),
@@ -183,6 +133,11 @@ QList<QCanBusDeviceInfo> SocketCanBackend::interfaces()
return result;
}
+QCanBusDeviceInfo SocketCanBackend::deviceInfo() const
+{
+ return socketCanDeviceInfo(canSocketName);
+}
+
SocketCanBackend::SocketCanBackend(const QString &name) :
canSocketName(name)
{
@@ -195,16 +150,6 @@ SocketCanBackend::SocketCanBackend(const QString &name) :
}
resetConfigurations();
-
- std::function<void()> f = std::bind(&SocketCanBackend::resetController, this);
- setResetControllerFunction(f);
-
- if (hasBusStatus()) {
- // Only register busStatus when libsocketcan is available
- // QCanBusDevice::hasBusStatus() will return false otherwise
- std::function<CanBusStatus()> g = std::bind(&SocketCanBackend::busStatus, this);
- setCanBusStatusGetter(g);
- }
}
SocketCanBackend::~SocketCanBackend()
@@ -248,7 +193,7 @@ void SocketCanBackend::close()
setState(QCanBusDevice::UnconnectedState);
}
-bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &value)
+bool SocketCanBackend::applyConfigurationParameter(ConfigurationKey key, const QVariant &value)
{
bool success = false;
@@ -308,7 +253,7 @@ bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &valu
break;
}
- QVector<can_filter> filters;
+ QList<can_filter> filters;
filters.resize(filterList.size());
for (int i = 0; i < filterList.size(); i++) {
const QCanBusDevice::Filter f = filterList.at(i);
@@ -373,11 +318,11 @@ bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &valu
case QCanBusDevice::BitRateKey:
{
const quint32 bitRate = value.toUInt();
- libSocketCan->setBitrate(canSocketName, bitRate);
+ success = libSocketCan->setBitrate(canSocketName, bitRate);
break;
}
default:
- setError(tr("SocketCanBackend: No such configuration as %1 in SocketCanBackend").arg(key),
+ setError(tr("Unsupported configuration key: %1").arg(key),
QCanBusDevice::CanBusError::ConfigurationError);
break;
}
@@ -425,7 +370,7 @@ bool SocketCanBackend::connectSocket()
//apply all stored configurations
const auto keys = configurationKeys();
- for (int key : keys) {
+ for (ConfigurationKey key : keys) {
const QVariant param = configurationParameter(key);
bool success = applyConfigurationParameter(key, param);
if (Q_UNLIKELY(!success)) {
@@ -437,7 +382,7 @@ bool SocketCanBackend::connectSocket()
return true;
}
-void SocketCanBackend::setConfigurationParameter(int key, const QVariant &value)
+void SocketCanBackend::setConfigurationParameter(ConfigurationKey key, const QVariant &value)
{
if (key == QCanBusDevice::RawFilterKey) {
//verify valid/supported filters
@@ -481,7 +426,7 @@ void SocketCanBackend::setConfigurationParameter(int key, const QVariant &value)
QCanBusDevice::setConfigurationParameter(key, value);
- // we need to check CAN FD option a lot -> cache it and avoid QVector lookup
+ // we need to check CAN FD option a lot -> cache it and avoid QList lookup
if (key == QCanBusDevice::CanFdKey)
canFdOptionEnabled = value.toBool();
}
@@ -516,8 +461,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
qint64 bytesWritten = 0;
if (newData.hasFlexibleDataRateFormat()) {
- canfd_frame frame;
- ::memset(&frame, 0, sizeof(frame));
+ canfd_frame frame = {};
frame.len = newData.payload().size();
frame.can_id = canId;
frame.flags = newData.hasBitrateSwitch() ? CANFD_BRS : 0;
@@ -526,8 +470,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
bytesWritten = ::write(canSocket, &frame, sizeof(frame));
} else {
- can_frame frame;
- ::memset(&frame, 0, sizeof(frame));
+ can_frame frame = {};
frame.can_dlc = newData.payload().size();
frame.can_id = canId;
::memcpy(frame.data, newData.payload().constData(), frame.can_dlc);
@@ -556,7 +499,7 @@ QString SocketCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
QString errorMsg;
if (errorFrame.error() & QCanBusFrame::TransmissionTimeoutError)
- errorMsg += QStringLiteral("TX timout\n");
+ errorMsg += QStringLiteral("TX timeout\n");
if (errorFrame.error() & QCanBusFrame::MissingAcknowledgmentError)
errorMsg += QStringLiteral("Received no ACK on transmission\n");
@@ -711,10 +654,10 @@ QString SocketCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
void SocketCanBackend::readSocket()
{
- QVector<QCanBusFrame> newFrames;
+ QList<QCanBusFrame> newFrames;
for (;;) {
- ::memset(&m_frame, 0, sizeof(m_frame));
+ m_frame = {};
m_iov.iov_len = sizeof(m_frame);
m_msg.msg_namelen = sizeof(m_addr);
m_msg.msg_controllen = sizeof(m_ctrlmsg);
@@ -734,11 +677,11 @@ void SocketCanBackend::readSocket()
continue;
}
- struct timeval timeStamp;
+ struct timeval timeStamp = {};
if (Q_UNLIKELY(ioctl(canSocket, SIOCGSTAMP, &timeStamp) < 0)) {
setError(qt_error_string(errno),
QCanBusDevice::CanBusError::ReadError);
- ::memset(&timeStamp, 0, sizeof(timeStamp));
+ timeStamp = {};
}
const QCanBusFrame::TimeStamp stamp(timeStamp.tv_sec, timeStamp.tv_usec);
@@ -778,10 +721,13 @@ void SocketCanBackend::resetController()
bool SocketCanBackend::hasBusStatus() const
{
+ if (isVirtual(canSocketName.toLatin1()))
+ return false;
+
return libSocketCan->hasBusStatus();
}
-QCanBusDevice::CanBusStatus SocketCanBackend::busStatus() const
+QCanBusDevice::CanBusStatus SocketCanBackend::busStatus()
{
return libSocketCan->busStatus(canSocketName);
}
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.h b/src/plugins/canbus/socketcan/socketcanbackend.h
index 0497244..89aa281 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.h
+++ b/src/plugins/canbus/socketcan/socketcanbackend.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef SOCKETCANBACKEND_H
#define SOCKETCANBACKEND_H
@@ -54,6 +21,30 @@
#include <memory>
+#ifndef CANFD_MTU
+// CAN FD support was added by Linux kernel 3.6
+// For prior kernels we redefine the missing defines here
+// they are taken from linux/can/raw.h & linux/can.h
+
+enum {
+ CAN_RAW_FD_FRAMES = 5
+};
+
+#define CAN_MAX_DLEN 8
+#define CANFD_MAX_DLEN 64
+struct canfd_frame {
+ canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
+ __u8 len; /* frame payload length in byte */
+ __u8 flags; /* additional flags for CAN FD */
+ __u8 __res0; /* reserved / padding */
+ __u8 __res1; /* reserved / padding */
+ __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
+};
+#define CAN_MTU (sizeof(struct can_frame))
+#define CANFD_MTU (sizeof(struct canfd_frame))
+
+#endif
+
QT_BEGIN_NAMESPACE
class LibSocketCan;
@@ -68,24 +59,27 @@ public:
bool open() override;
void close() override;
- void setConfigurationParameter(int key, const QVariant &value) override;
+ void setConfigurationParameter(ConfigurationKey key, const QVariant &value) override;
bool writeFrame(const QCanBusFrame &newData) override;
QString interpretErrorFrame(const QCanBusFrame &errorFrame) override;
+ static QCanBusDeviceInfo socketCanDeviceInfo(const QString &deviceName);
static QList<QCanBusDeviceInfo> interfaces();
+ void resetController() override;
+ bool hasBusStatus() const override;
+ CanBusStatus busStatus() override;
+ QCanBusDeviceInfo deviceInfo() const override;
+
private Q_SLOTS:
void readSocket();
private:
void resetConfigurations();
bool connectSocket();
- bool applyConfigurationParameter(int key, const QVariant &value);
- void resetController();
- bool hasBusStatus() const;
- QCanBusDevice::CanBusStatus busStatus() const;
+ bool applyConfigurationParameter(ConfigurationKey key, const QVariant &value);
int protocol = CAN_RAW;
canfd_frame m_frame;
diff --git a/src/plugins/canbus/systeccan/CMakeLists.txt b/src/plugins/canbus/systeccan/CMakeLists.txt
new file mode 100644
index 0000000..a36ee1c
--- /dev/null
+++ b/src/plugins/canbus/systeccan/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## SystecCanBusPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(SystecCanBusPlugin
+ OUTPUT_NAME qtsysteccanbus
+ PLUGIN_TYPE canbus
+ SOURCES
+ main.cpp
+ systeccan_symbols_p.h
+ systeccanbackend.cpp systeccanbackend.h systeccanbackend_p.h
+ LIBRARIES
+ Qt::Core
+ Qt::Network
+ Qt::SerialBus
+)
diff --git a/src/plugins/canbus/systeccan/main.cpp b/src/plugins/canbus/systeccan/main.cpp
index 89377a0..96ce57c 100644
--- a/src/plugins/canbus/systeccan/main.cpp
+++ b/src/plugins/canbus/systeccan/main.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "systeccanbackend.h"
@@ -46,11 +13,11 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_SYSTECCAN, "qt.canbus.plugins.systeccan")
-class SystecCanBusPlugin : public QObject, public QCanBusFactoryV2
+class SystecCanBusPlugin : public QObject, public QCanBusFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QCanBusFactory" FILE "plugin.json")
- Q_INTERFACES(QCanBusFactoryV2)
+ Q_INTERFACES(QCanBusFactory)
public:
QList<QCanBusDeviceInfo> availableDevices(QString *errorMessage) const override
diff --git a/src/plugins/canbus/systeccan/systeccan.pro b/src/plugins/canbus/systeccan/systeccan.pro
deleted file mode 100644
index 3520325..0000000
--- a/src/plugins/canbus/systeccan/systeccan.pro
+++ /dev/null
@@ -1,18 +0,0 @@
-TARGET = qtsysteccanbus
-
-QT = core serialbus
-
-HEADERS += \
- systeccanbackend.h \
- systeccanbackend_p.h \
- systeccan_symbols_p.h
-
-SOURCES += \
- main.cpp \
- systeccanbackend.cpp
-
-DISTFILES = plugin.json
-
-PLUGIN_TYPE = canbus
-PLUGIN_CLASS_NAME = SystecCanBusPlugin
-load(qt_plugin)
diff --git a/src/plugins/canbus/systeccan/systeccan_symbols_p.h b/src/plugins/canbus/systeccan/systeccan_symbols_p.h
index 037f994..4fa1a93 100644
--- a/src/plugins/canbus/systeccan/systeccan_symbols_p.h
+++ b/src/plugins/canbus/systeccan/systeccan_symbols_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef SYSTECCAN_SYMBOLS_P_H
#define SYSTECCAN_SYMBOLS_P_H
@@ -302,6 +269,8 @@ GENERATE_SYMBOL_VARIABLE(UCANRET, UcanReadCanMsgEx, tUcanHandle, quint8 *, tCanM
GENERATE_SYMBOL_VARIABLE(UCANRET, UcanResetCan, tUcanHandle)
GENERATE_SYMBOL_VARIABLE(UCANRET, UcanWriteCanMsgEx, tUcanHandle, quint8, tCanMsgStruct *, quint32 *)
GENERATE_SYMBOL_VARIABLE(UCANRET, UcanGetStatus, tUcanHandle, tStatusStruct *)
+GENERATE_SYMBOL_VARIABLE(UCANRET, UcanGetHardwareInfoEx2, tUcanHandle, tUcanHardwareInfoEx *,
+ void * /* channelInfo0 */, void * /* channelInfo1 */);
inline bool resolveSystecCanSymbols(QLibrary *systecLibrary)
{
@@ -324,6 +293,7 @@ inline bool resolveSystecCanSymbols(QLibrary *systecLibrary)
RESOLVE_SYMBOL(UcanResetCan);
RESOLVE_SYMBOL(UcanWriteCanMsgEx);
RESOLVE_SYMBOL(UcanGetStatus);
+ RESOLVE_SYMBOL(UcanGetHardwareInfoEx2);
return true;
}
diff --git a/src/plugins/canbus/systeccan/systeccanbackend.cpp b/src/plugins/canbus/systeccan/systeccanbackend.cpp
index a7de557..f14c27b 100644
--- a/src/plugins/canbus/systeccan/systeccanbackend.cpp
+++ b/src/plugins/canbus/systeccan/systeccanbackend.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "systeccanbackend.h"
#include "systeccanbackend_p.h"
@@ -69,7 +36,9 @@ QCanBusDeviceInfo SystecCanBackend::createDeviceInfo(const QString &serialNumber
int channelNumber)
{
const QString name = QString::fromLatin1("can%1.%2").arg(deviceNumber).arg(channelNumber);
- return QCanBusDevice::createDeviceInfo(name, serialNumber, description, channelNumber, false, false);
+ return QCanBusDevice::createDeviceInfo(QStringLiteral("systeccan"), name,
+ serialNumber, description,
+ QString(), channelNumber, false, false);
}
static QString descriptionString(uint productCode)
@@ -100,11 +69,11 @@ static void DRV_CALLBACK_TYPE ucanEnumCallback(DWORD index, BOOL isUsed,
const QString serialNumber = QString::number(hardwareInfo->m_dwSerialNr);
const QString description = descriptionString(hardwareInfo->m_dwProductCode);
- result->append(std::move(SystecCanBackend::createDeviceInfo(serialNumber, description,
- hardwareInfo->m_bDeviceNr, 0)));
+ result->append(SystecCanBackend::createDeviceInfo(serialNumber, description,
+ hardwareInfo->m_bDeviceNr, 0));
if (USBCAN_CHECK_SUPPORT_TWO_CHANNEL(hardwareInfo)) {
- result->append(std::move(SystecCanBackend::createDeviceInfo(serialNumber, description,
- hardwareInfo->m_bDeviceNr, 1)));
+ result->append(SystecCanBackend::createDeviceInfo(serialNumber, description,
+ hardwareInfo->m_bDeviceNr, 1));
}
initInfo->m_fTryNext = true; // continue enumerating with next device
@@ -202,8 +171,7 @@ bool SystecCanBackendPrivate::open()
const int bitrate = q->configurationParameter(QCanBusDevice::BitRateKey).toInt();
const bool receiveOwn = q->configurationParameter(QCanBusDevice::ReceiveOwnKey).toBool();
- tUcanInitCanParam param;
- ::memset(&param, 0, sizeof(param));
+ tUcanInitCanParam param = {};
param.m_dwSize = sizeof(param);
param.m_bMode = receiveOwn ? kUcanModeTxEcho : kUcanModeNormal;
param.m_bOCR = USBCAN_OCR_DEFAULT;
@@ -252,7 +220,8 @@ void SystecCanBackendPrivate::eventHandler(QEvent *event)
readAllReceivedMessages();
}
-bool SystecCanBackendPrivate::setConfigurationParameter(int key, const QVariant &value)
+bool SystecCanBackendPrivate::setConfigurationParameter(QCanBusDevice::ConfigurationKey key,
+ const QVariant &value)
{
Q_Q(SystecCanBackend);
@@ -372,19 +341,19 @@ void SystecCanBackendPrivate::startWrite()
const QCanBusFrame frame = q->dequeueOutgoingFrame();
const QByteArray payload = frame.payload();
+ const qsizetype payloadSize = payload.size();
- tCanMsgStruct message;
- ::memset(&message, 0, sizeof(message));
+ tCanMsgStruct message = {};
message.m_dwID = frame.frameId();
- message.m_bDLC = quint8(payload.size());
+ message.m_bDLC = quint8(payloadSize);
message.m_bFF = frame.hasExtendedFrameFormat() ? USBCAN_MSG_FF_EXT : USBCAN_MSG_FF_STD;
if (frame.frameType() == QCanBusFrame::RemoteRequestFrame)
message.m_bFF |= USBCAN_MSG_FF_RTR; // remote request frame without payload
else
- ::memcpy(message.m_bData, payload.constData(), sizeof(message.m_bData));
+ ::memcpy(message.m_bData, payload.constData(), payloadSize);
const UCANRET result = ::UcanWriteCanMsgEx(handle, channel, &message, nullptr);
if (Q_UNLIKELY(result != USBCAN_SUCCESSFUL))
@@ -400,11 +369,10 @@ void SystecCanBackendPrivate::readAllReceivedMessages()
{
Q_Q(SystecCanBackend);
- QVector<QCanBusFrame> newFrames;
+ QList<QCanBusFrame> newFrames;
for (;;) {
- tCanMsgStruct message;
- ::memset(&message, 0, sizeof(message));
+ tCanMsgStruct message = {};
const UCANRET result = ::UcanReadCanMsgEx(handle, &channel, &message, nullptr);
if (result == USBCAN_WARN_NODATA)
@@ -463,8 +431,7 @@ QCanBusDevice::CanBusStatus SystecCanBackendPrivate::busStatus()
{
Q_Q(SystecCanBackend);
- tStatusStruct status;
- ::memset(&status, 0, sizeof(status));
+ tStatusStruct status = {};
const UCANRET result = ::UcanGetStatus(handle, &status);
if (Q_UNLIKELY(result != USBCAN_SUCCESSFUL)) {
@@ -496,12 +463,6 @@ SystecCanBackend::SystecCanBackend(const QString &name, QObject *parent) :
d->setupChannel(name);
d->setupDefaultConfigurations();
-
- std::function<void()> f = std::bind(&SystecCanBackend::resetController, this);
- setResetControllerFunction(f);
-
- std::function<CanBusStatus()> g = std::bind(&SystecCanBackend::busStatus, this);
- setCanBusStatusGetter(g);
}
SystecCanBackend::~SystecCanBackend()
@@ -521,8 +482,8 @@ bool SystecCanBackend::open()
// Apply all stored configurations except bitrate and receive own,
// because these cannot be applied after opening the device
- const QVector<int> keys = configurationKeys();
- for (int key : keys) {
+ const auto keys = configurationKeys();
+ for (ConfigurationKey key : keys) {
if (key == BitRateKey || key == ReceiveOwnKey)
continue;
const QVariant param = configurationParameter(key);
@@ -546,7 +507,7 @@ void SystecCanBackend::close()
setState(QCanBusDevice::UnconnectedState);
}
-void SystecCanBackend::setConfigurationParameter(int key, const QVariant &value)
+void SystecCanBackend::setConfigurationParameter(ConfigurationKey key, const QVariant &value)
{
Q_D(SystecCanBackend);
@@ -599,6 +560,11 @@ void SystecCanBackend::resetController()
d->resetController();
}
+bool SystecCanBackend::hasBusStatus() const
+{
+ return true;
+}
+
QCanBusDevice::CanBusStatus SystecCanBackend::busStatus()
{
Q_D(SystecCanBackend);
@@ -606,4 +572,14 @@ QCanBusDevice::CanBusStatus SystecCanBackend::busStatus()
return d->busStatus();
}
+QCanBusDeviceInfo SystecCanBackend::deviceInfo() const
+{
+ tUcanHardwareInfoEx hardwareInfo = {};
+ UcanGetHardwareInfoEx2(d_ptr->handle, &hardwareInfo, nullptr, nullptr);
+
+ const QString serialNumber = QString::number(hardwareInfo.m_dwSerialNr);
+ const QString description = descriptionString(hardwareInfo.m_dwProductCode);
+ return createDeviceInfo(serialNumber, description, hardwareInfo.m_bDeviceNr, d_ptr->channel);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/canbus/systeccan/systeccanbackend.h b/src/plugins/canbus/systeccan/systeccanbackend.h
index 22c1193..d222592 100644
--- a/src/plugins/canbus/systeccan/systeccanbackend.h
+++ b/src/plugins/canbus/systeccan/systeccanbackend.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef SYSTECCANBACKEND_H
#define SYSTECCANBACKEND_H
@@ -60,7 +27,7 @@ public:
bool open() override;
void close() override;
- void setConfigurationParameter(int key, const QVariant &value) override;
+ void setConfigurationParameter(ConfigurationKey key, const QVariant &value) override;
bool writeFrame(const QCanBusFrame &newData) override;
@@ -75,10 +42,12 @@ public:
uint deviceNumber,
int channelNumber);
-private:
- void resetController();
- QCanBusDevice::CanBusStatus busStatus();
+ void resetController() override;
+ bool hasBusStatus() const override;
+ CanBusStatus busStatus() override;
+ QCanBusDeviceInfo deviceInfo() const override;
+private:
SystecCanBackendPrivate * const d_ptr;
};
diff --git a/src/plugins/canbus/systeccan/systeccanbackend_p.h b/src/plugins/canbus/systeccan/systeccanbackend_p.h
index b2da322..b8acfcb 100644
--- a/src/plugins/canbus/systeccan/systeccanbackend_p.h
+++ b/src/plugins/canbus/systeccan/systeccanbackend_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef SYSTECCANBACKEND_P_H
#define SYSTECCANBACKEND_P_H
@@ -58,8 +25,6 @@
QT_BEGIN_NAMESPACE
class QEvent;
-class QSocketNotifier;
-class QWinEventNotifier;
class QTimer;
class IncomingEventHandler : public QObject
@@ -70,7 +35,7 @@ public:
QObject(parent),
dptr(systecPrivate) { }
- void customEvent(QEvent *event);
+ void customEvent(QEvent *event) override;
private:
SystecCanBackendPrivate * const dptr;
@@ -86,7 +51,7 @@ public:
bool open();
void close();
void eventHandler(QEvent *event);
- bool setConfigurationParameter(int key, const QVariant &value);
+ bool setConfigurationParameter(QCanBusDevice::ConfigurationKey key, const QVariant &value);
bool setupChannel(const QString &interfaceName);
void setupDefaultConfigurations();
QString systemErrorString(int errorCode);
diff --git a/src/plugins/canbus/tinycan/CMakeLists.txt b/src/plugins/canbus/tinycan/CMakeLists.txt
new file mode 100644
index 0000000..b9eb5ee
--- /dev/null
+++ b/src/plugins/canbus/tinycan/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## TinyCanBusPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(TinyCanBusPlugin
+ OUTPUT_NAME qttinycanbus
+ PLUGIN_TYPE canbus
+ SOURCES
+ main.cpp
+ tinycan_symbols_p.h
+ tinycanbackend.cpp tinycanbackend.h tinycanbackend_p.h
+ LIBRARIES
+ Qt::Core
+ Qt::Network
+ Qt::SerialBus
+)
diff --git a/src/plugins/canbus/tinycan/main.cpp b/src/plugins/canbus/tinycan/main.cpp
index 36fb05d..38f8140 100644
--- a/src/plugins/canbus/tinycan/main.cpp
+++ b/src/plugins/canbus/tinycan/main.cpp
@@ -1,39 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "tinycanbackend.h"
@@ -47,11 +14,11 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_TINYCAN, "qt.canbus.plugins.tinycan")
-class TinyCanBusPlugin : public QObject, public QCanBusFactoryV2
+class TinyCanBusPlugin : public QObject, public QCanBusFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QCanBusFactory" FILE "plugin.json")
- Q_INTERFACES(QCanBusFactoryV2)
+ Q_INTERFACES(QCanBusFactory)
public:
QList<QCanBusDeviceInfo> availableDevices(QString *errorMessage) const override
diff --git a/src/plugins/canbus/tinycan/tinycan.pro b/src/plugins/canbus/tinycan/tinycan.pro
deleted file mode 100644
index c450bb9..0000000
--- a/src/plugins/canbus/tinycan/tinycan.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-TARGET = qttinycanbus
-
-QT = core serialbus
-
-HEADERS += \
- tinycanbackend.h \
- tinycanbackend_p.h \
- tinycan_symbols_p.h
-
-SOURCES += main.cpp \
- tinycanbackend.cpp
-
-DISTFILES = plugin.json
-
-PLUGIN_TYPE = canbus
-PLUGIN_CLASS_NAME = TinyCanBusPlugin
-load(qt_plugin)
diff --git a/src/plugins/canbus/tinycan/tinycan_symbols_p.h b/src/plugins/canbus/tinycan/tinycan_symbols_p.h
index 625edd3..18b14a9 100644
--- a/src/plugins/canbus/tinycan/tinycan_symbols_p.h
+++ b/src/plugins/canbus/tinycan/tinycan_symbols_p.h
@@ -1,39 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef TINYCAN_SYMBOLS_P_H
#define TINYCAN_SYMBOLS_P_H
diff --git a/src/plugins/canbus/tinycan/tinycanbackend.cpp b/src/plugins/canbus/tinycan/tinycanbackend.cpp
index fdd5aaa..9feb4b7 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend.cpp
+++ b/src/plugins/canbus/tinycan/tinycanbackend.cpp
@@ -1,39 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "tinycanbackend.h"
#include "tinycanbackend_p.h"
@@ -74,7 +41,8 @@ bool TinyCanBackend::canCreate(QString *errorReason)
QList<QCanBusDeviceInfo> TinyCanBackend::interfaces()
{
QList<QCanBusDeviceInfo> result;
- result.append(createDeviceInfo(QStringLiteral("can0.0")));
+ result.append(createDeviceInfo(QStringLiteral("tinycan"), QStringLiteral("can0.0"),
+ false, false));
return result;
}
@@ -121,7 +89,7 @@ static void DRV_CALLBACK_TYPE canRxEventCallback(quint32 index, TCanMsg *frame,
Q_UNUSED(count);
QMutexLocker lock(&gTinyCan->mutex);
- for (TinyCanBackendPrivate *p : qAsConst(gTinyCan->channels)) {
+ for (TinyCanBackendPrivate *p : std::as_const(gTinyCan->channels)) {
if (p->channelIndex == int(index)) {
p->startRead();
return;
@@ -232,7 +200,8 @@ void TinyCanBackendPrivate::close()
isOpen = false;
}
-bool TinyCanBackendPrivate::setConfigurationParameter(int key, const QVariant &value)
+bool TinyCanBackendPrivate::setConfigurationParameter(QCanBusDevice::ConfigurationKey key,
+ const QVariant &value)
{
Q_Q(TinyCanBackend);
@@ -351,28 +320,23 @@ void TinyCanBackendPrivate::startWrite()
const QCanBusFrame frame = q->dequeueOutgoingFrame();
const QByteArray payload = frame.payload();
-
- TCanMsg message;
- ::memset(&message, 0, sizeof(message));
-
- if (Q_UNLIKELY(payload.size() > int(sizeof(message.Data.Bytes)))) {
- qCWarning(QT_CANBUS_PLUGINS_TINYCAN, "Cannot write frame with payload size %d.", payload.size());
- } else {
- message.Id = frame.frameId();
- message.Flags.Flag.Len = payload.size();
- message.Flags.Flag.Error = (frame.frameType() == QCanBusFrame::ErrorFrame);
- message.Flags.Flag.RTR = (frame.frameType() == QCanBusFrame::RemoteRequestFrame);
- message.Flags.Flag.TxD = 1;
- message.Flags.Flag.EFF = frame.hasExtendedFrameFormat();
-
- const qint32 messagesToWrite = 1;
- ::memcpy(message.Data.Bytes, payload.constData(), sizeof(message.Data.Bytes));
- const int ret = ::CanTransmit(channelIndex, &message, messagesToWrite);
- if (Q_UNLIKELY(ret < 0))
- q->setError(systemErrorString(ret), QCanBusDevice::CanBusError::WriteError);
- else
- emit q->framesWritten(messagesToWrite);
- }
+ const qsizetype payloadSize = payload.size();
+
+ TCanMsg message = {};
+ message.Id = frame.frameId();
+ message.Flags.Flag.Len = payloadSize;
+ message.Flags.Flag.Error = (frame.frameType() == QCanBusFrame::ErrorFrame);
+ message.Flags.Flag.RTR = (frame.frameType() == QCanBusFrame::RemoteRequestFrame);
+ message.Flags.Flag.TxD = 1;
+ message.Flags.Flag.EFF = frame.hasExtendedFrameFormat();
+
+ const qint32 messagesToWrite = 1;
+ ::memcpy(message.Data.Bytes, payload.constData(), payloadSize);
+ const int ret = ::CanTransmit(channelIndex, &message, messagesToWrite);
+ if (Q_UNLIKELY(ret < 0))
+ q->setError(systemErrorString(ret), QCanBusDevice::CanBusError::WriteError);
+ else
+ emit q->framesWritten(messagesToWrite);
if (q->hasOutgoingFrames() && !writeNotifier->isActive())
writeNotifier->start();
@@ -383,22 +347,20 @@ void TinyCanBackendPrivate::startRead()
{
Q_Q(TinyCanBackend);
- QVector<QCanBusFrame> newFrames;
+ QList<QCanBusFrame> newFrames;
for (;;) {
if (!::CanReceiveGetCount(channelIndex))
break;
- TCanMsg message;
- ::memset(&message, 0, sizeof(message));
+ TCanMsg message = {};
const int messagesToRead = 1;
const int ret = ::CanReceive(channelIndex, &message, messagesToRead);
if (Q_UNLIKELY(ret < 0)) {
q->setError(systemErrorString(ret), QCanBusDevice::CanBusError::ReadError);
- TDeviceStatus status;
- ::memset(&status, 0, sizeof(status));
+ TDeviceStatus status = {};
if (::CanGetDeviceStatus(channelIndex, &status) < 0) {
q->setError(systemErrorString(ret), QCanBusDevice::CanBusError::ReadError);
@@ -509,9 +471,6 @@ TinyCanBackend::TinyCanBackend(const QString &name, QObject *parent)
d->setupChannel(name);
d->setupDefaultConfigurations();
-
- std::function<void()> f = std::bind(&TinyCanBackend::resetController, this);
- setResetControllerFunction(f);
}
TinyCanBackend::~TinyCanBackend()
@@ -532,7 +491,7 @@ bool TinyCanBackend::open()
// apply all stored configurations
const auto keys = configurationKeys();
- for (int key : keys) {
+ for (ConfigurationKey key : keys) {
const QVariant param = configurationParameter(key);
const bool success = d->setConfigurationParameter(key, param);
if (Q_UNLIKELY(!success)) {
@@ -555,7 +514,7 @@ void TinyCanBackend::close()
setState(QCanBusDevice::UnconnectedState);
}
-void TinyCanBackend::setConfigurationParameter(int key, const QVariant &value)
+void TinyCanBackend::setConfigurationParameter(ConfigurationKey key, const QVariant &value)
{
Q_D(TinyCanBackend);
@@ -611,4 +570,9 @@ void TinyCanBackend::resetController()
d->resetController();
}
+QCanBusDeviceInfo TinyCanBackend::deviceInfo() const
+{
+ return createDeviceInfo(QStringLiteral("tinycan"), QStringLiteral("can0.0"), false, false);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/canbus/tinycan/tinycanbackend.h b/src/plugins/canbus/tinycan/tinycanbackend.h
index 428e9bc..7d5b541 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend.h
+++ b/src/plugins/canbus/tinycan/tinycanbackend.h
@@ -1,50 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef TINYCANBACKEND_H
#define TINYCANBACKEND_H
-#include <QtSerialBus/qcanbusframe.h>
#include <QtSerialBus/qcanbusdevice.h>
#include <QtSerialBus/qcanbusdeviceinfo.h>
+#include <QtSerialBus/qcanbusframe.h>
-#include <QtCore/qvariant.h>
-#include <QtCore/qvector.h>
#include <QtCore/qlist.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
@@ -62,7 +28,7 @@ public:
bool open() override;
void close() override;
- void setConfigurationParameter(int key, const QVariant &value) override;
+ void setConfigurationParameter(ConfigurationKey key, const QVariant &value) override;
bool writeFrame(const QCanBusFrame &newData) override;
@@ -71,9 +37,10 @@ public:
static bool canCreate(QString *errorReason);
static QList<QCanBusDeviceInfo> interfaces();
-private:
- void resetController();
+ void resetController() override;
+ QCanBusDeviceInfo deviceInfo() const override;
+private:
TinyCanBackendPrivate * const d_ptr;
};
diff --git a/src/plugins/canbus/tinycan/tinycanbackend_p.h b/src/plugins/canbus/tinycan/tinycanbackend_p.h
index 25316a2..f9f61d5 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend_p.h
+++ b/src/plugins/canbus/tinycan/tinycanbackend_p.h
@@ -1,39 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef TINYCANBACKEND_P_H
#define TINYCANBACKEND_P_H
@@ -66,7 +33,7 @@ public:
bool open();
void close();
- bool setConfigurationParameter(int key, const QVariant &value);
+ bool setConfigurationParameter(QCanBusDevice::ConfigurationKey key, const QVariant &value);
QString systemErrorString(int errorCode);
void setupChannel(const QString &interfaceName);
diff --git a/src/plugins/canbus/vectorcan/CMakeLists.txt b/src/plugins/canbus/vectorcan/CMakeLists.txt
new file mode 100644
index 0000000..e5dfbdd
--- /dev/null
+++ b/src/plugins/canbus/vectorcan/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## VectorCanBusPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(VectorCanBusPlugin
+ OUTPUT_NAME qtvectorcanbus
+ PLUGIN_TYPE canbus
+ SOURCES
+ main.cpp
+ vectorcan_symbols_p.h
+ vectorcanbackend.cpp vectorcanbackend.h vectorcanbackend_p.h
+ LIBRARIES
+ Qt::Core
+ Qt::Network
+ Qt::SerialBus
+)
diff --git a/src/plugins/canbus/vectorcan/main.cpp b/src/plugins/canbus/vectorcan/main.cpp
index bbfb851..5a7ad60 100644
--- a/src/plugins/canbus/vectorcan/main.cpp
+++ b/src/plugins/canbus/vectorcan/main.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "vectorcanbackend.h"
@@ -46,11 +13,11 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_VECTORCAN, "qt.canbus.plugins.vectorcan")
-class VectorCanBusPlugin : public QObject, public QCanBusFactoryV2
+class VectorCanBusPlugin : public QObject, public QCanBusFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QCanBusFactory" FILE "plugin.json")
- Q_INTERFACES(QCanBusFactoryV2)
+ Q_INTERFACES(QCanBusFactory)
public:
QList<QCanBusDeviceInfo> availableDevices(QString *errorMessage) const override
diff --git a/src/plugins/canbus/vectorcan/vectorcan.pro b/src/plugins/canbus/vectorcan/vectorcan.pro
deleted file mode 100644
index 847f2aa..0000000
--- a/src/plugins/canbus/vectorcan/vectorcan.pro
+++ /dev/null
@@ -1,18 +0,0 @@
-TARGET = qtvectorcanbus
-
-QT = core serialbus
-
-HEADERS += \
- vectorcanbackend.h \
- vectorcanbackend_p.h \
- vectorcan_symbols_p.h
-
-SOURCES += \
- main.cpp \
- vectorcanbackend.cpp
-
-DISTFILES = plugin.json
-
-PLUGIN_TYPE = canbus
-PLUGIN_CLASS_NAME = VectorCanBusPlugin
-load(qt_plugin)
diff --git a/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h b/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h
index 9d6e841..b8df8e4 100644
--- a/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h
+++ b/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef VECTORCAN_SYMBOLS_P_H
#define VECTORCAN_SYMBOLS_P_H
@@ -228,6 +195,8 @@ typedef HANDLE XLhandle;
#define XL_EVENT_FLAG_OVERRUN 0x01 // Used in XLevent.flags
+#define XL_CAN_MAX_DATA_LEN 64
+
// structure for XL_RECEIVE_MSG, XL_TRANSMIT_MSG (32 bytes)
struct s_xl_can_msg {
unsigned long id;
@@ -256,6 +225,9 @@ static_assert(sizeof(s_xl_can_msg) == 32, "Invalid size of s_xl_can_msg structur
#define XL_CAN_STATE_FLAG_SJA_MODE 0x00000001
+#define XL_CANFD_RX_EVENT_HEADER_SIZE 32
+#define XL_CANFD_MAX_EVENT_SIZE 128
+
// CAN Chip status
struct s_xl_chip_state {
unsigned char busStatus;
@@ -285,6 +257,86 @@ typedef struct s_xl_event {
} XLevent;
static_assert(sizeof(s_xl_event) == 48, "Invalid size of s_xl_event structure");
+typedef struct {
+ quint32 id;
+ quint32 flags;
+ quint32 crc;
+ quint8 reserved1[12];
+ quint16 totalBitCnt;
+ quint8 dlc;
+ quint8 reserved[5];
+ quint8 data[XL_CAN_MAX_DATA_LEN];
+} XL_CAN_EV_RX_MSG;
+
+typedef struct {
+ quint32 canId;
+ quint32 msgFlags;
+ quint8 dlc;
+ quint8 reserved1;
+ quint16 reserved;
+ quint8 data[XL_CAN_MAX_DATA_LEN];
+} XL_CAN_EV_TX_REQUEST;
+
+typedef struct {
+ quint8 errorCode;
+ quint8 reserved[95];
+} XL_CAN_EV_ERROR;
+
+typedef struct {
+ quint8 busStatus;
+ quint8 txErrorCounter;
+ quint8 rxErrorCounter;
+ quint8 reserved;
+ quint32 reserved0;
+} XL_CAN_EV_CHIP_STATE;
+
+typedef struct s_xl_sync_pulse_ev {
+ quint32 triggerSource;
+ quint32 reserved;
+ quint64 time;
+} XL_SYNC_PULSE_EV;
+
+typedef XL_SYNC_PULSE_EV XL_CAN_EV_SYNC_PULSE;
+
+typedef struct {
+ quint32 size;
+ quint16 tag;
+ quint16 channelIndex;
+ quint32 userHandle;
+ quint16 flagsChip;
+ quint16 reserved0;
+ quint64 reserved1;
+ quint64 timeStamp;
+ union {
+ quint8 raw[XL_CANFD_MAX_EVENT_SIZE - XL_CANFD_RX_EVENT_HEADER_SIZE];
+ XL_CAN_EV_RX_MSG canRxOkMsg;
+ XL_CAN_EV_RX_MSG canTxOkMsg;
+ XL_CAN_EV_TX_REQUEST canTxRequest;
+ XL_CAN_EV_ERROR canError;
+ XL_CAN_EV_CHIP_STATE canChipState;
+ XL_CAN_EV_SYNC_PULSE canSyncPulse;
+ } tagData;
+} XLcanRxEvent;
+
+typedef struct {
+ quint32 id;
+ quint32 flags;
+ quint8 dlc;
+ quint8 reserved[7];
+ quint8 data[XL_CAN_MAX_DATA_LEN];
+} XL_CAN_TX_MSG;
+
+typedef struct {
+ quint16 tag;
+ quint16 transId;
+ quint8 channelIndex;
+ quint8 reserved[3];
+ union {
+ XL_CAN_TX_MSG canMsg;
+ } tagData;
+} XLcanTxEvent;
+
+
// build a channels mask from the channels index
#define XL_CHANNEL_MASK(x) (quint64(1) << (x))
@@ -354,6 +406,22 @@ typedef qint16 XLstatus;
#define XL_CAN_STD 01 // flag for standard ID's
#define XL_CAN_EXT 02 // flag for extended ID's
+#define XL_CAN_TXMSG_FLAG_EDL 0x0001 // extended data length
+#define XL_CAN_TXMSG_FLAG_BRS 0x0002 // baud rate switch
+#define XL_CAN_TXMSG_FLAG_RTR 0x0010 // remote transmission request
+#define XL_CAN_TXMSG_FLAG_HIGHPRIO 0x0080 // high priority message - clears all send buffers - then transmits
+#define XL_CAN_TXMSG_FLAG_WAKEUP 0x0200 // generate a wakeup message
+
+#define XL_CAN_RXMSG_FLAG_EDL 0x0001 // extended data length
+#define XL_CAN_RXMSG_FLAG_BRS 0x0002 // baud rate switch
+#define XL_CAN_RXMSG_FLAG_ESI 0x0004 // error state indicator
+#define XL_CAN_RXMSG_FLAG_RTR 0x0010 // remote transmission request
+#define XL_CAN_RXMSG_FLAG_EF 0x0200 // error frame (only posssible in XL_CAN_EV_TX_REQUEST/XL_CAN_EV_TX_REMOVED)
+#define XL_CAN_RXMSG_FLAG_ARB_LOST 0x0400 // Arbitration Lost
+ // set if the receiving node tried to transmit a message but lost arbitration process
+#define XL_CAN_RXMSG_FLAG_WAKEUP 0x2000 // high voltage message on single wire CAN
+#define XL_CAN_RXMSG_FLAG_TE 0x4000 // 1: transceiver error detected
+
typedef struct {
quint32 busType;
union {
@@ -447,6 +515,21 @@ typedef struct _XLacceptance {
XLaccFilt xtd;
} XLacceptance;
+typedef struct s_XLcanFdConf {
+ unsigned int arbitrationBitRate;
+ unsigned int sjwAbr;
+ unsigned int tseg1Abr;
+ unsigned int tseg2Abr;
+ unsigned int dataBitRate;
+ unsigned int sjwDbr;
+ unsigned int tseg1Dbr;
+ unsigned int tseg2Dbr;
+ unsigned char reserved;
+ unsigned char options;
+ unsigned char reserved1[2];
+ unsigned int reserved2;
+} XLcanFdConf;
+
// defines for xlSetGlobalTimeSync
#define XL_SET_TIMESYNC_NO_CHANGE ((unsigned long)0)
#define XL_SET_TIMESYNC_ON ((unsigned long)1)
@@ -476,6 +559,10 @@ GENERATE_SYMBOL_VARIABLE(XLstatus, xlReceive, XLportHandle, quint32 *, XLevent *
GENERATE_SYMBOL_VARIABLE(XLstatus, xlSetNotification, XLportHandle, XLhandle *, int)
GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanRequestChipState, XLportHandle, XLaccess)
GENERATE_SYMBOL_VARIABLE(char *, xlGetErrorString, XLstatus)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanFdSetConfiguration, XLportHandle, XLaccess, XLcanFdConf *)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanReceive, XLportHandle, XLcanRxEvent *)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanTransmitEx, XLportHandle, XLaccess, quint32, quint32 *, XLcanTxEvent *)
+GENERATE_SYMBOL_VARIABLE(XLaccess, xlGetChannelMask, int, int, int)
inline bool resolveVectorCanSymbols(QLibrary *vectorcanLibrary)
{
@@ -502,7 +589,10 @@ inline bool resolveVectorCanSymbols(QLibrary *vectorcanLibrary)
RESOLVE_SYMBOL(xlSetNotification)
RESOLVE_SYMBOL(xlCanRequestChipState)
RESOLVE_SYMBOL(xlGetErrorString)
-
+ RESOLVE_SYMBOL(xlCanFdSetConfiguration)
+ RESOLVE_SYMBOL(xlCanTransmitEx)
+ RESOLVE_SYMBOL(xlCanReceive)
+ RESOLVE_SYMBOL(xlGetChannelMask)
return true;
}
diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend.cpp b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
index 0382d66..c7ec84c 100644
--- a/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
+++ b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "vectorcanbackend.h"
#include "vectorcanbackend_p.h"
@@ -86,6 +53,8 @@ QList<QCanBusDeviceInfo> VectorCanBackend::interfaces()
for (uint i = 0; i < config.channelCount; ++i) {
if (config.channel[i].hwType == XL_HWTYPE_NONE)
continue;
+ if (!(config.channel[i].channelBusCapabilities & XL_BUS_ACTIVE_CAP_CAN))
+ continue;
const bool isVirtual = config.channel[i].hwType == XL_HWTYPE_VIRTUAL;
const bool isFd = config.channel[i].channelCapabilities & XL_CHANNEL_FLAG_CANFD_SUPPORT;
@@ -93,8 +62,9 @@ QList<QCanBusDeviceInfo> VectorCanBackend::interfaces()
const QString name = QStringLiteral("can") + QString::number(i);
const QString serial = QString::number(config.channel[i].serialNumber);
const QString description = QLatin1String(config.channel[i].name);
- result.append(std::move(createDeviceInfo(name, serial, description, channel,
- isVirtual, isFd)));
+ result.append(createDeviceInfo(QStringLiteral("vectorcan"), name,
+ serial, description, QString(),
+ channel, isVirtual, isFd));
}
VectorCanBackendPrivate::cleanupDriver();
@@ -112,16 +82,10 @@ public:
, dptr(d)
{
setHandle(dptr->readHandle);
- }
-protected:
- bool event(QEvent *e) override
- {
- if (e->type() == QEvent::WinEventAct) {
+ connect(this, &QWinEventNotifier::activated, this, [this]() {
dptr->startRead();
- return true;
- }
- return QWinEventNotifier::event(e);
+ });
}
private:
@@ -153,6 +117,79 @@ private:
VectorCanBackendPrivate * const dptr;
};
+XLcanFdConf xlCanFdConfInit(int arbitrationBitRate, int dataBitRate)
+{
+ XLcanFdConf conf = {};
+ const int minArbitrationBitRate = 5000;
+ if (arbitrationBitRate < minArbitrationBitRate) {
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN,
+ "Arbitration bit rate %d is to low (Minimum: %d)",
+ arbitrationBitRate, minArbitrationBitRate);
+ return conf;
+ }
+ if (dataBitRate < arbitrationBitRate) {
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN,
+ "Data bit rate %d must not be lower than arbitration bit rate %d",
+ dataBitRate, arbitrationBitRate);
+ return conf;
+ }
+
+ int prescalerArbitration = 1;
+ switch (arbitrationBitRate) {
+ case 5000: prescalerArbitration = 50; break;
+ case 10000: prescalerArbitration = 25; break;
+ case 20000: prescalerArbitration = 20; break;
+ case 33333: prescalerArbitration = 8; break;
+ case 50000: prescalerArbitration = 5; break;
+ case 83333: prescalerArbitration = 3; break;
+ case 100000: prescalerArbitration = 4; break;
+ case 125000: prescalerArbitration = 2; break;
+ }
+ conf.arbitrationBitRate = arbitrationBitRate;
+ const int clock = 80000000;
+ double samplePoint = 0.75;
+ const int btlCyclesAbr = clock / conf.arbitrationBitRate / prescalerArbitration;
+ conf.tseg1Abr = (btlCyclesAbr * samplePoint) - 1;
+ conf.tseg2Abr = btlCyclesAbr * (1 - samplePoint);
+ conf.sjwAbr = conf.tseg2Abr;
+
+ int prescalerData = 1;
+ switch (dataBitRate) {
+ case 25000: prescalerData = 20; break;
+ case 50000: prescalerData = 10; break;
+ case 83333: prescalerData = 6; break;
+ case 100000: prescalerData = 5; break;
+ case 125000: prescalerData = 4; break;
+ case 250000: prescalerData = 2; break;
+ case 8000000: samplePoint = 0.70; break;
+ }
+ conf.dataBitRate = dataBitRate;
+ const int btlCyclesDbr = clock / conf.dataBitRate / prescalerData;
+ conf.tseg1Dbr = (btlCyclesDbr * samplePoint) - 1;
+ conf.tseg2Dbr = btlCyclesDbr * (1 - samplePoint);
+ conf.sjwDbr = conf.tseg2Dbr;
+
+ return conf;
+}
+
+static qsizetype getDlcFromPayloadSize(const qsizetype size)
+{
+ if (size <= 8)
+ return size;
+ if (size <= 12)
+ return 9;
+ if (size <= 16)
+ return 10;
+ if (size <= 20)
+ return 11;
+ if (size <= 24)
+ return 12;
+ if (size <= 32)
+ return 13;
+ if (size <= 48)
+ return 14;
+ return 15;
+}
VectorCanBackendPrivate::VectorCanBackendPrivate(VectorCanBackend *q)
: q_ptr(q)
@@ -170,18 +207,48 @@ bool VectorCanBackendPrivate::open()
Q_Q(VectorCanBackend);
{
+ XLdriverConfig config;
+ if (Q_UNLIKELY(::xlGetDriverConfig(&config) != XL_SUCCESS)) {
+ q->setError(VectorCanBackend::tr("Unable to get driver configuration"),
+ QCanBusDevice::CanBusError::ConnectionError);
+ return false;
+ }
+ channelMask = config.channel[channelIndex].channelMask;
XLaccess permissionMask = channelMask;
- const quint32 queueSize = 256;
+ const quint32 queueSize = usesCanFd ? 8192 : 256;
const XLstatus status = ::xlOpenPort(&portHandle,
const_cast<char *>(qPrintable(qApp->applicationName())),
channelMask, &permissionMask, queueSize,
- XL_INTERFACE_VERSION, XL_BUS_TYPE_CAN);
+ usesCanFd ? XL_INTERFACE_VERSION_V4 : XL_INTERFACE_VERSION, XL_BUS_TYPE_CAN);
if (Q_UNLIKELY(status != XL_SUCCESS || portHandle == XL_INVALID_PORTHANDLE)) {
q->setError(systemErrorString(status), QCanBusDevice::ConnectionError);
portHandle = XL_INVALID_PORTHANDLE;
return false;
}
+ if (usesCanFd && arbBitRate != 0) {
+ if (permissionMask != 0) {
+ XLcanFdConf xlfdconf = xlCanFdConfInit(arbBitRate, dataBitRate);
+
+ const XLstatus statusFd = ::xlCanFdSetConfiguration(portHandle, channelMask, &xlfdconf);
+ if (Q_UNLIKELY(statusFd != XL_SUCCESS)) {
+ const QString errorString = systemErrorString(statusFd);
+ if (statusFd == XL_ERR_INVALID_ACCESS) {
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Unable to change the configuration: %ls.",
+ qUtf16Printable(errorString));
+ q->setError(errorString, QCanBusDevice::CanBusError::ConfigurationError);
+ } else {
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Connection error: %ls.",
+ qUtf16Printable(errorString));
+ q->setError(errorString, QCanBusDevice::CanBusError::ConnectionError);
+ return false;
+ }
+ }
+ } else {
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "No init access for channel %d! "
+ "Using existing configuration!", channelIndex);
+ }
+ }
}
{
@@ -242,7 +309,8 @@ void VectorCanBackendPrivate::close()
portHandle = XL_INVALID_PORTHANDLE;
}
-bool VectorCanBackendPrivate::setConfigurationParameter(int key, const QVariant &value)
+bool VectorCanBackendPrivate::setConfigurationParameter(QCanBusDevice::ConfigurationKey key,
+ const QVariant &value)
{
Q_Q(VectorCanBackend);
@@ -252,8 +320,27 @@ bool VectorCanBackendPrivate::setConfigurationParameter(int key, const QVariant
case QCanBusDevice::ReceiveOwnKey:
transmitEcho = value.toBool();
return true;
+ case QCanBusDevice::DataBitRateKey:
+ return setDataBitRate(value.toUInt());
+ case QCanBusDevice::CanFdKey:
+ {
+ if (value.toBool()) {
+ XLdriverConfig config;
+ if (Q_UNLIKELY(::xlGetDriverConfig(&config) == XL_SUCCESS)) {
+ if (config.channel[channelIndex].channelCapabilities & XL_CHANNEL_FLAG_CANFD_SUPPORT) {
+ usesCanFd = true;
+ return true;
+ }
+ }
+ q->setError(VectorCanBackend::tr("Unable to set CAN FD"),
+ QCanBusDevice::CanBusError::ConfigurationError);
+ return false;
+ }
+ usesCanFd = false;
+ return true;
+ }
default:
- q->setError(VectorCanBackend::tr("Unsupported configuration key"),
+ q->setError(VectorCanBackend::tr("Unsupported configuration key: %1").arg(key),
QCanBusDevice::ConfigurationError);
return false;
}
@@ -261,13 +348,18 @@ bool VectorCanBackendPrivate::setConfigurationParameter(int key, const QVariant
void VectorCanBackendPrivate::setupChannel(const QString &interfaceName)
{
+ Q_Q(VectorCanBackend);
if (Q_LIKELY(interfaceName.startsWith(QStringLiteral("can")))) {
- const QStringRef ref = interfaceName.midRef(3);
+ const QStringView ref = QStringView{interfaceName}.mid(3);
bool ok = false;
- const int channelIndex = ref.toInt(&ok);
+ channelIndex = ref.toInt(&ok);
if (ok && (channelIndex >= 0 && channelIndex < XL_CONFIG_MAX_CHANNELS)) {
- channelMask = XL_CHANNEL_MASK((channelIndex));
+ channelMask = xlGetChannelMask(-1, channelIndex, 0);
return;
+ } else {
+ channelIndex = -1;
+ q->setError(VectorCanBackend::tr("Unable to setup channel with interface name %1")
+ .arg(interfaceName), QCanBusDevice::CanBusError::ConfigurationError);
}
}
@@ -301,30 +393,51 @@ void VectorCanBackendPrivate::startWrite()
const QCanBusFrame frame = q->dequeueOutgoingFrame();
const QByteArray payload = frame.payload();
+ const qsizetype payloadSize = payload.size();
- XLevent event;
- ::memset(&event, 0, sizeof(event));
-
- event.tag = XL_TRANSMIT_MSG;
-
- s_xl_can_msg &msg = event.tagData.msg;
+ quint32 eventCount = 1;
+ XLstatus status = XL_ERROR;
+ if (usesCanFd) {
+ XLcanTxEvent event = {};
+
+ event.tag = XL_CAN_EV_TAG_TX_MSG;
+ XL_CAN_TX_MSG &msg = event.tagData.canMsg;
+
+ msg.id = frame.frameId();
+ if (frame.hasExtendedFrameFormat())
+ msg.id |= XL_CAN_EXT_MSG_ID;
+
+ msg.dlc = static_cast<quint8>(getDlcFromPayloadSize(payloadSize));
+ if (frame.hasFlexibleDataRateFormat())
+ msg.flags = XL_CAN_TXMSG_FLAG_EDL;
+ if (frame.hasBitrateSwitch())
+ msg.flags |= XL_CAN_TXMSG_FLAG_BRS;
+ if (frame.frameType() == QCanBusFrame::RemoteRequestFrame)
+ msg.flags |= XL_CAN_TXMSG_FLAG_RTR; // we do not care about the payload
+ else
+ ::memcpy(msg.data, payload.constData(), payloadSize);
+
+ status = ::xlCanTransmitEx(portHandle, channelMask, eventCount, &eventCount, &event);
+ } else {
+ XLevent event = {};
+ event.tag = XL_TRANSMIT_MSG;
+ s_xl_can_msg &msg = event.tagData.msg;
- msg.id = frame.frameId();
- if (frame.hasExtendedFrameFormat())
- msg.id |= XL_CAN_EXT_MSG_ID;
+ msg.id = frame.frameId();
+ if (frame.hasExtendedFrameFormat())
+ msg.id |= XL_CAN_EXT_MSG_ID;
- msg.dlc = payload.size();
+ msg.dlc = payloadSize;
- if (frame.frameType() == QCanBusFrame::RemoteRequestFrame)
- msg.flags |= XL_CAN_MSG_FLAG_REMOTE_FRAME; // we do not care about the payload
- else if (frame.frameType() == QCanBusFrame::ErrorFrame)
- msg.flags |= XL_CAN_MSG_FLAG_ERROR_FRAME; // we do not care about the payload
- else
- ::memcpy(msg.data, payload.constData(), sizeof(msg.data));
+ if (frame.frameType() == QCanBusFrame::RemoteRequestFrame)
+ msg.flags |= XL_CAN_MSG_FLAG_REMOTE_FRAME; // we do not care about the payload
+ else if (frame.frameType() == QCanBusFrame::ErrorFrame)
+ msg.flags |= XL_CAN_MSG_FLAG_ERROR_FRAME; // we do not care about the payload
+ else
+ ::memcpy(msg.data, payload.constData(), payloadSize);
- quint32 eventCount = 1;
- const XLstatus status = ::xlCanTransmit(portHandle, channelMask,
- &eventCount, &event);
+ status = ::xlCanTransmit(portHandle, channelMask, &eventCount, &event);
+ }
if (Q_UNLIKELY(status != XL_SUCCESS)) {
q->setError(systemErrorString(status),
QCanBusDevice::WriteError);
@@ -340,42 +453,80 @@ void VectorCanBackendPrivate::startRead()
{
Q_Q(VectorCanBackend);
- QVector<QCanBusFrame> newFrames;
+ QList<QCanBusFrame> newFrames;
for (;;) {
quint32 eventCount = 1;
- XLevent event;
- ::memset(&event, 0, sizeof(event));
+ if (usesCanFd) {
+ XLcanRxEvent event = {};
+
+ const XLstatus status = ::xlCanReceive(portHandle, &event);
+ if (Q_UNLIKELY(status != XL_SUCCESS)) {
+ if (status != XL_ERR_QUEUE_IS_EMPTY) {
+ q->setError(systemErrorString(status), QCanBusDevice::ReadError);
+ }
+ break;
+ }
+ if (event.tag != XL_CAN_EV_TAG_RX_OK)
+ continue;
+
+ const XL_CAN_EV_RX_MSG &msg = event.tagData.canRxOkMsg;
+
+ int dataLength = msg.dlc;
+ switch (msg.dlc) {
+ case 9: dataLength = 12; break;
+ case 10: dataLength = 16; break;
+ case 11: dataLength = 20; break;
+ case 12: dataLength = 24; break;
+ case 13: dataLength = 32; break;
+ case 14: dataLength = 48; break;
+ case 15: dataLength = 64; break;
+ }
- const XLstatus status = ::xlReceive(portHandle, &eventCount, &event);
- if (Q_UNLIKELY(status != XL_SUCCESS)) {
- if (status != XL_ERR_QUEUE_IS_EMPTY) {
- q->setError(systemErrorString(status),
- QCanBusDevice::ReadError);
+ QCanBusFrame frame(msg.id & ~XL_CAN_EXT_MSG_ID,
+ QByteArray(reinterpret_cast<const char *>(msg.data), dataLength));
+ frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(event.timeStamp / 1000));
+ frame.setExtendedFrameFormat(msg.id & XL_CAN_EXT_MSG_ID);
+ frame.setBitrateSwitch(msg.flags & XL_CAN_RXMSG_FLAG_BRS);
+ frame.setFrameType((msg.flags & XL_CAN_RXMSG_FLAG_RTR)
+ ? QCanBusFrame::RemoteRequestFrame
+ : (msg.flags & XL_CAN_RXMSG_FLAG_EF)
+ ? QCanBusFrame::ErrorFrame
+ : QCanBusFrame::DataFrame);
+
+ newFrames.append(std::move(frame));
+ } else {
+ XLevent event = {};
+
+ const XLstatus status = ::xlReceive(portHandle, &eventCount, &event);
+ if (Q_UNLIKELY(status != XL_SUCCESS)) {
+ if (status != XL_ERR_QUEUE_IS_EMPTY) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::ReadError);
+ }
+ break;
}
- break;
+ if (event.tag != XL_RECEIVE_MSG)
+ continue;
+
+ const s_xl_can_msg &msg = event.tagData.msg;
+
+ if ((msg.flags & XL_CAN_MSG_FLAG_TX_COMPLETED) && !transmitEcho)
+ continue;
+
+ QCanBusFrame frame(msg.id & ~XL_CAN_EXT_MSG_ID,
+ QByteArray(reinterpret_cast<const char *>(msg.data), int(msg.dlc)));
+ frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(event.timeStamp / 1000));
+ frame.setExtendedFrameFormat(msg.id & XL_CAN_EXT_MSG_ID);
+ frame.setLocalEcho(msg.flags & XL_CAN_MSG_FLAG_TX_COMPLETED);
+ frame.setFrameType((msg.flags & XL_CAN_MSG_FLAG_REMOTE_FRAME)
+ ? QCanBusFrame::RemoteRequestFrame
+ : (msg.flags & XL_CAN_MSG_FLAG_ERROR_FRAME)
+ ? QCanBusFrame::ErrorFrame
+ : QCanBusFrame::DataFrame);
+
+ newFrames.append(std::move(frame));
}
-
- if (event.tag != XL_RECEIVE_MSG)
- continue;
-
- const s_xl_can_msg &msg = event.tagData.msg;
-
- if ((msg.flags & XL_CAN_MSG_FLAG_TX_COMPLETED) && !transmitEcho)
- continue;
-
- QCanBusFrame frame(msg.id & ~XL_CAN_EXT_MSG_ID,
- QByteArray(reinterpret_cast<const char *>(msg.data), int(msg.dlc)));
- frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(event.timeStamp / 1000));
- frame.setExtendedFrameFormat(msg.id & XL_CAN_EXT_MSG_ID);
- frame.setLocalEcho(msg.flags & XL_CAN_MSG_FLAG_TX_COMPLETED);
- frame.setFrameType((msg.flags & XL_CAN_MSG_FLAG_REMOTE_FRAME)
- ? QCanBusFrame::RemoteRequestFrame
- : (msg.flags & XL_CAN_MSG_FLAG_ERROR_FRAME)
- ? QCanBusFrame::ErrorFrame
- : QCanBusFrame::DataFrame);
-
- newFrames.append(std::move(frame));
}
q->enqueueReceivedFrames(newFrames);
@@ -425,19 +576,40 @@ void VectorCanBackendPrivate::cleanupDriver()
bool VectorCanBackendPrivate::setBitRate(quint32 bitrate)
{
Q_Q(VectorCanBackend);
-
- if (q->state() != QCanBusDevice::UnconnectedState) {
+ if (!usesCanFd && q->state() != QCanBusDevice::UnconnectedState) {
const XLstatus status = ::xlCanSetChannelBitrate(portHandle, channelMask, bitrate);
+ arbBitRate = bitrate;
if (Q_UNLIKELY(status != XL_SUCCESS)) {
q->setError(systemErrorString(status),
QCanBusDevice::CanBusError::ConfigurationError);
return false;
}
+ } else if (arbBitRate != bitrate) {
+ arbBitRate = bitrate;
}
return true;
}
+bool VectorCanBackendPrivate::setDataBitRate(quint32 bitrate)
+{
+ if (!usesCanFd) {
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN,
+ "Cannot set data bit rate in CAN 2.0 mode, this is only available with CAN FD");
+ return false;
+ }
+ if (dataBitRate != bitrate) {
+ if (bitrate >= 25000) { // Minimum
+ dataBitRate = bitrate;
+ } else {
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN,
+ "Cannot set data bit rate to less than 25000 which is the minimum");
+ return false;
+ }
+ }
+ return true;
+}
+
VectorCanBackend::VectorCanBackend(const QString &name, QObject *parent)
: QCanBusDevice(parent)
, d_ptr(new VectorCanBackendPrivate(this))
@@ -446,9 +618,6 @@ VectorCanBackend::VectorCanBackend(const QString &name, QObject *parent)
d->setupChannel(name);
d->setupDefaultConfigurations();
-
- std::function<CanBusStatus()> g = std::bind(&VectorCanBackend::busStatus, this);
- setCanBusStatusGetter(g);
}
VectorCanBackend::~VectorCanBackend()
@@ -469,7 +638,7 @@ bool VectorCanBackend::open()
}
const auto keys = configurationKeys();
- for (int key : keys) {
+ for (ConfigurationKey key : keys) {
const QVariant param = configurationParameter(key);
const bool success = d->setConfigurationParameter(key, param);
if (!success) {
@@ -491,7 +660,7 @@ void VectorCanBackend::close()
setState(QCanBusDevice::UnconnectedState);
}
-void VectorCanBackend::setConfigurationParameter(int key, const QVariant &value)
+void VectorCanBackend::setConfigurationParameter(ConfigurationKey key, const QVariant &value)
{
Q_D(VectorCanBackend);
@@ -520,9 +689,8 @@ bool VectorCanBackend::writeFrame(const QCanBusFrame &newData)
return false;
}
- // CAN FD frame format not implemented at this stage
- if (Q_UNLIKELY(newData.hasFlexibleDataRateFormat())) {
- setError(tr("CAN FD frame format not supported."),
+ if (!d->usesCanFd && newData.hasFlexibleDataRateFormat()) {
+ setError(tr("Unable to write a flexible data rate format frame without CAN FD enabled."),
QCanBusDevice::WriteError);
return false;
}
@@ -543,6 +711,11 @@ QString VectorCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
return QString();
}
+bool VectorCanBackend::hasBusStatus() const
+{
+ return true;
+}
+
QCanBusDevice::CanBusStatus VectorCanBackend::busStatus()
{
Q_D(VectorCanBackend);
@@ -556,35 +729,71 @@ QCanBusDevice::CanBusStatus VectorCanBackend::busStatus()
return QCanBusDevice::CanBusStatus::Unknown;
}
- quint32 eventCount = 1;
- XLevent event;
- ::memset(&event, 0, sizeof(event));
+ quint8 busStatus = 0;
+ if (d->usesCanFd) {
+ XLcanRxEvent event = {};
+
+ const XLstatus receiveStatus = ::xlCanReceive(d->portHandle, &event);
+ if (Q_UNLIKELY(receiveStatus != XL_SUCCESS)) {
+ const QString errorString = d->systemErrorString(receiveStatus);
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Can not query CAN bus status: %ls.",
+ qUtf16Printable(errorString));
+ setError(errorString, QCanBusDevice::CanBusError::ReadError);
+ return QCanBusDevice::CanBusStatus::Unknown;
+ }
- const XLstatus receiveStatus = ::xlReceive(d->portHandle, &eventCount, &event);
- if (Q_UNLIKELY(receiveStatus != XL_SUCCESS)) {
- const QString errorString = d->systemErrorString(receiveStatus);
- qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Can not query CAN bus status: %ls.",
- qUtf16Printable(errorString));
- setError(errorString, QCanBusDevice::CanBusError::ReadError);
- return QCanBusDevice::CanBusStatus::Unknown;
- }
+ if (Q_LIKELY(event.tag == XL_CAN_EV_TAG_CHIP_STATE))
+ busStatus = event.tagData.canChipState.busStatus;
- if (Q_LIKELY(event.tag == XL_CHIP_STATE)) {
- switch (event.tagData.chipState.busStatus) {
- case XL_CHIPSTAT_BUSOFF:
- return QCanBusDevice::CanBusStatus::BusOff;
- case XL_CHIPSTAT_ERROR_PASSIVE:
- return QCanBusDevice::CanBusStatus::Error;
- case XL_CHIPSTAT_ERROR_WARNING:
- return QCanBusDevice::CanBusStatus::Warning;
- case XL_CHIPSTAT_ERROR_ACTIVE:
- return QCanBusDevice::CanBusStatus::Good;
+ } else {
+ quint32 eventCount = 1;
+ XLevent event = {};
+
+ const XLstatus receiveStatus = ::xlReceive(d->portHandle, &eventCount, &event);
+ if (Q_UNLIKELY(receiveStatus != XL_SUCCESS)) {
+ const QString errorString = d->systemErrorString(receiveStatus);
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Can not query CAN bus status: %ls.",
+ qUtf16Printable(errorString));
+ setError(errorString, QCanBusDevice::CanBusError::ReadError);
+ return QCanBusDevice::CanBusStatus::Unknown;
}
+
+ if (Q_LIKELY(event.tag == XL_CHIP_STATE))
+ busStatus = event.tagData.chipState.busStatus;
+ }
+
+ switch (busStatus) {
+ case XL_CHIPSTAT_BUSOFF:
+ return QCanBusDevice::CanBusStatus::BusOff;
+ case XL_CHIPSTAT_ERROR_PASSIVE:
+ return QCanBusDevice::CanBusStatus::Error;
+ case XL_CHIPSTAT_ERROR_WARNING:
+ return QCanBusDevice::CanBusStatus::Warning;
+ case XL_CHIPSTAT_ERROR_ACTIVE:
+ return QCanBusDevice::CanBusStatus::Good;
}
- qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Unknown CAN bus status: %u",
- uint(event.tagData.chipState.busStatus));
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Unknown CAN bus status: %u", busStatus);
return QCanBusDevice::CanBusStatus::Unknown;
}
+QCanBusDeviceInfo VectorCanBackend::deviceInfo() const
+{
+ const QList<QCanBusDeviceInfo> availableDevices = interfaces();
+ const int index = d_ptr->channelIndex;
+ const QString name = QStringLiteral("can%1").arg(index);
+
+ const auto deviceInfo = std::find_if(availableDevices.constBegin(),
+ availableDevices.constEnd(),
+ [name](const QCanBusDeviceInfo &info) {
+ return name == info.name();
+ });
+
+ if (Q_LIKELY(deviceInfo != availableDevices.constEnd()))
+ return *deviceInfo;
+
+ qWarning("%s: Cannot get device info for index %d.", Q_FUNC_INFO, index);
+ return QCanBusDevice::deviceInfo();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend.h b/src/plugins/canbus/vectorcan/vectorcanbackend.h
index 89b9da6..1b08dbc 100644
--- a/src/plugins/canbus/vectorcan/vectorcanbackend.h
+++ b/src/plugins/canbus/vectorcan/vectorcanbackend.h
@@ -1,49 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef VECTORCANBACKEND_H
#define VECTORCANBACKEND_H
-#include <QtSerialBus/qcanbusframe.h>
#include <QtSerialBus/qcanbusdevice.h>
#include <QtSerialBus/qcanbusdeviceinfo.h>
+#include <QtSerialBus/qcanbusframe.h>
-#include <QtCore/qvariant.h>
-#include <QtCore/qvector.h>
#include <QtCore/qlist.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
@@ -61,7 +27,7 @@ public:
bool open() override;
void close() override;
- void setConfigurationParameter(int key, const QVariant &value) override;
+ void setConfigurationParameter(ConfigurationKey key, const QVariant &value) override;
bool writeFrame(const QCanBusFrame &newData) override;
@@ -70,9 +36,11 @@ public:
static bool canCreate(QString *errorReason);
static QList<QCanBusDeviceInfo> interfaces();
-private:
- QCanBusDevice::CanBusStatus busStatus();
+ bool hasBusStatus() const override;
+ CanBusStatus busStatus() override;
+ QCanBusDeviceInfo deviceInfo() const override;
+private:
VectorCanBackendPrivate * const d_ptr;
};
diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend_p.h b/src/plugins/canbus/vectorcan/vectorcanbackend_p.h
index 3eafb0c..fefd8f7 100644
--- a/src/plugins/canbus/vectorcan/vectorcanbackend_p.h
+++ b/src/plugins/canbus/vectorcan/vectorcanbackend_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Denis Shienkov <denis.shienkov@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef VECTORCANBACKEND_P_H
#define VECTORCANBACKEND_P_H
@@ -71,7 +38,7 @@ public:
bool open();
void close();
- bool setConfigurationParameter(int key, const QVariant &value);
+ bool setConfigurationParameter(QCanBusDevice::ConfigurationKey key, const QVariant &value);
void setupChannel(const QString &interfaceName);
void setupDefaultConfigurations();
QString systemErrorString(int errorCode) const;
@@ -81,6 +48,7 @@ public:
void startupDriver();
static void cleanupDriver();
bool setBitRate(quint32 bitrate);
+ bool setDataBitRate(quint32 bitrate);
VectorCanBackend * const q_ptr;
@@ -90,6 +58,10 @@ public:
HANDLE readHandle = INVALID_HANDLE_VALUE;
QTimer *writeNotifier = nullptr;
QWinEventNotifier *readNotifier = nullptr;
+ quint32 dataBitRate = 0;
+ quint32 arbBitRate = 0;
+ int channelIndex = -1;
+ bool usesCanFd = false;
};
QT_END_NAMESPACE
diff --git a/src/plugins/canbus/virtualcan/CMakeLists.txt b/src/plugins/canbus/virtualcan/CMakeLists.txt
new file mode 100644
index 0000000..1b7b4ba
--- /dev/null
+++ b/src/plugins/canbus/virtualcan/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## VirtualCanBusPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(VirtualCanBusPlugin
+ OUTPUT_NAME qtvirtualcanbus
+ PLUGIN_TYPE canbus
+ SOURCES
+ main.cpp
+ virtualcanbackend.cpp virtualcanbackend.h
+ LIBRARIES
+ Qt::Core
+ Qt::Network
+ Qt::SerialBus
+)
diff --git a/src/plugins/canbus/virtualcan/main.cpp b/src/plugins/canbus/virtualcan/main.cpp
index 287b95a..8bf8121 100644
--- a/src/plugins/canbus/virtualcan/main.cpp
+++ b/src/plugins/canbus/virtualcan/main.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "virtualcanbackend.h"
@@ -46,11 +13,11 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_VIRTUALCAN, "qt.canbus.plugins.virtualcan")
-class VirtualCanBusPlugin : public QObject, public QCanBusFactoryV2
+class VirtualCanBusPlugin : public QObject, public QCanBusFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QCanBusFactory" FILE "plugin.json")
- Q_INTERFACES(QCanBusFactoryV2)
+ Q_INTERFACES(QCanBusFactory)
public:
QList<QCanBusDeviceInfo> availableDevices(QString *errorMessage) const override
diff --git a/src/plugins/canbus/virtualcan/virtualcan.pro b/src/plugins/canbus/virtualcan/virtualcan.pro
deleted file mode 100644
index d719f70..0000000
--- a/src/plugins/canbus/virtualcan/virtualcan.pro
+++ /dev/null
@@ -1,16 +0,0 @@
-TARGET = qtvirtualcanbus
-
-QT = core network serialbus
-
-HEADERS += \
- virtualcanbackend.h
-
-SOURCES += \
- main.cpp \
- virtualcanbackend.cpp
-
-DISTFILES = plugin.json
-
-PLUGIN_TYPE = canbus
-PLUGIN_CLASS_NAME = VirtualCanBusPlugin
-load(qt_plugin)
diff --git a/src/plugins/canbus/virtualcan/virtualcanbackend.cpp b/src/plugins/canbus/virtualcan/virtualcanbackend.cpp
index a7e23ff..c901669 100644
--- a/src/plugins/canbus/virtualcan/virtualcanbackend.cpp
+++ b/src/plugins/canbus/virtualcan/virtualcanbackend.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "virtualcanbackend.h"
@@ -45,6 +12,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals::StringLiterals;
+
Q_DECLARE_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_VIRTUALCAN)
enum {
@@ -145,7 +114,7 @@ void VirtualCanServer::readyRead()
const QByteArrayList commandList = command.split(':');
Q_ASSERT(commandList.size() == 2);
- for (QTcpSocket *writeSocket : qAsConst(m_serverSockets)) {
+ for (QTcpSocket *writeSocket : std::as_const(m_serverSockets)) {
// Don't send the frame back to its origin
if (writeSocket == readSocket)
continue;
@@ -221,10 +190,10 @@ void VirtualCanBackend::close()
{
qCDebug(QT_CANBUS_PLUGINS_VIRTUALCAN, "Client [%p] sends disconnect to server.", this);
- m_clientSocket->write("disconnect:can" + QByteArray::number(m_channel) + '\n');
+ m_clientSocket->write(QByteArray("disconnect:can"_ba + QByteArray::number(m_channel) + '\n'));
}
-void VirtualCanBackend::setConfigurationParameter(int key, const QVariant &value)
+void VirtualCanBackend::setConfigurationParameter(ConfigurationKey key, const QVariant &value)
{
if (key == QCanBusDevice::ReceiveOwnKey || key == QCanBusDevice::CanFdKey)
QCanBusDevice::setConfigurationParameter(key, value);
@@ -290,6 +259,7 @@ bool VirtualCanBackend::writeFrame(const QCanBusFrame &frame)
enqueueReceivedFrames({echoFrame});
}
+ emit framesWritten(qint64(1));
return true;
}
@@ -299,24 +269,34 @@ QString VirtualCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
return QString();
}
+QCanBusDeviceInfo VirtualCanBackend::virtualCanDeviceInfo(uint channel)
+{
+ return createDeviceInfo(
+ QStringLiteral("virtualcan"),
+ QStringLiteral("can%1").arg(channel), QString(),
+ QStringLiteral("Qt Virtual CAN bus"), QString(),
+ channel, true, true);
+}
+
QList<QCanBusDeviceInfo> VirtualCanBackend::interfaces()
{
QList<QCanBusDeviceInfo> result;
- for (int channel = 0; channel < VirtualChannels; ++channel) {
- result.append(std::move(createDeviceInfo(
- QStringLiteral("can%1").arg(channel), QString(),
- QStringLiteral("Qt Virtual CAN bus"), channel,
- true, true)));
- }
+ for (uint channel = 0; channel < VirtualChannels; ++channel)
+ result.append(virtualCanDeviceInfo(channel));
return result;
}
+QCanBusDeviceInfo VirtualCanBackend::deviceInfo() const
+{
+ return virtualCanDeviceInfo(m_channel);
+}
+
void VirtualCanBackend::clientConnected()
{
qCInfo(QT_CANBUS_PLUGINS_VIRTUALCAN, "Client [%p] socket connected.", this);
- m_clientSocket->write("connect:can" + QByteArray::number(m_channel) + '\n');
+ m_clientSocket->write(QByteArray("connect:can"_ba + QByteArray::number(m_channel) + '\n'));
setState(QCanBusDevice::ConnectedState);
}
@@ -335,7 +315,7 @@ void VirtualCanBackend::clientReadyRead()
qCDebug(QT_CANBUS_PLUGINS_VIRTUALCAN, "Client [%p] received: '%s'.",
this, answer.constData());
- if (answer.startsWith("disconnect:can" + QByteArray::number(m_channel))) {
+ if (answer.startsWith(QByteArray("disconnect:can"_ba + QByteArray::number(m_channel)))) {
m_clientSocket->disconnectFromHost();
continue;
}
@@ -343,7 +323,7 @@ void VirtualCanBackend::clientReadyRead()
const QByteArrayList list = answer.split('#');
Q_ASSERT(list.size() == 3);
- const quint32 id = list.at(0).toUInt();
+ const QCanBusFrame::FrameId id = list.at(0).toUInt();
const QByteArray flags = list.at(1);
const QByteArray data = QByteArray::fromHex(list.at(2));
const qint64 timeStamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
diff --git a/src/plugins/canbus/virtualcan/virtualcanbackend.h b/src/plugins/canbus/virtualcan/virtualcanbackend.h
index c83b568..93bae2a 100644
--- a/src/plugins/canbus/virtualcan/virtualcanbackend.h
+++ b/src/plugins/canbus/virtualcan/virtualcanbackend.h
@@ -1,50 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef VIRTUALCANBACKEND_H
#define VIRTUALCANBACKEND_H
-#include <QtSerialBus/qcanbusframe.h>
#include <QtSerialBus/qcanbusdevice.h>
#include <QtSerialBus/qcanbusdeviceinfo.h>
+#include <QtSerialBus/qcanbusframe.h>
#include <QtCore/qlist.h>
#include <QtCore/qurl.h>
#include <QtCore/qvariant.h>
-#include <QtCore/qvector.h>
QT_BEGIN_NAMESPACE
@@ -83,7 +49,7 @@ public:
bool open() override;
void close() override;
- void setConfigurationParameter(int key, const QVariant &value) override;
+ void setConfigurationParameter(ConfigurationKey key, const QVariant &value) override;
bool writeFrame(const QCanBusFrame &frame) override;
@@ -91,7 +57,11 @@ public:
static QList<QCanBusDeviceInfo> interfaces();
+ QCanBusDeviceInfo deviceInfo() const override;
+
private:
+ static QCanBusDeviceInfo virtualCanDeviceInfo(uint channel);
+
void clientConnected();
void clientDisconnected();
void clientReadyRead();
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
deleted file mode 100644
index 456289e..0000000
--- a/src/plugins/plugins.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TEMPLATE = subdirs
-
-SUBDIRS += canbus
diff --git a/src/serialbus/CMakeLists.txt b/src/serialbus/CMakeLists.txt
new file mode 100644
index 0000000..015e479
--- /dev/null
+++ b/src/serialbus/CMakeLists.txt
@@ -0,0 +1,62 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## SerialBus Module:
+#####################################################################
+
+qt_internal_add_module(SerialBus
+ PLUGIN_TYPES canbus
+ SOURCES
+ qcanbus.cpp qcanbus.h
+ qcanbusdevice.cpp qcanbusdevice.h qcanbusdevice_p.h
+ qcanbusdeviceinfo.cpp qcanbusdeviceinfo.h qcanbusdeviceinfo_p.h
+ qcanbusfactory.cpp qcanbusfactory.h
+ qcanbusframe.cpp qcanbusframe.h
+ qcancommondefinitions.cpp qcancommondefinitions.h
+ qcandbcfileparser.cpp qcandbcfileparser.h qcandbcfileparser_p.h
+ qcanframeprocessor.cpp qcanframeprocessor.h qcanframeprocessor_p.h
+ qcanmessagedescription.cpp qcanmessagedescription.h qcanmessagedescription_p.h
+ qcansignaldescription.cpp qcansignaldescription.h qcansignaldescription_p.h
+ qcanuniqueiddescription.cpp qcanuniqueiddescription.h qcanuniqueiddescription_p.h
+ qmodbus_symbols_p.h
+ qmodbusadu_p.h
+ qmodbusclient.cpp qmodbusclient.h qmodbusclient_p.h
+ qmodbuscommevent_p.h
+ qmodbusdataunit.cpp qmodbusdataunit.h
+ qmodbusdevice.cpp qmodbusdevice.h qmodbusdevice_p.h
+ qmodbusdeviceidentification.cpp qmodbusdeviceidentification.h
+ qmodbuspdu.cpp qmodbuspdu.h
+ qmodbusreply.cpp qmodbusreply.h
+ qmodbusserver.cpp qmodbusserver.h qmodbusserver_p.h
+ qmodbustcpclient.cpp qmodbustcpclient.h qmodbustcpclient_p.h
+ qmodbustcpserver.cpp qmodbustcpserver.h qmodbustcpserver_p.h
+ qtserialbusglobal.h
+ LIBRARIES
+ Qt::CorePrivate
+ PUBLIC_LIBRARIES
+ Qt::Core
+ Qt::Network # TODO: QTBUG-86533 workaround, Qt::Network should be moved to LIBRARIES
+ PRIVATE_MODULE_INTERFACE
+ Qt::CorePrivate
+ Qt::Network
+ GENERATE_CPP_EXPORTS
+)
+
+## Scopes:
+#####################################################################
+
+qt_internal_extend_target(SerialBus CONDITION QT_FEATURE_modbus_serialport
+ SOURCES
+ qmodbusrtuserialclient.cpp qmodbusrtuserialclient.h qmodbusrtuserialclient_p.h
+ qmodbusrtuserialserver.cpp qmodbusrtuserialserver.h qmodbusrtuserialserver_p.h
+ PUBLIC_LIBRARIES
+ Qt::SerialPort
+ PRIVATE_MODULE_INTERFACE
+ Qt::SerialPort
+)
+
+qt_internal_add_docs(SerialBus
+ doc/qtserialbus.qdocconf
+)
+
diff --git a/src/serialbus/configure.cmake b/src/serialbus/configure.cmake
new file mode 100644
index 0000000..7d13a3e
--- /dev/null
+++ b/src/serialbus/configure.cmake
@@ -0,0 +1,57 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+
+
+#### Inputs
+
+
+
+#### Libraries
+
+
+
+#### Tests
+
+
+qt_config_compile_test("socketcan"
+ LABEL "Socket CAN"
+ PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/socketcan"
+)
+
+qt_config_compile_test("socketcan_fd"
+ LABEL "Socket CAN FD"
+ PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/socketcan_fd"
+)
+
+
+#### Features
+
+qt_feature("socketcan" PRIVATE
+ LABEL "Socket CAN"
+ CONDITION LINUX AND TEST_socketcan
+)
+qt_feature("socketcan_fd" PRIVATE
+ LABEL "Socket CAN FD"
+ CONDITION LINUX AND QT_FEATURE_socketcan AND TEST_socketcan_fd
+)
+qt_feature("modbus-serialport" PUBLIC
+ LABEL "SerialPort Support"
+ PURPOSE "Enables Serial-based Modbus Support"
+ CONDITION TARGET Qt::SerialPort
+)
+qt_configure_add_summary_section(NAME "Qt SerialBus")
+qt_configure_add_summary_entry(ARGS "socketcan")
+qt_configure_add_summary_entry(ARGS "socketcan_fd")
+qt_configure_add_summary_entry(ARGS "modbus-serialport")
+qt_configure_end_summary_section() # end of "Qt SerialBus" section
+qt_configure_add_report_entry(
+ TYPE NOTE
+ MESSAGE "QtSerialBus: Cannot find linux/can.h and linux/can/raw.h Linux headers for socketCAN support."
+ CONDITION LINUX AND NOT QT_FEATURE_socketcan
+)
+qt_configure_add_report_entry(
+ TYPE NOTE
+ MESSAGE "QtSerialBus: Newer kernel needed for flexible data-rate frame support (canfd_frame)."
+ CONDITION LINUX AND QT_FEATURE_socketcan AND NOT QT_FEATURE_socketcan_fd
+)
diff --git a/src/serialbus/configure.json b/src/serialbus/configure.json
deleted file mode 100644
index 15d4863..0000000
--- a/src/serialbus/configure.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "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"]
- },
- "modbus-serialport" : {
- "label": "SerialPort Support",
- "condition": "module.serialport",
- "purpose": "Enables Serial-based Modbus Support",
- "output": [ "publicFeature"]
- }
- },
-
- "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",
- "modbus-serialport"
- ]
- }
- ]
-}
diff --git a/src/serialbus/doc/images/can-example.png b/src/serialbus/doc/images/can-example.png
index 4b44819..4e31331 100644
--- a/src/serialbus/doc/images/can-example.png
+++ b/src/serialbus/doc/images/can-example.png
Binary files differ
diff --git a/src/serialbus/doc/images/canbus_signals_be.png b/src/serialbus/doc/images/canbus_signals_be.png
new file mode 100644
index 0000000..1dd1229
--- /dev/null
+++ b/src/serialbus/doc/images/canbus_signals_be.png
Binary files differ
diff --git a/src/serialbus/doc/images/canbus_signals_le.png b/src/serialbus/doc/images/canbus_signals_le.png
new file mode 100644
index 0000000..e3524c7
--- /dev/null
+++ b/src/serialbus/doc/images/canbus_signals_le.png
Binary files differ
diff --git a/src/serialbus/doc/qtserialbus.qdocconf b/src/serialbus/doc/qtserialbus.qdocconf
index c512ea7..a58e84d 100644
--- a/src/serialbus/doc/qtserialbus.qdocconf
+++ b/src/serialbus/doc/qtserialbus.qdocconf
@@ -15,10 +15,6 @@ qhp.QtSerialBus.virtualFolder = qtserialbus
qhp.QtSerialBus.indexTitle = Qt Serial Bus
qhp.QtSerialBus.indexRoot =
-qhp.QtSerialBus.filterAttributes = qtserialbus $QT_VERSION qtrefdoc
-qhp.QtSerialBus.customFilters.Qt.name = QtSerialBus $QT_VERSION
-qhp.QtSerialBus.customFilters.Qt.filterAttributes = qtserialbus $QT_VERSION
-
qhp.QtSerialBus.subprojects = classes
qhp.QtSerialBus.subprojects.classes.title = C++ Classes
qhp.QtSerialBus.subprojects.classes.indexTitle = Qt Serial Bus C++ Classes
@@ -42,5 +38,10 @@ exampledirs += ../../../examples/serialbus \
imagedirs += images
+manifestmeta.highlighted.names = \
+ "QtSerialBus/CAN Bus Manager" \
+ "QtSerialBus/Modbus Client" \
+ "QtSerialBus/Modbus Server"
+
navigation.landingpage = "Qt Serial Bus"
navigation.cppclassespage = "Qt Serial Bus C++ Classes"
diff --git a/src/serialbus/doc/snippets/snippetmain.cpp b/src/serialbus/doc/snippets/snippetmain.cpp
index 0f3f1d9..85fefad 100644
--- a/src/serialbus/doc/snippets/snippetmain.cpp
+++ b/src/serialbus/doc/snippets/snippetmain.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtSerialBus module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QVariant>
#include <QCanBusDevice>
diff --git a/src/serialbus/doc/snippets/snippets.pro b/src/serialbus/doc/snippets/snippets.pro
deleted file mode 100644
index 4fdcd74..0000000
--- a/src/serialbus/doc/snippets/snippets.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-TEMPLATE = app
-TARGET = serialbus_cppsnippet
-QT = core serialbus
-
-SOURCES += \
- snippetmain.cpp
-
diff --git a/src/serialbus/doc/src/examples/can.qdoc b/src/serialbus/doc/src/examples/can.qdoc
index 0e67a8e..1d71f73 100644
--- a/src/serialbus/doc/src/examples/can.qdoc
+++ b/src/serialbus/doc/src/examples/can.qdoc
@@ -1,32 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*! \example can
- \title CAN Bus example
+ \title CAN Bus Manager
+ \ingroup qtserialbus-examples
+ \examplecategory Connectivity
\brief The example sends and receives CAN bus frames.
@@ -34,8 +12,6 @@
are ordered according to their type. A connect dialog is
provided to adjust the CAN Bus connection parameters.
- \ingroup qtserialbus-examples
-
Key \l{Qt Serial Bus} classes used in this example:
\list
@@ -45,5 +21,47 @@
\image ../images/can-example.png
+ \section1 Creating a QCanBusDevice
+
+ An instance of \l QCanBusDevice is required to perform any CAN
+ communication.
+
+ The \c ConnectDialog allows to specify all the required parameters. After
+ that the device is created using the provided plugin and interface names:
+
+ \snippet can/mainwindow.cpp create_can_device_0
+ \snippet can/mainwindow.cpp create_can_device_1
+
+ The established connections allow to process incoming frames, control the
+ sent frames and handle errors.
+
+ When the device is created, use \l QCanBusDevice::connectDevice() to
+ start the communication.
+
+ \section1 Processing Incoming Frames
+
+ \l QCanBusDevice emits a \l {QCanBusDevice::}{framesReceived()} signal when
+ new frames are available. The \l {QCanBusDevice::}{readFrame()} method
+ can be used to read a single \l QCanBusFrame while there are
+ \l {QCanBusDevice::framesAvailable}{available frames}. Once the frame is
+ received, individual parameters such as \l {QCanBusFrame::}{frameId},
+ \l {QCanBusFrame::}{timeStamp}, or \l {QCanBusFrame::}{payload} can be
+ extracted from it:
+
+ \snippet can/mainwindow.cpp receive_can_frame
+
+ \section1 Sending Frames
+
+ To send custom data over the CAN bus, the user needs to provide at least
+ a \l {QCanBusFrame::}{frameId} and a \l {QCanBusFrame::}{payload}.
+ Optionally other \l QCanBusFrame parameters can be configured:
+
+ \snippet can/sendframebox.cpp prepare_can_frame
+
+ Once the frame is prepared, the \l QCanBusDevice::writeFrame() method can
+ be used to send it:
+
+ \snippet can/mainwindow.cpp send_can_frame
+
\include examples-run.qdocinc
*/
diff --git a/src/serialbus/doc/src/examples/qtserialbus-examples.qdoc b/src/serialbus/doc/src/examples/qtserialbus-examples.qdoc
index 0e92556..81478ab 100644
--- a/src/serialbus/doc/src/examples/qtserialbus-examples.qdoc
+++ b/src/serialbus/doc/src/examples/qtserialbus-examples.qdoc
@@ -1,35 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\group qtserialbus-examples
\title Qt SerialBus Examples
\brief Examples for the Qt SerialBus module
- \ingroup all-examples
\ingroup qtserialbus
These are the \l{Qt Serial Bus} examples.
diff --git a/src/serialbus/doc/src/external-resources.qdoc b/src/serialbus/doc/src/external-resources.qdoc
new file mode 100644
index 0000000..e8d4a90
--- /dev/null
+++ b/src/serialbus/doc/src/external-resources.qdoc
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\externalpage https://docs.openvehicles.com/en/stable/components/vehicle_dbc/docs/dbc-primer.html
+\title OpenVehicles DBC Intro
+*/
+
+/*!
+\externalpage https://www.csselectronics.com/pages/can-dbc-file-database-intro
+\title CSSElectronics DBC Intro
+*/
diff --git a/src/serialbus/doc/src/passthrucan.qdoc b/src/serialbus/doc/src/passthrucan.qdoc
index eff2ef7..1227fcb 100644
--- a/src/serialbus/doc/src/passthrucan.qdoc
+++ b/src/serialbus/doc/src/passthrucan.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Ford Motor Company.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Ford Motor Company.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtserialbus-passthrucan-overview.html
\title Using PassThruCAN Plugin
@@ -31,7 +7,7 @@
\brief Overview of how to use the J2534 Pass-Thru CAN plugin.
The Pass-Thru CAN plugin accesses CAN adapters via the SAE J2534 Pass-Thru API.
- SAE J2534 is a standard for accessing vehicle busses from an x86 Windows PC.
+ SAE J2534 is a standard for accessing vehicle buses from an x86 Windows PC.
Although the API is specified only for 32-bit Windows, some vendors also provide
implementations for 64-bit Windows and other operating systems such as Linux.
diff --git a/src/serialbus/doc/src/peakcan.qdoc b/src/serialbus/doc/src/peakcan.qdoc
index a38ddf7..47efb6c 100644
--- a/src/serialbus/doc/src/peakcan.qdoc
+++ b/src/serialbus/doc/src/peakcan.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtserialbus-peakcan-overview.html
\title Using PeakCAN Plugin
@@ -34,9 +10,16 @@
\l{http://www.peak-system.com/}{PEAK-System} CAN adapters.
This plugin requires the PCAN device drivers and the PCAN-Basic library
- version 4.0.0 or higher on Windows (pcanbasic.dll) and Linux (libpcanbasic.so).
- On macOS the plugin requires the PCBUSB library from
- \l{http://www.mac-can.com}{UV Software}.
+ version 4.4.0 or higher on Windows (pcanbasic.dll) resp. 4.0.0 on Linux
+ (libpcanbasic.so). On macOS the plugin requires the PCBUSB library from
+ \l{http://www.mac-can.com}{UV Software}, version is 0.9 or higher.
+
+ \note The Qt versions 5.14 to 6.4 are only compatible to PCBUSB library
+ version 0.8.1, but Qt versions 6.5 and higher requires a PCBUSB
+ version 0.9 upwards.
+
+ \note QCanBusDeviceInfo::alias() is only supported on Windows and with
+ PCAN-Basic 4.4.0 or higher.
\section1 Creating CAN Bus Devices
@@ -126,6 +109,11 @@
\list
\li QCanBusDevice::resetController()
\li QCanBusDevice::busStatus()
+ \li QCanBusDeviceInfo::alias() (Windows and PCAN-Basic >= 4.4.0 only):
+ Returns the PCAN_DEVICE_ID which can be set to a user defined value
+ from 0..255 resp. 0..4294967295 (depending on the device) with PCAN-View.
+ The default value is 255 resp. 4294967295.
+
\endlist
*/
diff --git a/src/serialbus/doc/src/qt6-changes.qdoc b/src/serialbus/doc/src/qt6-changes.qdoc
new file mode 100644
index 0000000..c0b1053
--- /dev/null
+++ b/src/serialbus/doc/src/qt6-changes.qdoc
@@ -0,0 +1,64 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+/*!
+ \page qtserialbus-changes-qt6.html
+
+ \title Changes to Qt SerialBus
+ \ingroup changes-qt-5-to-6
+ \brief Migrate Qt SerialBus to Qt 6.
+
+ Qt 6 is a result of the conscious effort to make the framework more
+ efficient and easy to use.
+ We try to maintain binary and source compatibility for all the public
+ APIs in each release. But some changes were inevitable in an effort to
+ make Qt a better framework.
+ In this topic, we summarize those changes in Qt SerialBus module and
+ provide guidance to handle them.
+
+ \section1 Changes overview
+ The Qt SerialBus module is generally speaking source compatible with the
+ Qt 5 version and users of the library should be able to continue with no or
+ minor changes to their project.
+
+ \section1 Build system
+ As with Qt 6 in general, the Qt SerialBus module has CMake support in
+ addition to qmake.
+
+ \section1 API changes
+
+ \section2 Qt CAN bus
+
+ \section3 Removal of QCanBusFactoryV2
+ In Qt 6 the QCanBusFactoryV2 has been removed and is no longer part of the
+ public API. Instead QCanBusFactory has gained the additional method
+ QCanBusFactory::availableDevices that needs to be implemented by sub-classes
+ of QCanBusFactory.
+
+ \section3 Changes to QCanBusDevice
+ QCanBusDevice got the following changes:
+ \list
+ \li setConfigurationParameter() and configurationParameter() now use
+ the distinct type ConfigurationKey instead int.
+ \li The functions resetController(), hasBusStatus() and busStatus()
+ are now virtual functions. They have been internal callbacks in
+ Qt 5 due to binary compatibility.
+ \li Custom plugins using one of the private API function
+ QCanBusDevice::createDeviceInfo() need small adoptions as these
+ functions now have the \c plugin name as first parameter and
+ slighly adopted parameter lists.
+ \endlist
+
+ \section3 Changes to QCanBusFrame
+ QCanBusFrame now uses the distinct type \c FrameId, which is a typedef
+ to quint32, so existing code should still work. Anyway, it is recommended
+ to use \c FrameId when upgrading.
+
+ \section2 Qt Modbus
+
+ \section3 Renaming of QModbusRtuSerialMaster and QModbusRtuSerialSlave
+ Following the recommendation of the Modbus organization the class
+ \c QModbusRtuSerialMaster has been renamed to \l QModbusRtuSerialClient and
+ the class \c QModbusRtuSerialSlave has been renamed to \l QModbusRtuSerialServer.
+ It is advised to use the new class names in new or ported code to adhere to
+ the Modbus naming scheme.
+*/
diff --git a/src/serialbus/doc/src/qtcanbus-backends.qdoc b/src/serialbus/doc/src/qtcanbus-backends.qdoc
index 03f8de3..7b033d6 100644
--- a/src/serialbus/doc/src/qtcanbus-backends.qdoc
+++ b/src/serialbus/doc/src/qtcanbus-backends.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtcanbus-backends.html
\title Qt CAN Bus
@@ -47,6 +23,25 @@
\li QCanBusFrame defines a CAN frame that can be written and read from QCanBusDevice.
\endlist
+ Starting from Qt 6.5, the module provides APIs to decode actual signal
+ values from raw CAN frames and also to encode user data into CAN frames:
+
+ \list
+ \li \l QCanSignalDescription provides rules to process CAN signals.
+ \li \l QCanMessageDescription provides rules to process CAN messages.
+ A message description usually contains multiple signal descriptions.
+ \li \l QCanUniqueIdDescription provides rules to process a unique
+ identifier within a CAN frame.
+ \li \l QCanFrameProcessor uses descriptions provided by
+ \l QCanMessageDescription, \l QCanSignalDescription, and
+ \l QCanUniqueIdDescription classes to encode or decode CAN frames.
+ \li \l QCanDbcFileParser provides an API to extract message descriptions
+ from DBC files.
+ \endlist
+
+ \note All APIs for encoding and decoding CAN frames are experimental and
+ subject to change.
+
\section1 CAN Bus Plugins
Multiple vendors provide CAN devices with varying APIs for access. The QtSerialBus module
diff --git a/src/serialbus/doc/src/qtmodbus-backends.qdoc b/src/serialbus/doc/src/qtmodbus-backends.qdoc
index 4b3b3d5..b0513a0 100644
--- a/src/serialbus/doc/src/qtmodbus-backends.qdoc
+++ b/src/serialbus/doc/src/qtmodbus-backends.qdoc
@@ -1,39 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtmodbus-backends.html
\title Qt Modbus
\brief Implemented Qt Modbus.
- Modbus is a request/reply protocol that has one Modbus client in its network and may have many
- Modbus servers. Servers can control only their own internal states and clients can read and write
- data in them. Modbus is not restricted by the network type, in theory it can use any
- QIODevice. However, not every plugin supports all classes derived from QIODevice.
+ Modbus is a request/reply protocol that has one Modbus client in its
+ network and may have many Modbus servers. Servers can control only
+ their own internal states, and clients can read and write data in them.
Each Modbus server has four tables in which it can store data.
diff --git a/src/serialbus/doc/src/qtserialbus-index.qdoc b/src/serialbus/doc/src/qtserialbus-index.qdoc
index db9f241..acde5c5 100644
--- a/src/serialbus/doc/src/qtserialbus-index.qdoc
+++ b/src/serialbus/doc/src/qtserialbus-index.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtserialbus-index.html
@@ -36,18 +12,13 @@
\section1 Getting Started
- To include the definitions of the module's classes and functions, use the
- following directive:
+ To use the module with CMake, use the \c{find_package()} command to locate
+ the needed module components in the \c{Qt6} package:
+ \include qtserialbus-module-use.qdocinc cmakebuild
- \code
- #include <QtSerialBus>
- \endcode
-
- To link against the module, add this line to your qmake .pro file:
-
- \code
- QT += serialbus
- \endcode
+ To use the module for building with qmake, add the module as a value of the
+ \c QT variable in the project's .pro file:
+ \include qtserialbus-module-use.qdocinc qmakebuild
\section1 Supported Buses and Protocols
@@ -103,8 +74,13 @@
\section1 Examples
\list
- \li \l {CAN Bus Example}
- \li \l {Modbus Master example}
- \li \l {Modbus Slave example}
+ \li \l {can}{CAN Bus Manager example}
+ \li \l {modbus/client}{Modbus Client example}
+ \li \l {modbus/server}{Modbus Server example}
+ \li \l {modbus/custom}{Modbus Custom Command example}
\endlist
+
+ \section1 Module Evolution
+ \l {Changes to Qt SerialBus} lists important changes in the module API and
+ functionality that were done for the Qt 6 series of Qt.
*/
diff --git a/src/serialbus/doc/src/qtserialbus-module-cpp.qdoc b/src/serialbus/doc/src/qtserialbus-module-cpp.qdoc
index 57c81ea..439f090 100644
--- a/src/serialbus/doc/src/qtserialbus-module-cpp.qdoc
+++ b/src/serialbus/doc/src/qtserialbus-module-cpp.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -31,6 +7,7 @@
\title Qt Serial Bus C++ Classes
\ingroup modules
\qtvariable serialbus
+ \qtcmakepackage SerialBus
\since 5.8
\brief Provides classes to read and write serial bus data.
@@ -44,12 +21,13 @@
#include <QCanBusDevice>
\endcode
- The .pro file should have the \e serialbus keyword added
-
- \code
- QT += serialbus
- \endcode
+ To use the module with CMake, use the \c{find_package()} command to locate
+ the needed module components in the \c{Qt6} package:
+ \include qtserialbus-module-use.qdocinc cmakebuild
+ To use the module for building with qmake, add the module as a value of the
+ \c QT variable in the project's .pro file:
+ \include qtserialbus-module-use.qdocinc qmakebuild
See more in the \l {Qt Serial Bus} {Qt Serial Bus Overview}.
*/
diff --git a/src/serialbus/doc/src/qtserialbus-module-use.qdocinc b/src/serialbus/doc/src/qtserialbus-module-use.qdocinc
new file mode 100644
index 0000000..99e631e
--- /dev/null
+++ b/src/serialbus/doc/src/qtserialbus-module-use.qdocinc
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+//! [cmakebuild]
+ \code
+ find_package(Qt6 COMPONENTS SerialBus REQUIRED)
+ target_link_libraries(mytarget PRIVATE Qt6::SerialBus)
+ \endcode
+//! [cmakebuild]
+
+//! [qmakebuild]
+ \code
+ QT += serialbus
+ \endcode
+//! [qmakebuild]
diff --git a/src/serialbus/doc/src/socketcan.qdoc b/src/serialbus/doc/src/socketcan.qdoc
index e578969..31b18fa 100644
--- a/src/serialbus/doc/src/socketcan.qdoc
+++ b/src/serialbus/doc/src/socketcan.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtserialbus-socketcan-overview.html
\title Using SocketCAN Plugin
diff --git a/src/serialbus/doc/src/systeccan.qdoc b/src/serialbus/doc/src/systeccan.qdoc
index dc66023..d696c58 100644
--- a/src/serialbus/doc/src/systeccan.qdoc
+++ b/src/serialbus/doc/src/systeccan.qdoc
@@ -1,31 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Andre Hartmann <aha_1980@gmx.de>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
- \page qtserialbus-SystecCAN-overview.html
+ \page qtserialbus-systeccan-overview.html
\title Using SystecCAN Plugin
\brief Overview of how to use the SystecCAN plugin.
diff --git a/src/serialbus/doc/src/tinycan.qdoc b/src/serialbus/doc/src/tinycan.qdoc
index 8479576..b357a0a 100644
--- a/src/serialbus/doc/src/tinycan.qdoc
+++ b/src/serialbus/doc/src/tinycan.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtserialbus-tinycan-overview.html
\title Using TinyCAN Plugin
diff --git a/src/serialbus/doc/src/vectorcan.qdoc b/src/serialbus/doc/src/vectorcan.qdoc
index 70b6521..9c17f2d 100644
--- a/src/serialbus/doc/src/vectorcan.qdoc
+++ b/src/serialbus/doc/src/vectorcan.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtserialbus-vectorcan-overview.html
\title Using VectorCAN Plugin
@@ -105,6 +81,15 @@
bus immediately appear in the receive buffer. This can be used to check if sending
was successful. If this option is enabled, the therefore received frames are marked
with QCanBusFrame::hasLocalEcho()
+ \row
+ \li QCanBusDevice::CanFdKey
+ \li Enable the use of CAN FD on the CAN bus connection. If this option is enabled, then
+ it is not possible to receive your own CAN frames being sent, so setting
+ QCanBusDevice::ReceiveOwnKey to true has no effect. Since Qt 5.15.
+ \row
+ \li QCanBusDevice::DataBitRateKey
+ \li Determines the data bit rate of the CAN bus connection. This is only available when
+ \l QCanBusDevice::CanFdKey is set to true. Since Qt 5.15.
\endtable
VectorCAN supports the following additional functions:
diff --git a/src/serialbus/doc/src/virtualcan.qdoc b/src/serialbus/doc/src/virtualcan.qdoc
index 3dc9f76..8c2cf3e 100644
--- a/src/serialbus/doc/src/virtualcan.qdoc
+++ b/src/serialbus/doc/src/virtualcan.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtserialbus-virtualcan-overview.html
\title Using VirtualCAN Plugin
diff --git a/src/serialbus/qcanbus.cpp b/src/serialbus/qcanbus.cpp
index 5c1ddc8..f8130c2 100644
--- a/src/serialbus/qcanbus.cpp
+++ b/src/serialbus/qcanbus.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcanbus.h"
#include "qcanbusfactory.h"
@@ -53,9 +20,9 @@ class QCanBusPrivate
{
public:
QCanBusPrivate() { }
- QCanBusPrivate(int index, const QJsonObject &meta) : meta(meta), index(index) {}
+ QCanBusPrivate(int index, const QCborMap &meta) : meta(meta), index(index) {}
- QJsonObject meta;
+ QCborMap meta;
QObject *factory = nullptr;
int index = -1;
};
@@ -70,9 +37,9 @@ static QCanBus *globalInstance = nullptr;
static void loadPlugins()
{
- const QList<QJsonObject> meta = qFactoryLoader()->metaData();
- for (int i = 0; i < meta.count(); i++) {
- const QJsonObject obj = meta.at(i).value(QLatin1String("MetaData")).toObject();
+ const QList<QPluginParsedMetaData> meta = qFactoryLoader()->metaData();
+ for (int i = 0; i < meta.size(); i++) {
+ const QCborMap obj = meta.at(i).value(QtPluginMetaDataKeys::MetaData).toMap();
if (obj.isEmpty())
continue;
@@ -166,21 +133,43 @@ QList<QCanBusDeviceInfo> QCanBus::availableDevices(const QString &plugin, QStrin
if (Q_UNLIKELY(!obj))
return QList<QCanBusDeviceInfo>();
- const QCanBusFactoryV2 *factoryV2 = qobject_cast<QCanBusFactoryV2 *>(obj);
- if (Q_UNLIKELY(!factoryV2)) {
+ const QCanBusFactory *factory = qobject_cast<const QCanBusFactory *>(obj);
+ if (Q_UNLIKELY(!factory)) {
setErrorMessage(errorMessage,
tr("The plugin '%1' does not provide this function.").arg(plugin));
return QList<QCanBusDeviceInfo>();
}
QString errorString;
- QList<QCanBusDeviceInfo> result = factoryV2->availableDevices(&errorString);
+ QList<QCanBusDeviceInfo> result = factory->availableDevices(&errorString);
setErrorMessage(errorMessage, errorString);
return result;
}
/*!
+ \since 6.8
+ Returns the available devices for all plugins, i.e. all available CAN interfaces.
+
+ In case of failure, the optional parameter \a errorMessage returns a textual
+ error description.
+
+ \note Some plugins might not or only partially support this function.
+
+ \sa createDevice()
+*/
+QList<QCanBusDeviceInfo> QCanBus::availableDevices(QString *errorMessage) const
+{
+ const QStringList allPlugins = plugins();
+ QList<QCanBusDeviceInfo> result;
+
+ for (const QString &plugin : allPlugins)
+ result.append(availableDevices(plugin, errorMessage));
+
+ return result;
+}
+
+/*!
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.
@@ -213,12 +202,8 @@ QCanBusDevice *QCanBus::createDevice(const QString &plugin, const QString &inter
if (Q_UNLIKELY(!obj))
return nullptr;
- const QCanBusFactoryV2 *factoryV2 = qobject_cast<QCanBusFactoryV2 *>(obj);
- if (Q_LIKELY(factoryV2))
- return factoryV2->createDevice(interfaceName, errorMessage);
-
- const QCanBusFactory *factory = qobject_cast<QCanBusFactory *>(obj);
- if (factory)
+ const QCanBusFactory *factory = qobject_cast<const QCanBusFactory *>(obj);
+ if (Q_LIKELY(factory))
return factory->createDevice(interfaceName, errorMessage);
setErrorMessage(errorMessage,
diff --git a/src/serialbus/qcanbus.h b/src/serialbus/qcanbus.h
index 6170fcc..e952c68 100644
--- a/src/serialbus/qcanbus.h
+++ b/src/serialbus/qcanbus.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCANBUS_H
#define QCANBUS_H
@@ -53,6 +20,7 @@ public:
QStringList plugins() const;
QList<QCanBusDeviceInfo> availableDevices(const QString &plugin, QString *errorMessage = nullptr) const;
+ QList<QCanBusDeviceInfo> availableDevices(QString *errorMessage = nullptr) const;
QCanBusDevice *createDevice(const QString &plugin,
const QString &interfaceName,
diff --git a/src/serialbus/qcanbusdevice.cpp b/src/serialbus/qcanbusdevice.cpp
index 5b6c343..402c40c 100644
--- a/src/serialbus/qcanbusdevice.cpp
+++ b/src/serialbus/qcanbusdevice.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcanbusdevice.h"
#include "qcanbusdevice_p.h"
@@ -150,19 +117,17 @@ Q_LOGGING_CATEGORY(QT_CANBUS, "qt.canbus")
*/
/*!
- \fn bool operator==(const QCanBusDevice::Filter &a, const QCanBusDevice::Filter &b)
- \relates QCanBusDevice::Filter
+ \fn bool QCanBusDevice::Filter::operator==(const QCanBusDevice::Filter &a, const QCanBusDevice::Filter &b)
- Returns true, if the filter \a a is equal to the filter \a b,
- otherwise returns false.
+ Returns \c true, if the filter \a a is equal to the filter \a b,
+ otherwise returns \c false.
*/
/*!
- \fn bool operator!=(const QCanBusDevice::Filter &a, const QCanBusDevice::Filter &b)
- \relates QCanBusDevice::Filter
+ \fn bool QCanBusDevice::Filter::operator!=(const QCanBusDevice::Filter &a, const QCanBusDevice::Filter &b)
- Returns true, if the filter \a a is not equal to the filter \a b,
- otherwise returns false.
+ Returns \c true, if the filter \a a is not equal to the filter \a b,
+ otherwise returns \c false.
*/
/*!
@@ -293,7 +258,7 @@ void QCanBusDevice::clearError()
Subclasses must call this function when they receive frames.
*/
-void QCanBusDevice::enqueueReceivedFrames(const QVector<QCanBusFrame> &newFrames)
+void QCanBusDevice::enqueueReceivedFrames(const QList<QCanBusFrame> &newFrames)
{
Q_D(QCanBusDevice);
@@ -345,30 +310,6 @@ bool QCanBusDevice::hasOutgoingFrames() const
}
/*!
- * \since 5.14
- * Called from the derived plugin to register a function \a resetter which performs the
- * CAN controller hardware reset when resetController() is called.
- */
-void QCanBusDevice::setResetControllerFunction(std::function<void()> resetter)
-{
- Q_D(QCanBusDevice);
-
- d->m_resetControllerFunction = std::move(resetter);
-}
-
-/*!
- * \since 5.14
- * Called from the derived plugin to register a function \a busStatusGetter
- * which returns the CAN controller bus status when busStatus() is called.
- */
-void QCanBusDevice::setCanBusStatusGetter(std::function<CanBusStatus()> busStatusGetter)
-{
- Q_D(QCanBusDevice);
-
- d->m_busStatusGetter = std::move(busStatusGetter);
-}
-
-/*!
Sets the configuration parameter \a key for the CAN bus connection
to \a value. The potential keys are represented by \l ConfigurationKey.
@@ -381,7 +322,7 @@ void QCanBusDevice::setCanBusStatusGetter(std::function<CanBusStatus()> busStatu
\sa configurationParameter()
*/
-void QCanBusDevice::setConfigurationParameter(int key, const QVariant &value)
+void QCanBusDevice::setConfigurationParameter(ConfigurationKey key, const QVariant &value)
{
Q_D(QCanBusDevice);
@@ -411,7 +352,7 @@ void QCanBusDevice::setConfigurationParameter(int key, const QVariant &value)
\sa setConfigurationParameter(), configurationKeys()
*/
-QVariant QCanBusDevice::configurationParameter(int key) const
+QVariant QCanBusDevice::configurationParameter(ConfigurationKey key) const
{
Q_D(const QCanBusDevice);
@@ -426,15 +367,15 @@ QVariant QCanBusDevice::configurationParameter(int key) const
/*!
Returns the list of keys used by the CAN bus connection.
- The the meaning of the keys is equivalent to \l ConfigurationKey.
- If a key is not explicitly mentioned the platform's
+ The meaning of the keys is equivalent to \l ConfigurationKey.
+ If a key is not explicitly mentioned, the platform's
default setting for the relevant key is used.
*/
-QVector<int> QCanBusDevice::configurationKeys() const
+QList<QCanBusDevice::ConfigurationKey> QCanBusDevice::configurationKeys() const
{
Q_D(const QCanBusDevice);
- QVector<int> result;
+ QList<ConfigurationKey> result;
for (const ConfigEntry &e : d->configOptions)
result.append(e.first);
@@ -510,14 +451,10 @@ qint64 QCanBusDevice::framesToWrite() const
*/
void QCanBusDevice::resetController()
{
- if (d_func()->m_resetControllerFunction) {
- d_func()->m_resetControllerFunction();
- } else {
- const char error[] = QT_TRANSLATE_NOOP("QCanBusDevice",
- "This CAN bus plugin does not support hardware controller reset.");
- qCWarning(QT_CANBUS, error);
- setError(tr(error), QCanBusDevice::CanBusError::ConfigurationError);
- }
+ const char error[] = QT_TRANSLATE_NOOP("QCanBusDevice",
+ "This CAN bus plugin does not support hardware controller reset.");
+ qCWarning(QT_CANBUS, error);
+ setError(tr(error), QCanBusDevice::CanBusError::ConfigurationError);
}
/*!
@@ -529,7 +466,7 @@ void QCanBusDevice::resetController()
*/
bool QCanBusDevice::hasBusStatus() const
{
- return d_func()->m_busStatusGetter != nullptr;
+ return false;
}
/*!
@@ -561,11 +498,8 @@ bool QCanBusDevice::hasBusStatus() const
\sa hasBusStatus(), resetController()
*/
-QCanBusDevice::CanBusStatus QCanBusDevice::busStatus() const
+QCanBusDevice::CanBusStatus QCanBusDevice::busStatus()
{
- if (d_func()->m_busStatusGetter)
- return d_func()->m_busStatusGetter();
-
return QCanBusDevice::CanBusStatus::Unknown;
}
@@ -606,7 +540,7 @@ void QCanBusDevice::clear(QCanBusDevice::Directions direction)
clearError();
if (direction & Direction::Input) {
- QMutexLocker(&d->incomingFramesGuard);
+ QMutexLocker locker(&d->incomingFramesGuard);
d->incomingFrames.clear();
}
@@ -816,13 +750,13 @@ QCanBusFrame QCanBusDevice::readFrame()
/*!
\since 5.12
Returns all \l{QCanBusFrame}s from the queue; otherwise returns
- an empty QVector. The returned frames are removed from the queue.
+ an empty QList. The returned frames are removed from the queue.
The queue operates according to the FIFO principle.
\sa clear(), framesAvailable(), readFrame()
*/
-QVector<QCanBusFrame> QCanBusDevice::readAllFrames()
+QList<QCanBusFrame> QCanBusDevice::readAllFrames()
{
Q_D(QCanBusDevice);
@@ -830,14 +764,14 @@ QVector<QCanBusFrame> QCanBusDevice::readAllFrames()
const QString error = tr("Cannot read frame as device is not connected.");
qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
setError(error, CanBusError::OperationError);
- return QVector<QCanBusFrame>();
+ return QList<QCanBusFrame>();
}
clearError();
QMutexLocker locker(&d->incomingFramesGuard);
- QVector<QCanBusFrame> result;
+ QList<QCanBusFrame> result;
result.swap(d->incomingFrames);
return result;
}
@@ -977,35 +911,57 @@ void QCanBusDevice::setState(QCanBusDevice::CanBusDeviceState newState)
}
/*!
- * Returns a QCanBusDeviceInfo created from the given parameters \a name,
- * \a isVirtual, and \a isFlexibleDataRateCapable.
+ * \since 6.2
+ * Returns a QCanBusDeviceInfo created from the given parameters \a plugin,
+ * \a name, \a isVirtual, and \a isFlexibleDataRateCapable.
* \internal
*/
-QCanBusDeviceInfo QCanBusDevice::createDeviceInfo(const QString &name, bool isVirtual,
+QCanBusDeviceInfo QCanBusDevice::createDeviceInfo(const QString &plugin, const QString &name,
+ bool isVirtual,
bool isFlexibleDataRateCapable)
{
- return createDeviceInfo(name, QString(), QString(), 0, isVirtual, isFlexibleDataRateCapable);
+ return createDeviceInfo(plugin, name, QString(), QString(), QString(),
+ 0, isVirtual, isFlexibleDataRateCapable);
}
/*!
- \since 5.11
- Returns a QCanBusDeviceInfo created from the given parameters \a name,
- \a serialNumber, \a description, \a channel, \a isVirtual, and \a
- isFlexibleDataRateCapable.
+ \since 6.2
+ Returns a QCanBusDeviceInfo created from the given parameters \a plugin,
+ \a name, \a serialNumber, \a description, \a alias, \a channel, \a isVirtual,
+ and \a isFlexibleDataRateCapable.
\internal
*/
-QCanBusDeviceInfo QCanBusDevice::createDeviceInfo(const QString &name, const QString &serialNumber,
- const QString &description, int channel,
- bool isVirtual, bool isFlexibleDataRateCapable)
+QCanBusDeviceInfo QCanBusDevice::createDeviceInfo(const QString &plugin,
+ const QString &name,
+ const QString &serialNumber,
+ const QString &description,
+ const QString &alias,
+ int channel,
+ bool isVirtual,
+ bool isFlexibleDataRateCapable)
{
- QScopedPointer<QCanBusDeviceInfoPrivate> info(new QCanBusDeviceInfoPrivate);
+ std::unique_ptr<QCanBusDeviceInfoPrivate> info(new QCanBusDeviceInfoPrivate);
+ info->plugin = plugin;
info->name = name;
info->serialNumber = serialNumber;
info->description = description;
+ info->alias = alias;
info->channel = channel;
info->hasFlexibleDataRate = isFlexibleDataRateCapable;
info->isVirtual = isVirtual;
- return QCanBusDeviceInfo(*info.take());
+ return QCanBusDeviceInfo(*info.release());
+}
+
+/*!
+ \since 6.2
+
+ Returns a QCanBusDeviceInfo for the current QCanBusDevice. If the function
+ is not implemented by a sub-class of QCanBusDevice, a default constructed
+ object is returned.
+ */
+QCanBusDeviceInfo QCanBusDevice::deviceInfo() const
+{
+ return QCanBusDeviceInfo(*(new QCanBusDeviceInfoPrivate));
}
QT_END_NAMESPACE
diff --git a/src/serialbus/qcanbusdevice.h b/src/serialbus/qcanbusdevice.h
index 5d2d976..23be730 100644
--- a/src/serialbus/qcanbusdevice.h
+++ b/src/serialbus/qcanbusdevice.h
@@ -1,38 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2021 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCANBUSDEVICE_H
#define QCANBUSDEVICE_H
@@ -116,27 +84,27 @@ public:
};
Q_DECLARE_FLAGS(FormatFilters, FormatFilter)
- quint32 frameId = 0;
- quint32 frameIdMask = 0;
+ QCanBusFrame::FrameId frameId = 0;
+ QCanBusFrame::FrameId frameIdMask = 0;
QCanBusFrame::FrameType type = QCanBusFrame::InvalidFrame;
FormatFilter format = MatchBaseAndExtendedFormat;
};
explicit QCanBusDevice(QObject *parent = nullptr);
- virtual void setConfigurationParameter(int key, const QVariant &value);
- QVariant configurationParameter(int key) const;
- QVector<int> configurationKeys() const;
+ virtual void setConfigurationParameter(ConfigurationKey key, const QVariant &value);
+ QVariant configurationParameter(ConfigurationKey key) const;
+ QList<ConfigurationKey> configurationKeys() const;
virtual bool writeFrame(const QCanBusFrame &frame) = 0;
QCanBusFrame readFrame();
- QVector<QCanBusFrame> readAllFrames();
+ QList<QCanBusFrame> readAllFrames();
qint64 framesAvailable() const;
qint64 framesToWrite() const;
- void resetController();
- bool hasBusStatus() const;
- QCanBusDevice::CanBusStatus busStatus() const;
+ virtual void resetController();
+ virtual bool hasBusStatus() const;
+ virtual CanBusStatus busStatus();
enum Direction {
Input = 1,
@@ -149,7 +117,6 @@ public:
virtual bool waitForFramesWritten(int msecs);
virtual bool waitForFramesReceived(int msecs);
- // TODO rename these once QIODevice dependency has been removed
bool connectDevice();
void disconnectDevice();
@@ -159,6 +126,7 @@ public:
QString errorString() const;
virtual QString interpretErrorFrame(const QCanBusFrame &errorFrame) = 0;
+ virtual QCanBusDeviceInfo deviceInfo() const;
Q_SIGNALS:
void errorOccurred(QCanBusDevice::CanBusError);
@@ -171,26 +139,27 @@ protected:
void setError(const QString &errorText, QCanBusDevice::CanBusError);
void clearError();
- void enqueueReceivedFrames(const QVector<QCanBusFrame> &newFrames);
+ void enqueueReceivedFrames(const QList<QCanBusFrame> &newFrames);
void enqueueOutgoingFrame(const QCanBusFrame &newFrame);
QCanBusFrame dequeueOutgoingFrame();
bool hasOutgoingFrames() const;
- // TODO Remove once official plugin system is gone
- // Can be folded into one call to connectDevice() & disconnectDevice()
virtual bool open() = 0;
virtual void close() = 0;
- void setResetControllerFunction(std::function<void()> resetter);
- void setCanBusStatusGetter(std::function<CanBusStatus()> busStatusGetter);
-
- static QCanBusDeviceInfo createDeviceInfo(const QString &name,
- bool isVirtual = false,
- bool isFlexibleDataRateCapable = false);
- static QCanBusDeviceInfo createDeviceInfo(const QString &name, const QString &serialNumber,
- const QString &description, int channel,
- bool isVirtual, bool isFlexibleDataRateCapable);
+ static QCanBusDeviceInfo createDeviceInfo(const QString &plugin,
+ const QString &name,
+ bool isVirtual,
+ bool isFlexibleDataRateCapable);
+ static QCanBusDeviceInfo createDeviceInfo(const QString &plugin,
+ const QString &name,
+ const QString &serialNumber,
+ const QString &description,
+ const QString &alias,
+ int channel,
+ bool isVirtual,
+ bool isFlexibleDataRateCapable);
};
Q_DECLARE_TYPEINFO(QCanBusDevice::CanBusError, Q_PRIMITIVE_TYPE);
diff --git a/src/serialbus/qcanbusdevice_p.h b/src/serialbus/qcanbusdevice_p.h
index e74168c..202f2a4 100644
--- a/src/serialbus/qcanbusdevice_p.h
+++ b/src/serialbus/qcanbusdevice_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCANBUSDEVICE_P_H
#define QCANBUSDEVICE_P_H
@@ -55,7 +22,7 @@
QT_BEGIN_NAMESPACE
-typedef QPair<int, QVariant > ConfigEntry;
+typedef QPair<QCanBusDevice::ConfigurationKey, QVariant > ConfigEntry;
class QCanBusDevicePrivate : public QObjectPrivate
{
@@ -67,10 +34,10 @@ public:
QCanBusDevice::CanBusDeviceState state = QCanBusDevice::UnconnectedState;
QString errorText;
- QVector<QCanBusFrame> incomingFrames;
+ QList<QCanBusFrame> incomingFrames;
QMutex incomingFramesGuard;
- QVector<QCanBusFrame> outgoingFrames;
- QVector<ConfigEntry> configOptions;
+ QList<QCanBusFrame> outgoingFrames;
+ QList<ConfigEntry> configOptions;
bool waitForReceivedEntered = false;
bool waitForWrittenEntered = false;
diff --git a/src/serialbus/qcanbusdeviceinfo.cpp b/src/serialbus/qcanbusdeviceinfo.cpp
index 78dcd89..1fb496f 100644
--- a/src/serialbus/qcanbusdeviceinfo.cpp
+++ b/src/serialbus/qcanbusdeviceinfo.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcanbusdeviceinfo.h"
#include "qcanbusdeviceinfo_p.h"
@@ -78,7 +45,7 @@ QCanBusDeviceInfo::~QCanBusDeviceInfo() = default;
/*!
\fn QCanBusDeviceInfo &QCanBusDeviceInfo::operator=(QCanBusDeviceInfo &&other)
- Move-assigns other to this QCanBusDeviceInfo instance.
+ Move-assigns \a other to this QCanBusDeviceInfo instance.
*/
/*!
@@ -87,8 +54,21 @@ QCanBusDeviceInfo::~QCanBusDeviceInfo() = default;
*/
QCanBusDeviceInfo &QCanBusDeviceInfo::operator=(const QCanBusDeviceInfo &) = default;
+ /*!
+ \since 6.2
+ Returns the plugin name of this CAN bus interface, e.g. "peakcan".
+
+ This corresponds to the \c plugin parameter of QCanBus::createDevice().
+ */
+QString QCanBusDeviceInfo::plugin() const
+{
+ return d_ptr->plugin;
+}
+
/*!
- Returns the interface name of this CAN bus interface, e.g. can0.
+ Returns the interface name of this CAN bus interface, e.g. "can0".
+
+ This corresponds to the \c interfaceName parameter of QCanBus::createDevice().
*/
QString QCanBusDeviceInfo::name() const
{
@@ -110,6 +90,8 @@ QString QCanBusDeviceInfo::description() const
\since 5.11
Returns the serial number of the CAN bus interface as string, if available.
Otherwise, an empty string is returned.
+
+ \sa alias()
*/
QString QCanBusDeviceInfo::serialNumber() const
{
@@ -117,6 +99,24 @@ QString QCanBusDeviceInfo::serialNumber() const
}
/*!
+ \since 6.0
+ Returns a user defineable alias associated with this CAN bus interface.
+
+ Some CAN bus interfaces can have a user defined alias associated. This is mostly
+ done with the CAN hardware vendors tools. The alias allows to identify this
+ hardware later, especially when multiple interfaces are connected.
+
+ \note In contrast to serialNumber(), the alias is not guaranteed to be unique.
+
+ If this function is not supported by the CAN plugin, an empty string is returned.
+ \sa serialNumber()
+*/
+QString QCanBusDeviceInfo::alias() const
+{
+ return d_ptr->alias;
+}
+
+/*!
\since 5.11
Returns the sequential channel number of the CAN bus interface, starting
with zero. For example, a two channel CAN interface may have the channels
diff --git a/src/serialbus/qcanbusdeviceinfo.h b/src/serialbus/qcanbusdeviceinfo.h
index c46302d..8d56797 100644
--- a/src/serialbus/qcanbusdeviceinfo.h
+++ b/src/serialbus/qcanbusdeviceinfo.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCANBUSDEVICEINFO_H
#define QCANBUSDEVICEINFO_H
@@ -52,21 +19,23 @@ public:
QCanBusDeviceInfo(const QCanBusDeviceInfo &other);
~QCanBusDeviceInfo();
- void swap(QCanBusDeviceInfo &other) Q_DECL_NOTHROW
+ void swap(QCanBusDeviceInfo &other) noexcept
{
- qSwap(d_ptr, other.d_ptr);
+ d_ptr.swap(other.d_ptr);
}
QCanBusDeviceInfo &operator=(const QCanBusDeviceInfo &other);
- QCanBusDeviceInfo &operator=(QCanBusDeviceInfo &&other) Q_DECL_NOTHROW
+ QCanBusDeviceInfo &operator=(QCanBusDeviceInfo &&other) noexcept
{
swap(other);
return *this;
}
+ QString plugin() const;
QString name() const;
QString description() const;
QString serialNumber() const;
+ QString alias() const;
int channel() const;
bool hasFlexibleDataRate() const;
diff --git a/src/serialbus/qcanbusdeviceinfo_p.h b/src/serialbus/qcanbusdeviceinfo_p.h
index 78c9e1c..f8d7172 100644
--- a/src/serialbus/qcanbusdeviceinfo_p.h
+++ b/src/serialbus/qcanbusdeviceinfo_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2021 Andre Hartmann <aha_1980@gmx.de>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCANBUSDEVICEINFO_P_H
#define QCANBUSDEVICEINFO_P_H
@@ -50,6 +17,7 @@
#include <QtCore/qshareddata.h>
#include <QtCore/qstring.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -61,9 +29,11 @@ public:
{
}
+ QString plugin;
QString name;
QString description;
QString serialNumber;
+ QString alias;
int channel = 0;
bool hasFlexibleDataRate = false;
bool isVirtual = false;
diff --git a/src/serialbus/qcanbusfactory.cpp b/src/serialbus/qcanbusfactory.cpp
index 508741b..5335167 100644
--- a/src/serialbus/qcanbusfactory.cpp
+++ b/src/serialbus/qcanbusfactory.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcanbusfactory.h"
@@ -41,17 +8,12 @@ QT_BEGIN_NAMESPACE
/*!
\class QCanBusFactory
\inmodule QtSerialBus
- \since 5.8
- \deprecated
+ \since 5.9
\brief The QCanBusFactory class is a factory class used as the
plugin interface for CAN bus plugins.
All plugins must implement the functions provided by this factory class.
-
- This class is deprecated, you should use QCanBusFactoryV2 instead.
-
- \sa QCanBusFactoryV2
*/
/*!
@@ -67,36 +29,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \internal
-
- \fn QCanBusFactory::~QCanBusFactory()
-*/
-
-/*!
- \class QCanBusFactoryV2
- \inmodule QtSerialBus
- \since 5.9
-
- \brief The QCanBusFactoryV2 class is a factory class used as the
- plugin interface for CAN bus plugins.
-
- All plugins must implement the functions provided by this factory class.
-*/
-
-/*!
- \fn QCanBusDevice *QCanBusFactoryV2::createDevice(const QString &interfaceName,
- QString *errorMessage) const
-
- Creates a new QCanBusDevice. The caller must take ownership of the returned pointer.
-
- \a interfaceName is the CAN interface name and
- \a errorMessage contains an error description in case of failure.
-
- If the factory cannot create a plugin, it returns \c nullptr.
-*/
-
-/*!
- \fn QList<QCanBusDeviceInfo> QCanBusFactoryV2::availableDevices(QString *errorMessage) const
+ \fn QList<QCanBusDeviceInfo> QCanBusFactory::availableDevices(QString *errorMessage) const
Returns the list of available devices and their capabilities for the QCanBusDevice.
@@ -106,7 +39,7 @@ QT_BEGIN_NAMESPACE
/*!
* \internal
*/
-QCanBusFactoryV2::~QCanBusFactoryV2()
+QCanBusFactory::~QCanBusFactory()
{
}
diff --git a/src/serialbus/qcanbusfactory.h b/src/serialbus/qcanbusfactory.h
index cd7322b..726b3d2 100644
--- a/src/serialbus/qcanbusfactory.h
+++ b/src/serialbus/qcanbusfactory.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCANBUSFACTORY_H
#define QCANBUSFACTORY_H
@@ -48,25 +15,14 @@ class Q_SERIALBUS_EXPORT QCanBusFactory
{
public:
virtual QCanBusDevice *createDevice(const QString &interfaceName,
- QString *errorMessage) const = 0;
-protected:
- virtual ~QCanBusFactory() {}
-};
-
-Q_DECLARE_INTERFACE(QCanBusFactory, "org.qt-project.Qt.QCanBusFactory")
-
-class Q_SERIALBUS_EXPORT QCanBusFactoryV2 : public QCanBusFactory
-{
-public:
- virtual QCanBusDevice *createDevice(const QString &interfaceName,
- QString *errorMessage) const = 0;
+ QString *errorMessage) const = 0;
virtual QList<QCanBusDeviceInfo> availableDevices(QString *errorMessage) const = 0;
protected:
- virtual ~QCanBusFactoryV2();
+ virtual ~QCanBusFactory();
};
-Q_DECLARE_INTERFACE(QCanBusFactoryV2, "org.qt-project.Qt.QCanBusFactoryV2")
+Q_DECLARE_INTERFACE(QCanBusFactory, "org.qt-project.Qt.QCanBusFactory")
QT_END_NAMESPACE
diff --git a/src/serialbus/qcanbusframe.cpp b/src/serialbus/qcanbusframe.cpp
index 1476314..f672a5e 100644
--- a/src/serialbus/qcanbusframe.cpp
+++ b/src/serialbus/qcanbusframe.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcanbusframe.h"
@@ -40,6 +7,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QCanBusFrame
\inmodule QtSerialBus
@@ -50,19 +19,31 @@ QT_BEGIN_NAMESPACE
\l QCanBusDevice can use QCanBusFrame for read and write operations. It contains the frame
identifier and the data payload. QCanBusFrame contains the timestamp of the moment it was read.
- \sa QCanBusFrame::TimeStamp
+ \sa QCanBusFrame::FrameId, QCanBusFrame::TimeStamp, payload()
+*/
+
+/*!
+ \typedef QCanBusFrame::FrameId
+
+ A distinct type for a CAN bus frame identifier with either 11 or 29 bit.
+
+ \sa frameId(), setFrameId()
*/
/*!
\fn QCanBusFrame::QCanBusFrame(QCanBusFrame::FrameType type = DataFrame)
Constructs a CAN frame of the specified \a type.
+
+ \sa QCanBusFrame::FrameType, setFrameType()
*/
/*!
- \fn QCanBusFrame::QCanBusFrame(quint32 identifier, const QByteArray &data)
+ \fn QCanBusFrame::QCanBusFrame(QCanBusFrame::FrameId identifier, const QByteArray &data)
Constructs a CAN frame using \a identifier as the frame identifier and \a data as the payload.
+
+ \sa QCanBusFrame::FrameId
*/
/*!
@@ -78,7 +59,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QCanBusFrame::setFrameId(quint32 newFrameId)
+ \fn QCanBusFrame::setFrameId(QCanBusFrame::FrameId newFrameId)
Sets the identifier of the CAN frame to \a newFrameId.
@@ -90,7 +71,7 @@ QT_BEGIN_NAMESPACE
When the format is extended and a \a newFrameId with up to 11 bits or less
is passed, the \e {CAN extended frame format} setting is \b not changed.
- \sa frameId(), hasExtendedFrameFormat()
+ \sa QCanBusFrame::FrameId, frameId(), hasExtendedFrameFormat()
*/
/*!
@@ -102,7 +83,7 @@ QT_BEGIN_NAMESPACE
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
- provide an indication of the responses expected payload length. To set the length expection it
+ provide an indication of the responses expected payload length. To set the expected length it
is necessary to set a fake payload whose length matches the expected payload length of the
response. One way of doing this might be as follows:
@@ -125,7 +106,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn quint32 QCanBusFrame::frameId() const
+ \fn QCanBusFrame::FrameId QCanBusFrame::frameId() const
Returns the CAN frame identifier. If the CAN frame uses the
extended frame format, the identifier has a maximum of 29 bits;
@@ -133,20 +114,20 @@ QT_BEGIN_NAMESPACE
If the frame is of \l ErrorFrame type, this ID is always 0.
- \sa setFrameId(), hasExtendedFrameFormat()
+ \sa QCanBusFrame::FrameId, setFrameId(), hasExtendedFrameFormat()
*/
/*!
\fn bool QCanBusFrame::hasExtendedFrameFormat() const
- Returns \c true if the CAN frame uses a 29bit identifier;
- otherwise \c false, implying an 11bit identifier.
+ Returns \c true if the CAN frame uses a 29 bit identifier;
+ otherwise \c false, implying an 11 bit identifier.
\sa setExtendedFrameFormat(), frameId()
*/
/*!
- \fn void QCanBusFrame::setExtendedFrameFormat(bool isExtended)
+ \fn void QCanBusFrame::setExtendedFrameFormat(bool isExtended)
Sets the extended frame format flag to \a isExtended.
@@ -166,6 +147,7 @@ QT_BEGIN_NAMESPACE
\value Qt_5_8 This frame is the initial version introduced in Qt 5.8
\value Qt_5_9 This frame version was introduced in Qt 5.9
+ \value Qt_5_10 This frame version was introduced in Qt 5.10
*/
/*!
@@ -180,7 +162,7 @@ QT_BEGIN_NAMESPACE
\value InvalidFrame This value represents an invalid frame.
This type is used for error reporting.
- \sa setFrameType()
+ \sa frameType(), setFrameType()
*/
/*!
@@ -202,6 +184,8 @@ QT_BEGIN_NAMESPACE
\value ControllerRestartError The controller restarted.
\value UnknownError An unknown error has occurred.
\value AnyError Matches every other error type.
+
+ \sa error(), setError()
*/
/*!
@@ -209,7 +193,7 @@ QT_BEGIN_NAMESPACE
Returns the type of the frame.
- \sa setFrameType()
+ \sa QCanBusFrame::FrameType, setFrameType()
*/
/*!
@@ -217,7 +201,7 @@ QT_BEGIN_NAMESPACE
Sets the type of the frame to \a newType.
- \sa frameType()
+ \sa QCanBusFrame::FrameType, frameType()
*/
/*!
@@ -242,7 +226,7 @@ QT_BEGIN_NAMESPACE
Returns the error of the current error frame. If the frame
is not an \l ErrorFrame, this function returns \l NoError.
- \sa setError()
+ \sa QCanBusFrame::FrameError, setError()
*/
/*!
@@ -251,7 +235,7 @@ QT_BEGIN_NAMESPACE
Sets the frame's \a error type. This function does nothing if
\l frameType() is not an \l ErrorFrame.
- \sa error()
+ \sa QCanBusFrame::FrameError, error()
*/
/*!
@@ -421,17 +405,22 @@ QString QCanBusFrame::toString() const
break;
}
- const char * const idFormat = hasExtendedFrameFormat() ? "%08X" : " %03X";
- const char * const dlcFormat = hasFlexibleDataRateFormat() ? " [%02d]" : " [%d]";
QString result;
- result.append(QString::asprintf(idFormat, static_cast<uint>(frameId())));
- result.append(QString::asprintf(dlcFormat, payload().size()));
+ result.append(hasExtendedFrameFormat() ? u""_s : u" "_s);
+ result.append(u"%1"_s.arg(static_cast<uint>(frameId()),
+ hasExtendedFrameFormat() ? 8 : 3,
+ 16, QLatin1Char('0')).toUpper());
+
+ result.append(hasFlexibleDataRateFormat() ? u" "_s : u" "_s);
+ result.append(u"[%1]"_s.arg(payload().size(),
+ hasFlexibleDataRateFormat() ? 2 : 0,
+ 10, QLatin1Char('0')));
if (type == RemoteRequestFrame) {
- result.append(QLatin1String(" Remote Request"));
+ result.append(u" Remote Request"_s);
} else if (!payload().isEmpty()) {
const QByteArray data = payload().toHex(' ').toUpper();
- result.append(QLatin1String(" "));
+ result.append(u" "_s);
result.append(QLatin1String(data));
}
@@ -443,7 +432,7 @@ QString QCanBusFrame::toString() const
/*! \relates QCanBusFrame
Writes a \a frame to the stream (\a out) and returns a reference
- to the it.
+ to it.
*/
QDataStream &operator<<(QDataStream &out, const QCanBusFrame &frame)
{
@@ -466,11 +455,11 @@ QDataStream &operator<<(QDataStream &out, const QCanBusFrame &frame)
/*! \relates QCanBusFrame
Reads a \a frame from the stream (\a in) and returns a
- reference to the it.
+ reference to it.
*/
QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame)
{
- quint32 frameId;
+ QCanBusFrame::FrameId frameId;
quint8 frameType;
quint8 version;
bool extendedFrameFormat;
diff --git a/src/serialbus/qcanbusframe.h b/src/serialbus/qcanbusframe.h
index 69bde41..224c0b8 100644
--- a/src/serialbus/qcanbusframe.h
+++ b/src/serialbus/qcanbusframe.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCANBUSFRAME_H
#define QCANBUSFRAME_H
@@ -48,16 +15,18 @@ class QDataStream;
class Q_SERIALBUS_EXPORT QCanBusFrame
{
public:
+ using FrameId = quint32;
+
class TimeStamp {
public:
- Q_DECL_CONSTEXPR TimeStamp(qint64 s = 0, qint64 usec = 0) Q_DECL_NOTHROW
+ constexpr TimeStamp(qint64 s = 0, qint64 usec = 0) noexcept
: secs(s), usecs(usec) {}
- Q_DECL_CONSTEXPR static TimeStamp fromMicroSeconds(qint64 usec) Q_DECL_NOTHROW
+ constexpr static TimeStamp fromMicroSeconds(qint64 usec) noexcept
{ return TimeStamp(usec / 1000000, usec % 1000000); }
- Q_DECL_CONSTEXPR qint64 seconds() const Q_DECL_NOTHROW { return secs; }
- Q_DECL_CONSTEXPR qint64 microSeconds() const Q_DECL_NOTHROW { return usecs; }
+ constexpr qint64 seconds() const noexcept { return secs; }
+ constexpr qint64 microSeconds() const noexcept { return usecs; }
private:
qint64 secs;
@@ -72,7 +41,7 @@ public:
InvalidFrame = 0x4
};
- explicit QCanBusFrame(FrameType type = DataFrame) Q_DECL_NOTHROW :
+ explicit QCanBusFrame(FrameType type = DataFrame) noexcept :
isExtendedFrame(0x0),
version(Qt_5_10),
isFlexibleDataRate(0x0),
@@ -105,11 +74,11 @@ public:
Q_DECLARE_FLAGS(FrameErrors, FrameError)
Q_FLAGS(FrameErrors)
- explicit QCanBusFrame(quint32 identifier, const QByteArray &data) :
+ explicit QCanBusFrame(QCanBusFrame::FrameId identifier, const QByteArray &data) :
format(DataFrame),
isExtendedFrame(0x0),
version(Qt_5_10),
- isFlexibleDataRate(data.length() > 8 ? 0x1 : 0x0),
+ isFlexibleDataRate(data.size() > 8 ? 0x1 : 0x0),
isBitrateSwitch(0x0),
isErrorStateIndicator(0x0),
isLocalEcho(0x0),
@@ -120,7 +89,7 @@ public:
setFrameId(identifier);
}
- bool isValid() const Q_DECL_NOTHROW
+ bool isValid() const noexcept
{
if (format == InvalidFrame)
return false;
@@ -133,7 +102,7 @@ public:
return false;
// maximum permitted payload size in CAN or CAN FD
- const int length = load.length();
+ const qsizetype length = load.size();
if (isFlexibleDataRate) {
if (format == RemoteRequestFrame)
return false;
@@ -145,7 +114,7 @@ public:
return length <= 8;
}
- FrameType frameType() const Q_DECL_NOTHROW
+ constexpr FrameType frameType() const noexcept
{
switch (format) {
case 0x1: return DataFrame;
@@ -158,7 +127,7 @@ public:
return UnknownFrame;
}
- void setFrameType(FrameType newFormat) Q_DECL_NOTHROW
+ constexpr void setFrameType(FrameType newFormat) noexcept
{
switch (newFormat) {
case DataFrame:
@@ -174,19 +143,19 @@ public:
}
}
- bool hasExtendedFrameFormat() const Q_DECL_NOTHROW { return (isExtendedFrame & 0x1); }
- void setExtendedFrameFormat(bool isExtended) Q_DECL_NOTHROW
+ constexpr bool hasExtendedFrameFormat() const noexcept { return (isExtendedFrame & 0x1); }
+ constexpr void setExtendedFrameFormat(bool isExtended) noexcept
{
isExtendedFrame = (isExtended & 0x1);
}
- quint32 frameId() const Q_DECL_NOTHROW
+ constexpr QCanBusFrame::FrameId frameId() const noexcept
{
if (Q_UNLIKELY(format == ErrorFrame))
return 0;
return (canId & 0x1FFFFFFFU);
}
- void setFrameId(quint32 newFrameId)
+ constexpr void setFrameId(QCanBusFrame::FrameId newFrameId)
{
if (Q_LIKELY(newFrameId < 0x20000000U)) {
isValidFrameId = true;
@@ -201,32 +170,32 @@ public:
void setPayload(const QByteArray &data)
{
load = data;
- if (data.length() > 8)
+ if (data.size() > 8)
isFlexibleDataRate = 0x1;
}
- void setTimeStamp(TimeStamp ts) Q_DECL_NOTHROW { stamp = ts; }
+ constexpr void setTimeStamp(TimeStamp ts) noexcept { stamp = ts; }
QByteArray payload() const { return load; }
- TimeStamp timeStamp() const Q_DECL_NOTHROW { return stamp; }
+ constexpr TimeStamp timeStamp() const noexcept { return stamp; }
- FrameErrors error() const Q_DECL_NOTHROW
+ constexpr FrameErrors error() const noexcept
{
if (format != ErrorFrame)
return NoError;
return FrameErrors(canId & 0x1FFFFFFFU);
}
- void setError(FrameErrors e)
+ constexpr void setError(FrameErrors e)
{
if (format != ErrorFrame)
return;
- canId = (e & AnyError);
+ canId = (e & AnyError).toInt();
}
QString toString() const;
- bool hasFlexibleDataRateFormat() const Q_DECL_NOTHROW { return (isFlexibleDataRate & 0x1); }
- void setFlexibleDataRateFormat(bool isFlexibleData) Q_DECL_NOTHROW
+ constexpr bool hasFlexibleDataRateFormat() const noexcept { return (isFlexibleDataRate & 0x1); }
+ constexpr void setFlexibleDataRateFormat(bool isFlexibleData) noexcept
{
isFlexibleDataRate = (isFlexibleData & 0x1);
if (!isFlexibleData) {
@@ -235,23 +204,23 @@ public:
}
}
- bool hasBitrateSwitch() const Q_DECL_NOTHROW { return (isBitrateSwitch & 0x1); }
- void setBitrateSwitch(bool bitrateSwitch) Q_DECL_NOTHROW
+ constexpr bool hasBitrateSwitch() const noexcept { return (isBitrateSwitch & 0x1); }
+ constexpr void setBitrateSwitch(bool bitrateSwitch) noexcept
{
isBitrateSwitch = (bitrateSwitch & 0x1);
if (bitrateSwitch)
isFlexibleDataRate = 0x1;
}
- bool hasErrorStateIndicator() const Q_DECL_NOTHROW { return (isErrorStateIndicator & 0x1); }
- void setErrorStateIndicator(bool errorStateIndicator) Q_DECL_NOTHROW
+ constexpr bool hasErrorStateIndicator() const noexcept { return (isErrorStateIndicator & 0x1); }
+ constexpr void setErrorStateIndicator(bool errorStateIndicator) noexcept
{
isErrorStateIndicator = (errorStateIndicator & 0x1);
if (errorStateIndicator)
isFlexibleDataRate = 0x1;
}
- bool hasLocalEcho() const Q_DECL_NOTHROW { return (isLocalEcho & 0x1); }
- void setLocalEcho(bool localEcho) Q_DECL_NOTHROW
+ constexpr bool hasLocalEcho() const noexcept { return (isLocalEcho & 0x1); }
+ constexpr void setLocalEcho(bool localEcho) noexcept
{
isLocalEcho = (localEcho & 0x1);
}
@@ -288,7 +257,7 @@ private:
TimeStamp stamp;
};
-Q_DECLARE_TYPEINFO(QCanBusFrame, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QCanBusFrame, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(QCanBusFrame::FrameError, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QCanBusFrame::FrameType, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QCanBusFrame::TimeStamp, Q_PRIMITIVE_TYPE);
diff --git a/src/serialbus/qcancommondefinitions.cpp b/src/serialbus/qcancommondefinitions.cpp
new file mode 100644
index 0000000..ccd96da
--- /dev/null
+++ b/src/serialbus/qcancommondefinitions.cpp
@@ -0,0 +1,134 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qcancommondefinitions.h"
+
+#ifndef QT_NO_DEBUG_STREAM
+#include <QtCore/QDebug>
+#endif // QT_NO_DEBUG_STREAM
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \namespace QtCanBus
+ \inmodule QtSerialBus
+ \since 6.5
+ \brief The QtCanBus namespace provides some commons enums that are used in
+ the CAN bus handling part of the QtSerialPort module.
+*/
+
+/*!
+ \enum QtCanBus::DataSource
+
+ This enum represents the placement of the data within the CAN frame.
+
+ \value Payload The data will be extracted from the payload.
+ \value FrameId The data will be extracted from the frame ID.
+*/
+
+/*!
+ \enum QtCanBus::DataFormat
+
+ This enum represents the possible data formats. The format defines how the
+ value will be extracted from its source.
+
+ \value SignedInteger The signal value is a signed integer.
+ \value UnsignedInteger The signal value is an unsigned integer.
+ \value Float The signal value is float.
+ \value Double The signal value is double.
+ \value AsciiString The signal value is an ASCII string.
+*/
+
+/*!
+ \enum QtCanBus::MultiplexState
+
+ This enum represents the possible multiplex states of a signal.
+
+ \value None The signal is not used in multiplexing.
+ \value MultiplexorSwitch The signal is used as a multiplexor switch, which
+ means that other signals depend on the values of
+ this signal.
+ \value MultiplexedSignal The signal is multiplexed by some switch, and
+ therefore its value can only be extracted when the
+ switch has a specific value.
+ \value SwitchAndSignal The multiplexor switch of the signal must have the
+ value that enables us to use this signal. When used,
+ the signal also acts as a multiplexor switch for
+ other multiplexed signals.
+*/
+
+/*!
+ \enum QtCanBus::UniqueId
+
+ Represents a CAN unique identifier. The underlying type is quint32.
+
+ An enum is used to avoid implicit conversions to or from unsigned int.
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug QtCanBus::operator<<(QDebug dbg, DataSource source)
+{
+ QDebugStateSaver saver(dbg);
+ switch (source) {
+ case DataSource::Payload:
+ dbg << "Payload";
+ break;
+ case DataSource::FrameId:
+ dbg << "FrameId";
+ break;
+ }
+ return dbg;
+}
+
+QDebug QtCanBus::operator<<(QDebug dbg, DataFormat format)
+{
+ QDebugStateSaver saver(dbg);
+ switch (format) {
+ case DataFormat::UnsignedInteger:
+ dbg << "UnsignedInteger";
+ break;
+ case DataFormat::SignedInteger:
+ dbg << "SignedInteger";
+ break;
+ case DataFormat::Float:
+ dbg << "Float";
+ break;
+ case DataFormat::Double:
+ dbg << "Double";
+ break;
+ case DataFormat::AsciiString:
+ dbg << "ASCII";
+ break;
+ }
+ return dbg;
+}
+
+QDebug QtCanBus::operator<<(QDebug dbg, MultiplexState state)
+{
+ QDebugStateSaver saver(dbg);
+ switch (state) {
+ case MultiplexState::None:
+ dbg << "None";
+ break;
+ case MultiplexState::MultiplexorSwitch:
+ dbg << "MultiplexorSwitch";
+ break;
+ case MultiplexState::MultiplexedSignal:
+ dbg << "MultiplexedSignal";
+ break;
+ case MultiplexState::SwitchAndSignal:
+ dbg << "SwitchAndSignal";
+ break;
+ }
+ return dbg;
+}
+
+QDebug QtCanBus::operator<<(QDebug dbg, UniqueId uid)
+{
+ dbg << qToUnderlying(uid);
+ return dbg;
+}
+#endif // QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
diff --git a/src/serialbus/qcancommondefinitions.h b/src/serialbus/qcancommondefinitions.h
new file mode 100644
index 0000000..4956d95
--- /dev/null
+++ b/src/serialbus/qcancommondefinitions.h
@@ -0,0 +1,63 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANCOMMONDEFINITIONS_H
+#define QCANCOMMONDEFINITIONS_H
+
+#include <QtCore/qendian.h>
+#include <QtCore/qsysinfo.h>
+#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtypes.h>
+
+#include <QtSerialBus/qtserialbusglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtCanBus {
+
+enum class DataSource : quint8 {
+ Payload = 0,
+ FrameId,
+};
+
+enum class DataFormat : quint8 {
+ SignedInteger = 0,
+ UnsignedInteger,
+ Float,
+ Double,
+ AsciiString,
+};
+
+enum class MultiplexState : quint8 {
+ None = 0x00,
+ MultiplexorSwitch = 0x01,
+ MultiplexedSignal = 0x02,
+ SwitchAndSignal = MultiplexorSwitch | MultiplexedSignal,
+};
+
+enum class UniqueId : quint32 {};
+
+inline UniqueId qbswap(UniqueId src) noexcept
+{
+ return UniqueId{qbswap_helper(qToUnderlying(src))};
+}
+
+} // namespace QtCanBus
+
+
+#ifndef QT_NO_DEBUG_STREAM
+
+class QDebug;
+
+namespace QtCanBus {
+Q_SERIALBUS_EXPORT QDebug operator<<(QDebug dbg, DataSource source);
+Q_SERIALBUS_EXPORT QDebug operator<<(QDebug dbg, DataFormat format);
+Q_SERIALBUS_EXPORT QDebug operator<<(QDebug dbg, MultiplexState state);
+Q_SERIALBUS_EXPORT QDebug operator<<(QDebug dbg, UniqueId uid);
+} // namespace QtCanBus
+
+#endif // QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
+
+#endif // QCANCOMMONDEFINITIONS_H
diff --git a/src/serialbus/qcandbcfileparser.cpp b/src/serialbus/qcandbcfileparser.cpp
new file mode 100644
index 0000000..363f0b2
--- /dev/null
+++ b/src/serialbus/qcandbcfileparser.cpp
@@ -0,0 +1,1161 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qcandbcfileparser.h"
+#include "qcandbcfileparser_p.h"
+#include "qcanmessagedescription.h"
+#include "qcansignaldescription.h"
+#include "qcanuniqueiddescription.h"
+#include "private/qcanmessagedescription_p.h"
+#include "private/qcansignaldescription_p.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QRegularExpression>
+
+#include <optional>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCanDbcFileParser
+ \inmodule QtSerialBus
+ \since 6.5
+ \preliminary
+
+ \brief The QCanDbcFileParser class can be used to parse DBC files.
+
+ A CAN database or CAN DBC file is an ASCII text file that contains
+ information on how to decode and interpret raw CAN bus data. Some more
+ details about the format can be found \l {CSSElectronics DBC Intro}{here}
+ or \l {OpenVehicles DBC Intro}{here}.
+
+ The QCanDbcFileParser class takes the input DBC file, parses it, and
+ provides a list of \l {QCanMessageDescription}s as an output. These message
+ descriptions can be forwarded to \l QCanFrameProcessor, and later used
+ as rules to encode or decode \l {QCanBusFrame}s.
+
+ Use one of \l parse() overloads to specify a file or a list of files that
+ will be processed. Both overloads return \c true if the parsing completes
+ successfully and \c false otherwise.
+
+ Call the \l error() method to get the error which occurred during the
+ parsing. If the parsing completes successfully, this method will return
+ \l {QCanDbcFileParser::}{None}. Otherwise, you can use an
+ \l errorString() method to get the string representation of an error.
+
+ During the parsing some non-critical problems may occur as well. Such
+ problems will be logged, but the parsing process will not be aborted. You
+ can use the \l warnings() method to get the full list of such problems
+ after the parsing is completed.
+
+ If the parsing completes successfully, call \l messageDescriptions() to get
+ a list of the message descriptions that were extracted during the last
+ \l parse() call. Call \l messageValueDescriptions() to get the textual
+ descriptions of signal raw values, if they are available.
+
+ Use the static \l uniqueIdDescription() function to get a
+ \l QCanUniqueIdDescription for the DBC format.
+
+ \code
+ QCanDbcFileParser fileParser;
+ const bool result = fileParser.parse(u"path/to/file.dbc"_s);
+ // Check result, call error() and warnings() if needed
+
+ // Prepare a QCanFrameProcessor to decode or encode DBC frames
+ QCanFrameProcessor frameProcessor;
+ frameProcessor.setUniqueIdDescription(QCanDbcFileParser::uniqueIdDescription());
+ frameProcessor.setMessageDescriptions(fileParser.messageDescriptions());
+ \endcode
+
+ \note The parser is stateful, which means that all the results (like
+ extracted message descriptions, error code, or warnings) are reset once the
+ next parsing starts.
+
+ \section2 Supported Keywords
+
+ The current implementation supports only a subset of keywords that you can
+ find in a DBC file:
+
+ \list
+ \li \c {BO_} - message description.
+ \li \c {SG_} - signal description.
+ \li \c {SIG_VALTYPE_} - signal type description.
+ \li \c {SG_MUL_VAL_} - extended multiplexing description.
+ \li \c {CM_} - comments (only for message and signal descriptions).
+ \li \c {VAL_} - textual descriptions for raw signal values.
+ \endlist
+
+ Lines starting from other keywords are simply ignored.
+
+ \sa QCanMessageDescription, QCanFrameProcessor
+*/
+
+/*!
+ \typealias QCanDbcFileParser::ValueDescriptions
+
+ This is a type alias for \c {QHash<quint32, QString>}.
+
+ The keys of the hash represent raw signal values, and the values of the
+ hash represent corresponding string descriptions.
+*/
+
+/*!
+ \typealias QCanDbcFileParser::SignalValueDescriptions
+
+ This is a type alias for \c {QHash<QString, ValueDescriptions>}.
+
+ The keys of the hash represent signal names, and the values of the
+ hash contain the corresponding \l QCanDbcFileParser::ValueDescriptions
+ entries.
+
+ \sa QCanDbcFileParser::ValueDescriptions
+*/
+
+/*!
+ \typealias QCanDbcFileParser::MessageValueDescriptions
+
+ This is a type alias for
+ \c {QHash<QtCanBus::UniqueId, SignalValueDescriptions>}.
+
+ The keys of the hash represent message unique ids, and the values of the
+ hash contain the corresponding \l QCanDbcFileParser::SignalValueDescriptions
+ entries.
+
+ \sa QCanDbcFileParser::SignalValueDescriptions
+*/
+
+/*!
+ \enum QCanDbcFileParser::Error
+
+ This enum represents the possible errors that can happen during the parsing
+ of a DBC file.
+
+ \value None No error occurred.
+ \value FileReading An error occurred while opening or reading the file.
+ \value Parsing An error occurred while parsing the content of the file.
+*/
+
+/*!
+ Constructs a DBC file parser.
+*/
+QCanDbcFileParser::QCanDbcFileParser()
+ : d(std::make_unique<QCanDbcFileParserPrivate>())
+{
+}
+
+/*!
+ Destroys this DBC file parser.
+*/
+QCanDbcFileParser::~QCanDbcFileParser() = default;
+
+/*!
+ Parses the file \a fileName. Returns \c true if the parsing completed
+ successfully or \c false otherwise.
+
+ If the parsing completed successfully, call the \l messageDescriptions()
+ method to get the list of all extracted message descriptions.
+
+ If the parsing failed, call the \l error() and \l errorString() methods
+ to get the information about the error.
+
+ Call the \l warnings() method to get the list of warnings that were
+ logged during the parsing.
+
+ \note This method expects the file contents to be encoded in UTF-8. If the
+ file has a different encoding, decode it first, and use \l parseData()
+ to extract the DBC information.
+
+ \sa messageDescriptions(), error(), warnings(), parseData()
+*/
+bool QCanDbcFileParser::parse(const QString &fileName)
+{
+ d->reset();
+ return d->parseFile(fileName);
+}
+
+/*!
+ \overload
+
+ Parses a list of files \a fileNames. Returns \c true if the parsing
+ completed successfully or \c false otherwise.
+
+ If the parsing completed successfully, call the \l messageDescriptions()
+ method to get the list of all extracted message descriptions.
+
+ The parsing stops at the first error. Call the \l error() and
+ \l errorString() methods to get the information about the error.
+
+ Call the \l warnings() method to get the list of warnings that were
+ logged during the parsing.
+
+ \note This method expects the file contents to be encoded in UTF-8. If the
+ file has a different encoding, decode it first, and use \l parseData()
+ to extract the DBC information.
+
+ \sa messageDescriptions(), error(), warnings(), parseData()
+*/
+bool QCanDbcFileParser::parse(const QStringList &fileNames)
+{
+ d->reset();
+ for (const auto &fileName : fileNames) {
+ if (!d->parseFile(fileName))
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \since 6.7
+
+ Parses the input data \a data and returns \c true if the parsing completed
+ successfully or \c false otherwise.
+
+ If the parsing completed successfully, call the \l messageDescriptions()
+ method to get the list of all extracted message descriptions.
+
+ If the parsing failed, call the \l error() and \l errorString() methods
+ to get the information about the error.
+
+ Call the \l warnings() method to get the list of warnings that were
+ logged during the parsing.
+
+ The method expects that \a data is the content of a valid DBC file,
+ properly converted to QStringView.
+
+ Use this method when the input file has an encoding different from UTF-8.
+
+ \code
+ // Read the data from a DBC file with custom encoding
+ const QByteArray initialData = ...;
+ // Convert to UTF-16 using QStringDecoder or some other way
+ const QString decodedData = ...;
+ QCanDbcFileParser parser;
+ const bool result = parser.parseData(decodedData);
+ \endcode
+
+ \sa messageDescriptions(), error(), warnings(), parse()
+*/
+bool QCanDbcFileParser::parseData(QStringView data)
+{
+ d->reset();
+ return d->parseData(data);
+}
+
+/*!
+ Returns the list of message descriptions that were extracted during the
+ last \l parse() call.
+
+ \sa parse(), error()
+*/
+QList<QCanMessageDescription> QCanDbcFileParser::messageDescriptions() const
+{
+ return d->getMessages();
+}
+
+/*!
+ Returns the textual descriptions for signal raw values.
+
+ DBC supports the possibility to provide textual descriptions to signal raw
+ values. If such data exists in the parsed DBC file(s), it can be accessed
+ using this function.
+
+ The textual descriptions are unique for a certain signal within a specific
+ message, so the returned structure contains the information about the
+ message unique id and the signal name, as well as the actual value
+ descriptions.
+
+ \sa QCanDbcFileParser::MessageValueDescriptions,
+ QCanDbcFileParser::SignalValueDescriptions,
+ QCanDbcFileParser::ValueDescriptions
+*/
+QCanDbcFileParser::MessageValueDescriptions QCanDbcFileParser::messageValueDescriptions() const
+{
+ return d->m_valueDescriptions;
+}
+
+/*!
+ Returns the last error which occurred during the parsing.
+
+ \sa errorString(), parse()
+*/
+QCanDbcFileParser::Error QCanDbcFileParser::error() const
+{
+ return d->m_error;
+}
+
+/*!
+ Returns the text representation of the last error which occurred during the
+ parsing or an empty string if there was no error.
+
+ \sa error()
+*/
+QString QCanDbcFileParser::errorString() const
+{
+ return d->m_errorString;
+}
+
+/*!
+ Returns the list of non-critical problems which occurred during the parsing.
+
+ A typical problem can be a malformed message or signal description. In such
+ cases the malformed message or signal is skipped, but the rest of the file
+ can be processed as usual.
+
+ \sa error(), parse()
+*/
+QStringList QCanDbcFileParser::warnings() const
+{
+ return d->m_warnings;
+}
+
+/*!
+ Returns a unique identifier description. DBC protocol always uses the
+ Frame Id as an identifier, and therefore the unique identifier description
+ is always the same.
+
+ Use this method to get an instance of \l QCanUniqueIdDescription and pass
+ it to \l QCanFrameProcessor.
+
+ \sa QCanFrameProcessor::setUniqueIdDescription()
+*/
+QCanUniqueIdDescription QCanDbcFileParser::uniqueIdDescription()
+{
+ QCanUniqueIdDescription desc;
+ desc.setSource(QtCanBus::DataSource::FrameId);
+ desc.setEndian(QSysInfo::Endian::LittleEndian);
+ desc.setStartBit(0);
+ desc.setBitLength(29); // for both extended and normal frame id
+ return desc;
+}
+
+/* QCanDbcFileParserPrivate implementation */
+
+using namespace Qt::StringLiterals;
+
+// signal name with whitespaces is invalid in DBC, so we can safely use it
+// for internal purposes
+static const auto kQtDummySignal = u"Qt Dummy Signal"_s;
+
+static constexpr auto kMessageDef = "BO_ "_L1;
+static constexpr auto kSignalDef = "SG_ "_L1;
+static constexpr auto kSigValTypeDef = "SIG_VALTYPE_ "_L1;
+static constexpr auto kCommentDef = "CM_ "_L1;
+static constexpr auto kExtendedMuxDef = "SG_MUL_VAL_ "_L1;
+static constexpr auto kValDef = "VAL_ "_L1;
+
+static constexpr auto kUnsignedIntRegExp = "\\d+"_L1;
+static constexpr auto kDoubleRegExp = "[+-]?\\d+((.\\d*)?([eE][+-]?\\d+)?)?"_L1;
+static constexpr auto kDbcIdentRegExp = "[_[:alpha:]][_[:alnum:]]+"_L1;
+static constexpr auto kOneOrMoreSpaceRegExp = "[ ]+"_L1;
+static constexpr auto kMaybeSpaceRegExp = "[ ]*"_L1;
+static constexpr auto kMuxIndicatorRegExp = "M|m\\d+M?"_L1;
+static constexpr auto kByteOrderRegExp = "0|1"_L1;
+static constexpr auto kValueTypeRegExp = "\\+|\\-"_L1;
+// The pattern matches all printable characters, except double-quote (") and backslash (\).
+static constexpr auto kCharStrRegExp = "((?![\\\"\\\\])\\P{Cc})*"_L1;
+
+void QCanDbcFileParserPrivate::reset()
+{
+ m_fileName.clear();
+ m_error = QCanDbcFileParser::Error::None;
+ m_errorString.clear();
+ m_warnings.clear();
+ m_lineOffset = 0;
+ m_isProcessingMessage = false;
+ m_seenExtraData = false;
+ m_currentMessage = {};
+ m_messageDescriptions.clear();
+ m_valueDescriptions.clear();
+}
+
+/*!
+ \internal
+ Returns \c false only in case of hard error. Returns \c true even if some
+ warnings occurred during parsing.
+*/
+bool QCanDbcFileParserPrivate::parseFile(const QString &fileName)
+{
+ QFile f(fileName);
+ if (!f.open(QIODevice::ReadOnly)) {
+ m_error = QCanDbcFileParser::Error::FileReading;
+ m_errorString = f.errorString();
+ return false;
+ }
+ m_fileName = fileName;
+ m_seenExtraData = false;
+
+ while (!f.atEnd()) {
+ const QString str = QString::fromUtf8(f.readLine().trimmed());
+ if (!processLine({str.constData(), str.size()})) // also sets the error properly
+ return false;
+ }
+ addCurrentMessage(); // check if we need to add the message
+ // now when we parsed the whole file, we can verify the signal multiplexing
+ postProcessSignalMultiplexing();
+
+ return true;
+}
+
+struct ReadData
+{
+ qsizetype index;
+ QStringView result;
+};
+
+static ReadData readUntilNewline(QStringView in, qsizetype from)
+{
+ const qsizetype idx = in.indexOf('\n'_L1, from);
+
+ return (idx == -1) ? ReadData{idx, in.sliced(from).trimmed()}
+ : ReadData{idx, in.sliced(from, idx - from).trimmed()};
+}
+
+/*!
+ \internal
+ The implementation basically copies parseFile(), including all
+ post-processing. The only difference is in extracting the data.
+*/
+bool QCanDbcFileParserPrivate::parseData(QStringView data)
+{
+ if (data.isEmpty()) {
+ m_error = QCanDbcFileParser::Error::Parsing;
+ m_errorString = QObject::tr("Empty input data.");
+ return false;
+ }
+ m_seenExtraData = false;
+ qsizetype from = 0;
+ while (true) {
+ const auto [idx, sv] = readUntilNewline(data, from);
+ if (!processLine(sv))
+ return false;
+ if (idx == -1) // reached the end of the string
+ break;
+ from = idx + 1;
+ }
+ addCurrentMessage();
+ postProcessSignalMultiplexing();
+ return true;
+}
+
+/*!
+ \internal
+ Returns \c false only in case of hard error. Returns \c true even if some
+ warnings occurred during parsing.
+*/
+bool QCanDbcFileParserPrivate::processLine(const QStringView line)
+{
+ QStringView data = line;
+ m_lineOffset = 0;
+
+ auto handleParsingError = [this](QLatin1StringView section) {
+ m_error = QCanDbcFileParser::Error::Parsing;
+ m_errorString = !m_fileName.isEmpty()
+ ? QObject::tr("Failed to parse file %1. Unexpected position "
+ "of %2 section.").arg(m_fileName, section)
+ : QObject::tr("Failed to parse input data. Unexpected position "
+ "of %1 section.").arg(section);
+ };
+
+ if (data.startsWith(kMessageDef)) {
+ if (m_seenExtraData) {
+ // Unexpected position of message description
+ handleParsingError(kMessageDef);
+ return false;
+ }
+ addCurrentMessage();
+ if (!parseMessage(data))
+ return false;
+ }
+ // signal definitions can be on the same line as message definition,
+ // or on a separate line
+ data = data.sliced(m_lineOffset).trimmed();
+ while (data.startsWith(kSignalDef)) {
+ if (!m_isProcessingMessage || m_seenExtraData) {
+ // Unexpected position of signal description
+ handleParsingError(kSignalDef);
+ return false;
+ }
+ if (!parseSignal(data))
+ return false;
+ data = data.sliced(m_lineOffset).trimmed();
+ }
+ // If we detect one of the following lines, then message description is
+ // finished. We also assume that we can have only one key at each line.
+ if (data.startsWith(kSigValTypeDef)) {
+ m_seenExtraData = true;
+ addCurrentMessage();
+ parseSignalType(data);
+ } else if (data.startsWith(kCommentDef)) {
+ m_seenExtraData = true;
+ addCurrentMessage();
+ parseComment(data);
+ } else if (data.startsWith(kExtendedMuxDef)) {
+ m_seenExtraData = true;
+ addCurrentMessage();
+ parseExtendedMux(data);
+ } else if (data.startsWith(kValDef)) {
+ m_seenExtraData = true;
+ addCurrentMessage();
+ parseValueDescriptions(data);
+ }
+ return true;
+}
+
+static std::optional<QtCanBus::UniqueId> extractUniqueId(QStringView view)
+{
+ bool ok = false;
+ const uint value = view.toUInt(&ok);
+ if (ok)
+ return QtCanBus::UniqueId{value & 0x1FFFFFFF};
+ return std::nullopt;
+}
+
+/*!
+ \internal
+ Returns \c false only in case of hard error. Returns \c true even if some
+ warnings occurred during parsing.
+*/
+bool QCanDbcFileParserPrivate::parseMessage(const QStringView data)
+{
+ // The regexp matches the following definition:
+ // BO_ message_id message_name ':' message_size transmitter
+ // also considering the fact that spaces around ':' seem to be optional, and
+ // allowing more than one space between parts.
+
+ // %1 - messageDef
+ // %2 - maybeSpace
+ // %3 - unsignedInt
+ // %4 - oneOrMoreSpace
+ // %5 - DbcIdentifier
+ static const QString regExStr =
+ "%1%2(?<messageId>%3)%4(?<name>%5)%2:%2(?<size>%3)%4(?<transmitter>%5)"_L1.
+ arg(kMessageDef, kMaybeSpaceRegExp, kUnsignedIntRegExp, kOneOrMoreSpaceRegExp,
+ kDbcIdentRegExp);
+ static const QRegularExpression messageRegExp(regExStr);
+
+ m_isProcessingMessage = false;
+ const auto match = messageRegExp.matchView(data);
+ if (match.hasMatch()) {
+ m_currentMessage = extractMessage(match);
+ // can't check for isValid() here, because demands signal descriptions
+ if (!m_currentMessage.name().isEmpty()) {
+ m_isProcessingMessage = true;
+ } else {
+ addWarning(QObject::tr("Failed to parse message description from "
+ "string %1").arg(data));
+ }
+ m_lineOffset = match.capturedEnd(0);
+ } else {
+ addWarning(QObject::tr("Failed to find message description in string %1").arg(data));
+ m_lineOffset = data.size(); // skip this string
+ }
+ return true;
+}
+
+QCanMessageDescription
+QCanDbcFileParserPrivate::extractMessage(const QRegularExpressionMatch &match)
+{
+ Q_ASSERT(match.hasMatch());
+ QCanMessageDescription desc;
+ desc.setName(match.captured(u"name"_s));
+
+ const auto id = extractUniqueId(match.capturedView(u"messageId"_s));
+ if (id.has_value()) {
+ desc.setUniqueId(id.value());
+ } else {
+ addWarning(QObject::tr("Failed to parse frame id for message %1").arg(desc.name()));
+ return {};
+ }
+
+ bool ok = false;
+ const auto size = match.capturedView(u"size"_s).toUInt(&ok);
+ if (ok) {
+ desc.setSize(size);
+ } else {
+ addWarning(QObject::tr("Failed to parse size for message %1").arg(desc.name()));
+ return {};
+ }
+
+ desc.setTransmitter(match.captured(u"transmitter"_s));
+
+ return desc;
+}
+
+/*!
+ \internal
+ Returns \c false only in case of hard error. Returns \c true even if some
+ warnings occurred during parsing.
+*/
+bool QCanDbcFileParserPrivate::parseSignal(const QStringView data)
+{
+ // The regexp should match the following pattern:
+ // SG_ signal_name multiplexer_indicator : start_bit |
+ // signal_size @ byte_order value_type ( factor , offset )
+ // [ minimum | maximum ] unit receiver {, receiver}
+ // We also need to consider the fact that some of the spaces might be
+ // optional, and we can potentially allow more spaces between parts.
+ // Note that the end of the signal description can contain multiple
+ // receivers. The regexp is supposed to extract all of them, but we use
+ // only the first one for now.
+
+ // %1 - SignalDef
+ // %2 - MaybeSpace
+ // %3 - DbcIdentifier
+ // %4 - OneOrMoreSpace
+ // %5 - MuxIndicator
+ // %6 - unsignedInt
+ // %7 - byteOrder
+ // %8 - valueType
+ // %9 - double
+ // %10 - charStr
+ static const QString regExStr =
+ "%1%2(?<name>%3)(%4(?<mux>%5))?%2:%2(?<startBit>%6)%2\\|%2(?<sigSize>%6)%2@%2"
+ "(?<byteOrder>%7)%2(?<valueType>%8)%4\\(%2(?<factor>%9)%2,%2(?<offset>%9)%2\\)"
+ "%4\\[%2(?<min>%9)%2\\|%2(?<max>%9)%2\\]%4\"(?<unit>%10)\""
+ "%4(?<receiver>%3)(%2,%2%3)*"_L1.
+ arg(kSignalDef, kMaybeSpaceRegExp, kDbcIdentRegExp, kOneOrMoreSpaceRegExp,
+ kMuxIndicatorRegExp, kUnsignedIntRegExp, kByteOrderRegExp, kValueTypeRegExp,
+ kDoubleRegExp, kCharStrRegExp);
+ static const QRegularExpression signalRegExp(regExStr);
+
+ const auto match = signalRegExp.matchView(data);
+ if (match.hasMatch()) {
+ QCanSignalDescription desc = extractSignal(match);
+
+ if (desc.isValid())
+ m_currentMessage.addSignalDescription(desc);
+ else
+ addWarning(QObject::tr("Failed to parse signal description from string %1").arg(data));
+
+ m_lineOffset = match.capturedEnd(0);
+ } else {
+ addWarning(QObject::tr("Failed to find signal description in string %1").arg(data));
+ m_lineOffset = data.size(); // skip this string
+ }
+ return true;
+}
+
+QCanSignalDescription QCanDbcFileParserPrivate::extractSignal(const QRegularExpressionMatch &match)
+{
+ Q_ASSERT(match.hasMatch());
+ QCanSignalDescription desc;
+ desc.setName(match.captured(u"name"_s));
+
+ bool ok = false;
+
+ if (match.hasCaptured(u"mux"_s)) {
+ const auto muxStr = match.capturedView(u"mux"_s);
+ if (muxStr == u"M"_s) {
+ desc.setMultiplexState(QtCanBus::MultiplexState::MultiplexorSwitch);
+ } else if (muxStr.endsWith(u"M"_s, Qt::CaseSensitive)) {
+ desc.setMultiplexState(QtCanBus::MultiplexState::SwitchAndSignal);
+ const auto val = muxStr.sliced(1, muxStr.size() - 2).toUInt(&ok);
+ if (!ok) {
+ addWarning(QObject::tr("Failed to parse multiplexor value for signal %1").
+ arg(desc.name()));
+ return {};
+ }
+ // We have the value, but we do not really know the multiplexor
+ // switch name. To know it, we potentially need to parse all signals
+ // for the message. So for now we just create a dummy entry, and
+ // the actual signal name will be updated later;
+ desc.addMultiplexSignal(kQtDummySignal, val);
+ } else {
+ desc.setMultiplexState(QtCanBus::MultiplexState::MultiplexedSignal);
+ const auto val = muxStr.sliced(1).toUInt(&ok);
+ if (!ok) {
+ addWarning(QObject::tr("Failed to parse multiplexor value for signal %1").
+ arg(desc.name()));
+ return {};
+ }
+ // Same as above
+ desc.addMultiplexSignal(kQtDummySignal, val);
+ }
+ }
+
+ const uint startBit = match.capturedView(u"startBit"_s).toUInt(&ok);
+ if (ok) {
+ desc.setStartBit(startBit);
+ } else {
+ addWarning(QObject::tr("Failed to parse start bit for signal %1").arg(desc.name()));
+ return {};
+ }
+
+ const uint bitLength = match.capturedView(u"sigSize"_s).toUInt(&ok);
+ if (ok) {
+ desc.setBitLength(bitLength);
+ } else {
+ addWarning(QObject::tr("Failed to parse bit length for signal %1").arg(desc.name()));
+ return {};
+ }
+
+ // 0 = BE; 1 = LE
+ const auto endian = match.capturedView(u"byteOrder"_s) == u"0"_s
+ ? QSysInfo::Endian::BigEndian : QSysInfo::Endian::LittleEndian;
+ desc.setDataEndian(endian);
+
+ // + = unsigned; - = signed
+ const auto dataFormat = match.capturedView(u"valueType"_s) == u"+"_s
+ ? QtCanBus::DataFormat::UnsignedInteger : QtCanBus::DataFormat::SignedInteger;
+ desc.setDataFormat(dataFormat);
+
+ const double factor = match.capturedView(u"factor"_s).toDouble(&ok);
+ if (ok) {
+ desc.setFactor(factor);
+ } else {
+ addWarning(QObject::tr("Failed to parse factor for signal %1").arg(desc.name()));
+ return {};
+ }
+
+ const double offset = match.capturedView(u"offset"_s).toDouble(&ok);
+ if (ok) {
+ desc.setOffset(offset);
+ } else {
+ addWarning(QObject::tr("Failed to parse offset for signal %1").arg(desc.name()));
+ return {};
+ }
+
+ const double min = match.capturedView(u"min"_s).toDouble(&ok);
+ if (ok) {
+ const double max = match.capturedView(u"max"_s).toDouble(&ok);
+ if (ok)
+ desc.setRange(min, max);
+ }
+ if (!ok) {
+ addWarning(QObject::tr("Failed to parse value range from signal %1").arg(desc.name()));
+ return {};
+ }
+
+ desc.setPhysicalUnit(match.captured(u"unit"_s));
+ desc.setReceiver(match.captured(u"receiver"_s));
+
+ return desc;
+}
+
+void QCanDbcFileParserPrivate::parseSignalType(const QStringView data)
+{
+ // The regexp should match the following pattern:
+ // SIG_VALTYPE_ message_id signal_name signal_extended_value_type ;
+ // We also need to consider the fact that we can potentially allow more
+ // spaces between parts.
+
+ // %1 sigValTypeDef
+ // %2 maybeSpace
+ // %3 unsignedInt
+ // %4 oneOrMoreSpace
+ // %5 DbcIdentifier
+ const QString regExStr =
+ "%1%2(?<messageId>%3)%4(?<sigName>%5)%2:%2(?<type>%3)%2;"_L1.
+ arg(kSigValTypeDef, kMaybeSpaceRegExp, kUnsignedIntRegExp,
+ kOneOrMoreSpaceRegExp, kDbcIdentRegExp);
+ const QRegularExpression sigValTypeRegEx(regExStr);
+
+ const auto match = sigValTypeRegEx.matchView(data);
+ if (!match.hasMatch()) {
+ m_lineOffset = data.size();
+ addWarning(QObject::tr("Failed to find signal value type description in string %1").
+ arg(data));
+ return;
+ }
+
+ m_lineOffset = match.capturedEnd(0);
+
+ const auto uidOptional = extractUniqueId(match.capturedView(u"messageId"_s));
+ if (!uidOptional) {
+ addWarning(QObject::tr("Failed to parse frame id from string %1").arg(data));
+ return;
+ }
+
+ const QtCanBus::UniqueId uid = uidOptional.value();
+ auto msgDesc = m_messageDescriptions.value(uid);
+ if (msgDesc.isValid()) {
+ const QString sigName = match.captured(u"sigName"_s);
+ auto sigDesc = msgDesc.signalDescriptionForName(sigName);
+ if (sigDesc.isValid()) {
+ bool ok = false;
+ const auto type = match.capturedView(u"type").toUInt(&ok);
+ if (ok) {
+ bool sigDescChanged = false;
+ switch (type) {
+ case 0: /* signed or unsigned integer */
+ // do nothing, as we already have signed/unsinged integer
+ // based on "SG_ " string
+ break;
+ case 1: /* 32-bit IEEE-float */
+ sigDesc.setDataFormat(QtCanBus::DataFormat::Float);
+ sigDesc.setBitLength(32);
+ sigDescChanged = true;
+ break;
+ case 2: /* 64-bit IEEE-double */
+ sigDesc.setDataFormat(QtCanBus::DataFormat::Double);
+ sigDesc.setBitLength(64);
+ sigDescChanged = true;
+ break;
+ default:
+ // invalid value
+ break;
+ }
+ if (sigDescChanged) {
+ msgDesc.addSignalDescription(sigDesc);
+ m_messageDescriptions.insert(msgDesc.uniqueId(), msgDesc);
+ }
+ } else {
+ addWarning(QObject::tr("Failed to parse data type from string %1").arg(data));
+ }
+ } else {
+ addWarning(QObject::tr("Failed to find signal description for signal %1. "
+ "Skipping string %2").arg(sigName, data));
+ }
+ } else {
+ addWarning(QObject::tr("Failed to find message description for unique id %1. "
+ "Skipping string %2").arg(qToUnderlying(uid)).arg(data));
+ }
+}
+
+void QCanDbcFileParserPrivate::parseComment(const QStringView data)
+{
+ // The comment for message or signal description is represented by the
+ // following pattern:
+ // CM_ (BO_ message_id char_string | SG_ message_id signal_name char_string);
+
+ // %1 commentDef
+ // %2 maybeSpace
+ // %3 messageDef
+ // %4 signalDef
+ // %5 oneOrMoreSpace
+ // %6 unsignedInt
+ // %7 DbcIdentifier
+ // %8 charStr
+ const QString regExStr =
+ "%1%2(?<type>(%3|%4))%2(?<messageId>%6)%5((?<sigName>%7)%5)?\"(?<comment>%8)\"%2;"_L1.
+ arg(kCommentDef, kMaybeSpaceRegExp, kMessageDef, kSignalDef, kOneOrMoreSpaceRegExp,
+ kUnsignedIntRegExp, kDbcIdentRegExp, kCharStrRegExp);
+ const QRegularExpression commentRegExp(regExStr);
+
+ const auto match = commentRegExp.matchView(data);
+ if (!match.hasMatch()) {
+ // no warning here, as we ignore some "general" comments, and parse only
+ // comments related to messages and signals
+ m_lineOffset = data.size();
+ return;
+ }
+
+ m_lineOffset = match.capturedEnd(0);
+
+ const auto type = match.capturedView(u"type"_s);
+
+ const auto uidOptional = extractUniqueId(match.capturedView(u"messageId"_s));
+ if (!uidOptional) {
+ addWarning(QObject::tr("Failed to parse frame id from string %1").arg(data));
+ return;
+ }
+
+ const QtCanBus::UniqueId uid = uidOptional.value();
+ auto messageDesc = m_messageDescriptions.value(uid);
+ if (!messageDesc.isValid()) {
+ addWarning(QObject::tr("Failed to find message description for unique id %1. "
+ "Skipping string %2").arg(qToUnderlying(uid)).arg(data));
+ return;
+ }
+
+ if (type == kMessageDef) {
+ const QString comment = match.captured(u"comment"_s);
+ messageDesc.setComment(comment);
+ m_messageDescriptions.insert(uid, messageDesc);
+ } else if (type == kSignalDef) {
+ const QString sigName = match.captured(u"sigName"_s);
+ auto signalDesc = messageDesc.signalDescriptionForName(sigName);
+ if (signalDesc.isValid()) {
+ const QString comment = match.captured(u"comment"_s);
+ signalDesc.setComment(comment);
+ messageDesc.addSignalDescription(signalDesc);
+ m_messageDescriptions.insert(uid, messageDesc);
+ } else {
+ addWarning(QObject::tr("Failed to find signal description for signal %1. "
+ "Skipping string %2").arg(sigName, data));
+ }
+ }
+}
+
+void QCanDbcFileParserPrivate::parseExtendedMux(const QStringView data)
+{
+ // The extended multiplexing is defined by the following pattern:
+ // SG_MUL_VAL_ message_id multiplexed_signal_name
+ // multiplexor_switch_name multiplexor_value_ranges ;
+ // Here multiplexor_value_ranges consists of multiple ranges, separated
+ // by a whitespace, and one range is defined as follows:
+ // multiplexor_value_range = unsigned_integer - unsigned_integer
+
+ // %1 extendedMuxDef
+ // %2 maybeSpace
+ // %3 unsignedInt
+ // %4 oneOrMoreSpace
+ // %5 DbcIdentifier
+ const QString regExStr =
+ "%1%2(?<messageId>%3)%4(?<multiplexedSignal>%5)%4(?<multiplexorSwitch>%5)%4"
+ "(?<firstRange>%3%2-%2%3)(%2,%2%3%2-%2%3)*%2;"_L1.
+ arg(kExtendedMuxDef, kMaybeSpaceRegExp, kUnsignedIntRegExp, kOneOrMoreSpaceRegExp,
+ kDbcIdentRegExp);
+ const QRegularExpression extendedMuxRegExp(regExStr);
+
+ const auto match = extendedMuxRegExp.matchView(data);
+ if (!match.hasMatch()) {
+ m_lineOffset = data.size();
+ addWarning(QObject::tr("Failed to find extended multiplexing description in string %1").
+ arg(data));
+ return;
+ }
+
+ m_lineOffset = match.capturedEnd(0);
+
+ const auto uidOptional = extractUniqueId(match.capturedView(u"messageId"_s));
+ if (!uidOptional) {
+ addWarning(QObject::tr("Failed to parse frame id from string %1").arg(data));
+ return;
+ }
+
+ const QtCanBus::UniqueId uid = uidOptional.value();
+ auto messageDesc = m_messageDescriptions.value(uid);
+ if (!messageDesc.isValid()) {
+ addWarning(QObject::tr("Failed to find message description for unique id %1. "
+ "Skipping string %2").arg(qToUnderlying(uid)).arg(data));
+ return;
+ }
+
+ const QString multiplexedSignalName = match.captured(u"multiplexedSignal"_s);
+ const QString multiplexorSwitchName = match.captured(u"multiplexorSwitch"_s);
+
+ auto multiplexedSignal = messageDesc.signalDescriptionForName(multiplexedSignalName);
+ auto multiplexorSwitch = messageDesc.signalDescriptionForName(multiplexorSwitchName);
+
+ if (!multiplexedSignal.isValid() || !multiplexorSwitch.isValid()) {
+ const QString invalidName = multiplexedSignal.isValid() ? multiplexorSwitchName
+ : multiplexedSignalName;
+ addWarning(QObject::tr("Failed to find signal description for signal %1. "
+ "Skipping string %2").arg(invalidName, data));
+ return;
+ }
+
+ auto signalRanges = multiplexedSignal.multiplexSignals();
+ signalRanges.remove(kQtDummySignal); // dummy signal not needed anymore
+
+ QCanSignalDescription::MultiplexValues rangeValues;
+ auto rangeView = match.capturedView(u"firstRange"_s);
+ const auto sepIdx = rangeView.indexOf(u'-');
+ if (sepIdx != -1) {
+ const auto min = rangeView.first(sepIdx).trimmed().toUInt();
+ const auto max = rangeView.sliced(sepIdx + 1).trimmed().toUInt();
+ rangeValues.push_back({min, max});
+ }
+
+ // We can have an arbitrary amount of ranges, so we can't use capture groups
+ // to capture them. But we know that they follow a specific pattern (because
+ // the full string matched the regexp). So we need to parse the rest of the
+ // matched string manually
+ const auto totalEnd = match.capturedEnd(0); // including the ';'
+ const auto firstRangeEnd = match.capturedEnd(u"firstRange"_s);
+ const auto len = totalEnd - firstRangeEnd - 1;
+ if (len > 0) {
+ const auto otherRangesView = data.sliced(firstRangeEnd, len).trimmed();
+ const QStringTokenizer parts = otherRangesView.tokenize(u',', Qt::SkipEmptyParts);
+ for (const QStringView range : parts) {
+ const auto sepIdx = range.indexOf(u'-');
+ if (sepIdx != -1) {
+ const auto min = range.first(sepIdx).trimmed().toUInt();
+ const auto max = range.sliced(sepIdx + 1).trimmed().toUInt();
+ rangeValues.push_back({min, max});
+ }
+ }
+ }
+
+ if (!rangeValues.isEmpty())
+ signalRanges.insert(multiplexorSwitchName, rangeValues);
+ else
+ signalRanges.remove(multiplexorSwitchName);
+
+ // update the value
+ multiplexedSignal.setMultiplexSignals(signalRanges);
+ messageDesc.addSignalDescription(multiplexedSignal);
+ m_messageDescriptions.insert(uid, messageDesc);
+}
+
+void QCanDbcFileParserPrivate::parseValueDescriptions(const QStringView data)
+{
+ // The regexp should match the following pattern:
+ // VAL_ message_id signal_name { value_description };
+ // Here the value_description is defined as follows
+ // value_description = unsigned_int char_string
+
+ // %1 valDef
+ // %2 maybeSpace
+ // %3 unsignedInt
+ // %4 oneOrMoreSpace
+ // %5 DbcIdentifier
+ // %6 charStr
+ const QString regExStr =
+ "%1%2(?<messageId>%3)%4(?<signalName>%5)(%4%3%4\"(%6)\")+%2;"_L1.
+ arg(kValDef, kMaybeSpaceRegExp, kUnsignedIntRegExp, kOneOrMoreSpaceRegExp,
+ kDbcIdentRegExp, kCharStrRegExp);
+
+ const QRegularExpression valueDescRegExp(regExStr);
+
+ const auto match = valueDescRegExp.matchView(data);
+ if (!match.hasMatch()) {
+ m_lineOffset = data.size();
+ addWarning(QObject::tr("Failed to parse value description from string %1").arg(data));
+ return;
+ }
+
+ m_lineOffset = match.capturedEnd(0);
+
+ const auto uidOptional = extractUniqueId(match.capturedView(u"messageId"_s));
+ if (!uidOptional) {
+ addWarning(QObject::tr("Failed to parse value description from string %1").arg(data));
+ return;
+ }
+
+ const QtCanBus::UniqueId uid = uidOptional.value();
+ // Check if the message exists
+ const auto messageDesc = m_messageDescriptions.value(uid);
+ if (!messageDesc.isValid()) {
+ addWarning(QObject::tr("Failed to find message description for unique id %1. "
+ "Skipping string %2").arg(qToUnderlying(uid)).arg(data));
+ return;
+ }
+
+ // Check if the signal exists within the message
+ const QString signalName = match.captured(u"signalName"_s);
+ if (!messageDesc.signalDescriptionForName(signalName).isValid()) {
+ addWarning(QObject::tr("Failed to find signal description for signal %1. "
+ "Skipping string %2").arg(signalName, data));
+ return;
+ }
+
+ // We can have an arbitrary amount of value descriptions, so we can't use
+ // capture groups to capture them. But we know that they follow a specific
+ // pattern (because the full string matched the regexp). So we need to parse
+ // the rest of the matched string manually
+ const auto totalEnd = match.capturedEnd(0); // including the ';'
+ const auto signalNameEnd = match.capturedEnd(u"signalName"_s);
+ const auto len = totalEnd - signalNameEnd - 1;
+ if (len > 0) {
+ auto signalDescriptionsView = data.sliced(signalNameEnd, len).trimmed();
+ while (signalDescriptionsView.size()) {
+ const auto spacePos = signalDescriptionsView.indexOf(u' ');
+ if (spacePos == -1)
+ break;
+ bool ok = false;
+ const auto value = signalDescriptionsView.sliced(0, spacePos).toUInt(&ok);
+ if (!ok)
+ break;
+ const auto firstQuotePos = signalDescriptionsView.indexOf(u'"', spacePos + 1);
+ if (firstQuotePos == -1)
+ break;
+ const auto nextQuotePos = signalDescriptionsView.indexOf(u'"', firstQuotePos + 1);
+ if (nextQuotePos == -1)
+ break;
+ const auto description = signalDescriptionsView.sliced(
+ firstQuotePos + 1, nextQuotePos - firstQuotePos - 1);
+
+ m_valueDescriptions[uid][signalName].insert(value, description.toString());
+ signalDescriptionsView = signalDescriptionsView.sliced(nextQuotePos + 1).trimmed();
+ }
+ }
+}
+
+void QCanDbcFileParserPrivate::postProcessSignalMultiplexing()
+{
+ // For the case of simple multiplexing we need to do the following for
+ // every message description:
+ // 1. Find the multiplexor signal
+ // 2. Replace all kQtDummySignal entries with the name of the multiplexor
+ // 3. While doing so, check if we have any signals with type
+ // SwitchAndSignal. This will mean that extended multiplexing is used
+ // 4. Also detect conditions when we have more than one multiplexor signal.
+ // This is an error as well, and message description should be discarded.
+
+ QList<QtCanBus::UniqueId> uidsToRemove;
+
+ for (auto &messageDesc : m_messageDescriptions) {
+ bool useExtendedMux = false;
+ QString multiplexorSignal;
+ auto &signalDescriptions = QCanMessageDescriptionPrivate::get(messageDesc)->messageSignals;
+ for (const auto &signalDesc : std::as_const(signalDescriptions)) {
+ if (signalDesc.multiplexState() == QtCanBus::MultiplexState::MultiplexorSwitch) {
+ if (multiplexorSignal.isEmpty()) {
+ multiplexorSignal = signalDesc.name();
+ } else {
+ // invalid config
+ multiplexorSignal.clear();
+ uidsToRemove.push_back(messageDesc.uniqueId());
+ break;
+ }
+ } else if (signalDesc.multiplexState() == QtCanBus::MultiplexState::SwitchAndSignal) {
+ // extended multiplexing
+ useExtendedMux = true;
+ }
+ }
+ if (!useExtendedMux && !multiplexorSignal.isEmpty()) {
+ // iterate through all signal descriptions and update kQtDummySignal
+ for (auto &signalDesc : signalDescriptions) {
+ if (signalDesc.multiplexState() == QtCanBus::MultiplexState::MultiplexedSignal) {
+ auto &muxValues = QCanSignalDescriptionPrivate::get(signalDesc)->muxSignals;
+ auto val = muxValues.value(kQtDummySignal);
+ muxValues.remove(kQtDummySignal);
+ muxValues.insert(multiplexorSignal, val);
+ }
+ }
+ } else if (useExtendedMux) {
+ // Iterate through all signal descriptions and check that we do
+ // not have any kQtDummySignal entries. It such entry exists, this
+ // means that there were errors while parsing extended multiplexing
+ // table, and this message description is invalid
+ for (const auto &signalDesc : std::as_const(signalDescriptions)) {
+ const auto muxSignals = signalDesc.multiplexSignals();
+ if (muxSignals.contains(kQtDummySignal)) {
+ uidsToRemove.push_back(messageDesc.uniqueId());
+ break;
+ }
+ }
+ }
+ }
+
+ for (const auto &uid : std::as_const(uidsToRemove)) {
+ m_messageDescriptions.remove(uid);
+ addWarning(QObject::tr("Message description with unique id %1 is skipped because "
+ "it has invalid multiplexing description.").
+ arg(qToUnderlying(uid)));
+ }
+}
+
+void QCanDbcFileParserPrivate::addWarning(QString &&warning)
+{
+ m_warnings.emplace_back(warning);
+}
+
+void QCanDbcFileParserPrivate::addCurrentMessage()
+{
+ if (m_isProcessingMessage) {
+ auto uid = m_currentMessage.uniqueId();
+ if (!m_currentMessage.isValid()) {
+ addWarning(QObject::tr("Message description with unique id %1 is skipped "
+ "because it's not valid.").arg(qToUnderlying(uid)));
+ } else if (m_messageDescriptions.contains(uid)) {
+ addWarning(QObject::tr("Message description with unique id %1 is skipped "
+ "because such unique id is already used.").
+ arg(qToUnderlying(uid)));
+ } else {
+ m_messageDescriptions.insert(uid, m_currentMessage);
+ }
+ m_currentMessage = {};
+ m_isProcessingMessage = false;
+ }
+}
+
+QList<QCanMessageDescription> QCanDbcFileParserPrivate::getMessages() const
+{
+ return QList<QCanMessageDescription>(m_messageDescriptions.cbegin(),
+ m_messageDescriptions.cend());
+}
+
+QT_END_NAMESPACE
diff --git a/src/serialbus/qcandbcfileparser.h b/src/serialbus/qcandbcfileparser.h
new file mode 100644
index 0000000..3db6761
--- /dev/null
+++ b/src/serialbus/qcandbcfileparser.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANDBCFILEPARSER_H
+#define QCANDBCFILEPARSER_H
+
+#include <QtCore/QList>
+
+#include <QtSerialBus/qcancommondefinitions.h>
+#include <QtSerialBus/qtserialbusglobal.h>
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+class QCanDbcFileParserPrivate;
+class QCanMessageDescription;
+class QCanUniqueIdDescription;
+
+class QCanDbcFileParser
+{
+public:
+ enum class Error : quint8 {
+ None = 0,
+ FileReading,
+ Parsing
+ };
+
+ // The DBC protocol uses unsigned_integer to describe the supported values.
+ // Do we need to use QVariant instead of quint32? Or qint64 for better BC
+ // guarantees?
+ using ValueDescriptions = QHash<quint32, QString>;
+ using SignalValueDescriptions = QHash<QString, ValueDescriptions>;
+ using MessageValueDescriptions = QHash<QtCanBus::UniqueId, SignalValueDescriptions>;
+
+ Q_SERIALBUS_EXPORT QCanDbcFileParser();
+ Q_SERIALBUS_EXPORT ~QCanDbcFileParser();
+
+ Q_SERIALBUS_EXPORT bool parse(const QString &fileName);
+ Q_SERIALBUS_EXPORT bool parse(const QStringList &fileNames);
+ Q_SERIALBUS_EXPORT bool parseData(QStringView data);
+
+ Q_SERIALBUS_EXPORT QList<QCanMessageDescription> messageDescriptions() const;
+ Q_SERIALBUS_EXPORT MessageValueDescriptions messageValueDescriptions() const;
+
+ Q_SERIALBUS_EXPORT Error error() const;
+ Q_SERIALBUS_EXPORT QString errorString() const;
+ Q_SERIALBUS_EXPORT QStringList warnings() const;
+
+ Q_SERIALBUS_EXPORT static QCanUniqueIdDescription uniqueIdDescription();
+
+private:
+ std::unique_ptr<QCanDbcFileParserPrivate> d;
+ friend class QCanDbcFileParserPrivate;
+
+ Q_DISABLE_COPY_MOVE(QCanDbcFileParser)
+};
+
+QT_END_NAMESPACE
+
+#endif // QCANDBCFILEPARSER_H
diff --git a/src/serialbus/qcandbcfileparser_p.h b/src/serialbus/qcandbcfileparser_p.h
new file mode 100644
index 0000000..76cac49
--- /dev/null
+++ b/src/serialbus/qcandbcfileparser_p.h
@@ -0,0 +1,63 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANDBCFILEPARSER_P_H
+#define QCANDBCFILEPARSER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qcandbcfileparser.h"
+#include "qcanmessagedescription.h"
+
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QCanSignalDescription;
+
+class QCanDbcFileParserPrivate
+{
+public:
+ void reset();
+ bool parseFile(const QString &fileName);
+ bool parseData(QStringView data);
+ bool processLine(const QStringView line);
+ bool parseMessage(const QStringView data);
+ QCanMessageDescription extractMessage(const QRegularExpressionMatch &match);
+ bool parseSignal(const QStringView data);
+ QCanSignalDescription extractSignal(const QRegularExpressionMatch &match);
+ void parseSignalType(const QStringView data);
+ void parseComment(const QStringView data);
+ void parseExtendedMux(const QStringView data);
+ void parseValueDescriptions(const QStringView data);
+ void postProcessSignalMultiplexing();
+
+ void addWarning(QString &&warning);
+ void addCurrentMessage();
+
+ QList<QCanMessageDescription> getMessages() const;
+
+ QString m_fileName;
+ QCanDbcFileParser::Error m_error = QCanDbcFileParser::Error::None;
+ QString m_errorString;
+ QStringList m_warnings;
+ qsizetype m_lineOffset = 0;
+ bool m_isProcessingMessage = false;
+ bool m_seenExtraData = false;
+ QCanMessageDescription m_currentMessage;
+ QHash<QtCanBus::UniqueId, QCanMessageDescription> m_messageDescriptions;
+ QCanDbcFileParser::MessageValueDescriptions m_valueDescriptions;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCANDBCFILEPARSER_P_H
diff --git a/src/serialbus/qcanframeprocessor.cpp b/src/serialbus/qcanframeprocessor.cpp
new file mode 100644
index 0000000..72c2550
--- /dev/null
+++ b/src/serialbus/qcanframeprocessor.cpp
@@ -0,0 +1,1191 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qcanbusframe.h"
+#include "qcanframeprocessor.h"
+#include "qcanframeprocessor_p.h"
+#include "qcanmessagedescription.h"
+#include "qcanmessagedescription_p.h"
+#include "qcansignaldescription.h"
+#include "qcansignaldescription_p.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QMap>
+#include <QtCore/QVariant>
+#include <QtCore/QtEndian>
+
+QT_BEGIN_NAMESPACE
+
+// The initial revision of QCanFrameProcessor introduced the BE data processing
+// logic which is different from what is normally done in CAN protocols.
+// A later patch fixes the logic to be compliant with normal CAN approach
+// (taking DBC as a reference), and introduces this define to disable the
+// unused functions.
+// We could completely remove the "dead code", but for now we want to get some
+// feedback from the users to see if we need to have both approaches or not.
+#define USE_DBC_COMPATIBLE_BE_HANDLING
+
+// Helper method to extract the max bit number of the signal.
+// Note that for BE it's not the last bit of the signal.
+static quint16 extractMaxBitNum(quint16 startBit, quint16 bitLength, QSysInfo::Endian endian)
+{
+#ifdef USE_DBC_COMPATIBLE_BE_HANDLING
+ if (endian == QSysInfo::Endian::LittleEndian) {
+ return startBit + bitLength - 1;
+ } else {
+ const auto startByteNum = startBit / 8;
+ const auto bitsInStartByte = startBit % 8 + 1;
+ const auto leftBits = bitLength - bitsInStartByte;
+ if (leftBits <= 0)
+ return startBit; // so start bit is the largest
+
+ const auto leftBytesRounded = (leftBits % 8 == 0) ? leftBits / 8 : leftBits / 8 + 1;
+ return (startByteNum + leftBytesRounded + 1) * 8 - 1;
+ }
+#else
+ return startBit + bitLength - 1;
+#endif // USE_DBC_COMPATIBLE_BE_HANDLING
+}
+
+/*!
+ \class QCanFrameProcessor
+ \inmodule QtSerialBus
+ \since 6.5
+ \preliminary
+
+ \brief The QCanFrameProcessor class can be used to decode
+ a \l QCanBusFrame or to convert the input data into a \l QCanBusFrame that
+ is ready to be sent to the receiver.
+
+ The QCanFrameProcessor class operates on the CAN message descriptions
+ (represented by the \l QCanMessageDescription and \l QCanSignalDescription
+ classes) and a unique identifier description (represented by
+ \l QCanUniqueIdDescription). It uses the descriptions to decode the
+ incoming \l QCanBusFrame or to encode the user-specified data into the
+ proper payload.
+
+ Before doing any decoding or encoding, the QCanFrameProcessor instance
+ \e must be initialized properly. The following data needs to be provided:
+
+ \list
+ \li A \l {QCanUniqueIdDescription::isValid}{valid} unique identifier
+ description. Use the \l setUniqueIdDescription() method to provide
+ a proper description.
+ \li At least one message description. Use the
+ \l addMessageDescriptions() or \l setMessageDescriptions() method
+ to provide message descriptions.
+ All message descriptions \e must have distinct unique identifiers.
+ Each message can contain multiple signal descriptions, but signal
+ names within one message \e must be unique as well.
+ \endlist
+
+ The \l parseFrame() method can be used to process the incoming
+ \l QCanBusFrame. The method returns a \l {QCanFrameProcessor::}{ParseResult}
+ structure which contains the \l {QCanFrameProcessor::ParseResult::uniqueId}
+ {unique identifier} and the \l {QCanFrameProcessor::ParseResult::signalValues}
+ {signal values} map. The keys of the map are the
+ \l {QCanSignalDescription::name}{signal names}, and the values of the map
+ are signal values.
+
+ The \l prepareFrame() method can be used to generate a \l QCanBusFrame
+ object for a specific unique identifier, using the provided signal names
+ and desired values.
+
+ Errors can occur during the encoding or decoding process. In such cases
+ the \l error() and \l errorString() methods can be used to get the
+ information about the error.
+
+ Some non-critical problems may occur as well. Such problems will be logged,
+ but the process will not be stopped. After the process is completed, the
+ \l warnings() method can be used to access the list of all the warnings.
+
+ \note The last error and error description, as well as the warnings, are
+ reset once the decoding or encoding is started.
+
+ \sa QCanMessageDescription, QCanSignalDescription
+*/
+
+/*!
+ \enum QCanFrameProcessor::Error
+
+ This enum represents the possible errors that can occur while
+ encoding or decoding the \l QCanBusFrame.
+
+ \value None No error occurred.
+ \value InvalidFrame The received frame is invalid and cannot be parsed.
+ \value UnsupportedFrameFormat The format of the received frame is not
+ supported and cannot be parsed.
+ \value Decoding An error occurred during decoding. Use
+ \l errorString() to get a string representation
+ of the error.
+ \value Encoding An error occurred during encoding. Use
+ \l errorString() to get a string representation
+ of the error.
+*/
+
+/*!
+ \struct QCanFrameProcessor::ParseResult
+ \inmodule QtSerialBus
+ \since 6.5
+
+ \brief The struct is used as a return value for the
+ \l QCanFrameProcessor::parseFrame() method.
+*/
+
+/*!
+ \variable QCanFrameProcessor::ParseResult::uniqueId
+ \brief the value of the unique identifier of the parsed frame.
+*/
+
+/*!
+ \variable QCanFrameProcessor::ParseResult::signalValues
+ \brief the map containing the extracted signals and their values.
+ The keys of the map are the \l {QCanSignalDescription::name}{signal names},
+ and the values of the map are signal values.
+*/
+
+/*!
+ Creates a CAN frame processor.
+*/
+QCanFrameProcessor::QCanFrameProcessor()
+ : d(std::make_unique<QCanFrameProcessorPrivate>())
+{
+}
+
+/*!
+ Destroys this frame processor.
+*/
+QCanFrameProcessor::~QCanFrameProcessor() = default;
+
+/*!
+ Constructs a CAN data frame, using \a uniqueId and \a signalValues
+ and returns the constructed \l QCanBusFrame.
+
+ The \a signalValues parameter \e must contain signal names as keys, and
+ expected signal values as values.
+
+ The process of creating the frame is as follows:
+
+ \list 1
+ \li The \a uniqueId is used to find an appropriate message
+ description.
+ \li If the message description is found, a \l QCanBusFrame with
+ a payload of the specified size is created. All bytes of the
+ payload, as well as the frame id, are initialized to zeros.
+ \li The \l uniqueIdDescription() is used to encode the \a uniqueId into
+ the appropriate part of the frame (frame id or payload).
+ \li The selected message description is used to encode all the
+ \a signalValues into the frame.
+ \li The parts of the frame that are not covered by a unique id or
+ existing signal descriptions are untouched (and so still contain
+ zeros).
+ \endlist
+
+ If an error occurred during the encoding, an invalid \l QCanBusFrame is
+ returned. In such cases, the \l error() and \l errorString() methods
+ can be used to get information about the errors.
+
+ \note Calling this method clears all previous errors and warnings.
+
+ \sa addMessageDescriptions(), error(), errorString(), warnings()
+*/
+QCanBusFrame QCanFrameProcessor::prepareFrame(QtCanBus::UniqueId uniqueId,
+ const QVariantMap &signalValues)
+{
+ d->resetErrors();
+
+ if (!d->uidDescription.isValid()) {
+ d->setError(Error::Encoding,
+ QObject::tr("No valid unique identifier description is specified."));
+ return QCanBusFrame(QCanBusFrame::InvalidFrame);
+ }
+
+ if (!d->messages.contains(uniqueId)) {
+ d->setError(Error::Encoding,
+ QObject::tr("Failed to find message description for unique id %1.").
+ arg(qToUnderlying(uniqueId)));
+ return QCanBusFrame(QCanBusFrame::InvalidFrame);
+ }
+
+ const auto message = d->messages.value(uniqueId);
+ QCanBusFrame::FrameId canFrameId = 0; // may be modified by the signal values
+ QByteArray payload(message.size(), 0x00);
+
+ // encode the uniqueId value into the frame on the proper position
+ {
+ const bool uidInPayload = d->uidDescription.source() == QtCanBus::DataSource::Payload;
+ const quint16 bitsSize = uidInPayload ? payload.size() * 8 : 29;
+ unsigned char *data = uidInPayload ? reinterpret_cast<unsigned char *>(payload.data())
+ : reinterpret_cast<unsigned char *>(&canFrameId);
+ if (!d->fillUniqueId(data, bitsSize, uniqueId)) {
+ d->setError(Error::Encoding,
+ QObject::tr("Failed to encode unique id %1 into the frame").
+ arg(qToUnderlying(uniqueId)));
+ return QCanBusFrame(QCanBusFrame::InvalidFrame);
+ }
+ }
+
+ // helper function to check for multiplexor preconditions
+ auto checkMuxValues = [](const QCanSignalDescription &desc,
+ const QVariantMap &signalValues) -> bool
+ {
+ const auto muxValues = desc.multiplexSignals();
+ if (muxValues.isEmpty())
+ return true;
+ const auto *descPrivate = QCanSignalDescriptionPrivate::get(desc);
+ for (auto it = muxValues.cbegin(); it != muxValues.cend(); ++it) {
+ const auto &name = it.key();
+ const auto &ranges = it.value();
+ if (!signalValues.contains(name)
+ || !descPrivate->muxValueInRange(signalValues.value(name), ranges)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ auto descriptionsHash = QCanMessageDescriptionPrivate::get(message)->messageSignals;
+ for (auto it = signalValues.cbegin(); it != signalValues.cend(); ++it) {
+ const QString &signalName = it.key();
+ if (!descriptionsHash.contains(signalName)) {
+ d->addWarning(QObject::tr("Skipping signal %1. It is not found in "
+ "message description for unique id %2.").
+ arg(signalName, QString::number(qToUnderlying(uniqueId))));
+ continue;
+ }
+
+ const auto &signalDesc = descriptionsHash.value(signalName);
+ if (!signalDesc.isValid()) {
+ d->addWarning(QObject::tr("Skipping signal %1. Its description is invalid.").
+ arg(signalName));
+ continue;
+ }
+
+ // check for multiplexor prerequisites
+ if (!checkMuxValues(signalDesc, signalValues)) {
+ d->addWarning(QObject::tr("Skipping signal %1. Proper multiplexor values not found.").
+ arg(signalName));
+ continue;
+ }
+
+ const bool dataInPayload = signalDesc.dataSource() == QtCanBus::DataSource::Payload;
+ // For data in FrameId we consider max length == 29, because we do not
+ // know if the frame is extended or not.
+ const quint16 maxDataLength = dataInPayload ? payload.size() * 8 : 29;
+ const auto signalDataEnd = extractMaxBitNum(signalDesc.startBit(), signalDesc.bitLength(),
+ signalDesc.dataEndian());
+ if (signalDataEnd >= maxDataLength) {
+ d->addWarning(QObject::tr("Skipping signal %1. Its length exceeds the expected "
+ "message length.").arg(signalName));
+ continue;
+ }
+
+ unsigned char *data = dataInPayload ? reinterpret_cast<unsigned char *>(payload.data())
+ : reinterpret_cast<unsigned char *>(&canFrameId);
+ d->encodeSignal(data, it.value(), signalDesc);
+ }
+
+ return QCanBusFrame(canFrameId, payload);
+}
+
+/*!
+ Returns the last error.
+
+ \sa errorString(), prepareFrame(), parseFrame()
+*/
+QCanFrameProcessor::Error QCanFrameProcessor::error() const
+{
+ return d->error;
+}
+
+/*!
+ Returns the text description of the last error.
+
+ \sa error(), prepareFrame(), parseFrame()
+*/
+QString QCanFrameProcessor::errorString() const
+{
+ return d->errorString;
+}
+
+/*!
+ Returns the list of warnings generated during the last encoding or decoding
+ call.
+
+ \sa error(), errorString(), prepareFrame(), parseFrame()
+*/
+QStringList QCanFrameProcessor::warnings() const
+{
+ return d->warnings;
+}
+
+/*!
+ Returns all the message descriptions that are currently used by this frame
+ processor.
+
+ \sa addMessageDescriptions(), setMessageDescriptions(),
+ clearMessageDescriptions()
+*/
+QList<QCanMessageDescription> QCanFrameProcessor::messageDescriptions() const
+{
+ return QList<QCanMessageDescription>(d->messages.cbegin(), d->messages.cend());
+}
+
+/*!
+ Adds new message descriptions \a descriptions to the available message
+ descriptions.
+
+ All message descriptions should have distinct unique ids.
+
+ If some message descriptions have repeated unique ids, only the last
+ description will be used.
+
+ If the parser already had a message description with the same unique id, it
+ will be overwritten.
+
+ \sa messageDescriptions(), setMessageDescriptions(),
+ clearMessageDescriptions()
+*/
+void QCanFrameProcessor::addMessageDescriptions(const QList<QCanMessageDescription> &descriptions)
+{
+ for (const auto &desc : descriptions)
+ d->messages.insert(desc.uniqueId(), desc);
+}
+
+/*!
+ Replaces current message descriptions used by this frame processor with the
+ new message descriptions \a descriptions.
+
+ \sa messageDescriptions(), addMessageDescriptions(),
+ clearMessageDescriptions()
+*/
+void QCanFrameProcessor::setMessageDescriptions(const QList<QCanMessageDescription> &descriptions)
+{
+ d->messages.clear();
+ addMessageDescriptions(descriptions);
+}
+
+/*!
+ Removes all message descriptions for this frame processor.
+
+ \sa messageDescriptions(), addMessageDescriptions(),
+ setMessageDescriptions()
+*/
+void QCanFrameProcessor::clearMessageDescriptions()
+{
+ d->messages.clear();
+}
+
+/*!
+ Returns the unique identifier description.
+
+ The unique identifier description must be valid in order to encode or decode
+ the CAN bus frames. See the \l QCanUniqueIdDescription class documentation
+ for more details.
+
+ \sa setUniqueIdDescription(), QCanUniqueIdDescription
+*/
+QCanUniqueIdDescription QCanFrameProcessor::uniqueIdDescription() const
+{
+ return d->uidDescription;
+}
+
+/*!
+ Sets the unique identifier description to \a description.
+
+ The unique identifier description must be valid in order to encode or decode
+ the CAN bus frames. See the \l QCanUniqueIdDescription class documentation
+ for more details.
+
+ \sa uniqueIdDescription(), QCanUniqueIdDescription
+*/
+void QCanFrameProcessor::setUniqueIdDescription(const QCanUniqueIdDescription &description)
+{
+ d->uidDescription = description;
+}
+
+/*!
+ Parses the frame \a frame using the specified message descriptions.
+
+ The process of parsing is as follows:
+ \list 1
+ \li The \l uniqueIdDescription() is used to extract the unique
+ identifier of the message.
+ \li The extracted unique identifier is used to search for a suitable
+ \l QCanMessageDescription from the list of all available
+ \l messageDescriptions().
+ \li The matching \l QCanMessageDescription is used to extract
+ the signal values from the frame.
+ \endlist
+
+ This method returns a \l QCanFrameProcessor::ParseResult, which contains
+ both the extracted unique identifier and a \l QVariantMap with the signals
+ and their values. The keys of the map are the
+ \l {QCanSignalDescription::name}{signal names}, and the values of the map
+ are signal values.
+
+ If an error occurred during the decoding, a result with empty
+ \l {QCanFrameProcessor::ParseResult::}{signalValues} is returned.
+ In such cases, the \l error() and \l errorString() methods can be used
+ to get information about the errors.
+
+ \note Calling this method clears all previous errors and warnings.
+
+ \sa addMessageDescriptions(), error(), errorString(), warnings()
+*/
+QCanFrameProcessor::ParseResult QCanFrameProcessor::parseFrame(const QCanBusFrame &frame)
+{
+ d->resetErrors();
+
+ if (!frame.isValid()) {
+ d->setError(Error::InvalidFrame, QObject::tr("Invalid frame."));
+ return {};
+ }
+ if (frame.frameType() != QCanBusFrame::DataFrame) {
+ d->setError(Error::UnsupportedFrameFormat, QObject::tr("Unsupported frame format."));
+ return {};
+ }
+ if (!d->uidDescription.isValid()) {
+ d->setError(Error::Decoding,
+ QObject::tr("No valid unique identifier description is specified."));
+ return {};
+ }
+
+ const auto uidOpt = d->extractUniqueId(frame);
+ if (!uidOpt.has_value()) {
+ d->setError(Error::Decoding,
+ QObject::tr("Failed to extract unique id from the frame."));
+ return {};
+ }
+
+ const auto uniqueId = uidOpt.value();
+ if (!d->messages.contains(uniqueId)) {
+ d->setError(Error::Decoding,
+ QObject::tr("Could not find a message description for unique id %1.").
+ arg(qToUnderlying(uniqueId)));
+ return {};
+ }
+
+ const auto message = d->messages.value(uniqueId);
+ if (message.size() != frame.payload().size()) {
+ d->setError(Error::Decoding,
+ QObject::tr("Payload size does not match message description. "
+ "Actual size = %1, expected size = %2.").
+ arg(frame.payload().size()).arg(message.size()));
+ return {};
+ }
+
+ QVariantMap parsedSignals;
+ // The multiplexor signals can form a complex dependency, so we can't
+ // simply iterate through the signal descriptions in a natural order.
+ // Instead, we first need to process all signals with no dependency on
+ // other multiplexors, then handle the signals that have dependency on
+ // already parsed signals, and so on, until we parse all signals.
+ // One potential problem here is that the dependencies can be specified
+ // incorrectly (for example, we can have circular dependencies, or
+ // dependencies on non-existent signal), so we need to come up with a
+ // reasonable condition to stop.
+
+ auto seenNeededSignals = [](const QCanSignalDescription &desc,
+ const QVariantMap &parsedSignals) -> bool {
+ const auto muxSignals = desc.multiplexSignals();
+ if (muxSignals.isEmpty())
+ return true;
+ const auto *descPrivate = QCanSignalDescriptionPrivate::get(desc);
+ for (auto it = muxSignals.cbegin(); it != muxSignals.cend(); ++it) {
+ const auto &name = it.key();
+ const auto &ranges = it.value();
+ if (!parsedSignals.contains(name)
+ || !descPrivate->muxValueInRange(parsedSignals.value(name), ranges)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ auto descriptionsHash = QCanMessageDescriptionPrivate::get(message)->messageSignals;
+ while (true) {
+ QList<QString> newNames;
+ for (const auto &desc : std::as_const(descriptionsHash)) {
+ if (seenNeededSignals(desc, parsedSignals)) {
+ newNames.push_back(desc.name());
+ if (!desc.isValid()) {
+ d->addWarning(QObject::tr("Skipping signal %1 in message with unique id %2"
+ " because its description is invalid.").
+ arg(desc.name(), QString::number(qToUnderlying(uniqueId))));
+ continue;
+ }
+ const QVariant value = d->decodeSignal(frame, desc);
+ if (value.isValid())
+ parsedSignals.insert(desc.name(), value);
+ }
+ }
+ for (const auto &name : std::as_const(newNames))
+ descriptionsHash.remove(name);
+ if (newNames.isEmpty() || descriptionsHash.isEmpty()) {
+ // We either processed all signals, or failed to process more during
+ // the last loop. The latter means that the multiplexor conditions
+ // do not match for the rest of the signals, which is fine and will
+ // always happen when multiplexing
+ break;
+ }
+ }
+
+ return {uniqueId, parsedSignals};
+}
+
+/* QCanFrameProcessorPrivate implementation */
+
+void QCanFrameProcessorPrivate::resetErrors()
+{
+ error = QCanFrameProcessor::Error::None;
+ errorString.clear();
+ warnings.clear();
+}
+
+void QCanFrameProcessorPrivate::setError(QCanFrameProcessor::Error err, const QString &desc)
+{
+ error = err;
+ errorString = desc;
+}
+
+void QCanFrameProcessorPrivate::addWarning(const QString &warning)
+{
+ warnings.push_back(warning);
+}
+
+QVariant QCanFrameProcessorPrivate::decodeSignal(const QCanBusFrame &frame,
+ const QCanSignalDescription &signalDesc)
+{
+ const auto signalDataEnd = extractMaxBitNum(signalDesc.startBit(), signalDesc.bitLength(),
+ signalDesc.dataEndian());
+ const bool dataFromPayload =
+ signalDesc.dataSource() == QtCanBus::DataSource::Payload;
+
+ const auto frameIdLength = frame.hasExtendedFrameFormat() ? 29 : 11;
+ const auto maxDataLength = dataFromPayload ? frame.payload().size() * 8
+ : frameIdLength;
+
+ if (signalDataEnd >= maxDataLength) {
+ addWarning(QObject::tr("Skipping signal %1 in message with unique id %2. "
+ "Its expected length exceeds the data length.").
+ arg(signalDesc.name(), QString::number(frame.frameId())));
+ return QVariant();
+ }
+
+ const QByteArray payload = frame.payload();
+ const auto frameId = frame.frameId();
+ const unsigned char *data = dataFromPayload
+ ? reinterpret_cast<const unsigned char *>(payload.data())
+ : reinterpret_cast<const unsigned char *>(&frameId);
+
+ return parseData(data, signalDesc);
+}
+
+static bool needValueConversion(const QCanSignalDescription &signalDesc)
+{
+ return !qIsNaN(signalDesc.factor()) || !qIsNaN(signalDesc.offset())
+ || !qIsNaN(signalDesc.scaling());
+}
+
+template <typename T>
+static double convertFromCanValue(T value, const QCanSignalDescription &signalDesc)
+{
+ double result = static_cast<double>(value);
+ if (!qIsNaN(signalDesc.factor()))
+ result *= signalDesc.factor();
+
+ if (!qIsNaN(signalDesc.offset()))
+ result += signalDesc.offset();
+
+ if (!qIsNaN(signalDesc.scaling()))
+ result *= signalDesc.scaling();
+
+ return result;
+}
+
+static double convertToCanValue(const QVariant &value, const QCanSignalDescription &signalDesc)
+{
+ // Checks for 0 are done in the corresponding setters, so we can divide
+ // safely.
+ double result = value.toDouble();
+ if (!qIsNaN(signalDesc.scaling()))
+ result /= signalDesc.scaling();
+
+ if (!qIsNaN(signalDesc.offset()))
+ result -= signalDesc.offset();
+
+ if (!qIsNaN(signalDesc.factor()))
+ result /= signalDesc.factor();
+
+ return result;
+}
+
+#ifdef USE_DBC_COMPATIBLE_BE_HANDLING
+
+template <typename T>
+static QVariant extractValue(const unsigned char *data, const QCanSignalDescription &signalDesc)
+{
+ constexpr auto tBitLength = sizeof(T) * 8;
+ const auto length = signalDesc.bitLength();
+ if constexpr (std::is_floating_point_v<T>)
+ Q_ASSERT(tBitLength == length);
+ else
+ Q_ASSERT(tBitLength >= length);
+ const auto maxBytesToRead = (length % 8 == 0) ? length / 8 : length / 8 + 1;
+ const auto start = signalDesc.startBit();
+ T value = {};
+ const bool isBigEndian = signalDesc.dataEndian() == QSysInfo::Endian::BigEndian;
+ if (isBigEndian) {
+ // Big Endian - start bit is MSB
+ if (start % 8 == 7 && length % 8 == 0) {
+ // The data is aligned at byte offset, we can simply memcpy
+ memcpy(&value, &data[(start - 7) / 8], maxBytesToRead);
+ } else {
+ // Data is not aligned at byte offset, we need to do some bit
+ // shifting. We cannot perform bit operations on float or double
+ // types, so we convert the value to uchar *.
+ // Because of how BE data is organized, the indices for reading
+ // would not be continuous. If we want to extract BE data from the
+ // middle 12 bits of a 2-byte payload, we will need to read bits 5-0
+ // and 15-10:
+ // _________________________________________________________________
+ // |7 |6 |5(MSB) |4 |3 |2 |1 |0 |
+ // -----------------------------------------------------------------
+ // |15 |14 |13 |12 |11 |10(LSB)|9 |8 |
+ // -----------------------------------------------------------------
+ unsigned char *valueData = reinterpret_cast<unsigned char *>(&value);
+ qsizetype bitIdx = start;
+ for (qsizetype processedBits = 0; processedBits < length; ++processedBits) {
+ const auto dataByteIdx = bitIdx / 8;
+ const auto dataBitIdx = bitIdx % 8;
+ if (data[dataByteIdx] & (0x01 << dataBitIdx)) {
+ const auto byteIdx = processedBits / 8;
+ // start filling each byte from MSB
+ const auto bitIdx = 7 - (processedBits % 8);
+ valueData[byteIdx] |= (0x01 << bitIdx);
+ }
+ // handle jump like 0 -> 15 from the example above
+ if (bitIdx % 8 == 0)
+ bitIdx += 15;
+ else
+ --bitIdx;
+ }
+ }
+ } else {
+ // Little Endian - start bit is LSB
+ if (start % 8 == 0 && length % 8 == 0) {
+ // The data is aligned at byte offset, we can simply memcpy
+ memcpy(&value, &data[start / 8], maxBytesToRead);
+ } else {
+ // Data is not aligned at byte offset, we need to do some bit
+ // shifting. We cannot perform bit operations on float or double
+ // types, so we convert the value to uchar *.
+ unsigned char *valueData = reinterpret_cast<unsigned char *>(&value);
+ quint16 valueIdx = 0;
+ for (auto i = start; i < start + length; ++i, ++valueIdx) {
+ const auto byteIdx = i / 8;
+ const auto bitIdx = i % 8;
+ if (data[byteIdx] & (0x01 << bitIdx))
+ valueData[valueIdx / 8] |= 0x01 << (valueIdx % 8);
+ }
+ }
+ }
+ // check and convert endian
+ T convertedValue = {};
+ if (isBigEndian)
+ convertedValue = qFromBigEndian(value);
+ else
+ convertedValue = qFromLittleEndian(value);
+ const bool endianChanged = convertedValue != value;
+ value = convertedValue;
+ // for signed & unsigned fill the most significant bits with proper values
+ if constexpr (std::is_integral_v<T>) {
+ if (tBitLength > length) {
+ if (endianChanged) {
+ // After endian conversion we have unneeded bits in the end,
+ // so we need to cut them
+ value = value >> (tBitLength - length);
+ }
+ // value has more bits than we could actually read, so we need to
+ // fill the most significant bits properly
+ const auto dataFormat = signalDesc.dataFormat();
+ if (dataFormat == QtCanBus::DataFormat::SignedInteger) {
+ if (value & (0x01ULL << (length - 1))) {
+ // msb = 1 -> negative value, fill the rest with 1's
+ for (auto i = length; i < tBitLength; ++i)
+ value |= (0x01ULL << i);
+ } else {
+ // msb = 0 -> positive value, fill the rest with 0's
+ for (auto i = length; i < tBitLength; ++i)
+ value &= ~(0x01ULL << i);
+ }
+ } else if (dataFormat == QtCanBus::DataFormat::UnsignedInteger) {
+ // simply fill most significant bits with 0's
+ for (auto i = length; i < tBitLength; ++i)
+ value &= ~(0x01ULL << i);
+ }
+ }
+ }
+ // perform value conversions, if needed
+ if (needValueConversion(signalDesc))
+ return QVariant::fromValue(convertFromCanValue(value, signalDesc));
+
+ return QVariant::fromValue(value);
+}
+
+#else
+
+template <typename T>
+static QVariant extractValue(const unsigned char *data, const QCanSignalDescription &signalDesc)
+{
+ constexpr auto tBitLength = sizeof(T) * 8;
+ const auto length = signalDesc.bitLength();
+ if constexpr (std::is_floating_point_v<T>)
+ Q_ASSERT(tBitLength == length);
+ else
+ Q_ASSERT(tBitLength >= length);
+ const auto maxBytesToRead = (length % 8 == 0) ? length / 8 : length / 8 + 1;
+ const auto start = signalDesc.startBit();
+ T value = {};
+ if (start % 8 == 0 && length % 8 == 0) {
+ // The data is aligned at byte offset, we can simply memcpy
+ memcpy(&value, &data[start / 8], maxBytesToRead);
+ } else {
+ // Data is not aligned at byte offset, we need to do some bit shifting
+ // We cannot perform bit operations on float or double types, so we
+ // convert the value to uchar *.
+
+ // If the data is in big endian, and data length % 8 != 0, then the
+ // first byte is not full. So we need to read (8 - length % 8) bits
+ // from it, and then complete it properly
+
+ unsigned char *valueData = reinterpret_cast<unsigned char *>(&value);
+ quint16 valueIdx = 0;
+ quint16 startIdx = start;
+ quint16 numToRead = length;
+ if (signalDesc.dataEndian() == QSysInfo::Endian::BigEndian) {
+ const auto readInFirstByte = length % 8;
+ // else we have round number of bytes and all these tricks are not needed
+ if (readInFirstByte) {
+ const auto missingBits = 8 - readInFirstByte;
+ bool lastBitIsOne = false;
+ for (auto i = startIdx; i < startIdx + readInFirstByte; ++i, ++valueIdx) {
+ const auto byteIdx = i / 8;
+ const auto bitIdx = i % 8;
+ lastBitIsOne = data[byteIdx] & (0x01 << bitIdx);
+ if (lastBitIsOne)
+ valueData[valueIdx / 8] |= 0x01 << (valueIdx % 8);
+ }
+ if (lastBitIsOne) {
+ for (auto i = 0; i < missingBits; ++i, ++valueIdx)
+ valueData[valueIdx / 8] |= 0x01 << (valueIdx % 8);
+ } else {
+ // We simply have zeros there, but still need to increase valueIdx
+ valueIdx += missingBits;
+ }
+ startIdx += readInFirstByte;
+ numToRead -= readInFirstByte;
+ }
+ }
+ for (auto i = startIdx; i < startIdx + numToRead; ++i, ++valueIdx) {
+ const auto byteIdx = i / 8;
+ const auto bitIdx = i % 8;
+ if (data[byteIdx] & (0x01 << bitIdx))
+ valueData[valueIdx / 8] |= 0x01 << (valueIdx % 8);
+ }
+ }
+ // check and convert endian
+ T convertedValue = {};
+ if (signalDesc.dataEndian() == QSysInfo::Endian::LittleEndian)
+ convertedValue = qFromLittleEndian(value);
+ else
+ convertedValue = qFromBigEndian(value);
+ const bool endianChanged = convertedValue != value;
+ value = convertedValue;
+ // for signed & unsigned fill the most significant bits with proper values
+ if constexpr (std::is_integral_v<T>) {
+ if (tBitLength > length) {
+ if (endianChanged) {
+ // After endian conversion we have unneeded bits in the end,
+ // so we need to cut them
+ value = value >> (tBitLength - maxBytesToRead * 8);
+ }
+ // value has more bits than we could actually read, so we need to
+ // fill the most significant bits properly
+ const auto dataFormat = signalDesc.dataFormat();
+ if (dataFormat == QtCanBus::DataFormat::SignedInteger) {
+ if (value & (0x01ULL << (length - 1))) {
+ // msb = 1 -> negative value, fill the rest with 1's
+ for (auto i = length; i < tBitLength; ++i)
+ value |= (0x01ULL << i);
+ } else {
+ // msb = 0 -> positive value, fill the rest with 0's
+ for (auto i = length; i < tBitLength; ++i)
+ value &= ~(0x01ULL << i);
+ }
+ } else if (dataFormat == QtCanBus::DataFormat::UnsignedInteger) {
+ // simply fill most significant bits with 0's
+ for (auto i = length; i < tBitLength; ++i)
+ value &= ~(0x01ULL << i);
+ }
+ }
+ }
+ // perform value conversions, if needed
+ if (needValueConversion(signalDesc))
+ return QVariant::fromValue(convertFromCanValue(value, signalDesc));
+
+ return QVariant::fromValue(value);
+}
+
+#endif // USE_DBC_COMPATIBLE_BE_HANDLING
+
+static QVariant parseAscii(const unsigned char *data, const QCanSignalDescription &signalDesc)
+{
+ Q_ASSERT(signalDesc.bitLength() % 8 == 0);
+
+ const auto length = signalDesc.bitLength();
+ const auto start = signalDesc.startBit();
+
+ QByteArray value(length / 8, 0x00);
+
+ char *valueData = value.data();
+ quint16 valueIdx = 0;
+ for (quint16 i = start; i < start + length; ++i, ++valueIdx) {
+ const auto byteIdx = i / 8;
+ const auto bitIdx = i % 8;
+ if (data[byteIdx] & (0x01 << bitIdx))
+ valueData[valueIdx / 8] |= 0x01 << (valueIdx % 8);
+ }
+
+ return QVariant(value);
+}
+
+QVariant QCanFrameProcessorPrivate::parseData(const unsigned char *data,
+ const QCanSignalDescription &signalDesc)
+{
+ // We assume that signal's length does not exceed data size.
+ // That is checked as a precondition to calling this method, so we do not
+ // pass size for the data.
+ switch (signalDesc.dataFormat()) {
+ case QtCanBus::DataFormat::SignedInteger:
+ return extractValue<qint64>(data, signalDesc);
+ case QtCanBus::DataFormat::UnsignedInteger:
+ return extractValue<quint64>(data, signalDesc);
+ case QtCanBus::DataFormat::Float:
+ return extractValue<float>(data, signalDesc);
+ case QtCanBus::DataFormat::Double:
+ return extractValue<double>(data, signalDesc);
+ case QtCanBus::DataFormat::AsciiString:
+ return parseAscii(data, signalDesc);
+ }
+ Q_UNREACHABLE();
+}
+
+#ifdef USE_DBC_COMPATIBLE_BE_HANDLING
+
+template <typename T>
+static void encodeValue(unsigned char *data, const QVariant &valueVar,
+ const QCanSignalDescription &signalDesc)
+{
+ constexpr auto tBitLength = sizeof(T) * 8;
+ const auto length = signalDesc.bitLength();
+ if constexpr (std::is_floating_point_v<T>)
+ Q_ASSERT(tBitLength == length);
+ else
+ Q_ASSERT(tBitLength >= length);
+
+ // Perform value conversion.
+ T value = {};
+ if (needValueConversion(signalDesc))
+ value = static_cast<T>(std::round(convertToCanValue(valueVar, signalDesc)));
+ else
+ value = valueVar.value<T>();
+
+ const bool dataLittleEndian = signalDesc.dataEndian() == QSysInfo::Endian::LittleEndian;
+
+ const auto maxBytesToWrite = (length % 8 == 0) ? length / 8 : length / 8 + 1;
+
+ // always treat the value-to-write as LE for simplicity
+ value = qToLittleEndian(value);
+ const quint16 start = signalDesc.startBit();
+ if (dataLittleEndian) {
+ // Little Endian
+ if (start % 8 == 0 && length % 8 == 0) {
+ // The data is aligned at byte offset, and has a round number of
+ // bytes, so we can simply memcpy
+ memcpy(&data[start / 8], &value, maxBytesToWrite);
+ } else {
+ const uchar *valueData = reinterpret_cast<const uchar *>(&value);
+ for (quint16 i = 0; i < length; ++i) {
+ const auto valueByteIdx = i / 8;
+ const auto valueBitIdx = i % 8;
+ const auto dataByteIdx = (start + i) / 8;
+ const auto dataBitIdx = (start + i) % 8;
+
+ if (valueData[valueByteIdx] & (0x01 << valueBitIdx))
+ data[dataByteIdx] |= (0x01 << dataBitIdx);
+ else
+ data[dataByteIdx] &= ~(0x01 << dataBitIdx);
+ }
+ }
+ } else {
+ // Big Endian
+ if (start % 8 == 7 && length % 8 == 0) {
+ // The data is aligned at byte offset and has a round number of
+ // bytes, so we can simply memcpy. Just need to convert to BE and
+ // take the meaningful bytes (those will be the most significant
+ // bytes after switching to BE).
+ value = qToBigEndian(value);
+ const uchar *valueData = reinterpret_cast<const uchar *>(&value);
+ const auto byteIdx = sizeof(value) - maxBytesToWrite;
+ memcpy(&data[(start - 7) / 8], &valueData[byteIdx], maxBytesToWrite);
+ } else {
+ // We need to start from the MSB of the valueToWrite
+ // Because of how BE data is organized, the indices for writing
+ // would not be continuous. If we want to write BE data to the
+ // middle 12 bits of a 2-byte payload, we will need to write bits
+ // 5-0 and 15-10:
+ // _________________________________________________________________
+ // |7 |6 |5(MSB) |4 |3 |2 |1 |0 |
+ // -----------------------------------------------------------------
+ // |15 |14 |13 |12 |11 |10(LSB)|9 |8 |
+ // -----------------------------------------------------------------
+ const uchar *valueData = reinterpret_cast<const uchar *>(&value);
+ auto dataBit = signalDesc.startBit();
+ for (auto valueBit = length - 1; valueBit >= 0; --valueBit) {
+ const auto valueByteIdx = valueBit / 8;
+ const auto valueBitIdx = valueBit % 8;
+ const auto dataByteIdx = dataBit / 8;
+ const auto dataBitIdx = dataBit % 8;
+ if (valueData[valueByteIdx] & (0x01 << valueBitIdx))
+ data[dataByteIdx] |= (0x01 << dataBitIdx);
+ else
+ data[dataByteIdx] &= ~(0x01 << dataBitIdx);
+ // handle jumps like 0 -> 15
+ if (dataBit % 8 == 0)
+ dataBit += 15;
+ else
+ --dataBit;
+ }
+ }
+ }
+}
+
+#else
+
+static constexpr bool isNativeLittleEndian()
+{
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ return true;
+#else
+ return false;
+#endif
+}
+
+template <typename T>
+static void encodeValue(unsigned char *data, const QVariant &valueVar,
+ const QCanSignalDescription &signalDesc)
+{
+ constexpr auto tBitLength = sizeof(T) * 8;
+ const auto length = signalDesc.bitLength();
+ if constexpr (std::is_floating_point_v<T>)
+ Q_ASSERT(tBitLength == length);
+ else
+ Q_ASSERT(tBitLength >= length);
+ const auto maxBytesToWrite = (length % 8 == 0) ? length / 8 : length / 8 + 1;
+
+ // Perform value conversion.
+ T value = {};
+ if (needValueConversion(signalDesc))
+ value = static_cast<T>(std::round(convertToCanValue(valueVar, signalDesc)));
+ else
+ value = valueVar.value<T>();
+
+ // Check endian.
+ // When doing endian-conversion for values with (bitSize % 8 != 0) we must
+ // be very careful, because qTo{Little,Big}Endian swaps whole bytes.
+ // After swapping the last byte, which could have less than 8 meaningful
+ // bits, becomes the first byte. So we need to adjust it carefully, shifting
+ // it in such a way that all meaningless bits are skipped.
+ // We also need to consider that we operate on q{u}int64 values for
+ // {un}signed integers, so we need to chop the unneeded bytes first.
+ const bool dataLittleEndian =
+ signalDesc.dataEndian() == QSysInfo::Endian::LittleEndian;
+
+ T valueToWrite = value;
+ quint16 writeOffset = 0;
+ if (dataLittleEndian && !isNativeLittleEndian()) {
+ valueToWrite = qToLittleEndian(valueToWrite);
+ } else if (!dataLittleEndian && isNativeLittleEndian()) {
+ valueToWrite = qToBigEndian(valueToWrite);
+ // for floating point types we always pass the exact type, so no need
+ // to shift extra/unneeded bits
+ if constexpr (!std::is_floating_point_v<T>) {
+ // get rid of the unneeded bytes
+ valueToWrite = valueToWrite >> (tBitLength - maxBytesToWrite * 8);
+ // skip meaningless bits in the first byte
+ writeOffset = maxBytesToWrite * 8 - length;
+ if (writeOffset > 0) {
+ uchar *valueData = reinterpret_cast<uchar *>(&valueToWrite);
+ valueData[0] = valueData[0] << writeOffset;
+ }
+ }
+ }
+
+ const quint16 start = signalDesc.startBit();
+ if (start % 8 == 0 && length % 8 == 0) {
+ // The data is aligned at byte offset, and has a round number of bytes,
+ // so we can simply memcpy
+ memcpy(&data[start / 8], &valueToWrite, maxBytesToWrite);
+ } else {
+ const uchar *valueData = reinterpret_cast<const uchar *>(&valueToWrite);
+ for (quint16 i = 0; i < length; ++i) {
+ const auto valueByteIdx = (i + writeOffset) / 8;
+ const auto valueBitIdx = (i + writeOffset) % 8;
+ const auto dataByteIdx = (start + i) / 8;
+ const auto dataBitIdx = (start + i) % 8;
+
+ if (valueData[valueByteIdx] & (0x01 << valueBitIdx))
+ data[dataByteIdx] |= 0x01 << dataBitIdx;
+ else
+ data[dataByteIdx] &= ~(0x01 << dataBitIdx);
+ }
+ }
+}
+
+#endif // USE_DBC_COMPATIBLE_BE_HANDLING
+
+static void encodeAscii(unsigned char *data, const QVariant &value,
+ const QCanSignalDescription &signalDesc)
+{
+ Q_ASSERT(signalDesc.bitLength() % 8 == 0);
+
+ const QByteArray ascii = value.toByteArray();
+ // The ascii array can have more or less bytes. Handle it.
+ const auto length = std::min(ascii.size() * 8, static_cast<qsizetype>(signalDesc.bitLength()));
+
+ const auto start = signalDesc.startBit();
+ for (auto i = 0; i < length; ++i) {
+ const auto dataByteIdx = (start + i) / 8;
+ const auto dataBitIdx = (start + i) % 8;
+ if (ascii.data()[i / 8] & (0x01 << (i % 8)))
+ data[dataByteIdx] |= 0x01 << dataBitIdx;
+ else
+ data[dataByteIdx] &= ~(0x01 << dataBitIdx);
+ }
+ if (length < signalDesc.bitLength()) {
+ // fill the rest of the bits with 0's
+ for (auto i = length; i < signalDesc.bitLength(); ++i)
+ data[i / 8] &= ~(0x01 << (i % 8));
+ }
+}
+
+void QCanFrameProcessorPrivate::encodeSignal(unsigned char *data, const QVariant &value,
+ const QCanSignalDescription &signalDesc)
+{
+ // We assume that signal's length does not exceed data size.
+ // That is checked as a precondition to calling this method, so we do not
+ // pass size for the data.
+ switch (signalDesc.dataFormat()) {
+ case QtCanBus::DataFormat::SignedInteger:
+ encodeValue<qint64>(data, value, signalDesc);
+ break;
+ case QtCanBus::DataFormat::UnsignedInteger:
+ encodeValue<quint64>(data, value, signalDesc);
+ break;
+ case QtCanBus::DataFormat::Float:
+ encodeValue<float>(data, value, signalDesc);
+ break;
+ case QtCanBus::DataFormat::Double:
+ encodeValue<double>(data, value, signalDesc);
+ break;
+ case QtCanBus::DataFormat::AsciiString:
+ encodeAscii(data, value, signalDesc);
+ break;
+ }
+}
+
+std::optional<QtCanBus::UniqueId>
+QCanFrameProcessorPrivate::extractUniqueId(const QCanBusFrame &frame) const
+{
+ const auto signalDataEnd = extractMaxBitNum(uidDescription.startBit(),
+ uidDescription.bitLength(),
+ uidDescription.endian());
+ const bool dataFromPayload = uidDescription.source() == QtCanBus::DataSource::Payload;
+
+ // For the FrameId case we do not really care if the frame id is extended
+ // or not, because QCanBusFrame::FrameId is anyway 32-bit unsigned.
+ const auto maxDataLength = dataFromPayload ? frame.payload().size() * 8 : 29;
+
+ if (signalDataEnd >= maxDataLength)
+ return {}; // add a more specific error description?
+
+ const QByteArray payload = frame.payload();
+ const auto frameId = frame.frameId();
+ const unsigned char *data = dataFromPayload
+ ? reinterpret_cast<const unsigned char *>(payload.data())
+ : reinterpret_cast<const unsigned char *>(&frameId);
+
+ // Now we need to do the same as when extracting a value for a signal, but
+ // without additional value conversions. We have an extractValue() template
+ // function, but it takes a QCanSignalDescription as an input parameter.
+ // To reuse the code, we generate a dummy QCanSignalDescription based on the
+ // values of uidDescription and call extractValue().
+ // This approach introduces some unneeded checks and also result conversions
+ // to/from QVariant. If this becomes a problem, we can copy-paste the code
+ // from extractValue() and remove the unneeded parts.
+
+ QCanSignalDescription dummyDesc;
+ dummyDesc.setDataSource(uidDescription.source());
+ dummyDesc.setDataEndian(uidDescription.endian());
+ dummyDesc.setStartBit(uidDescription.startBit());
+ dummyDesc.setBitLength(uidDescription.bitLength());
+ dummyDesc.setDataFormat(QtCanBus::DataFormat::UnsignedInteger);
+ // other fields are unused, so default-initialized
+
+ using UnderlyingType = std::underlying_type_t<QtCanBus::UniqueId>;
+ const QVariant val = extractValue<UnderlyingType>(data, dummyDesc);
+ return QtCanBus::UniqueId{val.value<UnderlyingType>()};
+}
+
+bool QCanFrameProcessorPrivate::fillUniqueId(unsigned char *data, quint16 sizeInBits,
+ QtCanBus::UniqueId uniqueId)
+{
+ const auto uidDataEnd = extractMaxBitNum(uidDescription.startBit(),
+ uidDescription.bitLength(),
+ uidDescription.endian());
+ if (uidDataEnd >= sizeInBits) {
+ return false; // add a more specific error description?
+ }
+
+ // Now we need to do the same as when encoding signal value into the frame,
+ // but without additional value conversions. We have encodeValue() template
+ // function, but it takes QCanSignalDescription as an input parameter.
+ // To reuse the code, we generate a dummy QCanSignalDescription based on the
+ // values of uidDescription, and call encodeValue().
+ // This approach introduces some unneeded checks and QVariant conversions.
+ // If this becomes a problem, we can copy-paste the code from encodeValue()
+ // and remove all the unneeded parts.
+
+ QCanSignalDescription dummyDesc;
+ dummyDesc.setDataSource(uidDescription.source());
+ dummyDesc.setDataEndian(uidDescription.endian());
+ dummyDesc.setStartBit(uidDescription.startBit());
+ dummyDesc.setBitLength(uidDescription.bitLength());
+ dummyDesc.setDataFormat(QtCanBus::DataFormat::UnsignedInteger);
+ // other fields are unused, so default-initialized
+
+ using UnderlyingType = std::underlying_type_t<QtCanBus::UniqueId>;
+ encodeValue<UnderlyingType>(data, QVariant::fromValue(qToUnderlying(uniqueId)), dummyDesc);
+ return true;
+}
+
+QCanFrameProcessorPrivate *QCanFrameProcessorPrivate::get(const QCanFrameProcessor &processor)
+{
+ return processor.d.get();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qcanframeprocessor.cpp"
diff --git a/src/serialbus/qcanframeprocessor.h b/src/serialbus/qcanframeprocessor.h
new file mode 100644
index 0000000..bdfbde0
--- /dev/null
+++ b/src/serialbus/qcanframeprocessor.h
@@ -0,0 +1,67 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANFRAMEPROCESSOR_H
+#define QCANFRAMEPROCESSOR_H
+
+#include <QtCore/QVariantMap>
+
+#include <QtSerialBus/qcancommondefinitions.h>
+#include <QtSerialBus/qtserialbusglobal.h>
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+class QCanBusFrame;
+class QCanMessageDescription;
+class QCanUniqueIdDescription;
+class QCanFrameProcessorPrivate;
+
+class QCanFrameProcessor
+{
+public:
+ enum class Error : quint8 {
+ None = 0,
+ InvalidFrame,
+ UnsupportedFrameFormat,
+ Decoding,
+ Encoding,
+ };
+
+ struct ParseResult {
+ QtCanBus::UniqueId uniqueId = QtCanBus::UniqueId{0};
+ QVariantMap signalValues;
+ };
+
+ Q_SERIALBUS_EXPORT QCanFrameProcessor();
+ Q_SERIALBUS_EXPORT ~QCanFrameProcessor();
+
+ Q_SERIALBUS_EXPORT QCanBusFrame prepareFrame(QtCanBus::UniqueId uniqueId,
+ const QVariantMap &signalValues);
+ Q_SERIALBUS_EXPORT ParseResult parseFrame(const QCanBusFrame &frame);
+
+ Q_SERIALBUS_EXPORT Error error() const;
+ Q_SERIALBUS_EXPORT QString errorString() const;
+ Q_SERIALBUS_EXPORT QStringList warnings() const;
+
+ Q_SERIALBUS_EXPORT QList<QCanMessageDescription> messageDescriptions() const;
+ Q_SERIALBUS_EXPORT
+ void addMessageDescriptions(const QList<QCanMessageDescription> &descriptions);
+ Q_SERIALBUS_EXPORT
+ void setMessageDescriptions(const QList<QCanMessageDescription> &descriptions);
+ Q_SERIALBUS_EXPORT void clearMessageDescriptions();
+
+ Q_SERIALBUS_EXPORT QCanUniqueIdDescription uniqueIdDescription() const;
+ Q_SERIALBUS_EXPORT void setUniqueIdDescription(const QCanUniqueIdDescription &description);
+
+private:
+ std::unique_ptr<QCanFrameProcessorPrivate> d;
+ friend class QCanFrameProcessorPrivate;
+
+ Q_DISABLE_COPY_MOVE(QCanFrameProcessor)
+};
+
+QT_END_NAMESPACE
+
+#endif // QCANFRAMEPROCESSOR_H
diff --git a/src/serialbus/qcanframeprocessor_p.h b/src/serialbus/qcanframeprocessor_p.h
new file mode 100644
index 0000000..bd36323
--- /dev/null
+++ b/src/serialbus/qcanframeprocessor_p.h
@@ -0,0 +1,54 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANFRAMEPROCESSOR_P_H
+#define QCANFRAMEPROCESSOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtserialbusexports.h"
+#include "qcanframeprocessor.h"
+#include "qcanmessagedescription.h"
+#include "qcanuniqueiddescription.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QSharedData>
+
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+class QCanFrameProcessorPrivate
+{
+public:
+ void resetErrors();
+ void setError(QCanFrameProcessor::Error err, const QString &desc);
+ void addWarning(const QString &warning);
+ QVariant decodeSignal(const QCanBusFrame &frame, const QCanSignalDescription &signalDesc);
+ QVariant parseData(const unsigned char *data, const QCanSignalDescription &signalDesc);
+ void encodeSignal(unsigned char *data, const QVariant &value,
+ const QCanSignalDescription &signalDesc);
+ std::optional<QtCanBus::UniqueId> extractUniqueId(const QCanBusFrame &frame) const;
+ bool fillUniqueId(unsigned char *data, quint16 sizeInBits, QtCanBus::UniqueId uniqueId);
+
+ static QCanFrameProcessorPrivate *get(const QCanFrameProcessor &processor);
+
+ QCanFrameProcessor::Error error = QCanFrameProcessor::Error::None;
+ QString errorString;
+ QStringList warnings;
+ QHash<QtCanBus::UniqueId, QCanMessageDescription> messages;
+ QCanUniqueIdDescription uidDescription;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCANFRAMEPROCESSOR_P_H
diff --git a/src/serialbus/qcanmessagedescription.cpp b/src/serialbus/qcanmessagedescription.cpp
new file mode 100644
index 0000000..bbb5d85
--- /dev/null
+++ b/src/serialbus/qcanmessagedescription.cpp
@@ -0,0 +1,355 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qcanmessagedescription.h"
+#include "qcanmessagedescription_p.h"
+#include "qcansignaldescription.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QSharedData>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCanMessageDescription
+ \inmodule QtSerialBus
+ \since 6.5
+ \preliminary
+
+ \brief The QCanMessageDescription class describes the rules to process a CAN
+ message and represent it in an application-defined format.
+
+ A CAN message is basically a \l QCanBusFrame. The description of a CAN
+ message includes the following:
+ \list
+ \li Message ID.
+ \li Message name.
+ \li Message length in bytes.
+ \li Source of the message (transmitter).
+ \li Description of signals in the message.
+ \endlist
+
+ The QCanMessageDescription class provides methods to control all those
+ parameters.
+
+ \section2 Message ID
+ The message ID is a unique identifier, which is used to select the proper
+ message description when decoding the incoming \l QCanBusFrame or encoding
+ a \l QCanBusFrame based on the provided data.
+
+ See \l QCanUniqueIdDescription documentation for more details on the unique
+ identifier description.
+
+ \section2 Signal Description
+ The signal description is represented by the \l QCanSignalDescription
+ class. The QCanMessageDescription class only provides a list of signals that
+ belong to the message.
+
+ \sa QCanSignalDescription, QCanUniqueIdDescription
+*/
+
+/*!
+ Creates an empty message description.
+*/
+QCanMessageDescription::QCanMessageDescription() : d(new QCanMessageDescriptionPrivate)
+{
+}
+
+/*!
+ Creates a message description with the values copied from \a other.
+*/
+QCanMessageDescription::QCanMessageDescription(const QCanMessageDescription &other) : d(other.d)
+{
+}
+
+/*!
+ \fn QCanMessageDescription::QCanMessageDescription(QCanMessageDescription &&other) noexcept
+
+ Creates a message description by moving from \a other.
+
+ \note The moved-from QCanMessageDescription object can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor or
+ one of the assignment operators is undefined.
+*/
+
+/*!
+ \fn QCanMessageDescription::~QCanMessageDescription()
+
+ Destroys this message description.
+*/
+
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCanMessageDescriptionPrivate)
+
+/*!
+ Assigns the values from \a other to this message description.
+*/
+QCanMessageDescription &QCanMessageDescription::operator=(const QCanMessageDescription &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn QCanMessageDescription &QCanMessageDescription::operator=(QCanMessageDescription &&other) noexcept
+
+ Move-assigns the values from \a other to this message description.
+
+ \note The moved-from QCanMessageDescription object can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor or
+ one of the assignment operators is undefined.
+*/
+
+/*!
+ Returns \c true when the message description is valid and \c false
+ otherwise.
+
+ A valid message description \e must have at least one signal description.
+ All signal descriptions \e must be valid as well.
+
+ \sa signalDescriptions(), QCanSignalDescription::isValid()
+*/
+bool QCanMessageDescription::isValid() const
+{
+ if (d->messageSignals.isEmpty())
+ return false;
+
+ for (const auto &sigDesc : d->messageSignals) {
+ if (!sigDesc.isValid())
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ Returns the unique identifier of the CAN message.
+
+ See the \l {Message ID} section for more information about the unique
+ identifier.
+
+ \sa setUniqueId()
+*/
+QtCanBus::UniqueId QCanMessageDescription::uniqueId() const
+{
+ return d->id;
+}
+
+/*!
+ Sets the unique identifier of the CAN message to \a id.
+
+ See the \l {Message ID} section for more information about the unique
+ identifier.
+
+ \sa uniqueId()
+*/
+void QCanMessageDescription::setUniqueId(QtCanBus::UniqueId id)
+{
+ d.detach();
+ d->id = id;
+}
+
+/*!
+ Returns the name of the CAN message.
+
+//! [qcanmessagedesc-aux-parameter]
+ This parameter is introduced only for extra description. It's not used
+ during message encoding or decoding.
+//! [qcanmessagedesc-aux-parameter]
+
+ \sa setName()
+*/
+QString QCanMessageDescription::name() const
+{
+ return d->name;
+}
+
+/*!
+ Sets the name of the CAN message to \a name.
+
+ \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
+
+ \sa name()
+*/
+void QCanMessageDescription::setName(const QString &name)
+{
+ d.detach();
+ d->name = name;
+}
+
+/*!
+ Returns the size in bytes of the CAN message.
+
+ \sa setSize()
+*/
+quint8 QCanMessageDescription::size() const
+{
+ return d->size;
+}
+
+/*!
+ Sets the size in bytes of the CAN message to \a size.
+
+ \sa size()
+*/
+void QCanMessageDescription::setSize(quint8 size)
+{
+ d.detach();
+ d->size = size;
+}
+
+/*!
+ Returns the transmitter node of the message.
+
+ \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
+
+ \sa setTransmitter()
+*/
+QString QCanMessageDescription::transmitter() const
+{
+ return d->transmitter;
+}
+
+/*!
+ Sets the transmitter node of the message to \a transmitter.
+
+ \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
+
+ \sa transmitter()
+*/
+void QCanMessageDescription::setTransmitter(const QString &transmitter)
+{
+ d.detach();
+ d->transmitter = transmitter;
+}
+
+/*!
+ Returns the comment for the message.
+
+ \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
+
+ \sa setComment()
+*/
+QString QCanMessageDescription::comment() const
+{
+ return d->comment;
+}
+
+/*!
+ Sets the comment for the message to \a text.
+
+ \include qcanmessagedescription.cpp qcanmessagedesc-aux-parameter
+
+ \sa comment()
+*/
+void QCanMessageDescription::setComment(const QString &text)
+{
+ d.detach();
+ d->comment = text;
+}
+
+/*!
+ Returns the list of signal descriptions that belong to this message
+ description.
+
+ \sa signalDescriptionForName(), addSignalDescription(),
+ setSignalDescriptions(), clearSignalDescriptions()
+*/
+QList<QCanSignalDescription> QCanMessageDescription::signalDescriptions() const
+{
+ return QList<QCanSignalDescription>(d->messageSignals.cbegin(), d->messageSignals.cend());
+}
+
+/*!
+ Returns the signal description of a signal with the name \a name.
+
+ If the message description does not have such signal description, a
+ default-constructed \l QCanSignalDescription object is returned.
+
+ \sa signalDescriptions(), addSignalDescription(), setSignalDescriptions(),
+ clearSignalDescriptions()
+*/
+QCanSignalDescription QCanMessageDescription::signalDescriptionForName(const QString &name) const
+{
+ return d->messageSignals.value(name);
+}
+
+/*!
+ Clears all the signal descriptions of this message.
+
+ \sa signalDescriptions(), signalDescriptionForName(),
+ addSignalDescription(), setSignalDescriptions()
+*/
+void QCanMessageDescription::clearSignalDescriptions()
+{
+ d.detach();
+ d->messageSignals.clear();
+}
+
+/*!
+ Adds a new signal description \a description to this message description.
+
+ If the message description already has a signal description for a signal
+ with the same name, it is overwritten.
+
+ \sa signalDescriptions(), signalDescriptionForName(),
+ setSignalDescriptions(), clearSignalDescriptions()
+*/
+void QCanMessageDescription::addSignalDescription(const QCanSignalDescription &description)
+{
+ d.detach();
+ d->messageSignals.insert(description.name(), description);
+}
+
+/*!
+ Sets the descriptions of the signals belonging to this message description
+ to \a descriptions.
+
+ \note Message description \e must have signal descriptions with unique
+ signal names, so if the \a descriptions list contains entries with
+ duplicated names, only the last entry will be added.
+
+ \sa signalDescriptions(), signalDescriptionForName(),
+ addSignalDescription(), clearSignalDescriptions()
+*/
+void QCanMessageDescription::setSignalDescriptions(const QList<QCanSignalDescription> &descriptions)
+{
+ d.detach();
+ d->messageSignals.clear();
+ d->messageSignals.reserve(descriptions.size());
+ for (const auto &desc : descriptions)
+ d->messageSignals.insert(desc.name(), desc);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug QCanMessageDescription::debugStreaming(QDebug dbg, const QCanMessageDescription &msg)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QCanMessageDescription(" << msg.name() << ", ID = " << msg.uniqueId()
+ << ", Size = " << msg.size();
+ if (!msg.transmitter().isEmpty())
+ dbg << ", Transmitter = " << msg.transmitter();
+ if (!msg.comment().isEmpty())
+ dbg << ", Comment = " << msg.comment();
+ const auto msgSignals = msg.signalDescriptions();
+ if (!msgSignals.isEmpty()) {
+ dbg << ", Signals: {";
+ bool first = true;
+ for (const auto &sig : msgSignals) {
+ if (!first)
+ dbg << ", ";
+ dbg << sig;
+ first = false;
+ }
+ dbg << "}";
+ }
+ dbg << ")";
+ return dbg;
+}
+#endif // QT_NO_DEBUG_STREAM
+
+QCanMessageDescriptionPrivate *QCanMessageDescriptionPrivate::get(const QCanMessageDescription &desc)
+{
+ return desc.d.data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/serialbus/qcanmessagedescription.h b/src/serialbus/qcanmessagedescription.h
new file mode 100644
index 0000000..522cbd9
--- /dev/null
+++ b/src/serialbus/qcanmessagedescription.h
@@ -0,0 +1,80 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANMESSAGEDESCRIPTION_H
+#define QCANMESSAGEDESCRIPTION_H
+
+#include <QtCore/QDebug>
+#include <QtCore/QExplicitlySharedDataPointer>
+
+#include <QtSerialBus/qcancommondefinitions.h>
+#include <QtSerialBus/qtserialbusglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCanSignalDescription;
+
+class QCanMessageDescriptionPrivate;
+QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QCanMessageDescriptionPrivate, Q_SERIALBUS_EXPORT)
+
+class QCanMessageDescription
+{
+public:
+ Q_SERIALBUS_EXPORT QCanMessageDescription();
+ Q_SERIALBUS_EXPORT QCanMessageDescription(const QCanMessageDescription &other);
+ QCanMessageDescription(QCanMessageDescription &&other) noexcept = default;
+ ~QCanMessageDescription() = default;
+
+ Q_SERIALBUS_EXPORT QCanMessageDescription &operator=(const QCanMessageDescription &other);
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCanMessageDescription)
+
+ void swap(QCanMessageDescription &other) noexcept { d.swap(other.d); }
+
+ Q_SERIALBUS_EXPORT bool isValid() const;
+
+ Q_SERIALBUS_EXPORT QtCanBus::UniqueId uniqueId() const;
+ Q_SERIALBUS_EXPORT void setUniqueId(QtCanBus::UniqueId id);
+
+ Q_SERIALBUS_EXPORT QString name() const;
+ Q_SERIALBUS_EXPORT void setName(const QString &name);
+
+ Q_SERIALBUS_EXPORT quint8 size() const;
+ Q_SERIALBUS_EXPORT void setSize(quint8 size);
+
+ Q_SERIALBUS_EXPORT QString transmitter() const;
+ Q_SERIALBUS_EXPORT void setTransmitter(const QString &transmitter);
+
+ Q_SERIALBUS_EXPORT QString comment() const;
+ Q_SERIALBUS_EXPORT void setComment(const QString &text);
+
+ Q_SERIALBUS_EXPORT QList<QCanSignalDescription> signalDescriptions() const;
+ Q_SERIALBUS_EXPORT QCanSignalDescription signalDescriptionForName(const QString &name) const;
+ Q_SERIALBUS_EXPORT void clearSignalDescriptions();
+ Q_SERIALBUS_EXPORT void addSignalDescription(const QCanSignalDescription &description);
+ Q_SERIALBUS_EXPORT
+ void setSignalDescriptions(const QList<QCanSignalDescription> &descriptions);
+
+private:
+ QExplicitlySharedDataPointer<QCanMessageDescriptionPrivate> d;
+ friend class QCanMessageDescriptionPrivate;
+
+ friend void qHash(const QCanMessageDescription &desc, size_t seed) noexcept = delete;
+ friend void operator==(const QCanMessageDescription &lhs,
+ const QCanMessageDescription &rhs) noexcept = delete;
+ friend void operator!=(const QCanMessageDescription &lhs,
+ const QCanMessageDescription &rhs) noexcept = delete;
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend QDebug operator<<(QDebug dbg, const QCanMessageDescription &msg)
+ {
+ return debugStreaming(dbg, msg);
+ }
+ Q_SERIALBUS_EXPORT static QDebug debugStreaming(QDebug dbg, const QCanMessageDescription &msg);
+#endif // QT_NO_DEBUG_STREAM
+};
+
+Q_DECLARE_SHARED(QCanMessageDescription)
+
+QT_END_NAMESPACE
+
+#endif // QCANMESSAGEDESCRIPTION_H
diff --git a/src/serialbus/qcanmessagedescription_p.h b/src/serialbus/qcanmessagedescription_p.h
new file mode 100644
index 0000000..9090291
--- /dev/null
+++ b/src/serialbus/qcanmessagedescription_p.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANMESSAGEDESCRIPTION_P_H
+#define QCANMESSAGEDESCRIPTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtserialbusexports.h"
+#include "qcanmessagedescription.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_SERIALBUS_EXPORT QCanMessageDescriptionPrivate : public QSharedData
+{
+public:
+ QString name;
+ QString transmitter;
+ QString comment;
+ QtCanBus::UniqueId id{0};
+ quint8 size = 0; // even CAN FD has max 64 bytes
+ QHash<QString, QCanSignalDescription> messageSignals;
+
+ inline bool isShared() const { return ref.loadRelaxed() != 1; }
+ static QCanMessageDescriptionPrivate *get(const QCanMessageDescription &desc);
+};
+
+QT_END_NAMESPACE
+
+#endif // QCANMESSAGEDESCRIPTION_P_H
diff --git a/src/serialbus/qcansignaldescription.cpp b/src/serialbus/qcansignaldescription.cpp
new file mode 100644
index 0000000..0df6a4a
--- /dev/null
+++ b/src/serialbus/qcansignaldescription.cpp
@@ -0,0 +1,847 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qcansignaldescription.h"
+#include "qcansignaldescription_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCanSignalDescription
+ \inmodule QtSerialBus
+ \since 6.5
+ \preliminary
+
+ \brief The QCanSignalDescription class describes the rules to extract one
+ value out of the CAN frame and represent it in an application-defined
+ format.
+
+ The QCanSignalDescription class can be used to provide a signal description
+ and later use it to decode a received \l QCanBusFrame or encode the input
+ data into a \l QCanBusFrame that can be sent to the receiver.
+
+ \section2 General Description
+
+ Each CAN frame can contain multiple values. The rules to extract the values
+ from a CAN frame include the following:
+ \list
+ \li Data source (frame ID or payload).
+ \li Data endianness. See \l {Data Endianness Processing} section for
+ more details.
+ \li Data format.
+ \li Start bit position.
+ \li Data length in bits.
+ \li Multiplexing options.
+ \endlist
+
+ Start bit position is specified relative to the selected data source. The
+ bits are counted starting from the LSB.
+
+ Once the data is extracted, it might require conversion to an
+ application-defined format. The following parameters can be used for that:
+ \list
+ \li Various parameters for converting the extracted value to a physical
+ value (factor, offset, scale).
+ \li Expected data range.
+ \li Data units.
+ \endlist
+
+ The QCanSignalDescription class provides methods to control all those
+ parameters.
+
+ \section2 Data Endianness Processing
+
+ Little endian and big endian data is encoded differently.
+ For big endian values, start bit positions are given for the most
+ significant bit. For little endian values, the start position is that of
+ the least significant bit.
+
+ Let's consider two examples. In both examples we will encode two 12-bit
+ values in the 3-byte payload.
+
+ \section3 Little Endian
+
+ For the little endian case the data layout can be represented by the
+ following image:
+
+ \image canbus_signals_le.png
+
+ Here the columns represent bit numbers, and the rows represent byte numbers.
+ \c {LSB} marks the first (least significant) bit of the value, and \c {MSB}
+ marks the last (most significant) bit of the value. The blue color marks the
+ first value, and the orange color marks the second value.
+
+ The information about these values will be encoded in QCanSignalDescription
+ in the following way:
+
+ \code
+ QCanSignalDescription signal1;
+ signal1.setDataEndian(QSysInfo::Endian::LittleEndian);
+ signal1.setStartBit(0);
+ signal1.setBitLength(12);
+ // other parameters for signal1
+
+ QCanSignalDescription signal2;
+ signal2.setDataEndian(QSysInfo::Endian::LittleEndian);
+ signal2.setStartBit(12);
+ signal2.setBitLength(12);
+ // other parameters for signal2
+ \endcode
+
+ \section3 Big Endian
+
+ The following image represents the value layout for the big endian case:
+
+ \image canbus_signals_be.png
+
+ The values can be represented in QCanSignalDescription in the following
+ way:
+
+ \code
+ QCanSignalDescription signal1;
+ signal1.setDataEndian(QSysInfo::Endian::BigEndian);
+ signal1.setStartBit(7);
+ signal1.setBitLength(12);
+ // other parameters for signal1
+
+ QCanSignalDescription signal2;
+ signal2.setDataEndian(QSysInfo::Endian::BigEndian);
+ signal2.setStartBit(11);
+ signal2.setBitLength(12);
+ // other parameters for signal2
+ \endcode
+
+ Note how the start bits are different from the little endian case. Also the
+ values are aligned differently.
+
+ \section2 Multiplexed Signals Explained
+
+ There are two common ways to encode the data in the CAN payload:
+ \list
+ \li Each range of bits always represents the same signal. For example,
+ \c {Bytes 0-1} in a payload can represent an engine speed (in rpm),
+ and \c {Bytes 2-3} can represent the vehicle speed (in km/h).
+ \li The same range of bits can represent different data, depending on
+ the values of some other bits in the payload. For example, if
+ \c {Byte 0} has the value \c {0}, the \c {Bytes 1-2} represent an
+ engine speed (in rpm), and if \c {Byte 0} has the value \c {1}, the
+ same \c {Bytes 1-2} represent a vehicle speed (in km/h).
+ \endlist
+
+ The second case uses signal multiplexing. In the provided example we will
+ have three signals. The first signal represents the value of \c {Byte 0} and
+ acts like a multiplexor signal. The other two signals represent an engine
+ speed and a vehicle speed respectively, but only one of them can be
+ extracted from the CAN payload at a time. Which signal should be extracted
+ is defined by the value of the multiplexor signal.
+
+ In more complicated cases the payload can have multiple multiplexor signals.
+ In such cases the signal can be extracted from the payload only when all
+ multiplexors contain the expected values.
+
+ \section2 Value Conversions
+
+ In many cases the signals transferred over CAN bus cannot hold the full
+ range of the physical values that they represent. To overcome these
+ limitations, the physical values are converted to a smaller range before
+ transmission, and can be restored on the receiving end.
+
+ The following formulas are used to convert between the physical value and
+ the signal's value:
+
+ \badcode
+ physicalValue = scaling * (signalValue * factor + offset);
+ signalValue = (physicalValue / scaling - offset) / factor;
+ \endcode
+
+ The factor and scaling parameters cannot be equal to \c {0}.
+
+ If any of the parameters equals to \l qQNaN(), it is not used during the
+ conversion. If all of the parameters are equal to \l qQNaN() (which is the
+ default), the conversion is not performed.
+*/
+
+/*!
+ \struct QCanSignalDescription::MultiplexValueRange
+ \inmodule QtSerialBus
+ \since 6.5
+
+ \brief Defines a range of values for a multiplexor signal.
+
+ Each multiplexor signal can have several ranges of values assigned to it.
+ This type represents one range. Both minimum and maximum values are
+ included in the range. Minimum and maximum values can be equal, so a
+ MultiplexValueRange is never empty. If maximum is less than minimum, the
+ values will be swapped while doing the range check.
+
+ \sa {Multiplexed Signals Explained}
+*/
+
+/*!
+ \variable QCanSignalDescription::MultiplexValueRange::minimum
+ \brief the minimum value of the range.
+*/
+
+/*!
+ \variable QCanSignalDescription::MultiplexValueRange::maximum
+ \brief the maximum value of the range.
+*/
+
+/*!
+ \typealias QCanSignalDescription::MultiplexValues
+*/
+
+/*!
+ \typealias QCanSignalDescription::MultiplexSignalValues
+*/
+
+/*!
+ Creates an empty signal description.
+*/
+QCanSignalDescription::QCanSignalDescription() : d(new QCanSignalDescriptionPrivate)
+{
+}
+
+/*!
+ Creates a signal description with the values copied from \a other.
+*/
+QCanSignalDescription::QCanSignalDescription(const QCanSignalDescription &other) : d(other.d)
+{
+}
+
+/*!
+ \fn QCanSignalDescription::QCanSignalDescription(QCanSignalDescription &&other) noexcept
+
+ Creates a signal description by moving from \a other.
+
+ \note The moved-from QCanSignalDescription object can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor or
+ one of the assignment operators is undefined.
+*/
+
+/*!
+ \fn QCanSignalDescription::~QCanSignalDescription()
+
+ Destroys this signal description.
+*/
+
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCanSignalDescriptionPrivate)
+
+/*!
+ Assigns the values from \a other to this signal description.
+*/
+QCanSignalDescription &QCanSignalDescription::operator=(const QCanSignalDescription &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn QCanSignalDescription &QCanSignalDescription::operator=(QCanSignalDescription &&other) noexcept
+
+ Move-assigns the values from \a other to this signal description.
+
+ \note The moved-from QCanSignalDescription object can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor or
+ one of the assignment operators is undefined.
+*/
+
+/*!
+ Returns \c true when the signal description is valid and \c false otherwise.
+
+ A valid signal description \e must fulfill the following conditions:
+ \list
+ \li have a non-empty \l name()
+ \li have \l bitLength() \c {== 32} if the \l dataFormat() is
+ \l {QtCanBus::DataFormat::}{Float}
+ \li have \l bitLength() \c {== 64} if the \l dataFormat() is
+ \l {QtCanBus::DataFormat::}{Double}
+ \li the \l bitLength() \e must be a multiple of \c 8 if the
+ \l dataFormat() is \l {QtCanBus::DataFormat::}{AsciiString}
+ \li the \l bitLength() \e must be greater than \c 0 and less than or
+ equal to \c {64}.
+ \endlist
+
+ \sa bitLength(), dataFormat(), name()
+*/
+bool QCanSignalDescription::isValid() const
+{
+ const bool formatMatch = [this]() {
+ if (d->format == QtCanBus::DataFormat::Float)
+ return d->dataLength == 32;
+ if (d->format == QtCanBus::DataFormat::Double)
+ return d->dataLength == 64;
+ if (d->format == QtCanBus::DataFormat::AsciiString)
+ return d->dataLength % 8 == 0;
+ return d->dataLength > 0 && d->dataLength <= 64;
+ }();
+ return !d->name.isEmpty() && formatMatch;
+}
+
+/*!
+ Returns the name of the signal.
+
+ \sa setName(), isValid()
+*/
+QString QCanSignalDescription::name() const
+{
+ return d->name;
+}
+
+/*!
+ Sets the name of the signal to \a name.
+
+ The signal's name must be unique within a CAN message.
+
+ \sa name()
+*/
+void QCanSignalDescription::setName(const QString &name)
+{
+ d.detach();
+ d->name = name;
+}
+
+/*!
+ Returns the physical unit (e.g. km/h) of the signal's value or an empty
+ string if the unit is not set.
+
+//! [qcansignaldesc-aux-parameter]
+ This parameter is introduced only for extra description. It's not used
+ during signal processing.
+//! [qcansignaldesc-aux-parameter]
+
+ \sa setPhysicalUnit()
+*/
+QString QCanSignalDescription::physicalUnit() const
+{
+ return d->unit;
+}
+
+/*!
+ Sets the physical \a unit (e.g. km/h) of the signal's value.
+
+ \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
+
+ \sa physicalUnit()
+*/
+void QCanSignalDescription::setPhysicalUnit(const QString &unit)
+{
+ d.detach();
+ d->unit = unit;
+}
+
+/*!
+ Returns the receiver node for this signal.
+
+ \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
+
+ \sa setReceiver()
+*/
+QString QCanSignalDescription::receiver() const
+{
+ return d->receiver;
+}
+
+/*!
+ Sets the \a receiver node for this signal.
+
+ \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
+
+ \sa receiver()
+*/
+void QCanSignalDescription::setReceiver(const QString &receiver)
+{
+ d.detach();
+ d->receiver = receiver;
+}
+
+/*!
+ Returns the comment for the signal.
+
+ \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
+
+ \sa setComment()
+*/
+QString QCanSignalDescription::comment() const
+{
+ return d->comment;
+}
+
+/*!
+ Sets the comment for the signal to \a text.
+
+ \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
+
+ \sa comment()
+*/
+void QCanSignalDescription::setComment(const QString &text)
+{
+ d.detach();
+ d->comment = text;
+}
+
+/*!
+ Returns the data source of the signal's value.
+
+ By default, \l {QtCanBus::DataSource::}{Payload} is used.
+
+ \sa setDataSource(), QtCanBus::DataSource
+*/
+QtCanBus::DataSource QCanSignalDescription::dataSource() const
+{
+ return d->source;
+}
+
+/*!
+ Sets the data source of the signal's value to \a source.
+
+ \sa dataSource(), QtCanBus::DataSource
+*/
+void QCanSignalDescription::setDataSource(QtCanBus::DataSource source)
+{
+ d.detach();
+ d->source = source;
+}
+
+/*!
+ Returns the data endian of the signal's value.
+
+ By default, \l {QSysInfo::}{BigEndian} is used.
+
+ \note The data endian is ignored if the \l dataFormat() is set to
+ \l {QtCanBus::DataFormat::}{AsciiString}.
+
+ \sa setDataEndian(), QSysInfo::Endian
+*/
+QSysInfo::Endian QCanSignalDescription::dataEndian() const
+{
+ return d->endian;
+}
+
+/*!
+ Sets the data endian of the signal's value to \a endian.
+
+ \sa dataEndian(), QSysInfo::Endian
+*/
+void QCanSignalDescription::setDataEndian(QSysInfo::Endian endian)
+{
+ d.detach();
+ d->endian = endian;
+}
+
+/*!
+ Returns the data format of the signal's value.
+
+ By default, \l {QtCanBus::DataFormat::}{SignedInteger} is used.
+
+ \sa setDataFormat(), QtCanBus::DataFormat
+*/
+QtCanBus::DataFormat QCanSignalDescription::dataFormat() const
+{
+ return d->format;
+}
+
+/*!
+ Sets the data format of the signal's value to \a format.
+
+ \sa dataFormat(), QtCanBus::DataFormat
+*/
+void QCanSignalDescription::setDataFormat(QtCanBus::DataFormat format)
+{
+ d.detach();
+ d->format = format;
+}
+
+/*!
+ Returns the start bit of the signal's value in the \l dataSource().
+
+ \sa setStartBit(), bitLength(), setBitLength()
+*/
+quint16 QCanSignalDescription::startBit() const
+{
+ return d->startBit;
+}
+
+/*!
+ Sets the start bit of the signal's value in the \l dataSource() to \a bit.
+
+ \sa startBit(), bitLength(), setBitLength()
+*/
+void QCanSignalDescription::setStartBit(quint16 bit)
+{
+ d.detach();
+ d->startBit = bit;
+}
+
+/*!
+ Returns the bit length of the signal's value.
+
+ \sa setBitLength(), startBit(), setStartBit()
+*/
+quint16 QCanSignalDescription::bitLength() const
+{
+ return d->dataLength;
+}
+
+/*!
+ Sets the bit length of the signal's value to \a length.
+
+ \sa bitLength(), startBit(), setStartBit()
+*/
+void QCanSignalDescription::setBitLength(quint16 length)
+{
+ d.detach();
+ d->dataLength = length;
+}
+
+/*!
+ Returns the factor that is used to convert the signal's value to a physical
+ value and back.
+
+ By default the function returns \l qQNaN(), which means that a factor is not
+ used.
+
+ The \l {Value Conversions} section explains how this parameter is used.
+
+ \sa setFactor(), offset(), scaling()
+*/
+double QCanSignalDescription::factor() const
+{
+ return d->factor;
+}
+
+/*!
+ Sets the factor that is used to convert the signal's value to a physical
+ value and back to \a factor.
+
+ Pass \l qQNaN() to this method to skip this parameter during the conversion.
+
+ The factor cannot be 0. An attempt to set a zero factor is equivalent to
+ setting it to \l qQNaN().
+
+ The \l {Value Conversions} section explains how this parameter is used.
+
+ \sa factor(), setOffset(), setScaling()
+*/
+void QCanSignalDescription::setFactor(double factor)
+{
+ d.detach();
+ if (qFuzzyIsNull(factor))
+ d->factor = qQNaN();
+ else
+ d->factor = factor;
+}
+
+/*!
+ Returns the offset that is used to convert the signal's value to a physical
+ value and back.
+
+ By default the function returns \l qQNaN(), which means that an offset is
+ not used.
+
+ The \l {Value Conversions} section explains how this parameter is used.
+
+ \sa setOffset(), factor(), scaling()
+*/
+double QCanSignalDescription::offset() const
+{
+ return d->offset;
+}
+
+/*!
+ Sets the offset that is used to convert the signal's value to a physical
+ value and back to \a offset.
+
+ Pass \l qQNaN() to this method to skip this parameter during the conversion.
+
+ The \l {Value Conversions} section explains how this parameter is used.
+
+ \sa offset(), setFactor(), setScaling()
+*/
+void QCanSignalDescription::setOffset(double offset)
+{
+ d.detach();
+ d->offset = offset;
+}
+
+/*!
+ Returns the scaling that is used to convert the signal's value to a physical
+ value and back.
+
+ By default the function returns \l qQNaN(), which means that scaling is not
+ used.
+
+ The \l {Value Conversions} section explains how this parameter is used.
+
+ \sa setScaling(), offset(), factor()
+*/
+double QCanSignalDescription::scaling() const
+{
+ return d->scaling;
+}
+
+/*!
+ Sets the scaling that is used to convert the signal's value to a physical
+ value and back to \a scaling.
+
+ Pass \l qQNaN() to this method to skip this parameter during the conversion.
+
+ The scaling cannot be 0. An attempt to set zero scaling is equivalent to
+ setting it to \l qQNaN().
+
+ The \l {Value Conversions} section explains how this parameter is used.
+
+ \sa scaling(), setOffset(), setFactor()
+*/
+void QCanSignalDescription::setScaling(double scaling)
+{
+ d.detach();
+ if (qFuzzyIsNull(scaling))
+ d->scaling = qQNaN();
+ else
+ d->scaling = scaling;
+}
+
+/*!
+ Returns the minimum supported value for the signal.
+
+ By default the function returns \l qQNaN(), which means that there is no
+ minimum value.
+
+ \sa setRange(), maximum()
+*/
+double QCanSignalDescription::minimum() const
+{
+ return d->minimum;
+}
+
+/*!
+ Returns the maximum supported value for the signal.
+
+ By default the function returns \l qQNaN(), which means that there is no
+ maximum value.
+
+ \sa setRange(), minimum()
+*/
+double QCanSignalDescription::maximum() const
+{
+ return d->maximum;
+}
+
+/*!
+ Sets the \a minimum and \a maximum for the signal's value.
+
+ Setting one or both of the parameters to \l qQNaN() means that the
+ corresponding limit will not be used.
+
+ \sa minimum(), maximum()
+*/
+void QCanSignalDescription::setRange(double minimum, double maximum)
+{
+ d.detach();
+ if (qIsNaN(minimum) || qIsNaN(maximum) || minimum <= maximum) {
+ d->minimum = minimum;
+ d->maximum = maximum;
+ } else {
+ qWarning("Minimum value is greater than maximum. The values will be swapped.");
+ d->minimum = maximum;
+ d->maximum = minimum;
+ }
+}
+
+/*!
+ Returns the multiplex state of the signal.
+
+ See the \l {Multiplexed Signals Explained} section for more details on
+ multiplexed signals.
+
+ By default this method returns \l {QtCanBus::MultiplexState::}{None}.
+
+ \sa setMultiplexState(), QtCanBus::MultiplexState
+*/
+QtCanBus::MultiplexState QCanSignalDescription::multiplexState() const
+{
+ return d->muxState;
+}
+
+/*!
+ Sets the multiplex state of the signal to \a state.
+
+ See the \l {Multiplexed Signals Explained} section for more details on
+ multiplexed signals.
+
+ \sa multiplexState(), QtCanBus::MultiplexState
+*/
+void QCanSignalDescription::setMultiplexState(QtCanBus::MultiplexState state)
+{
+ d.detach();
+ d->muxState = state;
+}
+
+/*!
+ Returns the \l {Multiplexed Signals Explained}{multiplexor signals} and
+ their desired values that are used to properly identify this signal.
+
+ The returned hash contains signal names as keys and respective desired
+ ranges of values as values.
+
+ This signal's value can be extracted from the payload only when all the
+ signals from the hash have the expected values.
+
+ \sa multiplexState(), clearMultiplexSignals(), setMultiplexSignals(),
+ addMultiplexSignal()
+*/
+QCanSignalDescription::MultiplexSignalValues QCanSignalDescription::multiplexSignals() const
+{
+ return d->muxSignals;
+}
+
+/*!
+ Removes all \l {Multiplexed Signals Explained}{multiplexor signals} for
+ this signal.
+
+ \sa multiplexSignals(), setMultiplexSignals(), addMultiplexSignal()
+*/
+void QCanSignalDescription::clearMultiplexSignals()
+{
+ d.detach();
+ d->muxSignals.clear();
+}
+
+/*!
+ Sets the \l {Multiplexed Signals Explained}{multiplexor signals} for this
+ signal to \a multiplexorSignals.
+
+ The \a multiplexorSignals hash \e must contain signal names as keys and
+ respective desired value ranges as values.
+
+ \sa multiplexState(), multiplexSignals(), clearMultiplexSignals(),
+ addMultiplexSignal()
+*/
+void QCanSignalDescription::setMultiplexSignals(const MultiplexSignalValues &multiplexorSignals)
+{
+ d.detach();
+ d->muxSignals = multiplexorSignals;
+}
+
+/*!
+ Adds a new \l {Multiplexed Signals Explained}{multiplexor signal} for this
+ signal. The \a name parameter contains the name of the multiplexor signal,
+ and the \a ranges parameter contains the desired value ranges.
+
+ If this signal already has desired value ranges for the multiplexor signal
+ \a name, the ranges are overwritten.
+
+ \sa multiplexState(), multiplexSignals(), clearMultiplexSignals(),
+ setMultiplexSignals()
+*/
+void QCanSignalDescription::addMultiplexSignal(const QString &name, const MultiplexValues &ranges)
+{
+ d.detach();
+ d->muxSignals.insert(name, ranges);
+}
+
+/*!
+ \overload
+
+ This is a convenience overload for the case when the multiplexor signal is
+ expected to have only one specific value, not a range of values.
+
+ The \a name parameter contains the name of the multiplexor signal,
+ and the \a value parameter contains the desired value.
+
+ If this signal already has desired value ranges for the multiplexor signal
+ \a name, the ranges are overwritten.
+
+ \sa multiplexState(), multiplexSignals(), clearMultiplexSignals(),
+ setMultiplexSignals()
+*/
+void QCanSignalDescription::addMultiplexSignal(const QString &name, const QVariant &value)
+{
+ d.detach();
+ d->muxSignals.insert(name, { {value, value} });
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug QCanSignalDescription::debugStreaming(QDebug dbg, const QCanSignalDescription &sig)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QCanSignalDescription(" << sig.name() << ", Source = " << sig.dataSource()
+ << ", Format = " << sig.dataFormat() << ", Endian = " << sig.dataEndian()
+ << ", StartBit = " << sig.startBit() << ", BitLength = " << sig.bitLength();
+ if (!sig.physicalUnit().isEmpty())
+ dbg << ", Units = " << sig.physicalUnit();
+ if (!sig.receiver().isEmpty())
+ dbg << ", Receiver = " << sig.receiver();
+ if (!sig.comment().isEmpty())
+ dbg << ", Comment = " << sig.comment();
+ dbg << ", Factor = " << sig.factor() << ", Offset = " << sig.offset()
+ << ", Scaling = " << sig.scaling();
+ dbg << ", Minimum = " << sig.minimum() << ", Maximum = " << sig.maximum();
+ dbg << ", Multiplex State = " << sig.multiplexState();
+ const auto muxSignals = sig.multiplexSignals();
+ if (!muxSignals.isEmpty()) {
+ dbg << ", Multiplexor Signals: {";
+ for (auto it = muxSignals.cbegin(); it != muxSignals.cend(); ++it) {
+ if (it != muxSignals.cbegin())
+ dbg << ", ";
+ dbg << "(" << it.key() << ", " << it.value() << ")";
+ }
+ dbg << "}";
+ }
+ dbg << ")";
+ return dbg;
+}
+
+QDebug QCanSignalDescription::MultiplexValueRange::debugStreaming(QDebug dbg,
+ const MultiplexValueRange &range)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "MultiplexValueRange(" << range.minimum << ", " << range.maximum << ")";
+ return dbg;
+}
+#endif // QT_NO_DEBUG_STREAM
+
+template <typename T>
+static bool checkValue(const QVariant &valueVar,
+ const QCanSignalDescription::MultiplexValues &ranges)
+{
+ const T val = valueVar.value<T>();
+ for (const auto &pair : ranges) {
+ T min = pair.minimum.value<T>();
+ T max = pair.maximum.value<T>();
+ if (min > max)
+ max = std::exchange(min, max);
+ if (val >= min && val <= max)
+ return true;
+ }
+ return false;
+}
+
+bool QCanSignalDescriptionPrivate::muxValueInRange(
+ const QVariant &value, const QCanSignalDescription::MultiplexValues &ranges) const
+{
+ // Use the current data format to convert QVariant values.
+ // Do we really need it for Float, Double and Ascii?
+ switch (format) {
+ case QtCanBus::DataFormat::SignedInteger:
+ return checkValue<qint64>(value, ranges);
+ case QtCanBus::DataFormat::UnsignedInteger:
+ return checkValue<quint64>(value, ranges);
+ case QtCanBus::DataFormat::Float:
+ return checkValue<float>(value, ranges);
+ case QtCanBus::DataFormat::Double:
+ return checkValue<double>(value, ranges);
+ case QtCanBus::DataFormat::AsciiString:
+ return checkValue<QByteArray>(value, ranges);
+ }
+
+ Q_UNREACHABLE_RETURN(false);
+}
+
+QCanSignalDescriptionPrivate *QCanSignalDescriptionPrivate::get(const QCanSignalDescription &desc)
+{
+ return desc.d.data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/serialbus/qcansignaldescription.h b/src/serialbus/qcansignaldescription.h
new file mode 100644
index 0000000..65fd1f2
--- /dev/null
+++ b/src/serialbus/qcansignaldescription.h
@@ -0,0 +1,135 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANSIGNALDESCRIPTION_H
+#define QCANSIGNALDESCRIPTION_H
+
+#include <QtCore/QDebug>
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QVariant>
+
+#include <QtSerialBus/qcancommondefinitions.h>
+#include <QtSerialBus/qtserialbusglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCanSignalDescriptionPrivate;
+QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QCanSignalDescriptionPrivate, Q_SERIALBUS_EXPORT)
+
+class QCanSignalDescription
+{
+public:
+ struct MultiplexValueRange {
+ QVariant minimum;
+ QVariant maximum;
+ private:
+ friend bool operator==(const MultiplexValueRange &lhs,
+ const MultiplexValueRange &rhs) noexcept
+ {
+ return lhs.minimum == rhs.minimum && lhs.maximum == rhs.maximum;
+ }
+ friend bool operator!=(const MultiplexValueRange &lhs,
+ const MultiplexValueRange &rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+ friend size_t qHash(const MultiplexValueRange &, size_t) noexcept = delete;
+#ifndef QT_NO_DEBUG_STREAM
+ friend QDebug operator<<(QDebug dbg, const MultiplexValueRange &range)
+ {
+ return debugStreaming(dbg, range);
+ }
+ Q_SERIALBUS_EXPORT
+ static QDebug debugStreaming(QDebug dbg, const MultiplexValueRange &range);
+#endif // QT_NO_DEBUG_STREAM
+ };
+ using MultiplexValues = QList<MultiplexValueRange>;
+ using MultiplexSignalValues = QHash<QString, MultiplexValues>;
+
+
+ Q_SERIALBUS_EXPORT QCanSignalDescription();
+ Q_SERIALBUS_EXPORT QCanSignalDescription(const QCanSignalDescription &other);
+ QCanSignalDescription(QCanSignalDescription &&other) noexcept = default;
+ ~QCanSignalDescription() = default;
+
+ Q_SERIALBUS_EXPORT QCanSignalDescription &operator=(const QCanSignalDescription &other);
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCanSignalDescription)
+
+ void swap(QCanSignalDescription &other) noexcept { d.swap(other.d); }
+
+ Q_SERIALBUS_EXPORT bool isValid() const;
+
+ Q_SERIALBUS_EXPORT QString name() const;
+ Q_SERIALBUS_EXPORT void setName(const QString &name);
+
+ Q_SERIALBUS_EXPORT QString physicalUnit() const;
+ Q_SERIALBUS_EXPORT void setPhysicalUnit(const QString &unit);
+
+ Q_SERIALBUS_EXPORT QString receiver() const;
+ Q_SERIALBUS_EXPORT void setReceiver(const QString &receiver);
+
+ Q_SERIALBUS_EXPORT QString comment() const;
+ Q_SERIALBUS_EXPORT void setComment(const QString &text);
+
+ Q_SERIALBUS_EXPORT QtCanBus::DataSource dataSource() const;
+ Q_SERIALBUS_EXPORT void setDataSource(QtCanBus::DataSource source);
+
+ Q_SERIALBUS_EXPORT QSysInfo::Endian dataEndian() const;
+ Q_SERIALBUS_EXPORT void setDataEndian(QSysInfo::Endian endian);
+
+ Q_SERIALBUS_EXPORT QtCanBus::DataFormat dataFormat() const;
+ Q_SERIALBUS_EXPORT void setDataFormat(QtCanBus::DataFormat format);
+
+ Q_SERIALBUS_EXPORT quint16 startBit() const;
+ Q_SERIALBUS_EXPORT void setStartBit(quint16 bit);
+
+ Q_SERIALBUS_EXPORT quint16 bitLength() const;
+ Q_SERIALBUS_EXPORT void setBitLength(quint16 length);
+
+ Q_SERIALBUS_EXPORT double factor() const;
+ Q_SERIALBUS_EXPORT void setFactor(double factor);
+
+ Q_SERIALBUS_EXPORT double offset() const;
+ Q_SERIALBUS_EXPORT void setOffset(double offset);
+
+ Q_SERIALBUS_EXPORT double scaling() const;
+ Q_SERIALBUS_EXPORT void setScaling(double scaling);
+
+ Q_SERIALBUS_EXPORT double minimum() const;
+ Q_SERIALBUS_EXPORT double maximum() const;
+ Q_SERIALBUS_EXPORT void setRange(double minimum, double maximum);
+
+ Q_SERIALBUS_EXPORT QtCanBus::MultiplexState multiplexState() const;
+ Q_SERIALBUS_EXPORT void setMultiplexState(QtCanBus::MultiplexState state);
+
+ Q_SERIALBUS_EXPORT MultiplexSignalValues multiplexSignals() const;
+ Q_SERIALBUS_EXPORT void clearMultiplexSignals();
+ Q_SERIALBUS_EXPORT void setMultiplexSignals(const MultiplexSignalValues &multiplexorSignals);
+ Q_SERIALBUS_EXPORT void addMultiplexSignal(const QString &name,
+ const MultiplexValues &ranges);
+ Q_SERIALBUS_EXPORT void addMultiplexSignal(const QString &name, const QVariant &value);
+
+private:
+ QExplicitlySharedDataPointer<QCanSignalDescriptionPrivate> d;
+ friend class QCanSignalDescriptionPrivate;
+
+ friend void qHash(const QCanSignalDescription &desc, size_t seed) noexcept = delete;
+ friend void operator==(const QCanSignalDescription &lhs,
+ const QCanSignalDescription &rhs) noexcept = delete;
+ friend void operator!=(const QCanSignalDescription &lhs,
+ const QCanSignalDescription &rhs) noexcept = delete;
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend QDebug operator<<(QDebug dbg, const QCanSignalDescription &sig)
+ {
+ return debugStreaming(dbg, sig);
+ }
+ Q_SERIALBUS_EXPORT static QDebug debugStreaming(QDebug dbg, const QCanSignalDescription &sig);
+#endif // QT_NO_DEBUG_STREAM
+};
+
+Q_DECLARE_SHARED(QCanSignalDescription)
+
+QT_END_NAMESPACE
+
+#endif // QCANSIGNALDESCRIPTION_H
diff --git a/src/serialbus/qcansignaldescription_p.h b/src/serialbus/qcansignaldescription_p.h
new file mode 100644
index 0000000..c054761
--- /dev/null
+++ b/src/serialbus/qcansignaldescription_p.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANSIGNALDESCRIPTION_P_H
+#define QCANSIGNALDESCRIPTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtserialbusexports.h"
+#include "qcansignaldescription.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QSharedData>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class Q_SERIALBUS_EXPORT QCanSignalDescriptionPrivate : public QSharedData
+{
+public:
+ QString name;
+ QString unit;
+ QString receiver;
+ QString comment;
+ QtCanBus::DataSource source = QtCanBus::DataSource::Payload;
+ QSysInfo::Endian endian = QSysInfo::Endian::BigEndian;
+ QtCanBus::DataFormat format = QtCanBus::DataFormat::SignedInteger;
+ quint16 startBit = 0;
+ quint16 dataLength = 0;
+ // for conversion, possibly unused
+ double factor = qQNaN();
+ double offset = qQNaN();
+ double scaling = qQNaN();
+ // expected range, possibly unused
+ double minimum = qQNaN();
+ double maximum = qQNaN();
+ // multiplexing state
+ QtCanBus::MultiplexState muxState = QtCanBus::MultiplexState::None;
+ // Multiplexed values. The key of the hash represents the multiplex switch
+ // name, and the value represents the valid range(s) of the mux switch
+ // values.
+ QCanSignalDescription::MultiplexSignalValues muxSignals;
+
+ bool muxValueInRange(const QVariant &value,
+ const QCanSignalDescription::MultiplexValues &ranges) const;
+
+ inline bool isShared() const { return ref.loadRelaxed() != 1; }
+ static QCanSignalDescriptionPrivate *get(const QCanSignalDescription &desc);
+};
+
+QT_END_NAMESPACE
+
+#endif // QCANSIGNALDESCRIPTION_P_H
diff --git a/src/serialbus/qcanuniqueiddescription.cpp b/src/serialbus/qcanuniqueiddescription.cpp
new file mode 100644
index 0000000..3ec45b4
--- /dev/null
+++ b/src/serialbus/qcanuniqueiddescription.cpp
@@ -0,0 +1,210 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qcanuniqueiddescription.h"
+#include "qcanuniqueiddescription_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCanUniqueIdDescription
+ \inmodule QtSerialBus
+ \since 6.5
+ \preliminary
+
+ \brief The QCanUniqueIdDescription class describes the rules for accessing
+ a unique identifier in a \l QCanBusFrame.
+
+ A unique identifier is used to distinguish different CAN bus frames and
+ apply proper \l {QCanMessageDescription}s to encode or decode them.
+ Different CAN protocols can use different parts of the CAN frame as a unique
+ identifier (e.g. the DBC protocol uses the whole FrameId as a unique
+ identifier).
+
+ This class contains parameters to specify the unique identifier position
+ within a CAN frame in a flexible way:
+
+ \list
+ \li The part of the frame which will be used to extract the unique
+ identifier (FrameId or payload).
+ \li The start bit of the unique identifier, relative to the selected
+ part of the frame. The bits are counted starting from the LSB.
+ \li The number of bits used to represent the unique identifier.
+ \li The endian used to extract the value.
+ \endlist
+
+ Check the \l {Data Endianness Processing} section of the
+ \l QCanSignalDescription documentation to see how the start bit value
+ depends on the data endianness. The approach that is described there is
+ also used for unique id description.
+
+ The actual value of a unique identifier is represented by the
+ \l QtCanBus::UniqueId type.
+
+ \sa QCanMessageDescription
+*/
+
+/*!
+ Creates an empty unique identifier description.
+*/
+QCanUniqueIdDescription::QCanUniqueIdDescription()
+ : d(new QCanUniqueIdDescriptionPrivate)
+{
+}
+
+/*!
+ Creates a unique identifier description with the values copied from
+ \a other.
+*/
+QCanUniqueIdDescription::QCanUniqueIdDescription(const QCanUniqueIdDescription &other)
+ : d(other.d)
+{
+}
+
+/*!
+ \fn QCanUniqueIdDescription::QCanUniqueIdDescription(QCanUniqueIdDescription &&other) noexcept
+
+ Creates a unique identifier description by moving from \a other.
+
+ \note The moved-from QCanUniqueIdDescription object can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor or
+ one of the assignment operators is undefined.
+*/
+
+/*!
+ \fn QCanUniqueIdDescription::~QCanUniqueIdDescription()
+
+ Destroys this unique identifier description.
+*/
+
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCanUniqueIdDescriptionPrivate)
+
+/*!
+ Assigns the values from \a other to this unique identifier description.
+*/
+QCanUniqueIdDescription &QCanUniqueIdDescription::operator=(const QCanUniqueIdDescription &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn QCanUniqueIdDescription &QCanUniqueIdDescription::operator=(QCanUniqueIdDescription &&other) noexcept
+
+ Move-assigns the values from \a other to this unique identifier description.
+
+ \note The moved-from QCanUniqueIdDescription object can only be destroyed or
+ assigned to. The effect of calling other functions than the destructor or
+ one of the assignment operators is undefined.
+*/
+
+/*!
+ Returns \c true when this unique identifier description is valid and
+ \c false otherwise.
+
+ A valid unique identifier description \e must have a \l bitLength() which is
+ greater than zero and does not exceed the number of bits of the
+ \l QtCanBus::UniqueId type.
+
+ \sa bitLength()
+*/
+bool QCanUniqueIdDescription::isValid() const
+{
+ static constexpr auto uidSize = sizeof(QtCanBus::UniqueId) * 8;
+ return d->bitLength > 0 && d->bitLength <= uidSize;
+}
+
+/*!
+ Returns the data source of the unique identifier.
+
+ By default, \l {QtCanBus::}{FrameId} is used.
+
+ \sa setSource(), QtCanBus::DataSource
+*/
+QtCanBus::DataSource QCanUniqueIdDescription::source() const
+{
+ return d->source;
+}
+
+/*!
+ Sets the data source of the unique identifier to \a source.
+
+ \sa source(), QtCanBus::DataSource
+*/
+void QCanUniqueIdDescription::setSource(QtCanBus::DataSource source)
+{
+ d.detach();
+ d->source = source;
+}
+
+/*!
+ Returns the start bit of the unique identifier in the \l source().
+
+ \sa setStartBit(), bitLength(), setBitLength()
+*/
+quint16 QCanUniqueIdDescription::startBit() const
+{
+ return d->startBit;
+}
+
+/*!
+ Sets the start bit of the unique identifier in the \l source() to \a bit.
+
+ \sa startBit(), bitLength(), setBitLength()
+*/
+void QCanUniqueIdDescription::setStartBit(quint16 bit)
+{
+ d.detach();
+ d->startBit = bit;
+}
+
+/*!
+ Returns the bit length of the unique identifier.
+
+ \sa setBitLength(), startBit(), setStartBit()
+*/
+quint8 QCanUniqueIdDescription::bitLength() const
+{
+ return d->bitLength;
+}
+
+/*!
+ Sets the bit length of the unique identifier to \a length.
+
+ \sa bitLength(), startBit(), setStartBit()
+*/
+void QCanUniqueIdDescription::setBitLength(quint8 length)
+{
+ d.detach();
+ d->bitLength = length;
+}
+
+/*!
+ Returns the data endian of the unique identifier.
+
+ By default, \l {QSysInfo::}{LittleEndian} is used.
+
+ \sa setEndian(), QSysInfo::Endian
+*/
+QSysInfo::Endian QCanUniqueIdDescription::endian() const
+{
+ return d->endian;
+}
+
+/*!
+ Sets the data endian of the unique identifier to \a endian.
+
+ \sa endian(), QSysInfo::Endian
+*/
+void QCanUniqueIdDescription::setEndian(QSysInfo::Endian endian)
+{
+ d.detach();
+ d->endian = endian;
+}
+
+QCanUniqueIdDescriptionPrivate *QCanUniqueIdDescriptionPrivate::get(const QCanUniqueIdDescription &desc)
+{
+ return desc.d.data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/serialbus/qcanuniqueiddescription.h b/src/serialbus/qcanuniqueiddescription.h
new file mode 100644
index 0000000..3d22628
--- /dev/null
+++ b/src/serialbus/qcanuniqueiddescription.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANUNIQUEIDDESCRIPTION_H
+#define QCANUNIQUEIDDESCRIPTION_H
+
+#include <QtCore/QExplicitlySharedDataPointer>
+
+#include <QtSerialBus/qcancommondefinitions.h>
+#include <QtSerialBus/qtserialbusglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCanUniqueIdDescriptionPrivate;
+QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QCanUniqueIdDescriptionPrivate, Q_SERIALBUS_EXPORT)
+
+class QCanUniqueIdDescription
+{
+public:
+ Q_SERIALBUS_EXPORT QCanUniqueIdDescription();
+ Q_SERIALBUS_EXPORT QCanUniqueIdDescription(const QCanUniqueIdDescription &other);
+ QCanUniqueIdDescription(QCanUniqueIdDescription &&other) noexcept = default;
+ ~QCanUniqueIdDescription() = default;
+
+ Q_SERIALBUS_EXPORT QCanUniqueIdDescription &operator=(const QCanUniqueIdDescription &other);
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCanUniqueIdDescription)
+
+ void swap(QCanUniqueIdDescription &other) noexcept { d.swap(other.d); }
+
+ Q_SERIALBUS_EXPORT bool isValid() const;
+
+ Q_SERIALBUS_EXPORT QtCanBus::DataSource source() const;
+ Q_SERIALBUS_EXPORT void setSource(QtCanBus::DataSource source);
+
+ Q_SERIALBUS_EXPORT quint16 startBit() const;
+ Q_SERIALBUS_EXPORT void setStartBit(quint16 bit);
+
+ Q_SERIALBUS_EXPORT quint8 bitLength() const;
+ Q_SERIALBUS_EXPORT void setBitLength(quint8 length);
+
+ Q_SERIALBUS_EXPORT QSysInfo::Endian endian() const;
+ Q_SERIALBUS_EXPORT void setEndian(QSysInfo::Endian endian);
+
+private:
+ QExplicitlySharedDataPointer<QCanUniqueIdDescriptionPrivate> d;
+ friend class QCanUniqueIdDescriptionPrivate;
+
+ friend void qHash(const QCanUniqueIdDescription &desc, size_t seed) noexcept = delete;
+ friend void operator==(const QCanUniqueIdDescription &lhs,
+ const QCanUniqueIdDescription &rhs) noexcept = delete;
+ friend void operator!=(const QCanUniqueIdDescription &lhs,
+ const QCanUniqueIdDescription &rhs) noexcept = delete;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCANUNIQUEIDDESCRIPTION_H
diff --git a/src/serialbus/qcanuniqueiddescription_p.h b/src/serialbus/qcanuniqueiddescription_p.h
new file mode 100644
index 0000000..12138c9
--- /dev/null
+++ b/src/serialbus/qcanuniqueiddescription_p.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCANUNIQUEIDDESCRIPTION_P_H
+#define QCANUNIQUEIDDESCRIPTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtserialbusexports.h"
+#include "qcanuniqueiddescription.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_SERIALBUS_EXPORT QCanUniqueIdDescriptionPrivate : public QSharedData
+{
+public:
+ QtCanBus::DataSource source = QtCanBus::DataSource::FrameId;
+ QSysInfo::Endian endian = QSysInfo::Endian::LittleEndian;
+ quint16 startBit = 0;
+ quint8 bitLength = 0;
+
+ inline bool isShared() const { return ref.loadRelaxed() != 1; }
+ static QCanUniqueIdDescriptionPrivate *get(const QCanUniqueIdDescription &desc);
+};
+
+QT_END_NAMESPACE
+
+#endif // QCANUNIQUEIDDESCRIPTION_P_H
diff --git a/src/serialbus/qmodbus_symbols_p.h b/src/serialbus/qmodbus_symbols_p.h
index b678ff0..74cb717 100644
--- a/src/serialbus/qmodbus_symbols_p.h
+++ b/src/serialbus/qmodbus_symbols_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUS_SYMBOLS_P_H
#define QMODBUS_SYMBOLS_P_H
diff --git a/src/serialbus/qmodbusadu_p.h b/src/serialbus/qmodbusadu_p.h
index 846466d..0137d4a 100644
--- a/src/serialbus/qmodbusadu_p.h
+++ b/src/serialbus/qmodbusadu_p.h
@@ -1,43 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSADU_P_H
#define QMODBUSADU_P_H
#include <QtSerialBus/qmodbuspdu.h>
+#include <QtCore/private/qglobal_p.h>
//
// W A R N I N G
diff --git a/src/serialbus/qmodbusclient.cpp b/src/serialbus/qmodbusclient.cpp
index 56a1ab5..49ba61f 100644
--- a/src/serialbus/qmodbusclient.cpp
+++ b/src/serialbus/qmodbusclient.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmodbusclient.h"
#include "qmodbusclient_p.h"
@@ -129,7 +96,7 @@ QModbusReply *QModbusClient::sendReadWriteRequest(const QModbusDataUnit &read,
fits inside the Modbus PDU data section and has a valid function code.
The only check performed before sending is therefore the validity check,
see \l QModbusPdu::isValid. If no error occurred the function returns a
- a new valid \l QModbusReply; nullptr otherwise. Modbus networks may have
+ new valid \l QModbusReply; nullptr otherwise. Modbus networks may have
multiple servers, each server has a unique \a serverAddress.
\sa QModbusReply::rawResult()
@@ -140,13 +107,10 @@ QModbusReply *QModbusClient::sendRawRequest(const QModbusRequest &request, int s
}
/*!
- \property QModbusClient::timeout
- \brief the timeout value used by this client
-
Returns the timeout value used by this QModbusClient instance in ms.
A timeout is indicated by a \l TimeoutError. The default value is 1000 ms.
- \sa setTimeout
+ \sa setTimeout timeoutChanged()
*/
int QModbusClient::timeout() const
{
@@ -222,8 +186,12 @@ QModbusClient::QModbusClient(QModbusClientPrivate &dd, QObject *parent) :
}
/*!
- Processes a Modbus server \a response and stores the decoded information in \a data. Returns
- true on success; otherwise false.
+ Processes a Modbus server \a response and stores the decoded information in
+ \a data. Returns \c true on success; otherwise \c false.
+
+ \note The default implementation does not support all
+ \l {QModbusPdu::}{FunctionCode}s. Override this method in a custom Modbus
+ client implementations to handle the needed functions.
*/
bool QModbusClient::processResponse(const QModbusResponse &response, QModbusDataUnit *data)
{
@@ -236,8 +204,8 @@ bool QModbusClient::processResponse(const QModbusResponse &response, QModbusData
*/
bool QModbusClient::processPrivateResponse(const QModbusResponse &response, QModbusDataUnit *data)
{
- Q_UNUSED(response)
- Q_UNUSED(data)
+ Q_UNUSED(response);
+ Q_UNUSED(data);
return false;
}
@@ -297,12 +265,12 @@ QModbusRequest QModbusClientPrivate::createWriteRequest(const QModbusDataUnit &d
quint16((data.value(0) == 0u) ? Coil::Off : Coil::On));
}
- quint8 byteCount = data.valueCount() / 8;
+ quint8 byteCount = quint8(data.valueCount() / 8);
if ((data.valueCount() % 8) != 0)
byteCount += 1;
- quint8 address = 0;
- QVector<quint8> bytes;
+ qsizetype address = 0;
+ QList<quint8> bytes;
for (quint8 i = 0; i < byteCount; ++i) {
quint8 byte = 0;
for (int currentBit = 0; currentBit < 8; ++currentBit)
@@ -321,7 +289,7 @@ QModbusRequest QModbusClientPrivate::createWriteRequest(const QModbusDataUnit &d
data.value(0));
}
- const quint8 byteCount = data.valueCount() * 2;
+ const quint8 byteCount = quint8(data.valueCount() * 2);
return QModbusRequest(QModbusRequest::WriteMultipleRegisters, quint16(data.startAddress()),
quint16(data.valueCount()), byteCount, data.values());
} break;
@@ -342,7 +310,7 @@ QModbusRequest QModbusClientPrivate::createRWRequest(const QModbusDataUnit &read
return QModbusRequest();
}
- const quint8 byteCount = write.valueCount() * 2;
+ const quint8 byteCount = quint8(write.valueCount() * 2);
return QModbusRequest(QModbusRequest::ReadWriteMultipleRegisters, quint16(read.startAddress()),
quint16(read.valueCount()), quint16(write.startAddress()),
quint16(write.valueCount()), byteCount, write.values());
@@ -361,14 +329,14 @@ void QModbusClientPrivate::processQueueElement(const QModbusResponse &pdu,
return;
}
- if (element.reply->type() != QModbusReply::Common) {
+ if (element.reply->type() == QModbusReply::Broadcast) {
element.reply->setFinished(true);
return;
}
QModbusDataUnit unit = element.unit;
- if (!processResponse(pdu, &unit)) {
- element.reply->setError(QModbusDevice::UnknownError,
+ if (!q_func()->processResponse(pdu, &unit)) {
+ element.reply->setError(QModbusDevice::InvalidResponseError,
QModbusClient::tr("An invalid response has been received."));
return;
}
@@ -450,18 +418,23 @@ bool QModbusClientPrivate::collateBits(const QModbusPdu &response,
if (response.dataSize() < QModbusResponse::minimumDataSize(response))
return false;
- const QByteArray payload = response.data();
// byte count needs to match available bytes
- if ((payload.size() - 1) != payload[0])
+ const quint8 byteCount = quint8(response.data().at(0));
+ if ((response.dataSize() - 1) != byteCount)
return false;
if (data) {
- uint value = 0;
- for (qint32 i = 1; i < payload.size(); ++i) {
+ const int valueCount = byteCount *8;
+ const QByteArray payload = response.data();
+
+ qsizetype value = 0;
+ QList<quint16> values(valueCount);
+ for (qsizetype i = 1; i < payload.size(); ++i) {
const quint8 byte = quint8(payload[i]);
- for (qint32 currentBit = 0; currentBit < 8 && value < data->valueCount(); ++currentBit)
- data->setValue(value++, byte & (1U << currentBit) ? 1 : 0);
+ for (qint32 currentBit = 0; currentBit < 8 && value < valueCount; ++currentBit)
+ values[value++] = (byte & (1U << currentBit) ? 1 : 0);
}
+ data->setValues(values);
data->setRegisterType(type);
}
return true;
@@ -494,14 +467,14 @@ bool QModbusClientPrivate::collateBytes(const QModbusPdu &response,
if ((response.dataSize() - 1) != byteCount)
return false;
- // byte count needs to be odd to match full registers
+ // byte count needs to be even to match full registers
if (byteCount % 2 != 0)
return false;
if (data) {
QDataStream stream(response.data().remove(0, 1));
- QVector<quint16> values;
+ QList<quint16> values;
const quint8 itemCount = byteCount / 2;
for (int i = 0; i < itemCount; i++) {
quint16 tmp;
@@ -544,7 +517,7 @@ bool QModbusClientPrivate::collateSingleValue(const QModbusPdu &response,
if (data) {
data->setRegisterType(type);
data->setStartAddress(address);
- data->setValues(QVector<quint16>{ value });
+ data->setValues(QList<quint16> { value });
}
return true;
}
diff --git a/src/serialbus/qmodbusclient.h b/src/serialbus/qmodbusclient.h
index 3b6785d..86a35ff 100644
--- a/src/serialbus/qmodbusclient.h
+++ b/src/serialbus/qmodbusclient.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSCLIENT_H
#define QMODBUSCLIENT_H
@@ -51,7 +18,6 @@ class Q_SERIALBUS_EXPORT QModbusClient : public QModbusDevice
{
Q_OBJECT
Q_DECLARE_PRIVATE(QModbusClient)
- Q_PROPERTY(int timeout READ timeout WRITE setTimeout NOTIFY timeoutChanged)
public:
explicit QModbusClient(QObject *parent = nullptr);
diff --git a/src/serialbus/qmodbusclient_p.h b/src/serialbus/qmodbusclient_p.h
index 05c799a..7098b06 100644
--- a/src/serialbus/qmodbusclient_p.h
+++ b/src/serialbus/qmodbusclient_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSCLIENT_P_H
#define QMODBUSCLIENT_P_H
@@ -42,6 +9,9 @@
#include <QtSerialBus/qmodbuspdu.h>
#include <private/qmodbusdevice_p.h>
+
+#include <QtCore/qpointer.h>
+
#include <limits.h>
//
diff --git a/src/serialbus/qmodbuscommevent_p.h b/src/serialbus/qmodbuscommevent_p.h
index 087c060..19ee653 100644
--- a/src/serialbus/qmodbuscommevent_p.h
+++ b/src/serialbus/qmodbuscommevent_p.h
@@ -1,43 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSCOMMEVENT_P_H
#define QMODBUSCOMMEVENT_P_H
#include <QtSerialBus/qtserialbusglobal.h>
+#include <QtCore/private/qglobal_p.h>
//
// W A R N I N G
@@ -81,7 +49,7 @@ public:
InitiatedCommunicationRestart = 0x00
};
- inline QModbusCommEvent(QModbusCommEvent::EventByte byte)
+ constexpr QModbusCommEvent(QModbusCommEvent::EventByte byte) noexcept
: m_eventByte(byte) {}
operator quint8() const { return m_eventByte; }
@@ -89,15 +57,15 @@ public:
return static_cast<QModbusCommEvent::EventByte> (m_eventByte);
}
- inline QModbusCommEvent operator=(QModbusCommEvent::EventByte byte) {
+ inline QModbusCommEvent &operator=(QModbusCommEvent::EventByte byte) {
m_eventByte = byte;
return *this;
}
- inline QModbusCommEvent operator|=(QModbusCommEvent::SendFlag sf) {
+ inline QModbusCommEvent &operator|=(QModbusCommEvent::SendFlag sf) {
m_eventByte |= quint8(sf);
return *this;
}
- inline QModbusCommEvent operator|=(QModbusCommEvent::ReceiveFlag rf) {
+ inline QModbusCommEvent &operator|=(QModbusCommEvent::ReceiveFlag rf) {
m_eventByte |= quint8(rf);
return *this;
}
diff --git a/src/serialbus/qmodbusdataunit.cpp b/src/serialbus/qmodbusdataunit.cpp
index 6a07bba..d5ae656 100644
--- a/src/serialbus/qmodbusdataunit.cpp
+++ b/src/serialbus/qmodbusdataunit.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmodbusdataunit.h"
@@ -98,7 +65,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QModbusDataUnit::QModbusDataUnit(RegisterType type, int address,
- const QVector<quint16> &data)
+ const QList<quint16> &data)
Constructs a unit of data for register\a type. Start address of the data is
set to \a address and the unit's values to \a data.
@@ -138,7 +105,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QModbusDataUnit::setValues(const QVector<quint16> &values)
+ \fn void QModbusDataUnit::setValues(const QList<quint16> &values)
Sets the \a values of the data unit. \l QModbusDataUnit::DiscreteInputs
and \l QModbusDataUnit::Coils tables only accept single bit value, so \c 0
@@ -148,7 +115,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QVector<quint16> QModbusDataUnit::values() const
+ \fn QList<quint16> QModbusDataUnit::values() const
Returns the data in the data unit. \l QModbusDataUnit::DiscreteInputs
and \l QModbusDataUnit::Coils tables only accept single bit value, so \c 0
@@ -158,7 +125,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn uint QModbusDataUnit::valueCount() const
+ \fn qsizetype QModbusDataUnit::valueCount() const
Returns the size of the requested register's data block or the size of data
read from the device.
@@ -173,7 +140,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QModbusDataUnit::setValueCount(uint newCount)
+ \fn void QModbusDataUnit::setValueCount(qsizetype newCount)
Sets the size of the requested register's data block to \a newCount.
@@ -183,13 +150,13 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QModbusDataUnit::setValue(int index, quint16 value)
+ \fn void QModbusDataUnit::setValue(qsizetype index, quint16 value)
Sets the register at position \a index to \a value.
*/
/*!
- \fn quint16 QModbusDataUnit::value(int index) const
+ \fn quint16 QModbusDataUnit::value(qsizetype index) const
Return the value at position \a index.
*/
diff --git a/src/serialbus/qmodbusdataunit.h b/src/serialbus/qmodbusdataunit.h
index fcad4ac..be3a500 100644
--- a/src/serialbus/qmodbusdataunit.h
+++ b/src/serialbus/qmodbusdataunit.h
@@ -1,45 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSDATAUNIT_H
#define QMODBUSDATAUNIT_H
+#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qmetatype.h>
-#include <QtCore/qvector.h>
QT_BEGIN_NAMESPACE
@@ -56,15 +23,16 @@ public:
QModbusDataUnit() = default;
- explicit QModbusDataUnit(RegisterType type)
- : QModbusDataUnit(type, 0, 0)
+ constexpr explicit QModbusDataUnit(RegisterType type) noexcept
+ : m_type(type)
+ , m_startAddress(0)
{}
QModbusDataUnit(RegisterType type, int newStartAddress, quint16 newValueCount)
- : QModbusDataUnit(type, newStartAddress, QVector<quint16>(newValueCount))
+ : QModbusDataUnit(type, newStartAddress, QList<quint16>(newValueCount))
{}
- QModbusDataUnit(RegisterType type, int newStartAddress, const QVector<quint16> &newValues)
+ QModbusDataUnit(RegisterType type, int newStartAddress, const QList<quint16> &newValues)
: m_type(type)
, m_startAddress(newStartAddress)
, m_values(newValues)
@@ -77,35 +45,35 @@ public:
inline int startAddress() const { return m_startAddress; }
inline void setStartAddress(int newAddress) { m_startAddress = newAddress; }
- inline QVector<quint16> values() const { return m_values; }
- inline void setValues(const QVector<quint16> &newValues)
+ inline QList<quint16> values() const { return m_values; }
+ inline void setValues(const QList<quint16> &newValues)
{
m_values = newValues;
m_valueCount = newValues.size();
}
- inline uint valueCount() const { return m_valueCount; }
- inline void setValueCount(uint newCount) { m_valueCount = newCount; }
+ inline qsizetype valueCount() const { return m_valueCount; }
+ inline void setValueCount(qsizetype newCount) { m_valueCount = newCount; }
- inline void setValue(int index, quint16 newValue)
+ inline void setValue(qsizetype index, quint16 newValue)
{
if (m_values.isEmpty() || index >= m_values.size())
return;
m_values[index] = newValue;
}
- inline quint16 value(int index) const { return m_values.value(index); }
+ inline quint16 value(qsizetype index) const { return m_values.value(index); }
bool isValid() const { return m_type != Invalid && m_startAddress != -1; }
private:
RegisterType m_type = Invalid;
int m_startAddress = -1;
- QVector<quint16> m_values;
- uint m_valueCount = 0;
+ QList<quint16> m_values;
+ qsizetype m_valueCount = 0;
};
typedef QMap<QModbusDataUnit::RegisterType, QModbusDataUnit> QModbusDataUnitMap;
-Q_DECLARE_TYPEINFO(QModbusDataUnit, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QModbusDataUnit, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(QModbusDataUnit::RegisterType, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
diff --git a/src/serialbus/qmodbusdevice.cpp b/src/serialbus/qmodbusdevice.cpp
index ab8e126..d43f3b3 100644
--- a/src/serialbus/qmodbusdevice.cpp
+++ b/src/serialbus/qmodbusdevice.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmodbusdevice.h"
#include "qmodbusdevice_p.h"
@@ -95,11 +62,6 @@ QModbusDevice::~QModbusDevice()
\value NetworkPortParameter This parameter holds the network port. \c int
\value NetworkAddressParameter This parameter holds the host address for network
communication. \c QString
-
- User options:
-
- \value UserParameter This enum value has been deprecated. There
- will be no replacement.
*/
/*!
@@ -120,7 +82,7 @@ QModbusDevice::~QModbusDevice()
\sa ConnectionParameter
*/
-QVariant QModbusDevice::connectionParameter(int parameter) const
+QVariant QModbusDevice::connectionParameter(ConnectionParameter parameter) const
{
Q_D(const QModbusDevice);
switch (parameter) {
@@ -143,7 +105,7 @@ QVariant QModbusDevice::connectionParameter(int parameter) const
default:
break;
}
- return d->m_userConnectionParams.value(parameter); // ### Qt6: remove
+ return {};
}
/*!
@@ -154,7 +116,7 @@ QVariant QModbusDevice::connectionParameter(int parameter) const
\sa ConnectionParameter
\sa connectionParameter()
*/
-void QModbusDevice::setConnectionParameter(int parameter, const QVariant &value)
+void QModbusDevice::setConnectionParameter(ConnectionParameter parameter, const QVariant &value)
{
Q_D(QModbusDevice);
switch (parameter) {
@@ -182,7 +144,7 @@ void QModbusDevice::setConnectionParameter(int parameter, const QVariant &value)
d->m_networkAddress = value.toString();
break;
default:
- d->m_userConnectionParams.insert(parameter, value); // ### Qt6: remove
+ Q_ASSERT_X(false, "", "Connection parameter not supported.");
break;
}
}
@@ -204,6 +166,14 @@ void QModbusDevice::setConnectionParameter(int parameter, const QVariant &value)
\value ReplyAbortedError The reply was aborted due to a disconnection of
the device.
\value UnknownError An unknown error occurred.
+ \value [since 6.4] InvalidResponseError An error occurred while parsing the
+ response, or the \l {QModbusPdu::}{FunctionCode}
+ is not supported by the current implementation.
+ In the latter case custom Modbus client
+ implementation can override the
+ \l {QModbusClient::}{processResponse()} and
+ \l {QModbusClient::}{processPrivateResponse()}
+ methods to provide support for needed functions.
*/
/*!
@@ -217,6 +187,27 @@ void QModbusDevice::setConnectionParameter(int parameter, const QVariant &value)
*/
/*!
+ \since 6.0
+ \enum QModbusDevice::IntermediateError
+
+ This enum describes possible errors that can happen during a full send and
+ receive cycle for a Modbus reply.
+
+ \value ResponseCrcError A Modbus response with a wrong CRC was received.
+ \value ResponseRequestMismatch A Modbus response was received but did not
+ match the open request, probably due to the
+ PDU's function code not matching.
+
+ If any of the above intermediate errors occurred, the frame is likely
+ resent until the maximum number of retries has been reached.
+
+ The list of intermediate errors can be inspected from the \l QModbusReply
+ intermediate errors function.
+
+ \sa QModbusClient::numberOfRetries(), QModbusReply::intermediateErrors()
+*/
+
+/*!
\fn QModbusDevice::errorOccurred(QModbusDevice::Error error)
This signal is emitted when an error of the type, \a error, occurs.
diff --git a/src/serialbus/qmodbusdevice.h b/src/serialbus/qmodbusdevice.h
index 0e6dad7..878e3db 100644
--- a/src/serialbus/qmodbusdevice.h
+++ b/src/serialbus/qmodbusdevice.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSDEVICE_H
#define QMODBUSDEVICE_H
@@ -59,7 +26,8 @@ public:
TimeoutError,
ProtocolError,
ReplyAbortedError,
- UnknownError
+ UnknownError,
+ InvalidResponseError
};
Q_ENUM(Error)
@@ -79,18 +47,22 @@ public:
SerialStopBitsParameter,
NetworkPortParameter,
- NetworkAddressParameter,
-
- // Reserved
- UserParameter = 0x100 // ### Qt6: remove
+ NetworkAddressParameter
};
Q_ENUM(ConnectionParameter)
+ enum IntermediateError
+ {
+ ResponseCrcError,
+ ResponseRequestMismatch
+ };
+ Q_ENUM(IntermediateError)
+
explicit QModbusDevice(QObject *parent = nullptr);
~QModbusDevice();
- QVariant connectionParameter(int parameter) const;
- void setConnectionParameter(int parameter, const QVariant &value);
+ QVariant connectionParameter(ConnectionParameter parameter) const;
+ void setConnectionParameter(ConnectionParameter parameter, const QVariant &value);
bool connectDevice();
void disconnectDevice();
@@ -118,6 +90,7 @@ protected:
Q_DECLARE_TYPEINFO(QModbusDevice::Error, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QModbusDevice::State, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QModbusDevice::ConnectionParameter, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QModbusDevice::IntermediateError, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
diff --git a/src/serialbus/qmodbusdevice_p.h b/src/serialbus/qmodbusdevice_p.h
index 1526397..7df593c 100644
--- a/src/serialbus/qmodbusdevice_p.h
+++ b/src/serialbus/qmodbusdevice_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSDEVICE_P_H
#define QMODBUSDEVICE_P_H
@@ -73,13 +40,35 @@ public:
QSerialPort::Parity m_parity = QSerialPort::EvenParity;
QSerialPort::StopBits m_stopBits = QSerialPort::OneStop;
QSerialPort::BaudRate m_baudRate = QSerialPort::Baud19200;
+
+ /*!
+ According to the Modbus specification, in RTU mode message frames
+ are separated by a silent interval of at least 3.5 character times.
+ Calculate the timeout if we are less than 19200 baud, use a fixed
+ timeout for everything equal or greater than 19200 baud.
+ If the user set the timeout to be longer than the calculated one,
+ we'll keep the user defined.
+ */
+ void calculateInterFrameDelay()
+ {
+ // The spec recommends a timeout value of 1.750 msec. Without such
+ // precise single-shot timers use a approximated value of 1.750 msec.
+ int delayMilliSeconds = RecommendedDelay;
+ if (m_baudRate < 19200) {
+ // Example: 9600 baud, 11 bit per packet -> 872 char/sec so:
+ // 1000 ms / 872 char = 1.147 ms/char * 3.5 character = 4.0145 ms
+ // Always round up because the spec requests at least 3.5 char.
+ delayMilliSeconds = qCeil(3500. / (qreal(m_baudRate) / 11.));
+ }
+ m_interFrameDelayMilliseconds = qMax(m_interFrameDelayMilliseconds, delayMilliSeconds);
+ }
+ static constexpr int RecommendedDelay = 2; // A approximated value of 1.750 msec.
+ int m_interFrameDelayMilliseconds = RecommendedDelay;
#endif
int m_networkPort = 502;
QString m_networkAddress = QStringLiteral("127.0.0.1");
- QHash<int, QVariant> m_userConnectionParams; // ### Qt6: remove
-
virtual QIODevice *device() const { return nullptr; }
};
diff --git a/src/serialbus/qmodbusdeviceidentification.cpp b/src/serialbus/qmodbusdeviceidentification.cpp
index 77c2663..1297e59 100644
--- a/src/serialbus/qmodbusdeviceidentification.cpp
+++ b/src/serialbus/qmodbusdeviceidentification.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmodbusdeviceidentification.h"
#include "qmodbus_symbols_p.h"
diff --git a/src/serialbus/qmodbusdeviceidentification.h b/src/serialbus/qmodbusdeviceidentification.h
index 9f08f55..7334fb0 100644
--- a/src/serialbus/qmodbusdeviceidentification.h
+++ b/src/serialbus/qmodbusdeviceidentification.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSDEVICEIDENTIFICATION_P_H
#define QMODBUSDEVICEIDENTIFICATION_P_H
@@ -110,7 +77,7 @@ private:
QMap<int, QByteArray> m_objects;
ConformityLevel m_conformityLevel = BasicConformityLevel;
};
-Q_DECLARE_TYPEINFO(QModbusDeviceIdentification, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QModbusDeviceIdentification, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(QModbusDeviceIdentification::ObjectId, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QModbusDeviceIdentification::ReadDeviceIdCode, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QModbusDeviceIdentification::ConformityLevel, Q_PRIMITIVE_TYPE);
diff --git a/src/serialbus/qmodbuspdu.cpp b/src/serialbus/qmodbuspdu.cpp
index 9ca9027..d06e75f 100644
--- a/src/serialbus/qmodbuspdu.cpp
+++ b/src/serialbus/qmodbuspdu.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmodbuspdu.h"
#include "qmodbus_symbols_p.h"
@@ -48,13 +15,23 @@ Q_GLOBAL_STATIC(ReqSizeCalc, requestSizeCalculators);
using ResSizeCalc = QHash<quint8, QModbusResponse::CalcFuncPtr>;
Q_GLOBAL_STATIC(ResSizeCalc, responseSizeCalculators);
-namespace Private {
+struct QModbusPduPrivate
+{
+ QModbusPduPrivate() = delete;
+ Q_DISABLE_COPY_MOVE(QModbusPduPrivate)
enum struct Type {
Request,
Response
};
+/*!
+ \internal
+
+ Returns the minimum data size in bytes for the given \a pdu and the
+ Modbus PDU \a type. If the PDU's function code is invalid, undefined
+ or unknown, the return value will be \c {-1}.
+*/
static int minimumDataSize(const QModbusPdu &pdu, Type type)
{
if (pdu.isException())
@@ -103,44 +80,54 @@ static int minimumDataSize(const QModbusPdu &pdu, Type type)
return -1;
}
-static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type type)
+/*!
+ \internal
+
+ Extracts a Modbus PDU from a \a stream into the given \a pdu based on \a type.
+*/
+static QDataStream &pduFromStream(QDataStream &stream, Type type, QModbusPdu *pdu)
{
- quint8 codeByte = 0;
- if (stream.readRawData(reinterpret_cast<char *>(&codeByte), sizeof(quint8)) != sizeof(quint8))
+ struct RAII {
+ RAII(QModbusPdu *ptr = nullptr)
+ : tmp(ptr) {}
+ QModbusPdu *tmp{ nullptr };
+ ~RAII() { if (tmp) *tmp = {}; }
+ } raii = { pdu };
+
+ QModbusPdu::FunctionCode code = QModbusPdu::FunctionCode::Invalid;
+ stream >> code;
+ if (stream.status() == QDataStream::ReadPastEnd)
return stream;
- QModbusPdu::FunctionCode code = QModbusPdu::FunctionCode(codeByte);
- pdu.setFunctionCode(code);
-
- auto needsAdditionalRead = [](QModbusPdu &pdu, int size) -> bool {
- if (size < 0)
- pdu.setFunctionCode(QModbusResponse::Invalid);
- if (size <= 0)
- return false;
- return true;
- };
+ pdu->setFunctionCode(code);
- const bool isResponse = (type == Type::Response);
- int size = isResponse ? QModbusResponse::minimumDataSize(pdu)
- : QModbusRequest::minimumDataSize(pdu);
- if (!needsAdditionalRead(pdu, size))
+ if (code == QModbusPdu::Invalid) // shortcut
return stream;
- QByteArray data(size, Qt::Uninitialized);
- if (stream.device()->peek(data.data(), data.size()) != size)
- return stream;
+ constexpr const int MaxPduDataSize = 252; // in bytes
- pdu.setData(data);
- size = isResponse ? QModbusResponse::calculateDataSize(pdu)
- : QModbusRequest::calculateDataSize(pdu);
- if (!needsAdditionalRead(pdu, size))
+ // The calculateDataSize(...) function might need some data inside the
+ // given PDU argument to be able to figure out the right data size (e.g.
+ // WriteMultipleCoils contains some kind of "header"). So fake fill the PDU
+ // with the maximum available data but no more than the allowed max PDU
+ // data size.
+ QByteArray data(MaxPduDataSize, Qt::Uninitialized);
+ int read = stream.device()->peek(data.data(), MaxPduDataSize);
+ if (read < 0)
return stream;
+ data.resize(read);
+ pdu->setData(data);
+
+ const bool isResponse = (type == Type::Response);
+ int size = isResponse ? QModbusResponse::calculateDataSize(*pdu)
+ : QModbusRequest::calculateDataSize(*pdu);
+
if (isResponse && (code == QModbusPdu::EncapsulatedInterfaceTransport)) {
quint8 meiType;
- pdu.decodeData(&meiType);
+ pdu->decodeData(&meiType);
if (meiType == EncapsulatedInterfaceTransport::ReadDeviceIdentification) {
int left = size, offset = 0;
- while ((left > 0) && (size <= 252)) { // The maximum PDU data size is 252 bytes.
+ while ((left > 0) && (size <= MaxPduDataSize)) {
data.resize(size);
const int read = stream.readRawData(data.data() + offset, size - offset);
if ((read < 0) || (read != (size - offset))) {
@@ -152,35 +139,31 @@ static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type typ
left = QModbusResponse::calculateDataSize(QModbusResponse(code, data)) - offset;
size += left;
}
- if ((stream.status() == QDataStream::Ok) && (size <= 252)) {
- pdu.setData(data);
+ if ((stream.status() == QDataStream::Ok) && (size <= MaxPduDataSize)) {
+ raii = {};
+ pdu->setData(data);
return stream; // early return to avoid second read
}
} else {
data.resize(int(stream.device()->size() - 1)); // One byte for the function code.
}
- } else if (pdu.functionCode() == QModbusPdu::Diagnostics) {
+ } else if (pdu->functionCode() == QModbusPdu::Diagnostics) {
quint16 subCode;
- pdu.decodeData(&subCode);
+ pdu->decodeData(&subCode);
if (subCode == Diagnostics::ReturnQueryData)
data.resize(int(stream.device()->size() - 1)); // One byte for the function code.
}
- // reset what we have so far, next read might fail as well
- pdu.setData(QByteArray());
- pdu.setFunctionCode(QModbusPdu::Invalid);
-
- if (data.size() <= 252) { // The maximum PDU data size is 252 bytes.
+ if (data.size() <= MaxPduDataSize) {
data.resize(size);
if (stream.readRawData(data.data(), data.size()) == size) {
- pdu.setData(data);
- pdu.setFunctionCode(code);
+ raii = {};
+ pdu->setData(data);
}
}
return stream;
}
-
-} // namespace Private
+};
/*!
\class QModbusPdu
@@ -290,6 +273,8 @@ static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type typ
Destroys a QModbusPdu.
*/
+QModbusPdu::~QModbusPdu()
+ = default;
/*!
\fn QModbusPdu::QModbusPdu(const QModbusPdu &other)
@@ -439,7 +424,7 @@ static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type typ
QDebug operator<<(QDebug debug, const QModbusPdu &pdu)
{
QDebugStateSaver _(debug);
- debug.nospace().noquote() << "0x" << Qt::hex << qSetFieldWidth(2) << qSetPadChar('0')
+ debug.nospace().noquote() << "0x" << Qt::hex << qSetFieldWidth(2) << qSetPadChar(u'0')
<< (pdu.isException() ? pdu.functionCode() | QModbusPdu::ExceptionByte : pdu.functionCode())
<< qSetFieldWidth(0) << pdu.data().toHex();
return debug;
@@ -528,12 +513,18 @@ QDataStream &operator<<(QDataStream &stream, const QModbusPdu &pdu)
*/
/*!
+ \internal
+*/
+QModbusRequest::~QModbusRequest()
+ = default;
+
+/*!
Returns the expected minimum data size for \a request based on the
request's function code; \c {-1} if the function code is not known.
*/
int QModbusRequest::minimumDataSize(const QModbusRequest &request)
{
- return Private::minimumDataSize(request, Private::Type::Request);
+ return QModbusPduPrivate::minimumDataSize(request, QModbusPduPrivate::Type::Request);
}
/*!
@@ -555,7 +546,7 @@ int QModbusRequest::calculateDataSize(const QModbusRequest &request)
return 1;
int size = -1;
- int minimum = Private::minimumDataSize(request, Private::Type::Request);
+ int minimum = QModbusPduPrivate::minimumDataSize(request, QModbusPduPrivate::Type::Request);
if (minimum < 0)
return size;
@@ -608,6 +599,22 @@ void QModbusRequest::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr cal
}
/*!
+ \internal
+
+ Reads a FunctionCode from a \a stream.
+ In stream we serialize FunctionCode as one byte, so we use a temporary char
+ variable to make the code work on both little endian and big endian systems.
+ If reading from stream fails, code will retain original value.
+*/
+QDataStream &operator>>(QDataStream &stream, QModbusPdu::FunctionCode &code)
+{
+ char buffer;
+ if (stream.readRawData(&buffer, 1) == 1)
+ code = static_cast<QModbusPdu::FunctionCode>(buffer);
+ return stream;
+}
+
+/*!
\relates QModbusRequest
Reads a \a pdu from the \a stream and returns a reference to the stream.
@@ -620,7 +627,7 @@ void QModbusRequest::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr cal
*/
QDataStream &operator>>(QDataStream &stream, QModbusRequest &pdu)
{
- return Private::pduFromStream(stream, pdu, Private::Type::Request);
+ return QModbusPduPrivate::pduFromStream(stream, QModbusPduPrivate::Type::Request, &pdu);
}
/*!
@@ -684,12 +691,18 @@ QDataStream &operator>>(QDataStream &stream, QModbusRequest &pdu)
*/
/*!
+ \internal
+*/
+QModbusResponse::~QModbusResponse()
+ = default;
+
+/*!
Returns the expected minimum data size for \a response based on the
response's function code; \c {-1} if the function code is not known.
*/
int QModbusResponse::minimumDataSize(const QModbusResponse &response)
{
- return Private::minimumDataSize(response, Private::Type::Response);
+ return QModbusPduPrivate::minimumDataSize(response, QModbusPduPrivate::Type::Response);
}
/*!
@@ -711,7 +724,7 @@ int QModbusResponse::calculateDataSize(const QModbusResponse &response)
return 1;
int size = -1;
- int minimum = Private::minimumDataSize(response, Private::Type::Response);
+ int minimum = QModbusPduPrivate::minimumDataSize(response, QModbusPduPrivate::Type::Response);
if (minimum < 0)
return size;
@@ -806,7 +819,7 @@ void QModbusResponse::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr ca
*/
QDataStream &operator>>(QDataStream &stream, QModbusResponse &pdu)
{
- return Private::pduFromStream(stream, pdu, Private::Type::Response);
+ return QModbusPduPrivate::pduFromStream(stream, QModbusPduPrivate::Type::Response, &pdu);
}
/*!
@@ -844,6 +857,12 @@ QDataStream &operator>>(QDataStream &stream, QModbusResponse &pdu)
*/
/*!
+ \internal
+*/
+QModbusExceptionResponse::~QModbusExceptionResponse()
+ = default;
+
+/*!
\fn void QModbusExceptionResponse::setFunctionCode(FunctionCode c)
Sets the response's function code to \a c.
diff --git a/src/serialbus/qmodbuspdu.h b/src/serialbus/qmodbuspdu.h
index 30904a7..5d34d78 100644
--- a/src/serialbus/qmodbuspdu.h
+++ b/src/serialbus/qmodbuspdu.h
@@ -1,49 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSPDU_H
#define QMODBUSPDU_H
#include <QtCore/qdatastream.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qlist.h>
#include <QtCore/qmetatype.h>
-#include <QtCore/qvector.h>
#include <QtSerialBus/qtserialbusglobal.h>
QT_BEGIN_NAMESPACE
-class QModbusPdu
+class Q_SERIALBUS_EXPORT QModbusPdu
{
public:
enum ExceptionCode {
@@ -85,7 +53,7 @@ public:
};
QModbusPdu() = default;
- virtual ~QModbusPdu() = default;
+ virtual ~QModbusPdu();
bool isValid() const {
return (m_code >= ReadCoils && m_code < UndefinedFunctionCode)
@@ -141,38 +109,45 @@ private:
enum { value = std::is_same<T, T1>::value || IsType<T, Ts...>::value };
};
+ template <typename T>
+ using is_pod = std::integral_constant<bool, std::is_trivial<T>::value && std::is_standard_layout<T>::value>;
+
template <typename T> void encode(QDataStream *stream, const T &t) {
- static_assert(std::is_pod<T>::value, "Only POD types supported.");
+ static_assert(is_pod<T>::value, "Only POD types supported.");
static_assert(IsType<T, quint8, quint16>::value, "Only quint8 and quint16 supported.");
(*stream) << t;
}
template <typename T> void decode(QDataStream *stream, T &t) const {
- static_assert(std::is_pod<T>::value, "Only POD types supported.");
+ static_assert(is_pod<T>::value, "Only POD types supported.");
static_assert(IsType<T, quint8 *, quint16 *>::value, "Only quint8* and quint16* supported.");
(*stream) >> *t;
}
- template <typename T> void encode(QDataStream *stream, const QVector<T> &vector) {
- static_assert(std::is_pod<T>::value, "Only POD types supported.");
+ template<typename T>
+ void encode(QDataStream *stream, const QList<T> &vector)
+ {
+ static_assert(is_pod<T>::value, "Only POD types supported.");
static_assert(IsType<T, quint8, quint16>::value, "Only quint8 and quint16 supported.");
- for (int i = 0; i < vector.count(); ++i)
+ for (int i = 0; i < vector.size(); ++i)
(*stream) << vector[i];
}
template<typename ... Args> void encode(Args ... newData) {
m_data.clear();
- Q_CONSTEXPR quint32 argCount = sizeof...(Args);
- if (argCount > 0) {
+ constexpr size_t argCount = sizeof...(Args);
+ if constexpr (argCount > 0) {
QDataStream stream(&m_data, QIODevice::WriteOnly);
char tmp[argCount] = { (encode(&stream, newData), void(), '0')... };
- Q_UNUSED(tmp)
+ Q_UNUSED(tmp);
}
}
template<typename ... Args> void decode(Args ... newData) const {
- Q_CONSTEXPR quint32 argCount = sizeof...(Args);
- if (argCount > 0 && !m_data.isEmpty()) {
- QDataStream stream(m_data);
- char tmp[argCount] = { (decode(&stream, newData), void(), '0')... };
- Q_UNUSED(tmp)
+ constexpr size_t argCount = sizeof...(Args);
+ if constexpr (argCount > 0) {
+ if (!m_data.isEmpty()) {
+ QDataStream stream(m_data);
+ char tmp[argCount] = { (decode(&stream, newData), void(), '0')... };
+ Q_UNUSED(tmp);
+ }
}
}
@@ -180,11 +155,13 @@ private:
FunctionCode m_code = Invalid;
QByteArray m_data;
friend class QModbusSerialAdu;
+ friend struct QModbusPduPrivate;
};
Q_SERIALBUS_EXPORT QDebug operator<<(QDebug debug, const QModbusPdu &pdu);
Q_SERIALBUS_EXPORT QDataStream &operator<<(QDataStream &stream, const QModbusPdu &pdu);
+Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &stream, QModbusPdu::FunctionCode &code);
-class QModbusRequest : public QModbusPdu
+class Q_SERIALBUS_EXPORT QModbusRequest : public QModbusPdu
{
public:
QModbusRequest() = default;
@@ -195,12 +172,13 @@ public:
explicit QModbusRequest(FunctionCode code, const QByteArray &newData = QByteArray())
: QModbusPdu(code, newData)
{}
+ ~QModbusRequest() override;
- Q_SERIALBUS_EXPORT static int minimumDataSize(const QModbusRequest &pdu);
- Q_SERIALBUS_EXPORT static int calculateDataSize(const QModbusRequest &pdu);
+ static int minimumDataSize(const QModbusRequest &pdu);
+ static int calculateDataSize(const QModbusRequest &pdu);
using CalcFuncPtr = decltype(&calculateDataSize);
- Q_SERIALBUS_EXPORT static void registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr func);
+ static void registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr func);
template <typename ... Args>
QModbusRequest(FunctionCode code, Args ... newData)
@@ -211,7 +189,7 @@ Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &stream, QModbusRequest &
inline QDataStream &operator<<(QDataStream &stream, const QModbusRequest &pdu)
{ return stream << static_cast<const QModbusPdu &>(pdu); }
-class QModbusResponse : public QModbusPdu
+class Q_SERIALBUS_EXPORT QModbusResponse : public QModbusPdu
{
public:
QModbusResponse() = default;
@@ -222,12 +200,13 @@ public:
explicit QModbusResponse(FunctionCode code, const QByteArray &newData = QByteArray())
: QModbusPdu(code, newData)
{}
+ ~QModbusResponse() override;
- Q_SERIALBUS_EXPORT static int minimumDataSize(const QModbusResponse &pdu);
- Q_SERIALBUS_EXPORT static int calculateDataSize(const QModbusResponse &pdu);
+ static int minimumDataSize(const QModbusResponse &pdu);
+ static int calculateDataSize(const QModbusResponse &pdu);
using CalcFuncPtr = decltype(&calculateDataSize);
- Q_SERIALBUS_EXPORT static void registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr func);
+ static void registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr func);
template <typename ... Args>
QModbusResponse(FunctionCode code, Args ... newData)
@@ -235,7 +214,7 @@ public:
{}
};
-class QModbusExceptionResponse : public QModbusResponse
+class Q_SERIALBUS_EXPORT QModbusExceptionResponse : public QModbusResponse
{
public:
QModbusExceptionResponse() = default;
@@ -245,8 +224,9 @@ public:
QModbusExceptionResponse(FunctionCode fc, ExceptionCode ec)
: QModbusResponse(FunctionCode(quint8(fc) | ExceptionByte), static_cast<quint8> (ec))
{}
+ ~QModbusExceptionResponse() override;
- void setFunctionCode(FunctionCode c) {
+ void setFunctionCode(FunctionCode c) override {
QModbusPdu::setFunctionCode(FunctionCode(quint8(c) | ExceptionByte));
}
void setExceptionCode(ExceptionCode ec) { QModbusPdu::encodeData(quint8(ec)); }
@@ -255,14 +235,6 @@ Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &stream, QModbusResponse
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);
-Q_DECLARE_TYPEINFO(QModbusPdu::FunctionCode, Q_PRIMITIVE_TYPE);
-
-Q_DECLARE_TYPEINFO(QModbusRequest, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(QModbusResponse, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(QModbusExceptionResponse, Q_MOVABLE_TYPE);
-
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QModbusPdu::ExceptionCode)
diff --git a/src/serialbus/qmodbusreply.cpp b/src/serialbus/qmodbusreply.cpp
index caa2dd9..47ff27e 100644
--- a/src/serialbus/qmodbusreply.cpp
+++ b/src/serialbus/qmodbusreply.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmodbusreply.h"
@@ -53,6 +20,7 @@ public:
QString m_errorText;
QModbusResponse m_response;
QModbusReply::ReplyType m_type;
+ QList<QModbusDevice::IntermediateError> m_intermediateErrors;
};
/*!
@@ -82,7 +50,7 @@ public:
/*!
Constructs a QModbusReply object with a given \a type and the specified \a parent.
- The reply will be send to the Modbus client represented by
+ The reply will be sent to the Modbus client represented by
\a serverAddress.
*/
QModbusReply::QModbusReply(ReplyType type, int serverAddress, QObject *parent)
@@ -147,15 +115,17 @@ void QModbusReply::setFinished(bool isFinished)
If the request has not finished, has failed with an error or was a write
request then the returned \l QModbusDataUnit instance is invalid.
- \note If the \l type() of the reply is \l QModbusReply::Raw, the return
- value will always be invalid.
+ \note If the \l type() of the reply is \l QModbusReply::Broadcast, the
+ return value will always be invalid. If the \l type() of the reply is
+ \l QModbusReply::Raw, the return value might be invalid depending on the
+ implementation of \l QModbusClient::processPrivateResponse().
- \sa type(), rawResult()
+ \sa type(), rawResult(), QModbusClient::processPrivateResponse()
*/
QModbusDataUnit QModbusReply::result() const
{
Q_D(const QModbusReply);
- if (type() == QModbusReply::Common)
+ if (type() != QModbusReply::Broadcast)
return d->m_unit;
return QModbusDataUnit();
}
@@ -239,7 +209,6 @@ QString QModbusReply::errorString() const
return d->m_errorText;
}
-
/*!
Returns the type of the reply.
@@ -278,6 +247,41 @@ void QModbusReply::setRawResult(const QModbusResponse &response)
d->m_response = response;
}
+/*!
+ \since 6.0
+ \fn void intermediateErrorOccurred(QModbusDevice::IntermediateError error)
+
+ This signal is emitted when an error has been detected in the processing of
+ this reply. The error will be described by the error code \a error.
+*/
+
+/*!
+ \since 6.0
+
+ Returns the list of intermediate errors that might have happened during
+ the send-receive cycle of a Modbus request until the QModbusReply reports
+ to be finished.
+*/
+QList<QModbusDevice::IntermediateError> QModbusReply::intermediateErrors() const
+{
+ Q_D(const QModbusReply);
+ return d->m_intermediateErrors;
+}
+
+/*!
+ \internal
+ \since 6.0
+
+ Adds an intermediate error to the list of intermediate errors.
+ This will also cause the \l intermediateErrorOccurred() signal to be emitted.
+*/
+void QModbusReply::addIntermediateError(QModbusDevice::IntermediateError error)
+{
+ Q_D(QModbusReply);
+ d->m_intermediateErrors.append(error);
+ emit intermediateErrorOccurred(error);
+}
+
QT_END_NAMESPACE
#include "moc_qmodbusreply.cpp"
diff --git a/src/serialbus/qmodbusreply.h b/src/serialbus/qmodbusreply.h
index ffefc89..f35bd4a 100644
--- a/src/serialbus/qmodbusreply.h
+++ b/src/serialbus/qmodbusreply.h
@@ -1,42 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSREPLY_H
#define QMODBUSREPLY_H
+#include <QtCore/qlist.h>
#include <QtSerialBus/qmodbusdataunit.h>
#include <QtSerialBus/qmodbusdevice.h>
#include <QtSerialBus/qmodbuspdu.h>
@@ -77,9 +45,13 @@ public:
void setFinished(bool isFinished);
void setError(QModbusDevice::Error error, const QString &errorText);
+ QList<QModbusDevice::IntermediateError> intermediateErrors() const;
+ void addIntermediateError(QModbusDevice::IntermediateError error);
+
Q_SIGNALS:
void finished();
void errorOccurred(QModbusDevice::Error error);
+ void intermediateErrorOccurred(QModbusDevice::IntermediateError error);
};
Q_DECLARE_TYPEINFO(QModbusReply::ReplyType, Q_PRIMITIVE_TYPE);
diff --git a/src/serialbus/qmodbusrtuserialmaster.cpp b/src/serialbus/qmodbusrtuserialclient.cpp
index a54b253..c5e4a99 100644
--- a/src/serialbus/qmodbusrtuserialmaster.cpp
+++ b/src/serialbus/qmodbusrtuserialclient.cpp
@@ -1,41 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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 "qmodbusrtuserialmaster.h"
-#include "qmodbusrtuserialmaster_p.h"
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qmodbusrtuserialclient.h"
+#include "qmodbusrtuserialclient_p.h"
#include <QtCore/qloggingcategory.h>
@@ -45,11 +12,11 @@ Q_DECLARE_LOGGING_CATEGORY(QT_MODBUS)
Q_DECLARE_LOGGING_CATEGORY(QT_MODBUS_LOW)
/*!
- \class QModbusRtuSerialMaster
+ \class QModbusRtuSerialClient
\inmodule QtSerialBus
- \since 5.8
+ \since 6.2
- \brief The QModbusRtuSerialMaster class represents a Modbus client
+ \brief The QModbusRtuSerialClient class represents a Modbus client
that uses a serial bus for its communication with the Modbus server.
Communication via Modbus requires the interaction between a single
@@ -58,19 +25,19 @@ Q_DECLARE_LOGGING_CATEGORY(QT_MODBUS_LOW)
*/
/*!
- Constructs a serial Modbus master with the specified \a parent.
+ Constructs a serial Modbus client with the specified \a parent.
*/
-QModbusRtuSerialMaster::QModbusRtuSerialMaster(QObject *parent)
- : QModbusClient(*new QModbusRtuSerialMasterPrivate, parent)
+QModbusRtuSerialClient::QModbusRtuSerialClient(QObject *parent)
+ : QModbusClient(*new QModbusRtuSerialClientPrivate, parent)
{
- Q_D(QModbusRtuSerialMaster);
+ Q_D(QModbusRtuSerialClient);
d->setupSerialPort();
}
/*!
\internal
*/
-QModbusRtuSerialMaster::~QModbusRtuSerialMaster()
+QModbusRtuSerialClient::~QModbusRtuSerialClient()
{
close();
}
@@ -81,9 +48,9 @@ QModbusRtuSerialMaster::~QModbusRtuSerialMaster()
\sa setInterFrameDelay()
*/
-int QModbusRtuSerialMaster::interFrameDelay() const
+int QModbusRtuSerialClient::interFrameDelay() const
{
- Q_D(const QModbusRtuSerialMaster);
+ Q_D(const QModbusRtuSerialClient);
return d->m_interFrameDelayMilliseconds * 1000;
}
@@ -96,9 +63,9 @@ int QModbusRtuSerialMaster::interFrameDelay() const
\note If \a microseconds is set to -1 or \a microseconds is less than the
pre-calculated delay then this pre-calculated value is used as frame delay.
*/
-void QModbusRtuSerialMaster::setInterFrameDelay(int microseconds)
+void QModbusRtuSerialClient::setInterFrameDelay(int microseconds)
{
- Q_D(QModbusRtuSerialMaster);
+ Q_D(QModbusRtuSerialClient);
d->m_interFrameDelayMilliseconds = qCeil(qreal(microseconds) / 1000.);
d->calculateInterFrameDelay();
}
@@ -110,9 +77,9 @@ void QModbusRtuSerialMaster::setInterFrameDelay(int microseconds)
broadcast and a consecutive Modbus messages. The default value is set to
\c 100 milliseconds.
*/
-int QModbusRtuSerialMaster::turnaroundDelay() const
+int QModbusRtuSerialClient::turnaroundDelay() const
{
- Q_D(const QModbusRtuSerialMaster);
+ Q_D(const QModbusRtuSerialClient);
return d->m_turnaroundDelay;
}
@@ -124,19 +91,19 @@ int QModbusRtuSerialMaster::turnaroundDelay() const
Typically the turnaround delay is in the range of \c 100 to \c 200
milliseconds.
*/
-void QModbusRtuSerialMaster::setTurnaroundDelay(int turnaroundDelay)
+void QModbusRtuSerialClient::setTurnaroundDelay(int turnaroundDelay)
{
- Q_D(QModbusRtuSerialMaster);
+ Q_D(QModbusRtuSerialClient);
d->m_turnaroundDelay = turnaroundDelay;
}
/*!
\internal
*/
-QModbusRtuSerialMaster::QModbusRtuSerialMaster(QModbusRtuSerialMasterPrivate &dd, QObject *parent)
+QModbusRtuSerialClient::QModbusRtuSerialClient(QModbusRtuSerialClientPrivate &dd, QObject *parent)
: QModbusClient(dd, parent)
{
- Q_D(QModbusRtuSerialMaster);
+ Q_D(QModbusRtuSerialClient);
d->setupSerialPort();
}
@@ -146,12 +113,12 @@ QModbusRtuSerialMaster::QModbusRtuSerialMaster(QModbusRtuSerialMasterPrivate &dd
\note When calling this function, existing buffered data is removed from
the serial port.
*/
-bool QModbusRtuSerialMaster::open()
+bool QModbusRtuSerialClient::open()
{
if (state() == QModbusDevice::ConnectedState)
return true;
- Q_D(QModbusRtuSerialMaster);
+ Q_D(QModbusRtuSerialClient);
d->setupEnvironment(); // to be done before open
if (d->m_serialPort->open(QIODevice::ReadWrite)) {
setState(QModbusDevice::ConnectedState);
@@ -165,14 +132,14 @@ bool QModbusRtuSerialMaster::open()
/*!
\reimp
*/
-void QModbusRtuSerialMaster::close()
+void QModbusRtuSerialClient::close()
{
if (state() == QModbusDevice::UnconnectedState)
return;
setState(QModbusDevice::ClosingState);
- Q_D(QModbusRtuSerialMaster);
+ Q_D(QModbusRtuSerialClient);
if (d->m_serialPort->isOpen())
d->m_serialPort->close();
@@ -180,7 +147,7 @@ void QModbusRtuSerialMaster::close()
int numberOfAborts = 0;
while (!d->m_queue.isEmpty()) {
// Finish each open reply and forget them
- QModbusRtuSerialMasterPrivate::QueueElement elem = d->m_queue.dequeue();
+ QModbusRtuSerialClientPrivate::QueueElement elem = d->m_queue.dequeue();
if (!elem.reply.isNull()) {
elem.reply->setError(QModbusDevice::ReplyAbortedError,
QModbusClient::tr("Reply aborted due to connection closure."));
@@ -195,3 +162,5 @@ void QModbusRtuSerialMaster::close()
}
QT_END_NAMESPACE
+
+#include "moc_qmodbusrtuserialclient.cpp"
diff --git a/src/serialbus/qmodbusrtuserialclient.h b/src/serialbus/qmodbusrtuserialclient.h
new file mode 100644
index 0000000..2e31dc2
--- /dev/null
+++ b/src/serialbus/qmodbusrtuserialclient.h
@@ -0,0 +1,49 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QMODBUSRTUSERIALCLIENT_H
+#define QMODBUSRTUSERIALCLIENT_H
+
+// The pragma is required to generate proper headers for source compatibility.
+#if 0
+#pragma qt_deprecates(QModbusRtuSerialMaster, 7.0)
+#endif
+
+#include <QtSerialBus/qmodbusclient.h>
+
+QT_BEGIN_NAMESPACE
+
+class QModbusRtuSerialClientPrivate;
+
+class Q_SERIALBUS_EXPORT QModbusRtuSerialClient : public QModbusClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QModbusRtuSerialClient)
+
+public:
+ explicit QModbusRtuSerialClient(QObject *parent = nullptr);
+ ~QModbusRtuSerialClient();
+
+ int interFrameDelay() const;
+ void setInterFrameDelay(int microseconds);
+
+ int turnaroundDelay() const;
+ void setTurnaroundDelay(int turnaroundDelay);
+
+protected:
+ QModbusRtuSerialClient(QModbusRtuSerialClientPrivate &dd, QObject *parent = nullptr);
+
+ void close() override;
+ bool open() override;
+};
+
+#if QT_DEPRECATED_SINCE(6, 2)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wattributes")
+using QModbusRtuSerialMaster
+ Q_DECL_DEPRECATED_X("Please port your application to QModbusRtuSerialClient.") = QModbusRtuSerialClient;
+#endif
+QT_WARNING_POP
+QT_END_NAMESPACE
+
+#endif // QMODBUSRTUSERIALCLIENT_H
diff --git a/src/serialbus/qmodbusrtuserialmaster_p.h b/src/serialbus/qmodbusrtuserialclient_p.h
index d206eec..f499c0e 100644
--- a/src/serialbus/qmodbusrtuserialmaster_p.h
+++ b/src/serialbus/qmodbusrtuserialclient_p.h
@@ -1,48 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
-
-#ifndef QMODBUSSERIALMASTER_P_H
-#define QMODBUSSERIALMASTER_P_H
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QMODBUSRTUSERIALCLIENT_P_H
+#define QMODBUSRTUSERIALCLIENT_P_H
#include <QtCore/qloggingcategory.h>
#include <QtCore/qmath.h>
#include <QtCore/qpointer.h>
#include <QtCore/qqueue.h>
#include <QtCore/qtimer.h>
-#include <QtSerialBus/qmodbusrtuserialmaster.h>
+#include <QtSerialBus/qmodbusrtuserialclient.h>
#include <QtSerialPort/qserialport.h>
#include <private/qmodbusadu_p.h>
@@ -95,10 +62,10 @@ private:
QBasicTimer m_timer;
};
-class QModbusRtuSerialMasterPrivate : public QModbusClientPrivate
+class QModbusRtuSerialClientPrivate : public QModbusClientPrivate
{
- Q_DECLARE_PUBLIC(QModbusRtuSerialMaster)
- enum State
+ Q_DECLARE_PUBLIC(QModbusRtuSerialClient)
+ enum State
{
Idle,
WaitingForReplay,
@@ -165,6 +132,7 @@ public:
qCWarning(QT_MODBUS) << "(RTU client) Discarding response with wrong CRC, received:"
<< adu.checksum<quint16>() << ", calculated CRC:"
<< QModbusSerialAdu::calculateCRC(adu.data(), adu.size());
+ m_queue.first().reply->addIntermediateError(QModbusClient::ResponseCrcError);
return;
}
@@ -172,6 +140,7 @@ public:
if (!canMatchRequestAndResponse(response, adu.serverAddress())) {
qCWarning(QT_MODBUS) << "(RTU client) Cannot match response with open request, "
"ignoring";
+ m_queue.first().reply->addIntermediateError(QModbusClient::ResponseRequestMismatch);
return;
}
@@ -187,8 +156,8 @@ public:
void onAboutToClose()
{
- Q_Q(QModbusRtuSerialMaster);
- Q_UNUSED(q) // avoid warning in release mode
+ Q_Q(QModbusRtuSerialClient);
+ Q_UNUSED(q); // avoid warning in release mode
Q_ASSERT(q->state() == QModbusDevice::ClosingState);
m_responseTimer.stop();
@@ -199,7 +168,7 @@ public:
m_responseTimer.stop();
if (m_state != State::WaitingForReplay || m_queue.isEmpty())
return;
- const auto current = m_queue.first();
+ const auto &current = m_queue.first();
if (current.m_timerId != timerId)
return;
@@ -248,7 +217,7 @@ public:
qCDebug(QT_MODBUS) << "(RTU server) QSerialPort error:" << error
<< (m_serialPort ? m_serialPort->errorString() : QString());
- Q_Q(QModbusRtuSerialMaster);
+ Q_Q(QModbusRtuSerialClient);
switch (error) {
case QSerialPort::DeviceNotFoundError:
@@ -291,7 +260,7 @@ public:
void setupSerialPort()
{
- Q_Q(QModbusRtuSerialMaster);
+ Q_Q(QModbusRtuSerialClient);
m_serialPort = new QSerialPort(q);
QObject::connect(&m_responseTimer, &Timer::timeout, q, [this](int timerId) {
@@ -316,29 +285,6 @@ public:
});
}
- /*!
- According to the Modbus specification, in RTU mode message frames
- are separated by a silent interval of at least 3.5 character times.
- Calculate the timeout if we are less than 19200 baud, use a fixed
- timeout for everything equal or greater than 19200 baud.
- If the user set the timeout to be longer than the calculated one,
- we'll keep the user defined.
- */
- void calculateInterFrameDelay()
- {
- // The spec recommends a timeout value of 1.750 msec. Without such
- // precise single-shot timers use a approximated value of 1.750 msec.
- int delayMilliSeconds = 2;
- if (m_baudRate < 19200) {
- // Example: 9600 baud, 11 bit per packet -> 872 char/sec
- // so: 1000 ms / 872 char = 1.147 ms/char * 3.5 character
- // Always round up because the spec requests at least 3.5 char.
- delayMilliSeconds = qCeil(3500. / (qreal(m_baudRate) / 11.));
- }
- if (m_interFrameDelayMilliseconds < delayMilliSeconds)
- m_interFrameDelayMilliseconds = delayMilliSeconds;
- }
-
void setupEnvironment()
{
if (m_serialPort) {
@@ -352,13 +298,13 @@ public:
calculateInterFrameDelay();
m_responseBuffer.clear();
- m_state = QModbusRtuSerialMasterPrivate::Idle;
+ m_state = QModbusRtuSerialClientPrivate::Idle;
}
QModbusReply *enqueueRequest(const QModbusRequest &request, int serverAddress,
const QModbusDataUnit &unit, QModbusReply::ReplyType type) override
{
- Q_Q(QModbusRtuSerialMaster);
+ Q_Q(QModbusRtuSerialClient);
auto reply = new QModbusReply(serverAddress == 0 ? QModbusReply::Broadcast : type,
serverAddress, q);
@@ -373,7 +319,7 @@ public:
void scheduleNextRequest(int delay)
{
- Q_Q(QModbusRtuSerialMaster);
+ Q_Q(QModbusRtuSerialClient);
if (m_state == Idle && !m_queue.isEmpty()) {
m_state = WaitingForReplay;
@@ -435,12 +381,9 @@ public:
QQueue<QueueElement> m_queue;
QSerialPort *m_serialPort = nullptr;
- int m_interFrameDelayMilliseconds = 2; // A approximated value of 1.750 msec.
int m_turnaroundDelay = 100; // Recommended value is between 100 and 200 msec.
};
QT_END_NAMESPACE
-#include "qmodbusrtuserialmaster_p.h"
-
-#endif // QMODBUSSERIALMASTER_P_H
+#endif // QMODBUSRTUSERIALCLIENT_P_H
diff --git a/src/serialbus/qmodbusrtuserialmaster.h b/src/serialbus/qmodbusrtuserialmaster.h
deleted file mode 100644
index 87f58df..0000000
--- a/src/serialbus/qmodbusrtuserialmaster.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
-
-#ifndef QMODBUSRTUSERIALMASTER_H
-#define QMODBUSRTUSERIALMASTER_H
-
-#include <QtSerialBus/qmodbusclient.h>
-
-QT_BEGIN_NAMESPACE
-
-class QModbusRtuSerialMasterPrivate;
-
-class Q_SERIALBUS_EXPORT QModbusRtuSerialMaster : public QModbusClient
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QModbusRtuSerialMaster)
-
-public:
- explicit QModbusRtuSerialMaster(QObject *parent = nullptr);
- ~QModbusRtuSerialMaster();
-
- int interFrameDelay() const;
- void setInterFrameDelay(int microseconds);
-
- int turnaroundDelay() const;
- void setTurnaroundDelay(int turnaroundDelay);
-
-protected:
- QModbusRtuSerialMaster(QModbusRtuSerialMasterPrivate &dd, QObject *parent = nullptr);
-
- void close() override;
- bool open() override;
-};
-
-QT_END_NAMESPACE
-
-#endif // QMODBUSRTUSERIALMASTER_H
diff --git a/src/serialbus/qmodbusrtuserialserver.cpp b/src/serialbus/qmodbusrtuserialserver.cpp
new file mode 100644
index 0000000..fa93e06
--- /dev/null
+++ b/src/serialbus/qmodbusrtuserialserver.cpp
@@ -0,0 +1,160 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qmodbusrtuserialserver.h"
+#include "qmodbusrtuserialserver_p.h"
+
+#include <QtCore/qloggingcategory.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QModbusRtuSerialServer
+ \inmodule QtSerialBus
+ \since 6.2
+
+ \brief The QModbusRtuSerialServer class represents a Modbus server
+ that uses a serial port for its communication with the Modbus client.
+
+ Communication via Modbus requires the interaction between a single Modbus
+ client instance and multiple Modbus server. This class provides the Modbus
+ server implementation via a serial port.
+
+ Since multiple Modbus server instances can interact with a Modbus client
+ at the same time (using a serial bus), servers are identified by their
+ \l serverAddress().
+*/
+
+/*!
+ Constructs a QModbusRtuSerialServer with the specified \a parent. The
+ \l serverAddress preset is \c 1.
+*/
+QModbusRtuSerialServer::QModbusRtuSerialServer(QObject *parent)
+ : QModbusServer(*new QModbusRtuSerialServerPrivate, parent)
+{
+ Q_D(QModbusRtuSerialServer);
+ d->setupSerialPort();
+}
+
+/*!
+ Destroys the QModbusRtuSerialServer instance.
+*/
+QModbusRtuSerialServer::~QModbusRtuSerialServer()
+{
+ close();
+}
+
+/*!
+ \internal
+*/
+QModbusRtuSerialServer::QModbusRtuSerialServer(QModbusRtuSerialServerPrivate &dd, QObject *parent)
+ : QModbusServer(dd, parent)
+{
+ Q_D(QModbusRtuSerialServer);
+ d->setupSerialPort();
+}
+
+/*!
+ \reimp
+*/
+bool QModbusRtuSerialServer::processesBroadcast() const
+{
+ return d_func()->m_processesBroadcast;
+}
+
+/*!
+ \since 6.2
+
+ Returns the amount of microseconds for the silent interval between two
+ consecutive Modbus messages.
+
+ \sa setInterFrameDelay()
+*/
+int QModbusRtuSerialServer::interFrameDelay() const
+{
+ Q_D(const QModbusRtuSerialServer);
+ return d->m_interFrameDelayMilliseconds * 1000;
+}
+
+/*!
+ \since 6.2
+
+ Sets the amount of \a microseconds for the silent interval between two
+ consecutive Modbus messages. By default, the class implementation will use
+ a pre-calculated value according to the Modbus specification. A active or
+ running connection is not affected by such delay changes.
+
+ \note If \a microseconds is set to -1 or \a microseconds is less than the
+ pre-calculated delay then this pre-calculated value is used as frame delay.
+*/
+void QModbusRtuSerialServer::setInterFrameDelay(int microseconds)
+{
+ Q_D(QModbusRtuSerialServer);
+ d->m_interFrameDelayMilliseconds = qCeil(qreal(microseconds) / 1000.);
+ d->calculateInterFrameDelay();
+}
+
+/*!
+ \reimp
+
+ \note When calling this function, existing buffered data is removed from
+ the serial port.
+*/
+bool QModbusRtuSerialServer::open()
+{
+ if (state() == QModbusDevice::ConnectedState)
+ return true;
+
+ Q_D(QModbusRtuSerialServer);
+ d->setupEnvironment(); // to be done before open
+ if (d->m_serialPort->open(QIODevice::ReadWrite)) {
+ setState(QModbusDevice::ConnectedState);
+ d->m_serialPort->clear(); // only possible after open
+ } else {
+ setError(d->m_serialPort->errorString(), QModbusDevice::ConnectionError);
+ }
+ return (state() == QModbusDevice::ConnectedState);
+}
+
+/*!
+ \reimp
+*/
+void QModbusRtuSerialServer::close()
+{
+ if (state() == QModbusDevice::UnconnectedState)
+ return;
+
+ Q_D(QModbusRtuSerialServer);
+ if (d->m_serialPort->isOpen())
+ d->m_serialPort->close();
+
+ setState(QModbusDevice::UnconnectedState);
+}
+
+/*!
+ \reimp
+
+ Processes the Modbus client request specified by \a request and returns a
+ Modbus response.
+
+ The Modbus function \l QModbusRequest::EncapsulatedInterfaceTransport with
+ MEI Type 13 (0x0D) CANopen General Reference is filtered out because it is
+ usually Modbus TCP or Modbus serial ASCII only.
+
+ A request to the RTU serial server will be answered with a Modbus exception
+ response with the exception code QModbusExceptionResponse::IllegalFunction.
+*/
+QModbusResponse QModbusRtuSerialServer::processRequest(const QModbusPdu &request)
+{
+ if (request.functionCode() == QModbusRequest::EncapsulatedInterfaceTransport) {
+ quint8 meiType;
+ request.decodeData(&meiType);
+ if (meiType == EncapsulatedInterfaceTransport::CanOpenGeneralReference) {
+ return QModbusExceptionResponse(request.functionCode(),
+ QModbusExceptionResponse::IllegalFunction);
+ }
+ }
+ return QModbusServer::processRequest(request);
+}
+
+QT_END_NAMESPACE
diff --git a/src/serialbus/qmodbusrtuserialserver.h b/src/serialbus/qmodbusrtuserialserver.h
new file mode 100644
index 0000000..4d430eb
--- /dev/null
+++ b/src/serialbus/qmodbusrtuserialserver.h
@@ -0,0 +1,50 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QMODBUSRTUSERIALSERVER_H
+#define QMODBUSRTUSERIALSERVER_H
+
+// The pragma is required to generate proper headers for source compatibility.
+#if 0
+#pragma qt_deprecates(QModbusRtuSerialSlave, 7.0)
+#endif
+
+#include <QtSerialBus/qmodbusserver.h>
+
+QT_BEGIN_NAMESPACE
+
+class QModbusRtuSerialServerPrivate;
+
+class Q_SERIALBUS_EXPORT QModbusRtuSerialServer : public QModbusServer
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QModbusRtuSerialServer)
+
+public:
+ explicit QModbusRtuSerialServer(QObject *parent = nullptr);
+ ~QModbusRtuSerialServer();
+
+ bool processesBroadcast() const override;
+
+ int interFrameDelay() const;
+ void setInterFrameDelay(int microseconds);
+
+protected:
+ QModbusRtuSerialServer(QModbusRtuSerialServerPrivate &dd, QObject *parent = nullptr);
+
+ bool open() override;
+ void close() override;
+
+ QModbusResponse processRequest(const QModbusPdu &request) override;
+};
+
+#if QT_DEPRECATED_SINCE(6, 2)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wattributes")
+using QModbusRtuSerialSlave
+ Q_DECL_DEPRECATED_X("Please port your application to QModbusRtuSerialServer.") = QModbusRtuSerialServer;
+#endif
+QT_WARNING_POP
+QT_END_NAMESPACE
+
+#endif // QMODBUSRTUSERIALSERVER_H
diff --git a/src/serialbus/qmodbusrtuserialslave_p.h b/src/serialbus/qmodbusrtuserialserver_p.h
index d6ff8d6..39d5eb6 100644
--- a/src/serialbus/qmodbusrtuserialslave_p.h
+++ b/src/serialbus/qmodbusrtuserialserver_p.h
@@ -1,48 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
-
-#ifndef QMODBUSRTUSERIALSLAVE_P_H
-#define QMODBUSRTUSERIALSLAVE_P_H
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QMODBUSRTUSERIALSERVER_P_H
+#define QMODBUSRTUSERIALSERVER_P_H
#include <QtCore/qbytearray.h>
#include <QtCore/qdebug.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qmath.h>
-#include <QtSerialBus/qmodbusrtuserialslave.h>
+#include <QtSerialBus/qmodbusrtuserialserver.h>
#include <QtSerialPort/qserialport.h>
#include <private/qmodbusadu_p.h>
@@ -64,14 +31,14 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_MODBUS)
Q_DECLARE_LOGGING_CATEGORY(QT_MODBUS_LOW)
-class QModbusRtuSerialSlavePrivate : public QModbusServerPrivate
+class QModbusRtuSerialServerPrivate : public QModbusServerPrivate
{
- Q_DECLARE_PUBLIC(QModbusRtuSerialSlave)
+ Q_DECLARE_PUBLIC(QModbusRtuSerialServer)
public:
void setupSerialPort()
{
- Q_Q(QModbusRtuSerialSlave);
+ Q_Q(QModbusRtuSerialServer);
m_serialPort = new QSerialPort(q);
QObject::connect(m_serialPort, &QSerialPort::readyRead, q, [this]() {
@@ -101,7 +68,7 @@ public:
// FunctionCode -> 1 byte
// FunctionCode specific content -> 0-252 bytes
// CRC -> 2 bytes
- Q_Q(QModbusRtuSerialSlave);
+ Q_Q(QModbusRtuSerialServer);
QModbusCommEvent event = QModbusCommEvent::ReceiveEvent;
if (q->value(QModbusServer::ListenOnlyMode).toBool())
event |= QModbusCommEvent::ReceiveFlag::CurrentlyInListenOnlyMode;
@@ -211,7 +178,7 @@ public:
if (!m_serialPort->isOpen()) {
qCDebug(QT_MODBUS) << "(RTU server) Requesting serial port has closed.";
- q->setError(QModbusRtuSerialSlave::tr("Requesting serial port is closed"),
+ q->setError(QModbusRtuSerialServer::tr("Requesting serial port is closed"),
QModbusDevice::WriteError);
incrementCounter(QModbusServerPrivate::Counter::ServerNoResponse);
storeModbusCommEvent(event);
@@ -221,7 +188,7 @@ public:
qint64 writtenBytes = m_serialPort->write(result);
if ((writtenBytes == -1) || (writtenBytes < result.size())) {
qCDebug(QT_MODBUS) << "(RTU server) Cannot write requested response to serial port.";
- q->setError(QModbusRtuSerialSlave::tr("Could not write response to client"),
+ q->setError(QModbusRtuSerialServer::tr("Could not write response to client"),
QModbusDevice::WriteError);
incrementCounter(QModbusServerPrivate::Counter::ServerNoResponse);
storeModbusCommEvent(event);
@@ -288,7 +255,7 @@ public:
qCDebug(QT_MODBUS) << "(RTU server) QSerialPort error:" << error
<< (m_serialPort ? m_serialPort->errorString() : QString());
- Q_Q(QModbusRtuSerialSlave);
+ Q_Q(QModbusRtuSerialServer);
switch (error) {
case QSerialPort::DeviceNotFoundError:
@@ -330,14 +297,15 @@ public:
});
QObject::connect(m_serialPort, &QSerialPort::aboutToClose, q, [this]() {
- Q_Q(QModbusRtuSerialSlave);
+ Q_Q(QModbusRtuSerialServer);
// update state if socket closure was caused by remote side
if (q->state() != QModbusDevice::ClosingState)
q->setState(QModbusDevice::UnconnectedState);
});
}
- void setupEnvironment() {
+ void setupEnvironment()
+ {
if (m_serialPort) {
m_serialPort->setPortName(m_comPort);
m_serialPort->setParity(m_parity);
@@ -346,10 +314,7 @@ public:
m_serialPort->setStopBits(m_stopBits);
}
- // for calculation details see
- // QModbusRtuSerialMasterPrivate::calculateInterFrameDelay()
- m_interFrameDelayMilliseconds = qMax(m_interFrameDelayMilliseconds,
- qCeil(3500. / (qreal(m_baudRate) / 11.)));
+ calculateInterFrameDelay();
m_requestBuffer.clear();
}
@@ -360,9 +325,8 @@ public:
bool m_processesBroadcast = false;
QSerialPort *m_serialPort = nullptr;
QElapsedTimer m_interFrameTimer;
- int m_interFrameDelayMilliseconds = 2;
};
QT_END_NAMESPACE
-#endif // QMODBUSRTUSERIALSLAVE_P_H
+#endif // QMODBUSRTUSERIALSERVER_P_H
diff --git a/src/serialbus/qmodbusrtuserialslave.cpp b/src/serialbus/qmodbusrtuserialslave.cpp
deleted file mode 100644
index 36a845c..0000000
--- a/src/serialbus/qmodbusrtuserialslave.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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 "qmodbusrtuserialslave.h"
-#include "qmodbusrtuserialslave_p.h"
-
-#include <QtCore/qloggingcategory.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QModbusRtuSerialSlave
- \inmodule QtSerialBus
- \since 5.8
-
- \brief The QModbusRtuSerialSlave class represents a Modbus server
- that uses a serial port for its communication with the Modbus client.
-
- Communication via Modbus requires the interaction between a single Modbus
- client instance and multiple Modbus server. This class provides the Modbus
- server implementation via a serial port.
-
- Since multiple Modbus server instances can interact with a Modbus client
- at the same time (using a serial bus), servers are identified by their
- \l serverAddress().
-*/
-
-/*!
- Constructs a QModbusRtuSerialSlave with the specified \a parent. The
- \l serverAddress preset is \c 1.
-*/
-QModbusRtuSerialSlave::QModbusRtuSerialSlave(QObject *parent)
- : QModbusServer(*new QModbusRtuSerialSlavePrivate, parent)
-{
- Q_D(QModbusRtuSerialSlave);
- d->setupSerialPort();
-}
-
-/*!
- Destroys the QModbusRtuSerialSlave instance.
-*/
-QModbusRtuSerialSlave::~QModbusRtuSerialSlave()
-{
- close();
-}
-
-/*!
- \internal
-*/
-QModbusRtuSerialSlave::QModbusRtuSerialSlave(QModbusRtuSerialSlavePrivate &dd, QObject *parent)
- : QModbusServer(dd, parent)
-{
- Q_D(QModbusRtuSerialSlave);
- d->setupSerialPort();
-}
-
-/*!
- \reimp
-*/
-bool QModbusRtuSerialSlave::processesBroadcast() const
-{
- return d_func()->m_processesBroadcast;
-}
-
-/*!
- \reimp
-
- \note When calling this function, existing buffered data is removed from
- the serial port.
-*/
-bool QModbusRtuSerialSlave::open()
-{
- if (state() == QModbusDevice::ConnectedState)
- return true;
-
- Q_D(QModbusRtuSerialSlave);
- d->setupEnvironment(); // to be done before open
- if (d->m_serialPort->open(QIODevice::ReadWrite)) {
- setState(QModbusDevice::ConnectedState);
- d->m_serialPort->clear(); // only possible after open
- } else {
- setError(d->m_serialPort->errorString(), QModbusDevice::ConnectionError);
- }
- return (state() == QModbusDevice::ConnectedState);
-}
-
-/*!
- \reimp
-*/
-void QModbusRtuSerialSlave::close()
-{
- if (state() == QModbusDevice::UnconnectedState)
- return;
-
- Q_D(QModbusRtuSerialSlave);
- if (d->m_serialPort->isOpen())
- d->m_serialPort->close();
-
- setState(QModbusDevice::UnconnectedState);
-}
-
-/*!
- \reimp
-
- Processes the Modbus client request specified by \a request and returns a
- Modbus response.
-
- The Modbus function \l QModbusRequest::EncapsulatedInterfaceTransport with
- MEI Type 13 (0x0D) CANopen General Reference is filtered out because it is
- usually Modbus TCP or Modbus serial ASCII only.
-
- A request to the RTU serial slave will be answered with a Modbus exception
- response with the exception code QModbusExceptionResponse::IllegalFunction.
-*/
-QModbusResponse QModbusRtuSerialSlave::processRequest(const QModbusPdu &request)
-{
- if (request.functionCode() == QModbusRequest::EncapsulatedInterfaceTransport) {
- quint8 meiType;
- request.decodeData(&meiType);
- if (meiType == EncapsulatedInterfaceTransport::CanOpenGeneralReference) {
- return QModbusExceptionResponse(request.functionCode(),
- QModbusExceptionResponse::IllegalFunction);
- }
- }
- return QModbusServer::processRequest(request);
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qmodbusrtuserialslave.cpp"
diff --git a/src/serialbus/qmodbusrtuserialslave.h b/src/serialbus/qmodbusrtuserialslave.h
deleted file mode 100644
index 2194bce..0000000
--- a/src/serialbus/qmodbusrtuserialslave.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
-
-#ifndef QMODBUSRTUSERIALSLAVE_H
-#define QMODBUSRTUSERIALSLAVE_H
-
-#include <QtSerialBus/qmodbusserver.h>
-
-QT_BEGIN_NAMESPACE
-
-class QModbusRtuSerialSlavePrivate;
-
-class Q_SERIALBUS_EXPORT QModbusRtuSerialSlave : public QModbusServer
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QModbusRtuSerialSlave)
-
-public:
- explicit QModbusRtuSerialSlave(QObject *parent = nullptr);
- ~QModbusRtuSerialSlave();
-
- bool processesBroadcast() const override;
-
-protected:
- QModbusRtuSerialSlave(QModbusRtuSerialSlavePrivate &dd, QObject *parent = nullptr);
-
- bool open() override;
- void close() override;
-
- QModbusResponse processRequest(const QModbusPdu &request) override;
-};
-
-QT_END_NAMESPACE
-
-#endif // QMODBUSRTUSERIALSLAVE_H
diff --git a/src/serialbus/qmodbusserver.cpp b/src/serialbus/qmodbusserver.cpp
index 929ac9a..70be415 100644
--- a/src/serialbus/qmodbusserver.cpp
+++ b/src/serialbus/qmodbusserver.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmodbusdeviceidentification.h"
#include "qmodbusserver.h"
@@ -41,8 +8,8 @@
#include <QtCore/qbitarray.h>
#include <QtCore/qdebug.h>
+#include <QtCore/qlist.h>
#include <QtCore/qloggingcategory.h>
-#include <QtCore/qvector.h>
#include <algorithm>
@@ -139,7 +106,7 @@ void QModbusServer::setServerAddress(int serverAddress)
}
/*!
- Returns the address of this Mobus server instance.
+ Returns the address of this Modbus server instance.
\sa setServerAddress()
*/
@@ -311,7 +278,7 @@ bool QModbusServer::setValue(int option, const QVariant &newValue)
{
#define CHECK_INT_OR_UINT(val) \
do { \
- if ((val.type() != QVariant::Int) && (val.type() != QVariant::UInt)) \
+ if ((val.typeId() != QMetaType::Type::Int) && (val.typeId() != QMetaType::Type::UInt)) \
return false; \
} while (0)
@@ -347,7 +314,7 @@ bool QModbusServer::setValue(int option, const QVariant &newValue)
return true;
}
case ListenOnlyMode: {
- if (newValue.type() != QVariant::Bool)
+ if (newValue.typeId() != QMetaType::Type::Bool)
return false;
d->m_serverOptions.insert(option, newValue);
return true;
@@ -365,7 +332,7 @@ bool QModbusServer::setValue(int option, const QVariant &newValue)
return true;
}
case AdditionalData: {
- if (newValue.type() != QVariant::ByteArray)
+ if (newValue.typeId() != QMetaType::Type::QByteArray)
return false;
const QByteArray additionalData = newValue.toByteArray();
if (additionalData.size() > 249)
@@ -448,7 +415,7 @@ bool QModbusServer::data(QModbusDataUnit *newData) const
*/
bool QModbusServer::setData(QModbusDataUnit::RegisterType table, quint16 address, quint16 data)
{
- return writeData(QModbusDataUnit(table, address, QVector<quint16>() << data));
+ return writeData(QModbusDataUnit(table, address, QList<quint16> { data }));
}
/*!
@@ -502,9 +469,9 @@ bool QModbusServer::writeData(const QModbusDataUnit &newData)
return false;
bool changeRequired = false;
- for (uint i = 0; i < newData.valueCount(); i++) {
+ for (qsizetype i = 0; i < newData.valueCount(); i++) {
const quint16 newValue = newData.value(i);
- const int translatedIndex = newData.startAddress() - current.startAddress() + i;
+ const qsizetype translatedIndex = newData.startAddress() - current.startAddress() + i;
changeRequired |= (current.value(translatedIndex) != newValue);
current.setValue(translatedIndex, newValue);
}
@@ -725,7 +692,7 @@ QModbusResponse QModbusServerPrivate::readBits(const QModbusPdu &request,
QModbusExceptionResponse::IllegalDataAddress);
}
- quint8 byteCount = count / 8;
+ quint8 byteCount = quint8(count / 8);
if ((count % 8) != 0) {
byteCount += 1;
// If the range is not a multiple of 8, resize.
@@ -829,7 +796,7 @@ QModbusResponse QModbusServerPrivate::processReadExceptionStatusRequest(const QM
QModbusExceptionResponse::IllegalDataAddress);
}
- quint16 address = 0;
+ qsizetype address = 0;
quint8 byte = 0;
for (int currentBit = 0; currentBit < 8; ++currentBit)
if (coils.value(address++)) // The padding happens inside value().
@@ -946,7 +913,7 @@ QModbusResponse QModbusServerPrivate::processGetCommEventLogRequest(const QModbu
}
const quint16 deviceBusy = tmp.value<quint16>();
- QVector<quint8> eventLog(int(m_commEventLog.size()));
+ QList<quint8> eventLog(int(m_commEventLog.size()));
std::copy(m_commEventLog.cbegin(), m_commEventLog.cend(), eventLog.begin());
// 6 -> 3 x 2 Bytes (Status, Event Count and Message Count)
@@ -983,7 +950,7 @@ QModbusResponse QModbusServerPrivate::processWriteMultipleCoilsRequest(const QMo
QModbusExceptionResponse::IllegalDataAddress);
}
- QVector<quint8> bytes;
+ QList<quint8> bytes;
const QByteArray payload = request.data().mid(5);
for (qint32 i = payload.size() - 1; i >= 0; --i)
bytes.append(quint8(payload[i]));
@@ -992,7 +959,7 @@ QModbusResponse QModbusServerPrivate::processWriteMultipleCoilsRequest(const QMo
// range is numberOfCoils and therefore index too.
quint16 coil = numberOfCoils;
qint32 currentBit = 8 - ((byteCount * 8) - numberOfCoils);
- for (quint8 currentByte : qAsConst(bytes)) {
+ for (quint8 currentByte : std::as_const(bytes)) {
for (currentBit -= 1; currentBit >= 0; --currentBit)
coils.setValue(--coil, currentByte & (1U << currentBit) ? 1 : 0);
currentBit = 8;
@@ -1035,7 +1002,7 @@ QModbusResponse QModbusServerPrivate::processWriteMultipleRegistersRequest(
const QByteArray pduData = request.data().remove(0,5);
QDataStream stream(pduData);
- QVector<quint16> values;
+ QList<quint16> values;
quint16 tmp;
for (int i = 0; i < numberOfRegisters; i++) {
stream >> tmp;
@@ -1134,7 +1101,7 @@ QModbusResponse QModbusServerPrivate::processReadWriteMultipleRegistersRequest(
const QByteArray pduData = request.data().remove(0,9);
QDataStream stream(pduData);
- QVector<quint16> values;
+ QList<quint16> values;
quint16 tmp;
for (int i = 0; i < writeQuantity; i++) {
stream >> tmp;
@@ -1286,7 +1253,7 @@ QModbusResponse QModbusServerPrivate::processEncapsulatedInterfaceTransportReque
header[4] = quint8(0x00); // next object id
header[5] = quint8(0x01); // number of objects
header[6] = objectId;
- header[7] = quint8(object.length());
+ header[7] = quint8(object.size());
return QModbusResponse(request.functionCode(), QByteArray(header + object));
}
default:
diff --git a/src/serialbus/qmodbusserver.h b/src/serialbus/qmodbusserver.h
index 0f513d8..57f422a 100644
--- a/src/serialbus/qmodbusserver.h
+++ b/src/serialbus/qmodbusserver.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSERVER_H
#define QMODBUSERVER_H
diff --git a/src/serialbus/qmodbusserver_p.h b/src/serialbus/qmodbusserver_p.h
index a527317..96a51cb 100644
--- a/src/serialbus/qmodbusserver_p.h
+++ b/src/serialbus/qmodbusserver_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSERVER_P_H
#define QMODBUSERVER_P_H
diff --git a/src/serialbus/qmodbustcpclient.cpp b/src/serialbus/qmodbustcpclient.cpp
index c897390..bf2dad6 100644
--- a/src/serialbus/qmodbustcpclient.cpp
+++ b/src/serialbus/qmodbustcpclient.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmodbustcpclient.h"
#include "qmodbustcpclient_p.h"
diff --git a/src/serialbus/qmodbustcpclient.h b/src/serialbus/qmodbustcpclient.h
index 481d558..2b0f374 100644
--- a/src/serialbus/qmodbustcpclient.h
+++ b/src/serialbus/qmodbustcpclient.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSTCPCLIENT_H
#define QMODBUSTCPCLIENT_H
diff --git a/src/serialbus/qmodbustcpclient_p.h b/src/serialbus/qmodbustcpclient_p.h
index 649b48e..9492a66 100644
--- a/src/serialbus/qmodbustcpclient_p.h
+++ b/src/serialbus/qmodbustcpclient_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSTCPCLIENT_P_H
#define QMODBUSTCPCLIENT_P_H
@@ -86,8 +53,7 @@ public:
cleanupTransactionStore();
});
- QObject::connect(m_socket,
- QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), q,
+ QObject::connect(m_socket, &QAbstractSocket::errorOccurred, q,
[this](QAbstractSocket::SocketError /*error*/)
{
Q_Q(QModbusTcpClient);
@@ -107,7 +73,7 @@ public:
while (!responseBuffer.isEmpty()) {
// can we read enough for Modbus ADU header?
if (responseBuffer.size() < mbpaHeaderSize) {
- qCDebug(QT_MODBUS_LOW) << "(TCP client) Modbus ADU not complete";
+ qCDebug(QT_MODBUS_LOW) << "(TCP client) MBPA header too short. Waiting for more data.";
return;
}
@@ -241,7 +207,7 @@ public:
qCDebug(QT_MODBUS) << "(TCP client) Cleanup of pending requests";
- for (const auto &elem : qAsConst(m_transactionStore)) {
+ for (const auto &elem : std::as_const(m_transactionStore)) {
if (elem.reply.isNull())
continue;
elem.reply->setError(QModbusDevice::ReplyAbortedError,
diff --git a/src/serialbus/qmodbustcpserver.cpp b/src/serialbus/qmodbustcpserver.cpp
index 3a15e9e..ad7e2e5 100644
--- a/src/serialbus/qmodbustcpserver.cpp
+++ b/src/serialbus/qmodbustcpserver.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmodbustcpserver.h"
#include "qmodbustcpserver_p.h"
@@ -131,7 +98,9 @@ void QModbusTcpServer::close()
if (d->m_tcpServer->isListening())
d->m_tcpServer->close();
- for (auto socket : qAsConst(d->connections))
+ const auto childSockets =
+ d->m_tcpServer->findChildren<QTcpSocket *>(Qt::FindDirectChildrenOnly);
+ for (auto socket : childSockets)
socket->disconnectFromHost();
setState(QModbusDevice::UnconnectedState);
diff --git a/src/serialbus/qmodbustcpserver.h b/src/serialbus/qmodbustcpserver.h
index cf24d42..1f0e692 100644
--- a/src/serialbus/qmodbustcpserver.h
+++ b/src/serialbus/qmodbustcpserver.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSTCPSERVER_H
#define QMODBUSTCPSERVER_H
diff --git a/src/serialbus/qmodbustcpserver_p.h b/src/serialbus/qmodbustcpserver_p.h
index 3e73de3..f7c392f 100644
--- a/src/serialbus/qmodbustcpserver_p.h
+++ b/src/serialbus/qmodbustcpserver_p.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMODBUSTCPSERVER_P_H
#define QMODBUSTCPSERVER_P_H
@@ -132,17 +99,13 @@ public:
return;
}
- connections.append(socket);
-
auto buffer = new QByteArray();
- QObject::connect(socket, &QObject::destroyed, q, [buffer]() {
+ QObject::connect(socket, &QObject::destroyed, socket, [buffer]() {
// cleanup buffer
delete buffer;
});
QObject::connect(socket, &QTcpSocket::disconnected, q, [socket, this]() {
- connections.removeAll(socket);
-
Q_Q(QModbusTcpServer);
emit q->modbusClientDisconnected(socket);
socket->deleteLater();
@@ -157,7 +120,7 @@ public:
+ buffer->toHex();
if (buffer->size() < mbpaHeaderSize) {
- qCDebug(QT_MODBUS) << "(TCP server) ADU too short. Waiting for more data.";
+ qCDebug(QT_MODBUS) << "(TCP server) MBPA header too short. Waiting for more data.";
return;
}
@@ -174,7 +137,8 @@ public:
// Identifier and the PDU, so we remove on byte.
bytesPdu--;
- if (buffer->size() < mbpaHeaderSize + bytesPdu) {
+ const quint16 current = mbpaHeaderSize + bytesPdu;
+ if (buffer->size() < current) {
qCDebug(QT_MODBUS) << "(TCP server) PDU too short. Waiting for more data";
return;
}
@@ -182,7 +146,7 @@ public:
QModbusRequest request;
input >> request;
- buffer->remove(0, mbpaHeaderSize + bytesPdu);
+ buffer->remove(0, current);
if (!matchingServerAddress(unitId))
continue;
@@ -225,7 +189,6 @@ public:
}
QTcpServer *m_tcpServer { nullptr };
- QVector<QTcpSocket *> connections;
std::unique_ptr<QModbusTcpConnectionObserver> m_observer;
diff --git a/src/serialbus/qt_cmdline.cmake b/src/serialbus/qt_cmdline.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/serialbus/qt_cmdline.cmake
diff --git a/src/serialbus/qtserialbusglobal.h b/src/serialbus/qtserialbusglobal.h
index 31c1f85..9b33c71 100644
--- a/src/serialbus/qtserialbusglobal.h
+++ b/src/serialbus/qtserialbusglobal.h
@@ -1,57 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTSERIALBUSGLOBAL_H
#define QTSERIALBUSGLOBAL_H
#include <QtCore/qglobal.h>
#include <QtSerialBus/qtserialbus-config.h>
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_STATIC
-# if defined(QT_BUILD_SERIALBUS_LIB)
-# define Q_SERIALBUS_EXPORT Q_DECL_EXPORT
-# else
-# define Q_SERIALBUS_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define Q_SERIALBUS_EXPORT
-#endif
-
-QT_END_NAMESPACE
+#include <QtSerialBus/qtserialbusexports.h>
#endif // QTSERIALBUSGLOBAL_H
diff --git a/src/serialbus/serialbus.pro b/src/serialbus/serialbus.pro
deleted file mode 100644
index 3abba31..0000000
--- a/src/serialbus/serialbus.pro
+++ /dev/null
@@ -1,74 +0,0 @@
-TARGET = QtSerialBus
-
-QT = core-private
-QT_FOR_PRIVATE = network
-
-CONFIG += c++11
-
-QMAKE_DOCS = $$PWD/doc/qtserialbus.qdocconf
-
-PUBLIC_HEADERS += \
- qcanbusdevice.h \
- qcanbusdeviceinfo.h \
- qcanbusfactory.h \
- qcanbusframe.h \
- qcanbus.h \
- qtserialbusglobal.h \
- qmodbusserver.h \
- qmodbusdevice.h \
- qmodbusdataunit.h \
- qmodbusclient.h \
- qmodbusreply.h \
- qmodbustcpclient.h \
- qmodbustcpserver.h \
- qmodbuspdu.h \
- qmodbusdeviceidentification.h
-
-PRIVATE_HEADERS += \
- qcanbusdevice_p.h \
- qcanbusdeviceinfo_p.h \
- qmodbusserver_p.h \
- qmodbusclient_p.h \
- qmodbusdevice_p.h \
- qmodbustcpclient_p.h \
- qmodbustcpserver_p.h \
- qmodbus_symbols_p.h \
- qmodbuscommevent_p.h \
- qmodbusadu_p.h \
-
-SOURCES += \
- qcanbusdevice.cpp \
- qcanbusdeviceinfo.cpp \
- qcanbus.cpp \
- qcanbusfactory.cpp \
- qcanbusframe.cpp \
- qmodbusserver.cpp \
- qmodbusdevice.cpp \
- qmodbusdataunit.cpp \
- qmodbusclient.cpp \
- qmodbusreply.cpp \
- qmodbustcpclient.cpp \
- qmodbustcpserver.cpp \
- qmodbuspdu.cpp \
- qmodbusdeviceidentification.cpp
-
-qtConfig(modbus-serialport) {
- QT_FOR_PRIVATE += serialport
-
- PUBLIC_HEADERS += \
- qmodbusrtuserialmaster.h \
- qmodbusrtuserialslave.h
-
- PRIVATE_HEADERS += \
- qmodbusrtuserialmaster_p.h \
- qmodbusrtuserialslave_p.h
-
- SOURCES += \
- qmodbusrtuserialmaster.cpp \
- qmodbusrtuserialslave.cpp
-}
-HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
-
-MODULE_PLUGIN_TYPES = \
- canbus
-load(qt_module)
diff --git a/src/src.pro b/src/src.pro
deleted file mode 100644
index c1543b3..0000000
--- a/src/src.pro
+++ /dev/null
@@ -1,23 +0,0 @@
-TEMPLATE = subdirs
-
-SUBDIRS += serialbus
-serialbus.subdir = serialbus
-serialbus.target = sub-serialbus
-
-SUBDIRS += plugins
-plugins.subdir = plugins
-plugins.target = sub-plugins
-plugins.depends = serialbus
-
-SUBDIRS += tools
-tools.subdir = tools
-tools.target = sub-tools
-tools.depends = serialbus plugins
-
-!android:contains(QT_CONFIG, private_tests) {
- SUBDIRS += serialbus_doc_snippets
- serialbus_doc_snippets.subdir = serialbus/doc/snippets
-
- #plugin dependency required during static builds
- serialbus_doc_snippets.depends = serialbus plugins
-}
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
new file mode 100644
index 0000000..61928ae
--- /dev/null
+++ b/src/tools/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(android_app OR
+ (QT_FEATURE_commandlineparser
+ AND NOT ANDROID
+ AND NOT IOS
+ AND NOT WASM
+ AND NOT rtems))
+ add_subdirectory(canbusutil)
+endif()
diff --git a/src/tools/canbusutil/CMakeLists.txt b/src/tools/canbusutil/CMakeLists.txt
new file mode 100644
index 0000000..532329b
--- /dev/null
+++ b/src/tools/canbusutil/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## canbusutil Tool:
+#####################################################################
+
+qt_internal_add_app(canbusutil
+ TARGET_DESCRIPTION "Qt CAN Bus Util"
+ SOURCES
+ canbusutil.cpp canbusutil.h
+ main.cpp
+ readtask.cpp readtask.h
+ sigtermhandler.cpp sigtermhandler.h
+ LIBRARIES
+ Qt::Network
+ Qt::SerialBus
+)
+set_target_properties(canbusutil PROPERTIES WIN32_EXECUTABLE FALSE)
diff --git a/src/tools/canbusutil/canbusutil.cpp b/src/tools/canbusutil/canbusutil.cpp
index b07d97c..00a8629 100644
--- a/src/tools/canbusutil/canbusutil.cpp
+++ b/src/tools/canbusutil/canbusutil.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the QtSerialBus module.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "canbusutil.h"
@@ -82,7 +49,7 @@ bool CanBusUtil::start(const QString &pluginName, const QString &deviceName, con
if (m_listening) {
if (m_readTask->isShowFlags())
m_canDevice->setConfigurationParameter(QCanBusDevice::CanFdKey, true);
- connect(m_canDevice.data(), &QCanBusDevice::framesReceived,
+ connect(m_canDevice.get(), &QCanBusDevice::framesReceived,
m_readTask, &ReadTask::handleFrames);
} else {
if (!sendData())
@@ -125,7 +92,7 @@ int CanBusUtil::printDevices(const QString &pluginName)
return 0;
}
-bool CanBusUtil::parseDataField(quint32 &id, QString &payload)
+bool CanBusUtil::parseDataField(QCanBusFrame::FrameId &id, QString &payload)
{
int hashMarkPos = m_data.indexOf('#');
if (hashMarkPos < 0) {
@@ -133,7 +100,7 @@ bool CanBusUtil::parseDataField(quint32 &id, QString &payload)
return false;
}
- id = m_data.leftRef(hashMarkPos).toUInt(nullptr, 16);
+ id = QStringView{m_data}.left(hashMarkPos).toUInt(nullptr, 16);
payload = m_data.right(m_data.size() - hashMarkPos - 1);
return true;
@@ -148,7 +115,7 @@ bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame)
return true;
bool ok = false;
- int rtrFrameLength = payload.midRef(1).toInt(&ok);
+ int rtrFrameLength = QStringView{payload}.mid(1).toInt(&ok);
if (ok && rtrFrameLength >= 0 && rtrFrameLength <= 8) { // payload = "R8"
frame->setPayload(QByteArray(rtrFrameLength, 0));
return true;
@@ -172,7 +139,7 @@ bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame)
if (payload.size() % 2 != 0) {
if (frame->hasFlexibleDataRateFormat()) {
enum { BitrateSwitchFlag = 1, ErrorStateIndicatorFlag = 2 };
- const int flags = payload.leftRef(1).toInt(nullptr, 16);
+ const int flags = QStringView{payload}.left(1).toInt(nullptr, 16);
frame->setBitrateSwitch(flags & BitrateSwitchFlag);
frame->setErrorStateIndicator(flags & ErrorStateIndicatorFlag);
payload.remove(0, 1);
@@ -212,7 +179,7 @@ bool CanBusUtil::connectCanDevice()
for (auto i = m_configurationParameter.constBegin(); i != constEnd; ++i)
m_canDevice->setConfigurationParameter(i.key(), i.value());
- connect(m_canDevice.data(), &QCanBusDevice::errorOccurred, m_readTask, &ReadTask::handleError);
+ connect(m_canDevice.get(), &QCanBusDevice::errorOccurred, m_readTask, &ReadTask::handleError);
if (!m_canDevice->connectDevice()) {
m_output << tr("Cannot create CAN bus device: '%1'").arg(m_deviceName) << Qt::endl;
return false;
diff --git a/src/tools/canbusutil/canbusutil.h b/src/tools/canbusutil/canbusutil.h
index 4d1b7f4..1f04021 100644
--- a/src/tools/canbusutil/canbusutil.h
+++ b/src/tools/canbusutil/canbusutil.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the QtSerialBus module.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef CANBUSUTIL_H
#define CANBUSUTIL_H
@@ -40,7 +7,6 @@
#include "readtask.h"
#include <QObject>
-#include <QScopedPointer>
QT_BEGIN_NAMESPACE
@@ -64,7 +30,7 @@ public:
int printDevices(const QString &pluginName);
private:
- bool parseDataField(quint32 &id, QString &payload);
+ bool parseDataField(QCanBusFrame::FrameId &id, QString &payload);
bool setFrameFromPayload(QString payload, QCanBusFrame *frame);
bool connectCanDevice();
bool sendData();
@@ -77,7 +43,7 @@ private:
QString m_pluginName;
QString m_deviceName;
QString m_data;
- QScopedPointer<QCanBusDevice> m_canDevice;
+ std::unique_ptr<QCanBusDevice> m_canDevice;
ReadTask *m_readTask = nullptr;
using ConfigurationParameter = QHash<QCanBusDevice::ConfigurationKey, QVariant>;
ConfigurationParameter m_configurationParameter;
diff --git a/src/tools/canbusutil/canbusutil.pro b/src/tools/canbusutil/canbusutil.pro
deleted file mode 100644
index b3e0504..0000000
--- a/src/tools/canbusutil/canbusutil.pro
+++ /dev/null
@@ -1,14 +0,0 @@
-QT = core serialbus
-
-SOURCES += main.cpp \
- readtask.cpp \
- canbusutil.cpp \
- sigtermhandler.cpp
-
-HEADERS += \
- readtask.h \
- canbusutil.h \
- sigtermhandler.h
-
-QMAKE_TARGET_DESCRIPTION = "Qt CAN Bus Util"
-load(qt_tool)
diff --git a/src/tools/canbusutil/main.cpp b/src/tools/canbusutil/main.cpp
index cbb7d7f..0c5ec1a 100644
--- a/src/tools/canbusutil/main.cpp
+++ b/src/tools/canbusutil/main.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the QtSerialBus module.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "canbusutil.h"
#include "sigtermhandler.h"
@@ -40,7 +7,6 @@
#include <QCommandLineParser>
#include <QCoreApplication>
#include <QTextStream>
-#include <QScopedPointer>
#include <signal.h>
@@ -50,10 +16,10 @@ int main(int argc, char *argv[])
QCoreApplication::setApplicationName(QStringLiteral("canbusutil"));
QCoreApplication::setApplicationVersion(QStringLiteral(QT_VERSION_STR));
- QScopedPointer<SigTermHandler> s(SigTermHandler::instance());
+ std::unique_ptr<SigTermHandler> s(SigTermHandler::instance());
if (signal(SIGINT, SigTermHandler::handle) == SIG_ERR)
return -1;
- QObject::connect(s.data(), &SigTermHandler::sigTermSignal, &app, &QCoreApplication::quit);
+ QObject::connect(s.get(), &SigTermHandler::sigTermSignal, &app, &QCoreApplication::quit);
QTextStream output(stdout);
CanBusUtil util(output, app);
diff --git a/src/tools/canbusutil/readtask.cpp b/src/tools/canbusutil/readtask.cpp
index 1b07fe8..e9af7d9 100644
--- a/src/tools/canbusutil/readtask.cpp
+++ b/src/tools/canbusutil/readtask.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the QtSerialBus module.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "readtask.h"
diff --git a/src/tools/canbusutil/readtask.h b/src/tools/canbusutil/readtask.h
index 345af35..bc90de6 100644
--- a/src/tools/canbusutil/readtask.h
+++ b/src/tools/canbusutil/readtask.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the QtSerialBus module.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef READTASK_H
#define READTASK_H
diff --git a/src/tools/canbusutil/sigtermhandler.cpp b/src/tools/canbusutil/sigtermhandler.cpp
index a882a55..6158dec 100644
--- a/src/tools/canbusutil/sigtermhandler.cpp
+++ b/src/tools/canbusutil/sigtermhandler.cpp
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the QtSerialBus module.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "sigtermhandler.h"
diff --git a/src/tools/canbusutil/sigtermhandler.h b/src/tools/canbusutil/sigtermhandler.h
index 1d72f0a..585e6ba 100644
--- a/src/tools/canbusutil/sigtermhandler.h
+++ b/src/tools/canbusutil/sigtermhandler.h
@@ -1,38 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the QtSerialBus module.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef SIGTERMHANDLER_H
#define SIGTERMHANDLER_H
diff --git a/src/tools/tools.pro b/src/tools/tools.pro
deleted file mode 100644
index 72d34fb..0000000
--- a/src/tools/tools.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TEMPLATE = subdirs
-
-qtConfig(commandlineparser):!android|android_app: SUBDIRS += canbusutil