summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/serialbus/can/bitratebox.h2
-rw-r--r--examples/serialbus/can/can.pro5
-rw-r--r--examples/serialbus/can/connectdialog.cpp14
-rw-r--r--examples/serialbus/can/connectdialog.h4
-rw-r--r--examples/serialbus/can/connectdialog.ui6
-rw-r--r--examples/serialbus/can/mainwindow.cpp107
-rw-r--r--examples/serialbus/can/mainwindow.h11
-rw-r--r--examples/serialbus/can/mainwindow.ui125
-rw-r--r--examples/serialbus/can/sendframebox.cpp191
-rw-r--r--examples/serialbus/can/sendframebox.h102
-rw-r--r--examples/serialbus/can/sendframebox.ui211
-rw-r--r--examples/serialbus/modbus/adueditor/mainwindow.cpp2
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend.cpp2
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp57
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.h13
-rw-r--r--src/plugins/canbus/systeccan/systeccanbackend.cpp1
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend.cpp23
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend.cpp1
-rw-r--r--src/serialbus/doc/src/socketcan.qdoc5
-rw-r--r--src/serialbus/doc/src/systeccan.qdoc3
-rw-r--r--src/serialbus/doc/src/vectorcan.qdoc3
-rw-r--r--src/serialbus/qcanbusframe.cpp37
-rw-r--r--src/serialbus/qcanbusframe.h21
-rw-r--r--src/serialbus/qmodbusclient.cpp2
-rw-r--r--src/serialbus/qmodbuspdu.cpp6
-rw-r--r--src/tools/canbusutil/canbusutil.cpp10
-rw-r--r--src/tools/canbusutil/canbusutil.h2
-rw-r--r--src/tools/canbusutil/canbusutil.pro1
-rw-r--r--tests/auto/qcanbusframe/tst_qcanbusframe.cpp55
30 files changed, 756 insertions, 268 deletions
diff --git a/.qmake.conf b/.qmake.conf
index dea15b4..168dab9 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
CONFIG += warning_clean
DEFINES += QT_NO_FOREACH
-MODULE_VERSION = 5.9.3
+MODULE_VERSION = 5.10.0
diff --git a/examples/serialbus/can/bitratebox.h b/examples/serialbus/can/bitratebox.h
index d15ea9b..9156104 100644
--- a/examples/serialbus/can/bitratebox.h
+++ b/examples/serialbus/can/bitratebox.h
@@ -60,7 +60,7 @@ QT_END_NAMESPACE
class BitRateBox : public QComboBox
{
public:
- BitRateBox(QWidget *parent = nullptr);
+ explicit BitRateBox(QWidget *parent = nullptr);
~BitRateBox();
int bitRate() const;
diff --git a/examples/serialbus/can/can.pro b/examples/serialbus/can/can.pro
index c667dbb..017589a 100644
--- a/examples/serialbus/can/can.pro
+++ b/examples/serialbus/can/can.pro
@@ -8,14 +8,17 @@ SOURCES += \
connectdialog.cpp \
main.cpp \
mainwindow.cpp \
+ sendframebox.cpp
HEADERS += \
bitratebox.h \
connectdialog.h \
mainwindow.h \
+ sendframebox.h
FORMS += mainwindow.ui \
- connectdialog.ui
+ connectdialog.ui \
+ sendframebox.ui
RESOURCES += can.qrc
diff --git a/examples/serialbus/can/connectdialog.cpp b/examples/serialbus/can/connectdialog.cpp
index ae6e7f0..5a12592 100644
--- a/examples/serialbus/can/connectdialog.cpp
+++ b/examples/serialbus/can/connectdialog.cpp
@@ -78,14 +78,14 @@ ConnectDialog::ConnectDialog(QWidget *parent) :
connect(m_ui->cancelButton, &QPushButton::clicked, this, &ConnectDialog::cancel);
connect(m_ui->useConfigurationBox, &QCheckBox::clicked,
m_ui->configurationBox, &QGroupBox::setEnabled);
- connect(m_ui->backendListBox, &QComboBox::currentTextChanged,
- this, &ConnectDialog::backendChanged);
+ connect(m_ui->pluginListBox, &QComboBox::currentTextChanged,
+ this, &ConnectDialog::pluginChanged);
connect(m_ui->interfaceListBox, &QComboBox::currentTextChanged,
this, &ConnectDialog::interfaceChanged);
m_ui->rawFilterEdit->hide();
m_ui->rawFilterLabel->hide();
- m_ui->backendListBox->addItems(QCanBus::instance()->plugins());
+ m_ui->pluginListBox->addItems(QCanBus::instance()->plugins());
updateSettings();
}
@@ -100,10 +100,10 @@ ConnectDialog::Settings ConnectDialog::settings() const
return m_currentSettings;
}
-void ConnectDialog::backendChanged(const QString &backend)
+void ConnectDialog::pluginChanged(const QString &plugin)
{
m_ui->interfaceListBox->clear();
- m_interfaces = QCanBus::instance()->availableDevices(backend);
+ m_interfaces = QCanBus::instance()->availableDevices(plugin);
for (const QCanBusDeviceInfo &info : qAsConst(m_interfaces))
m_ui->interfaceListBox->addItem(info.name());
}
@@ -156,7 +156,7 @@ QString ConnectDialog::configurationValue(QCanBusDevice::ConfigurationKey key)
void ConnectDialog::revertSettings()
{
- m_ui->backendListBox->setCurrentText(m_currentSettings.backendName);
+ m_ui->pluginListBox->setCurrentText(m_currentSettings.pluginName);
m_ui->interfaceListBox->setCurrentText(m_currentSettings.deviceInterfaceName);
m_ui->useConfigurationBox->setChecked(m_currentSettings.useConfigurationEnabled);
@@ -181,7 +181,7 @@ void ConnectDialog::revertSettings()
void ConnectDialog::updateSettings()
{
- m_currentSettings.backendName = m_ui->backendListBox->currentText();
+ m_currentSettings.pluginName = m_ui->pluginListBox->currentText();
m_currentSettings.deviceInterfaceName = m_ui->interfaceListBox->currentText();
m_currentSettings.useConfigurationEnabled = m_ui->useConfigurationBox->isChecked();
diff --git a/examples/serialbus/can/connectdialog.h b/examples/serialbus/can/connectdialog.h
index f2ad9bf..d7a0a55 100644
--- a/examples/serialbus/can/connectdialog.h
+++ b/examples/serialbus/can/connectdialog.h
@@ -72,7 +72,7 @@ public:
typedef QPair<QCanBusDevice::ConfigurationKey, QVariant> ConfigurationItem;
struct Settings {
- QString backendName;
+ QString pluginName;
QString deviceInterfaceName;
QList<ConfigurationItem> configurations;
bool useConfigurationEnabled = false;
@@ -84,7 +84,7 @@ public:
Settings settings() const;
private slots:
- void backendChanged(const QString &backend);
+ void pluginChanged(const QString &plugin);
void interfaceChanged(const QString &interface);
void ok();
void cancel();
diff --git a/examples/serialbus/can/connectdialog.ui b/examples/serialbus/can/connectdialog.ui
index aad6bef..def6e59 100644
--- a/examples/serialbus/can/connectdialog.ui
+++ b/examples/serialbus/can/connectdialog.ui
@@ -55,13 +55,13 @@
</layout>
</item>
<item row="0" column="0">
- <widget class="QGroupBox" name="selectBackendBox">
+ <widget class="QGroupBox" name="selectPluginBox">
<property name="title">
- <string>Select CAN backend</string>
+ <string>Select CAN plugin</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
- <widget class="QComboBox" name="backendListBox"/>
+ <widget class="QComboBox" name="pluginListBox"/>
</item>
</layout>
</widget>
diff --git a/examples/serialbus/can/mainwindow.cpp b/examples/serialbus/can/mainwindow.cpp
index 1d95f22..fd5861f 100644
--- a/examples/serialbus/can/mainwindow.cpp
+++ b/examples/serialbus/can/mainwindow.cpp
@@ -56,7 +56,6 @@
#include <QCanBusFrame>
#include <QCloseEvent>
#include <QDesktopServices>
-#include <QtDebug>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent) :
@@ -68,14 +67,13 @@ MainWindow::MainWindow(QWidget *parent) :
m_connectDialog = new ConnectDialog;
m_status = new QLabel;
- m_ui->statusBar->addWidget(m_status);
+ m_ui->statusBar->addPermanentWidget(m_status);
- m_ui->sendMessagesBox->setEnabled(false);
+ m_written = new QLabel;
+ m_ui->statusBar->addWidget(m_written);
initActionsConnections();
QTimer::singleShot(50, m_connectDialog, &ConnectDialog::show);
-
- connect(m_ui->sendButton, &QPushButton::clicked, this, &MainWindow::sendMessage);
}
MainWindow::~MainWindow()
@@ -86,17 +84,12 @@ MainWindow::~MainWindow()
delete m_ui;
}
-void MainWindow::showStatusMessage(const QString &message)
-{
- m_status->setText(message);
-}
-
void MainWindow::initActionsConnections()
{
- m_ui->actionConnect->setEnabled(true);
m_ui->actionDisconnect->setEnabled(false);
- m_ui->actionQuit->setEnabled(true);
+ m_ui->sendFrameBox->setEnabled(false);
+ connect(m_ui->sendFrameBox, &SendFrameBox::sendFrame, this, &MainWindow::sendFrame);
connect(m_ui->actionConnect, &QAction::triggered, m_connectDialog, &ConnectDialog::show);
connect(m_connectDialog, &QDialog::accepted, this, &MainWindow::connectDevice);
connect(m_ui->actionDisconnect, &QAction::triggered, this, &MainWindow::disconnectDevice);
@@ -108,7 +101,7 @@ void MainWindow::initActionsConnections()
});
}
-void MainWindow::receiveError(QCanBusDevice::CanBusError error) const
+void MainWindow::processErrors(QCanBusDevice::CanBusError error) const
{
switch (error) {
case QCanBusDevice::ReadError:
@@ -116,7 +109,8 @@ void MainWindow::receiveError(QCanBusDevice::CanBusError error) const
case QCanBusDevice::ConnectionError:
case QCanBusDevice::ConfigurationError:
case QCanBusDevice::UnknownError:
- qWarning() << m_canDevice->errorString();
+ m_status->setText(m_canDevice->errorString());
+ break;
default:
break;
}
@@ -127,20 +121,19 @@ void MainWindow::connectDevice()
const ConnectDialog::Settings p = m_connectDialog->settings();
QString errorString;
- m_canDevice = QCanBus::instance()->createDevice(p.backendName, p.deviceInterfaceName,
+ m_canDevice = QCanBus::instance()->createDevice(p.pluginName, p.deviceInterfaceName,
&errorString);
if (!m_canDevice) {
- showStatusMessage(tr("Error creating device '%1', reason: '%2'")
- .arg(p.backendName).arg(errorString));
+ m_status->setText(tr("Error creating device '%1', reason: '%2'")
+ .arg(p.pluginName).arg(errorString));
return;
}
- connect(m_canDevice, &QCanBusDevice::errorOccurred,
- this, &MainWindow::receiveError);
- connect(m_canDevice, &QCanBusDevice::framesReceived,
- this, &MainWindow::checkMessages);
- connect(m_canDevice, &QCanBusDevice::framesWritten,
- this, &MainWindow::framesWritten);
+ m_numberFramesWritten = 0;
+
+ connect(m_canDevice, &QCanBusDevice::errorOccurred, this, &MainWindow::processErrors);
+ connect(m_canDevice, &QCanBusDevice::framesReceived, this, &MainWindow::processReceivedFrames);
+ connect(m_canDevice, &QCanBusDevice::framesWritten, this, &MainWindow::processFramesWritten);
if (p.useConfigurationEnabled) {
for (const ConnectDialog::ConfigurationItem &item : p.configurations)
@@ -148,7 +141,7 @@ void MainWindow::connectDevice()
}
if (!m_canDevice->connectDevice()) {
- showStatusMessage(tr("Connection error: %1").arg(m_canDevice->errorString()));
+ m_status->setText(tr("Connection error: %1").arg(m_canDevice->errorString()));
delete m_canDevice;
m_canDevice = nullptr;
@@ -156,16 +149,16 @@ void MainWindow::connectDevice()
m_ui->actionConnect->setEnabled(false);
m_ui->actionDisconnect->setEnabled(true);
- m_ui->sendMessagesBox->setEnabled(true);
+ m_ui->sendFrameBox->setEnabled(true);
QVariant bitRate = m_canDevice->configurationParameter(QCanBusDevice::BitRateKey);
if (bitRate.isValid()) {
- showStatusMessage(tr("Backend: %1, connected to %2 at %3 kBit/s")
- .arg(p.backendName).arg(p.deviceInterfaceName)
+ m_status->setText(tr("Plugin: %1, connected to %2 at %3 kBit/s")
+ .arg(p.pluginName).arg(p.deviceInterfaceName)
.arg(bitRate.toInt() / 1000));
} else {
- showStatusMessage(tr("Backend: %1, connected to %2")
- .arg(p.backendName).arg(p.deviceInterfaceName));
+ m_status->setText(tr("Plugin: %1, connected to %2")
+ .arg(p.pluginName).arg(p.deviceInterfaceName));
}
}
}
@@ -182,14 +175,15 @@ void MainWindow::disconnectDevice()
m_ui->actionConnect->setEnabled(true);
m_ui->actionDisconnect->setEnabled(false);
- m_ui->sendMessagesBox->setEnabled(false);
+ m_ui->sendFrameBox->setEnabled(false);
- showStatusMessage(tr("Disconnected"));
+ m_status->setText(tr("Disconnected"));
}
-void MainWindow::framesWritten(qint64 count)
+void MainWindow::processFramesWritten(qint64 count)
{
- qDebug() << "Number of frames written:" << count;
+ m_numberFramesWritten += count;
+ m_written->setText(tr("%1 frames written").arg(m_numberFramesWritten));
}
void MainWindow::closeEvent(QCloseEvent *event)
@@ -200,16 +194,19 @@ void MainWindow::closeEvent(QCloseEvent *event)
static QString frameFlags(const QCanBusFrame &frame)
{
- if (frame.hasBitrateSwitch() && frame.hasErrorStateIndicator())
- return QStringLiteral(" B E ");
+ QString result = QLatin1String(" --- ");
+
if (frame.hasBitrateSwitch())
- return QStringLiteral(" B - ");
+ result[1] = QLatin1Char('B');
if (frame.hasErrorStateIndicator())
- return QStringLiteral(" - E ");
- return QStringLiteral(" - - ");
+ result[2] = QLatin1Char('E');
+ if (frame.hasLocalEcho())
+ result[3] = QLatin1Char('L');
+
+ return result;
}
-void MainWindow::checkMessages()
+void MainWindow::processReceivedFrames()
{
if (!m_canDevice)
return;
@@ -233,40 +230,10 @@ void MainWindow::checkMessages()
}
}
-static QByteArray dataFromHex(const QString &hex)
-{
- QByteArray line = hex.toLatin1();
- line.replace(' ', QByteArray());
- return QByteArray::fromHex(line);
-}
-
-void MainWindow::sendMessage() const
+void MainWindow::sendFrame(const QCanBusFrame &frame) const
{
if (!m_canDevice)
return;
- QByteArray writings = dataFromHex(m_ui->lineEdit->displayText());
-
- QCanBusFrame frame;
- const int maxPayload = m_ui->fdBox->checkState() ? 64 : 8;
- writings.truncate(maxPayload);
- frame.setPayload(writings);
-
- qint32 id = m_ui->idEdit->displayText().toInt(nullptr, 16);
- if (!m_ui->effBox->checkState() && id > 2047) //11 bits
- id = 2047;
-
- frame.setFrameId(id);
- frame.setExtendedFrameFormat(m_ui->effBox->checkState());
- frame.setFlexibleDataRateFormat(m_ui->fdBox->checkState());
- frame.setBitrateSwitch(m_ui->bitrateSwitchBox->checkState());
-
- if (m_ui->remoteFrame->isChecked())
- frame.setFrameType(QCanBusFrame::RemoteRequestFrame);
- else if (m_ui->errorFrame->isChecked())
- frame.setFrameType(QCanBusFrame::ErrorFrame);
- else
- frame.setFrameType(QCanBusFrame::DataFrame);
-
m_canDevice->writeFrame(frame);
}
diff --git a/examples/serialbus/can/mainwindow.h b/examples/serialbus/can/mainwindow.h
index 273045f..40b2e4a 100644
--- a/examples/serialbus/can/mainwindow.h
+++ b/examples/serialbus/can/mainwindow.h
@@ -77,22 +77,23 @@ public:
~MainWindow();
private slots:
- void checkMessages();
- void sendMessage() const;
- void receiveError(QCanBusDevice::CanBusError) const;
+ void processReceivedFrames();
+ void sendFrame(const QCanBusFrame &frame) const;
+ void processErrors(QCanBusDevice::CanBusError) const;
void connectDevice();
void disconnectDevice();
- void framesWritten(qint64);
+ void processFramesWritten(qint64);
protected:
void closeEvent(QCloseEvent *event) override;
private:
- void showStatusMessage(const QString &message);
void initActionsConnections();
+ qint64 m_numberFramesWritten = 0;
Ui::MainWindow *m_ui = nullptr;
QLabel *m_status = nullptr;
+ QLabel *m_written = nullptr;
ConnectDialog *m_connectDialog = nullptr;
QCanBusDevice *m_canDevice = nullptr;
};
diff --git a/examples/serialbus/can/mainwindow.ui b/examples/serialbus/can/mainwindow.ui
index 04f8c93..1d5a657 100644
--- a/examples/serialbus/can/mainwindow.ui
+++ b/examples/serialbus/can/mainwindow.ui
@@ -14,123 +14,12 @@
<string>CAN Example</string>
</property>
<widget class="QWidget" name="centralWidget">
- <layout class="QVBoxLayout" name="verticalLayout_3">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QGroupBox" name="sendMessagesBox">
+ <widget class="SendFrameBox" name="sendFrameBox">
<property name="title">
- <string>Send CAN message</string>
+ <string>Send CAN frame</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>&amp;ID (hex)</string>
- </property>
- <property name="buddy">
- <cstring>idEdit</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="idEdit">
- <property name="placeholderText">
- <string>123</string>
- </property>
- </widget>
- </item>
- <item row="0" column="2" rowspan="4">
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Frame Type</string>
- </property>
- <property name="checkable">
- <bool>false</bool>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QRadioButton" name="dataFrame">
- <property name="text">
- <string>D&amp;ata</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="remoteFrame">
- <property name="text">
- <string>Re&amp;mote Request</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="errorFrame">
- <property name="text">
- <string>&amp;Error</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="QCheckBox" name="fdBox">
- <property name="text">
- <string>&amp;Flexible Data-Rate
-(64 byte payload)</string>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <widget class="QCheckBox" name="effBox">
- <property name="toolTip">
- <string>Allow extended frames with 29 bit identifier.
-Otherwise, the standard format with 11 bit idenfier is used.</string>
- </property>
- <property name="text">
- <string>E&amp;xtended Frame
-(29 bit identifier)</string>
- </property>
- </widget>
- </item>
- <item row="3" column="3">
- <widget class="QPushButton" name="sendButton">
- <property name="text">
- <string>&amp;Send</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="lineEdit">
- <property name="placeholderText">
- <string>12 34 AB CE</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>&amp;Data (hex)</string>
- </property>
- <property name="buddy">
- <cstring>lineEdit</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QCheckBox" name="bitrateSwitchBox">
- <property name="text">
- <string>&amp;Bitrate Switch
-(Higher data rate)</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
</widget>
</item>
<item>
@@ -276,6 +165,14 @@ Otherwise, the standard format with 11 bit idenfier is used.</string>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+ <customwidget>
+ <class>SendFrameBox</class>
+ <extends>QGroupBox</extends>
+ <header location="global">sendframebox.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
<resources>
<include location="can.qrc"/>
</resources>
diff --git a/examples/serialbus/can/sendframebox.cpp b/examples/serialbus/can/sendframebox.cpp
new file mode 100644
index 0000000..d7a25ba
--- /dev/null
+++ b/examples/serialbus/can/sendframebox.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtSerialBus module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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$
+**
+****************************************************************************/
+
+#include "sendframebox.h"
+#include "ui_sendframebox.h"
+
+enum {
+ MaxStandardId = 0x7FF,
+ MaxExtendedId = 0x10000000
+};
+
+enum {
+ MaxPayload = 8,
+ MaxPayloadFd = 64
+};
+
+HexIntegerValidator::HexIntegerValidator(QObject *parent) :
+ QValidator(parent),
+ m_maximum(MaxStandardId)
+{
+}
+
+QValidator::State HexIntegerValidator::validate(QString &input, int &) const
+{
+ bool ok;
+ uint value = input.toUInt(&ok, 16);
+
+ if (!value)
+ return Intermediate;
+
+ if (!ok || value > m_maximum)
+ return Invalid;
+
+ return Acceptable;
+}
+
+void HexIntegerValidator::setMaximum(uint maximum)
+{
+ m_maximum = maximum;
+}
+
+HexStringValidator::HexStringValidator(QObject *parent) :
+ QValidator(parent),
+ m_maxLength(MaxPayload)
+{
+}
+
+QValidator::State HexStringValidator::validate(QString &input, int &pos) const
+{
+ const int maxSize = 2 * m_maxLength;
+ const QChar space = QLatin1Char(' ');
+ QString data = input;
+ data.remove(space);
+
+ if (data.isEmpty())
+ return Intermediate;
+
+ // limit maximum size and forbid trailing spaces
+ if ((data.size() > maxSize) || (data.size() == maxSize && input.endsWith(space)))
+ return Invalid;
+
+ // check if all input is valid
+ const QRegularExpression re(QStringLiteral("^[[:xdigit:]]*$"));
+ if (!re.match(data).hasMatch())
+ return Invalid;
+
+ // insert a space after every two hex nibbles
+ const QRegularExpression insertSpace(QStringLiteral("(?:[[:xdigit:]]{2} )*[[:xdigit:]]{3}"));
+ if (insertSpace.match(input).hasMatch()) {
+ input.insert(input.size() - 1, space);
+ pos = input.size();
+ }
+
+ return Acceptable;
+}
+
+void HexStringValidator::setMaxLength(int maxLength)
+{
+ m_maxLength = maxLength;
+}
+
+SendFrameBox::SendFrameBox(QWidget *parent) :
+ QGroupBox(parent),
+ m_ui(new Ui::SendFrameBox)
+{
+ m_ui->setupUi(this);
+
+ m_hexIntegerValidator = new HexIntegerValidator(this);
+ m_ui->frameIdEdit->setValidator(m_hexIntegerValidator);
+ m_hexStringValidator = new HexStringValidator(this);
+ m_ui->payloadEdit->setValidator(m_hexStringValidator);
+
+ connect(m_ui->dataFrame, &QRadioButton::toggled, [this](bool set) {
+ if (set)
+ m_ui->flexibleDataRateBox->setEnabled(true);
+ });
+
+ connect(m_ui->remoteFrame, &QRadioButton::toggled, [this](bool set) {
+ if (set) {
+ m_ui->flexibleDataRateBox->setEnabled(false);
+ m_ui->flexibleDataRateBox->setChecked(false);
+ }
+ });
+
+ connect(m_ui->errorFrame, &QRadioButton::toggled, [this](bool set) {
+ if (set) {
+ m_ui->flexibleDataRateBox->setEnabled(false);
+ m_ui->flexibleDataRateBox->setChecked(false);
+ }
+ });
+
+ connect(m_ui->extendedFormatBox, &QCheckBox::toggled, [this](bool set) {
+ m_hexIntegerValidator->setMaximum(set ? MaxExtendedId : MaxStandardId);
+ });
+
+ connect(m_ui->flexibleDataRateBox, &QCheckBox::toggled, [this](bool set) {
+ m_hexStringValidator->setMaxLength(set ? MaxPayloadFd : MaxPayload);
+ m_ui->bitrateSwitchBox->setEnabled(set);
+ if (!set)
+ m_ui->bitrateSwitchBox->setChecked(false);
+ });
+
+ auto frameIdTextChanged = [this]() {
+ const bool hasFrameId = !m_ui->frameIdEdit->text().isEmpty();
+ m_ui->sendButton->setEnabled(hasFrameId);
+ m_ui->sendButton->setToolTip(hasFrameId
+ ? QString() : tr("Cannot send because no Frame ID was given."));
+ };
+ connect(m_ui->frameIdEdit, &QLineEdit::textChanged, frameIdTextChanged);
+ frameIdTextChanged();
+
+ connect(m_ui->sendButton, &QPushButton::clicked, [this]() {
+ const uint frameId = m_ui->frameIdEdit->text().toUInt(nullptr, 16);
+ QString data = m_ui->payloadEdit->text();
+ const QByteArray payload = QByteArray::fromHex(data.remove(QLatin1Char(' ')).toLatin1());
+
+ QCanBusFrame frame = QCanBusFrame(frameId, payload);
+ frame.setExtendedFrameFormat(m_ui->extendedFormatBox->isChecked());
+ frame.setFlexibleDataRateFormat(m_ui->flexibleDataRateBox->isChecked());
+ frame.setBitrateSwitch(m_ui->bitrateSwitchBox->isChecked());
+
+ if (m_ui->errorFrame->isChecked())
+ frame.setFrameType(QCanBusFrame::ErrorFrame);
+ else if (m_ui->remoteFrame->isChecked())
+ frame.setFrameType(QCanBusFrame::RemoteRequestFrame);
+
+ emit sendFrame(frame);
+ });
+}
+
+SendFrameBox::~SendFrameBox()
+{
+ delete m_ui;
+}
diff --git a/examples/serialbus/can/sendframebox.h b/examples/serialbus/can/sendframebox.h
new file mode 100644
index 0000000..465ba02
--- /dev/null
+++ b/examples/serialbus/can/sendframebox.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtSerialBus module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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$
+**
+****************************************************************************/
+
+#ifndef SENDFRAMEBOX_H
+#define SENDFRAMEBOX_H
+
+#include <QCanBusFrame>
+#include <QGroupBox>
+#include <QRegularExpression>
+#include <QValidator>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+class SendFrameBox;
+}
+QT_END_NAMESPACE
+
+class HexIntegerValidator : public QValidator
+{
+ Q_OBJECT
+public:
+ explicit HexIntegerValidator(QObject *parent = nullptr);
+
+ QValidator::State validate(QString &input, int &) const;
+
+ void setMaximum(uint maximum);
+
+private:
+ uint m_maximum = 0;
+};
+
+class HexStringValidator : public QValidator
+{
+ Q_OBJECT
+
+public:
+ explicit HexStringValidator(QObject *parent = nullptr);
+
+ QValidator::State validate(QString &input, int &pos) const;
+
+ void setMaxLength(int maxLength);
+
+private:
+ int m_maxLength = 0;
+};
+
+class SendFrameBox : public QGroupBox
+{
+ Q_OBJECT
+
+public:
+ explicit SendFrameBox(QWidget *parent = nullptr);
+ ~SendFrameBox();
+
+signals:
+ void sendFrame(const QCanBusFrame &frame);
+
+private:
+ Ui::SendFrameBox *m_ui = nullptr;
+
+ HexIntegerValidator *m_hexIntegerValidator = nullptr;
+ HexStringValidator *m_hexStringValidator = nullptr;
+};
+
+#endif // SENDFRAMEBOX_H
diff --git a/examples/serialbus/can/sendframebox.ui b/examples/serialbus/can/sendframebox.ui
new file mode 100644
index 0000000..0abeff5
--- /dev/null
+++ b/examples/serialbus/can/sendframebox.ui
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SendFrameBox</class>
+ <widget class="QGroupBox" name="SendFrameBox">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>485</width>
+ <height>206</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <property name="title">
+ <string/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QGroupBox" name="frameTypeBox">
+ <property name="title">
+ <string>Frame Type</string>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="dataFrame">
+ <property name="toolTip">
+ <string>Sends a CAN data frame.</string>
+ </property>
+ <property name="text">
+ <string>D&amp;ata Frame</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="remoteFrame">
+ <property name="toolTip">
+ <string>Sends a CAN remote request frame.</string>
+ </property>
+ <property name="text">
+ <string>Re&amp;mote Request Frame</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="errorFrame">
+ <property name="toolTip">
+ <string>Sends an error frame.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Error Frame</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="frameOptionsBox">
+ <property name="title">
+ <string>Frame Options</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="extendedFormatBox">
+ <property name="toolTip">
+ <string>Allows extended frames with 29 bit identifier.</string>
+ </property>
+ <property name="text">
+ <string>E&amp;xtended Format</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="flexibleDataRateBox">
+ <property name="toolTip">
+ <string>Allows up to 64 byte payload data.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Flexible Data-Rate</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="bitrateSwitchBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Sends payload at higher data rate.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Bitrate Switch</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="frameIdLabel">
+ <property name="text">
+ <string>Frame &amp;ID (hex)</string>
+ </property>
+ <property name="buddy">
+ <cstring>frameIdEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="frameIdEdit">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="placeholderText">
+ <string>123</string>
+ </property>
+ <property name="clearButtonEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="payloadLabel">
+ <property name="text">
+ <string>&amp;Payload (hex)</string>
+ </property>
+ <property name="buddy">
+ <cstring>payloadEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="payloadEdit">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>2</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="placeholderText">
+ <string>12 34 AB CE</string>
+ </property>
+ <property name="clearButtonEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="sendButton">
+ <property name="text">
+ <string>&amp;Send</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/serialbus/modbus/adueditor/mainwindow.cpp b/examples/serialbus/modbus/adueditor/mainwindow.cpp
index beabfdf..862be6a 100644
--- a/examples/serialbus/modbus/adueditor/mainwindow.cpp
+++ b/examples/serialbus/modbus/adueditor/mainwindow.cpp
@@ -198,7 +198,7 @@ void MainWindow::on_connectButton_clicked()
emit disconnectButton->clicked();
}, Qt::QueuedConnection);
- connect(m_device, &QModbusDevice::stateChanged, [this](QModbusDevice::State state) {
+ connect(m_device, &QModbusDevice::stateChanged, [](QModbusDevice::State state) {
switch (state) {
case QModbusDevice::UnconnectedState:
qDebug().noquote() << QStringLiteral("State: Entered unconnected state.");
diff --git a/src/plugins/canbus/peakcan/peakcanbackend.cpp b/src/plugins/canbus/peakcan/peakcanbackend.cpp
index 075cd5d..8f97f5d 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend.cpp
+++ b/src/plugins/canbus/peakcan/peakcanbackend.cpp
@@ -310,7 +310,7 @@ void PeakCanBackendPrivate::close()
quint32 value = 0;
const TPCANStatus err = ::CAN_SetValue(channelIndex, PCAN_RECEIVE_EVENT, &value, sizeof(value));
if (Q_UNLIKELY(err != PCAN_ERROR_OK))
- emit q->setError(systemErrorString(err), QCanBusDevice::ConnectionError);
+ q->setError(systemErrorString(err), QCanBusDevice::ConnectionError);
const TPCANStatus st = ::CAN_Uninitialize(channelIndex);
if (Q_UNLIKELY(st != PCAN_ERROR_OK))
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index 930221d..14a4cde 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.cpp
+++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp
@@ -255,9 +255,7 @@ bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &valu
filters.resize(filterList.size());
for (int i = 0; i < filterList.size(); i++) {
const QCanBusDevice::Filter f = filterList.at(i);
- can_filter filter;
- filter.can_id = f.frameId;
- filter.can_mask = f.frameIdMask;
+ can_filter filter = { f.frameId, f.frameIdMask };
// frame type filter
switch (f.type) {
@@ -321,13 +319,11 @@ bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &valu
break;
}
- //qDebug() << "applyConfiguration" << key << value << success;
return success;
}
bool SocketCanBackend::connectSocket()
{
- struct sockaddr_can address;
struct ifreq interface;
if (Q_UNLIKELY((canSocket = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)) < 0)) {
@@ -343,15 +339,21 @@ bool SocketCanBackend::connectSocket()
return false;
}
- address.can_family = AF_CAN;
- address.can_ifindex = interface.ifr_ifindex;
+ m_address.can_family = AF_CAN;
+ m_address.can_ifindex = interface.ifr_ifindex;
- if (Q_UNLIKELY(bind(canSocket, reinterpret_cast<struct sockaddr *>(&address), sizeof(address)) < 0)) {
+ if (Q_UNLIKELY(bind(canSocket, reinterpret_cast<struct sockaddr *>(&m_address), sizeof(m_address)) < 0)) {
setError(qt_error_string(errno),
QCanBusDevice::CanBusError::ConnectionError);
return false;
}
+ m_iov.iov_base = &m_frame;
+ m_msg.msg_name = &m_address;
+ m_msg.msg_iov = &m_iov;
+ m_msg.msg_iovlen = 1;
+ m_msg.msg_control = &m_ctrlmsg;
+
delete notifier;
notifier = new QSocketNotifier(canSocket, QSocketNotifier::Read, this);
@@ -428,12 +430,12 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
if (newData.frameType() == QCanBusFrame::RemoteRequestFrame) {
canId |= CAN_RTR_FLAG;
} else if (newData.frameType() == QCanBusFrame::ErrorFrame) {
- canId = (uint)(newData.error() & QCanBusFrame::AnyError);
+ canId = static_cast<canid_t>((newData.error() & QCanBusFrame::AnyError));
canId |= CAN_ERR_FLAG;
}
if (Q_UNLIKELY(!canFdOptionEnabled && newData.hasFlexibleDataRateFormat())) {
- const QString error = tr("Sending CAN FD frame although CAN FD option not enabled.");
+ const QString error = tr("Cannot write CAN FD frame because CAN FD option is not enabled.");
qDebug("%ls", qUtf16Printable(error));
setError(error, QCanBusDevice::WriteError);
return false;
@@ -442,7 +444,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
qint64 bytesWritten = 0;
if (newData.hasFlexibleDataRateFormat()) {
canfd_frame frame;
- memset(&frame, 0, sizeof(frame));
+ ::memset(&frame, 0, sizeof(frame));
frame.len = newData.payload().size();
frame.can_id = canId;
frame.flags = newData.hasBitrateSwitch() ? CANFD_BRS : 0;
@@ -452,7 +454,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
bytesWritten = ::write(canSocket, &frame, sizeof(frame));
} else {
can_frame frame;
- memset(&frame, 0, sizeof(frame));
+ ::memset(&frame, 0, sizeof(frame));
frame.can_dlc = newData.payload().size();
frame.can_id = canId;
::memcpy(frame.data, newData.payload().constData(), frame.can_dlc);
@@ -639,10 +641,13 @@ void SocketCanBackend::readSocket()
QVector<QCanBusFrame> newFrames;
for (;;) {
- struct canfd_frame frame;
- int bytesReceived;
+ ::memset(&m_frame, 0, sizeof(m_frame));
+ m_iov.iov_len = sizeof(m_frame);
+ m_msg.msg_namelen = sizeof(m_addr);
+ m_msg.msg_controllen = sizeof(m_ctrlmsg);
+ m_msg.msg_flags = 0;
- bytesReceived = ::read(canSocket, &frame, sizeof(frame));
+ const int bytesReceived = ::recvmsg(canSocket, &m_msg, 0);
if (bytesReceived <= 0) {
break;
@@ -650,7 +655,7 @@ void SocketCanBackend::readSocket()
setError(tr("ERROR SocketCanBackend: incomplete CAN frame"),
QCanBusDevice::CanBusError::ReadError);
continue;
- } else if (Q_UNLIKELY(frame.len > bytesReceived - offsetof(canfd_frame, data))) {
+ } else if (Q_UNLIKELY(m_frame.len > bytesReceived - offsetof(canfd_frame, data))) {
setError(tr("ERROR SocketCanBackend: invalid CAN frame length"),
QCanBusDevice::CanBusError::ReadError);
continue;
@@ -660,7 +665,7 @@ void SocketCanBackend::readSocket()
if (Q_UNLIKELY(ioctl(canSocket, SIOCGSTAMP, &timeStamp) < 0)) {
setError(qt_error_string(errno),
QCanBusDevice::CanBusError::ReadError);
- memset(&timeStamp, 0, sizeof(timeStamp));
+ ::memset(&timeStamp, 0, sizeof(timeStamp));
}
const QCanBusFrame::TimeStamp stamp(timeStamp.tv_sec, timeStamp.tv_usec);
@@ -668,21 +673,23 @@ void SocketCanBackend::readSocket()
bufferedFrame.setTimeStamp(stamp);
bufferedFrame.setFlexibleDataRateFormat(bytesReceived == CANFD_MTU);
- bufferedFrame.setExtendedFrameFormat(frame.can_id & CAN_EFF_FLAG);
- Q_ASSERT(frame.len <= CANFD_MAX_DLEN);
+ bufferedFrame.setExtendedFrameFormat(m_frame.can_id & CAN_EFF_FLAG);
+ Q_ASSERT(m_frame.len <= CANFD_MAX_DLEN);
- if (frame.can_id & CAN_RTR_FLAG)
+ if (m_frame.can_id & CAN_RTR_FLAG)
bufferedFrame.setFrameType(QCanBusFrame::RemoteRequestFrame);
- if (frame.can_id & CAN_ERR_FLAG)
+ if (m_frame.can_id & CAN_ERR_FLAG)
bufferedFrame.setFrameType(QCanBusFrame::ErrorFrame);
- if (frame.flags & CANFD_BRS)
+ if (m_frame.flags & CANFD_BRS)
bufferedFrame.setBitrateSwitch(true);
- if (frame.flags & CANFD_ESI)
+ if (m_frame.flags & CANFD_ESI)
bufferedFrame.setErrorStateIndicator(true);
+ if (m_msg.msg_flags & MSG_CONFIRM)
+ bufferedFrame.setLocalEcho(true);
- bufferedFrame.setFrameId(frame.can_id & CAN_EFF_MASK);
+ bufferedFrame.setFrameId(m_frame.can_id & CAN_EFF_MASK);
- const QByteArray load(reinterpret_cast<char *>(frame.data), frame.len);
+ const QByteArray load(reinterpret_cast<char *>(m_frame.data), m_frame.len);
bufferedFrame.setPayload(load);
newFrames.append(std::move(bufferedFrame));
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.h b/src/plugins/canbus/socketcan/socketcanbackend.h
index 70c47c8..50976b1 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.h
+++ b/src/plugins/canbus/socketcan/socketcanbackend.h
@@ -45,6 +45,12 @@
#include <QtCore/qstring.h>
#include <QtCore/qvariant.h>
+// The order of the following includes is mandatory, because some
+// distributions use sa_family_t in can.h without including socket.h
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <linux/can.h>
+
QT_BEGIN_NAMESPACE
class SocketCanBackend : public QCanBusDevice
@@ -73,6 +79,13 @@ private:
bool connectSocket();
bool applyConfigurationParameter(int key, const QVariant &value);
+ canfd_frame m_frame;
+ sockaddr_can m_address;
+ msghdr m_msg;
+ iovec m_iov;
+ sockaddr_can m_addr;
+ char m_ctrlmsg[CMSG_SPACE(sizeof(timeval)) + CMSG_SPACE(sizeof(__u32))];
+
qint64 canSocket = -1;
QSocketNotifier *notifier = nullptr;
QString canSocketName;
diff --git a/src/plugins/canbus/systeccan/systeccanbackend.cpp b/src/plugins/canbus/systeccan/systeccanbackend.cpp
index 2662c42..996122d 100644
--- a/src/plugins/canbus/systeccan/systeccanbackend.cpp
+++ b/src/plugins/canbus/systeccan/systeccanbackend.cpp
@@ -395,6 +395,7 @@ void SystecCanBackendPrivate::readAllReceivedMessages()
// TODO: Timestamp can also be set to 100 us resolution with kUcanModeHighResTimer
frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(message.m_dwTime * 1000));
frame.setExtendedFrameFormat(message.m_bFF & USBCAN_MSG_FF_EXT);
+ frame.setLocalEcho(message.m_bFF & USBCAN_MSG_FF_ECHO);
frame.setFrameType((message.m_bFF & USBCAN_MSG_FF_RTR)
? QCanBusFrame::RemoteRequestFrame
: QCanBusFrame::DataFrame);
diff --git a/src/plugins/canbus/tinycan/tinycanbackend.cpp b/src/plugins/canbus/tinycan/tinycanbackend.cpp
index 6405308..2d3488a 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend.cpp
+++ b/src/plugins/canbus/tinycan/tinycanbackend.cpp
@@ -73,9 +73,16 @@ QList<QCanBusDeviceInfo> TinyCanBackend::interfaces()
return { createDeviceInfo(QStringLiteral("can0.0")), createDeviceInfo(QStringLiteral("can0.1")) };
}
-Q_GLOBAL_STATIC(QList<TinyCanBackendPrivate *>, qChannels)
+namespace {
-static QMutex channelsGuard(QMutex::NonRecursive);
+struct TinyCanGlobal {
+ QList<TinyCanBackendPrivate *> channels;
+ QMutex mutex;
+};
+
+} // namespace
+
+Q_GLOBAL_STATIC(TinyCanGlobal, gTinyCan)
class WriteNotifier : public QTimer
{
@@ -108,8 +115,8 @@ static void DRV_CALLBACK_TYPE canRxEventCallback(quint32 index, TCanMsg *frame,
Q_UNUSED(frame);
Q_UNUSED(count);
- QMutexLocker lock(&channelsGuard);
- for (TinyCanBackendPrivate *p : qAsConst(*qChannels())) {
+ QMutexLocker lock(&gTinyCan->mutex);
+ for (TinyCanBackendPrivate *p : qAsConst(gTinyCan->channels)) {
if (p->channelIndex == int(index)) {
p->startRead();
return;
@@ -122,16 +129,16 @@ TinyCanBackendPrivate::TinyCanBackendPrivate(TinyCanBackend *q)
{
startupDriver();
- QMutexLocker lock(&channelsGuard);
- qChannels()->append(this);
+ QMutexLocker lock(&gTinyCan->mutex);
+ gTinyCan->channels.append(this);
}
TinyCanBackendPrivate::~TinyCanBackendPrivate()
{
cleanupDriver();
- QMutexLocker lock(&channelsGuard);
- qChannels()->removeAll(this);
+ QMutexLocker lock(&gTinyCan->mutex);
+ gTinyCan->channels.removeAll(this);
}
struct BitrateItem
diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend.cpp b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
index 6c455da..c84658b 100644
--- a/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
+++ b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
@@ -359,6 +359,7 @@ void VectorCanBackendPrivate::startRead()
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)
diff --git a/src/serialbus/doc/src/socketcan.qdoc b/src/serialbus/doc/src/socketcan.qdoc
index 6886d3b..a7cac9f 100644
--- a/src/serialbus/doc/src/socketcan.qdoc
+++ b/src/serialbus/doc/src/socketcan.qdoc
@@ -149,12 +149,15 @@
\li To meet the multiple-user needs, the local loopback is enabled by default.
This means, whenever a CAN frame is transmitted on the CAN bus, a local
echo of this frame is sent to all applications connected to this CAN device.
+ If this option is enabled, the therefore received frames are marked with
+ QCanBusFrame::hasLocalEcho()
\row
\li QCanBusDevice::ReceiveOwnKey
\li The reception of the CAN frames on the same socket that was sending the CAN frame
is disabled by default. When enabling this option, all CAN frames sent to the CAN
bus immediately appear in the receive buffer. This can be used to check if sending
- was successful.
+ was successful. If this option is enabled, the therefore received frames are marked
+ with QCanBusFrame::hasLocalEcho()
\row
\li QCanBusDevice::ErrorFilterKey
\li A CAN interface driver can generate so called \e {Error Message Frames} that can
diff --git a/src/serialbus/doc/src/systeccan.qdoc b/src/serialbus/doc/src/systeccan.qdoc
index 5116241..bd8ee61 100644
--- a/src/serialbus/doc/src/systeccan.qdoc
+++ b/src/serialbus/doc/src/systeccan.qdoc
@@ -98,6 +98,7 @@
\row
\li QCanBusDevice::ReceiveOwnKey
\li The reception of CAN frames on the same channel that was sending the CAN frame
- is disabled by default.
+ is disabled by default. If this option is enabled, the therefore received frames
+ are marked with QCanBusFrame::hasLocalEcho()
\endtable
*/
diff --git a/src/serialbus/doc/src/vectorcan.qdoc b/src/serialbus/doc/src/vectorcan.qdoc
index 4290e7a..5b23c8e 100644
--- a/src/serialbus/doc/src/vectorcan.qdoc
+++ b/src/serialbus/doc/src/vectorcan.qdoc
@@ -96,6 +96,7 @@
\li The reception of the CAN frames on the same device that was sending the CAN frame
is disabled by default. When enabling this option, all CAN frames sent to the CAN
bus immediately appear in the receive buffer. This can be used to check if sending
- was successful.
+ was successful. If this option is enabled, the therefore received frames are marked
+ with QCanBusFrame::hasLocalEcho()
\endtable
*/
diff --git a/src/serialbus/qcanbusframe.cpp b/src/serialbus/qcanbusframe.cpp
index d8d6985..8644701 100644
--- a/src/serialbus/qcanbusframe.cpp
+++ b/src/serialbus/qcanbusframe.cpp
@@ -312,6 +312,36 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QCanBusFrame::hasLocalEcho() const
+ \since 5.10
+
+ Returns \c true if the frame is a local echo frame, i.e. a frame that is received as echo when
+ the frame with the same content was successfully sent to the CAN bus. This flag is set for
+ frames sent by the application itself as well as for frames sent by other applications running
+ on the same system.
+
+ QCanBusDevice::ReceiveOwnKey must be set to true to receive echo frames.
+
+ \sa setLocalEcho()
+ \sa QCanBusDevice::ReceiveOwnKey
+ \sa QCanBusDevice::LoopbackKey
+*/
+
+/*!
+ \fn void QCanBusFrame::setLocalEcho(bool echo)
+ \since 5.10
+
+ Set the \e {Local Echo} flag to \a echo.
+
+ When sending CAN bus frames with QCanBusDevice::ReceiveOwnKey enabled, all successfully sent
+ frames are echoed to the receive queue and marked as local echo frames.
+ \c QCanBusFrame::setLocalEcho should therefore only be used for application testing,
+ e.g. on virtual CAN busses.
+
+ \sa hasLocalEcho()
+*/
+
+/*!
\class QCanBusFrame::TimeStamp
\inmodule QtSerialBus
\since 5.8
@@ -422,6 +452,8 @@ QDataStream &operator<<(QDataStream &out, const QCanBusFrame &frame)
out << stamp.microSeconds();
if (frame.version >= QCanBusFrame::Version::Qt_5_9)
out << frame.hasBitrateSwitch() << frame.hasErrorStateIndicator();
+ if (frame.version >= QCanBusFrame::Version::Qt_5_10)
+ out << frame.hasLocalEcho();
return out;
}
@@ -439,6 +471,7 @@ QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame)
bool flexibleDataRate;
bool bitrateSwitch = false;
bool errorStateIndicator = false;
+ bool localEcho = false;
QByteArray payload;
qint64 seconds;
qint64 microSeconds;
@@ -449,6 +482,9 @@ QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame)
if (version >= QCanBusFrame::Version::Qt_5_9)
in >> bitrateSwitch >> errorStateIndicator;
+ if (version >= QCanBusFrame::Version::Qt_5_10)
+ in >> localEcho;
+
frame.setFrameId(frameId);
frame.version = version;
@@ -457,6 +493,7 @@ QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame)
frame.setFlexibleDataRateFormat(flexibleDataRate);
frame.setBitrateSwitch(bitrateSwitch);
frame.setErrorStateIndicator(errorStateIndicator);
+ frame.setLocalEcho(localEcho);
frame.setPayload(payload);
frame.setTimeStamp(QCanBusFrame::TimeStamp(seconds, microSeconds));
diff --git a/src/serialbus/qcanbusframe.h b/src/serialbus/qcanbusframe.h
index 5e285c1..0300a9c 100644
--- a/src/serialbus/qcanbusframe.h
+++ b/src/serialbus/qcanbusframe.h
@@ -74,14 +74,15 @@ public:
explicit QCanBusFrame(FrameType type = DataFrame) Q_DECL_NOTHROW :
isExtendedFrame(0x0),
- version(Qt_5_9),
+ version(Qt_5_10),
isFlexibleDataRate(0x0),
isBitrateSwitch(0x0),
isErrorStateIndicator(0x0),
+ isLocalEcho(0x0),
reserved0(0x0)
{
Q_UNUSED(reserved0);
- memset(reserved, 0, sizeof(reserved));
+ ::memset(reserved, 0, sizeof(reserved));
setFrameId(0x0);
setFrameType(type);
}
@@ -107,14 +108,15 @@ public:
explicit QCanBusFrame(quint32 identifier, const QByteArray &data) :
format(DataFrame),
isExtendedFrame(0x0),
- version(Qt_5_9),
+ version(Qt_5_10),
isFlexibleDataRate(data.length() > 8 ? 0x1 : 0x0),
isBitrateSwitch(0x0),
isErrorStateIndicator(0x0),
+ isLocalEcho(0x0),
reserved0(0x0),
load(data)
{
- memset(reserved, 0, sizeof(reserved));
+ ::memset(reserved, 0, sizeof(reserved));
setFrameId(identifier);
}
@@ -249,6 +251,11 @@ public:
if (errorStateIndicator)
isFlexibleDataRate = 0x1;
}
+ bool hasLocalEcho() const Q_DECL_NOTHROW { return (isLocalEcho & 0x1); }
+ void setLocalEcho(bool localEcho) Q_DECL_NOTHROW
+ {
+ isLocalEcho = (localEcho & 0x1);
+ }
#ifndef QT_NO_DATASTREAM
friend Q_SERIALBUS_EXPORT QDataStream &operator<<(QDataStream &, const QCanBusFrame &);
@@ -258,7 +265,8 @@ public:
private:
enum Version {
Qt_5_8 = 0x0,
- Qt_5_9 = 0x1
+ Qt_5_9 = 0x1,
+ Qt_5_10 = 0x2
};
quint32 canId:29; // acts as container for error codes too
@@ -271,7 +279,8 @@ private:
quint8 isBitrateSwitch:1;
quint8 isErrorStateIndicator:1;
- quint8 reserved0:6;
+ quint8 isLocalEcho:1;
+ quint8 reserved0:5;
// reserved for future use
quint8 reserved[2];
diff --git a/src/serialbus/qmodbusclient.cpp b/src/serialbus/qmodbusclient.cpp
index 7f63afa..182a212 100644
--- a/src/serialbus/qmodbusclient.cpp
+++ b/src/serialbus/qmodbusclient.cpp
@@ -486,7 +486,7 @@ bool QModbusClientPrivate::collateBytes(const QModbusPdu &response,
return false;
// byte count needs to match available bytes
- const quint8 byteCount = response.data()[0];
+ const quint8 byteCount = quint8(response.data().at(0));
if ((response.dataSize() - 1) != byteCount)
return false;
diff --git a/src/serialbus/qmodbuspdu.cpp b/src/serialbus/qmodbuspdu.cpp
index e1ce0c6..6b1cee4 100644
--- a/src/serialbus/qmodbuspdu.cpp
+++ b/src/serialbus/qmodbuspdu.cpp
@@ -555,18 +555,18 @@ int QModbusRequest::calculateDataSize(const QModbusRequest &request)
case QModbusPdu::WriteMultipleCoils:
minimum -= 1; // first payload payload byte
if (request.dataSize() >= minimum)
- size = minimum + quint8(request.data()[minimum - 1]) /*byte count*/;
+ size = minimum + quint8(request.data().at(minimum - 1)) /*byte count*/;
break;
case QModbusPdu::WriteMultipleRegisters:
case QModbusPdu::ReadWriteMultipleRegisters:
minimum -= 2; // first 2 payload payload bytes
if (request.dataSize() >= minimum)
- size = minimum + quint8(request.data()[minimum - 1]) /*byte count*/;
+ size = minimum + quint8(request.data().at(minimum - 1)) /*byte count*/;
break;
case QModbusPdu::ReadFileRecord:
case QModbusPdu::WriteFileRecord:
if (request.dataSize() >= 1)
- size = 1 /*byte count*/ + quint8(request.data()[0]) /*actual bytes*/;
+ size = 1 /*byte count*/ + quint8(request.data().at(0)) /*actual bytes*/;
break;
case QModbusPdu::EncapsulatedInterfaceTransport: {
if (request.dataSize() < minimum)
diff --git a/src/tools/canbusutil/canbusutil.cpp b/src/tools/canbusutil/canbusutil.cpp
index 0a0a6df..c553c52 100644
--- a/src/tools/canbusutil/canbusutil.cpp
+++ b/src/tools/canbusutil/canbusutil.cpp
@@ -104,7 +104,7 @@ int CanBusUtil::printDevices(const QString &pluginName)
return 0;
}
-bool CanBusUtil::parseDataField(qint32 &id, QString &payload)
+bool CanBusUtil::parseDataField(quint32 &id, QString &payload)
{
int hashMarkPos = m_data.indexOf('#');
if (hashMarkPos < 0) {
@@ -112,7 +112,7 @@ bool CanBusUtil::parseDataField(qint32 &id, QString &payload)
return false;
}
- id = m_data.left(hashMarkPos).toInt(nullptr, 16);
+ id = m_data.leftRef(hashMarkPos).toUInt(nullptr, 16);
payload = m_data.right(m_data.length() - hashMarkPos - 1);
return true;
@@ -158,7 +158,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.left(1).toInt(nullptr, 16);
+ const int flags = payload.leftRef(1).toInt(nullptr, 16);
frame->setBitrateSwitch(flags & BitrateSwitchFlag);
frame->setErrorStateIndicator(flags & ErrorStateIndicatorFlag);
payload.remove(0, 1);
@@ -206,7 +206,7 @@ bool CanBusUtil::connectCanDevice()
bool CanBusUtil::sendData()
{
- qint32 id;
+ quint32 id;
QString payload;
QCanBusFrame frame;
@@ -216,7 +216,7 @@ bool CanBusUtil::sendData()
if (setFrameFromPayload(payload, &frame) == false)
return false;
- if (id < 0 || id > 0x1FFFFFFF) { // 29 bits
+ if (id > 0x1FFFFFFF) { // 29 bits
id = 0x1FFFFFFF;
m_output << "Warning! Id does not fit into Extended Frame Format, setting id to: " << id << endl;
}
diff --git a/src/tools/canbusutil/canbusutil.h b/src/tools/canbusutil/canbusutil.h
index e9e7d2b..356b3df 100644
--- a/src/tools/canbusutil/canbusutil.h
+++ b/src/tools/canbusutil/canbusutil.h
@@ -63,7 +63,7 @@ public:
int printDevices(const QString &pluginName);
private:
- bool parseDataField(qint32 &id, QString &payload);
+ bool parseDataField(quint32 &id, QString &payload);
bool setFrameFromPayload(QString payload, QCanBusFrame *frame);
bool connectCanDevice();
bool sendData();
diff --git a/src/tools/canbusutil/canbusutil.pro b/src/tools/canbusutil/canbusutil.pro
index a446682..b3e0504 100644
--- a/src/tools/canbusutil/canbusutil.pro
+++ b/src/tools/canbusutil/canbusutil.pro
@@ -10,4 +10,5 @@ HEADERS += \
canbusutil.h \
sigtermhandler.h
+QMAKE_TARGET_DESCRIPTION = "Qt CAN Bus Util"
load(qt_tool)
diff --git a/tests/auto/qcanbusframe/tst_qcanbusframe.cpp b/tests/auto/qcanbusframe/tst_qcanbusframe.cpp
index 043d89e..38c3784 100644
--- a/tests/auto/qcanbusframe/tst_qcanbusframe.cpp
+++ b/tests/auto/qcanbusframe/tst_qcanbusframe.cpp
@@ -50,6 +50,7 @@ private slots:
void timeStamp();
void bitRateSwitch();
void errorStateIndicator();
+ void localEcho();
void tst_isValid_data();
void tst_isValid();
@@ -264,6 +265,21 @@ void tst_QCanBusFrame::errorStateIndicator()
QVERIFY(!frame2.hasErrorStateIndicator());
}
+void tst_QCanBusFrame::localEcho()
+{
+ QCanBusFrame frame(QCanBusFrame::DataFrame);
+ QVERIFY(!frame.hasLocalEcho());
+
+ frame.setLocalEcho(true);
+ QVERIFY(frame.hasLocalEcho());
+
+ frame.setLocalEcho(false);
+ QVERIFY(!frame.hasLocalEcho());
+
+ const QCanBusFrame frame2(0x123, QByteArray());
+ QVERIFY(!frame2.hasLocalEcho());
+}
+
void tst_QCanBusFrame::tst_isValid_data()
{
QTest::addColumn<QCanBusFrame::FrameType>("frameType");
@@ -432,39 +448,54 @@ void tst_QCanBusFrame::streaming_data()
QTest::addColumn<bool>("isFlexibleDataRate");
QTest::addColumn<bool>("isBitrateSwitch");
QTest::addColumn<bool>("isErrorStateIndicator");
+ QTest::addColumn<bool>("isLocalEcho");
QTest::addColumn<QCanBusFrame::FrameType>("frameType");
QTest::newRow("emptyFrame") << quint32(0) << QByteArray()
<< qint64(0) << qint64(0)
- << false << false << false << false << QCanBusFrame::DataFrame;
+ << false << false << false << false << false
+ << QCanBusFrame::DataFrame;
QTest::newRow("fullFrame1") << quint32(123) << QByteArray("abcde1")
<< qint64(456) << qint64(784)
- << true << false << false << false << QCanBusFrame::DataFrame;
+ << true << false << false << false << false
+ << QCanBusFrame::DataFrame;
QTest::newRow("fullFrame2") << quint32(123) << QByteArray("abcde2")
<< qint64(457) << qint64(785)
- << false << false << false << false << QCanBusFrame::DataFrame;
+ << false << false << false << false << false
+ << QCanBusFrame::DataFrame;
QTest::newRow("fullFrameFD") << quint32(123) << QByteArray("abcdfd")
<< qint64(457) << qint64(785)
- << false << true << false << false << QCanBusFrame::DataFrame;
+ << false << true << false << false << false
+ << QCanBusFrame::DataFrame;
QTest::newRow("fullFrameBRS") << quint32(123) << QByteArray("abcdfd")
<< qint64(457) << qint64(785)
- << false << true << true << false << QCanBusFrame::DataFrame;
+ << false << true << true << false << false
+ << QCanBusFrame::DataFrame;
QTest::newRow("fullFrameESI") << quint32(123) << QByteArray("abcdfd")
<< qint64(457) << qint64(785)
- << false << true << false << true << QCanBusFrame::DataFrame;
+ << false << true << false << true << false
+ << QCanBusFrame::DataFrame;
+ QTest::newRow("echoFrame") << quint32(123) << QByteArray("abcde7")
+ << qint64(888) << qint64(777)
+ << false << false << false << false << true
+ << QCanBusFrame::DataFrame;
QTest::newRow("fullFrame3") << quint32(123) << QByteArray("abcde3")
<< qint64(458) << qint64(786)
- << true << false << false << false << QCanBusFrame::RemoteRequestFrame;
+ << true << false << false << false << false
+ << QCanBusFrame::RemoteRequestFrame;
QTest::newRow("fullFrame4") << quint32(123) << QByteArray("abcde4")
<< qint64(459) << qint64(787)
- << false << false << false << false << QCanBusFrame::RemoteRequestFrame;
+ << false << false << false << false << false
+ << QCanBusFrame::RemoteRequestFrame;
QTest::newRow("fullFrame5") << quint32(123) << QByteArray("abcde5")
<< qint64(460) << qint64(789)
- << true << false << false << false << QCanBusFrame::ErrorFrame;
+ << true << false << false << false << false
+ << QCanBusFrame::ErrorFrame;
QTest::newRow("fullFrame6") << quint32(123) << QByteArray("abcde6")
<< qint64(453) << qint64(788)
- << false << false << false << false << QCanBusFrame::ErrorFrame;
+ << false << false << false << false << false
+ << QCanBusFrame::ErrorFrame;
}
void tst_QCanBusFrame::streaming()
@@ -477,6 +508,7 @@ void tst_QCanBusFrame::streaming()
QFETCH(bool, isFlexibleDataRate);
QFETCH(bool, isBitrateSwitch);
QFETCH(bool, isErrorStateIndicator);
+ QFETCH(bool, isLocalEcho);
QFETCH(QCanBusFrame::FrameType, frameType);
QCanBusFrame originalFrame(frameId, payload);
@@ -487,6 +519,7 @@ void tst_QCanBusFrame::streaming()
originalFrame.setFlexibleDataRateFormat(isFlexibleDataRate);
originalFrame.setBitrateSwitch(isBitrateSwitch);
originalFrame.setErrorStateIndicator(isErrorStateIndicator);
+ originalFrame.setLocalEcho(isLocalEcho);
originalFrame.setFrameType(frameType);
QByteArray buffer;
@@ -513,6 +546,8 @@ void tst_QCanBusFrame::streaming()
originalFrame.hasBitrateSwitch());
QCOMPARE(restoredFrame.hasErrorStateIndicator(),
originalFrame.hasErrorStateIndicator());
+ QCOMPARE(restoredFrame.hasLocalEcho(),
+ originalFrame.hasLocalEcho());
}
void tst_QCanBusFrame::tst_error()