summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/serialbus/can/connectdialog.cpp12
-rw-r--r--examples/serialbus/can/connectdialog.ui10
-rw-r--r--examples/serialbus/can/mainwindow.cpp6
-rw-r--r--examples/serialbus/can/mainwindow.ui22
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp3
-rw-r--r--src/serialbus/doc/src/socketcan.qdoc20
-rw-r--r--src/serialbus/qcanbusdevice.cpp11
-rw-r--r--src/serialbus/qcanbusdevice.h1
-rw-r--r--src/serialbus/qcanbusframe.cpp42
-rw-r--r--src/serialbus/qcanbusframe.h31
-rw-r--r--tests/auto/qcanbusframe/tst_qcanbusframe.cpp66
11 files changed, 200 insertions, 24 deletions
diff --git a/examples/serialbus/can/connectdialog.cpp b/examples/serialbus/can/connectdialog.cpp
index 5d9e33d..920aeef 100644
--- a/examples/serialbus/can/connectdialog.cpp
+++ b/examples/serialbus/can/connectdialog.cpp
@@ -62,6 +62,8 @@ ConnectDialog::ConnectDialog(QWidget *parent) :
m_ui->canFdBox->addItem(tr("false"), QVariant(false));
m_ui->canFdBox->addItem(tr("true"), QVariant(true));
+ m_ui->dataBitrateBox->setFlexibleDateRateEnabled(true);
+
connect(m_ui->okButton, &QPushButton::clicked, this, &ConnectDialog::ok);
connect(m_ui->cancelButton, &QPushButton::clicked, this, &ConnectDialog::cancel);
connect(m_ui->useConfigurationBox, &QCheckBox::clicked,
@@ -162,6 +164,9 @@ void ConnectDialog::revertSettings()
value = configurationValue(QCanBusDevice::CanFdKey);
m_ui->canFdBox->setCurrentText(value);
+
+ value = configurationValue(QCanBusDevice::DataBitRateKey);
+ m_ui->dataBitrateBox->setCurrentText(value);
}
void ConnectDialog::updateSettings()
@@ -218,5 +223,12 @@ void ConnectDialog::updateSettings()
fdItem.first = QCanBusDevice::CanFdKey;
fdItem.second = m_ui->canFdBox->currentData();
m_currentSettings.configurations.append(fdItem);
+
+ // process data bitrate
+ const int dataBitrate = m_ui->dataBitrateBox->bitRate();
+ if (dataBitrate > 0) {
+ const ConfigurationItem item(QCanBusDevice::DataBitRateKey, QVariant(dataBitrate));
+ m_currentSettings.configurations.append(item);
+ }
}
}
diff --git a/examples/serialbus/can/connectdialog.ui b/examples/serialbus/can/connectdialog.ui
index 345ff64..aad6bef 100644
--- a/examples/serialbus/can/connectdialog.ui
+++ b/examples/serialbus/can/connectdialog.ui
@@ -146,6 +146,16 @@
<item row="5" column="1">
<widget class="QComboBox" name="canFdBox"/>
</item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="dataBitrateLabel">
+ <property name="text">
+ <string>Data Bitrate</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="BitRateBox" name="dataBitrateBox"/>
+ </item>
</layout>
</widget>
</item>
diff --git a/examples/serialbus/can/mainwindow.cpp b/examples/serialbus/can/mainwindow.cpp
index 2e75037..b27baaa 100644
--- a/examples/serialbus/can/mainwindow.cpp
+++ b/examples/serialbus/can/mainwindow.cpp
@@ -202,7 +202,10 @@ void MainWindow::checkMessages()
.arg(frame.timeStamp().seconds(), 10, 10, QLatin1Char(' '))
.arg(frame.timeStamp().microSeconds() / 100, 4, 10, QLatin1Char('0'));
- m_ui->receivedMessagesEdit->append(time + view);
+ const QString flags = frame.hasBitrateSwitch()
+ ? QStringLiteral(" B - ") : QStringLiteral(" - - ");
+
+ m_ui->receivedMessagesEdit->append(time + flags + view);
}
}
@@ -232,6 +235,7 @@ void MainWindow::sendMessage() const
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);
diff --git a/examples/serialbus/can/mainwindow.ui b/examples/serialbus/can/mainwindow.ui
index 38e1157..72dc62b 100644
--- a/examples/serialbus/can/mainwindow.ui
+++ b/examples/serialbus/can/mainwindow.ui
@@ -40,7 +40,7 @@
</property>
</widget>
</item>
- <item row="0" column="2" rowspan="3">
+ <item row="0" column="2" rowspan="4">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Frame Type</string>
@@ -84,7 +84,7 @@
</property>
</widget>
</item>
- <item row="1" column="3">
+ <item row="2" column="3">
<widget class="QCheckBox" name="effBox">
<property name="toolTip">
<string>Allow extended frames with 29 bit identifier.
@@ -96,21 +96,21 @@ Otherwise, the standard format with 11 bit idenfier is used.</string>
</property>
</widget>
</item>
- <item row="2" column="3">
+ <item row="3" column="3">
<widget class="QPushButton" name="sendButton">
<property name="text">
<string>&amp;Send</string>
</property>
</widget>
</item>
- <item row="1" column="1">
+ <item row="2" column="1">
<widget class="QLineEdit" name="lineEdit">
<property name="placeholderText">
<string>12 34 AB CE</string>
</property>
</widget>
</item>
- <item row="1" column="0">
+ <item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&amp;Data (hex)</string>
@@ -120,6 +120,14 @@ Otherwise, the standard format with 11 bit idenfier is used.</string>
</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>
@@ -143,7 +151,7 @@ Otherwise, the standard format with 11 bit idenfier is used.</string>
<enum>QFrame::StyledPanel</enum>
</property>
<property name="text">
- <string>Timestamp CAN-ID DLC Data</string>
+ <string>Timestamp Flags CAN-ID DLC Data</string>
</property>
</widget>
</item>
@@ -180,7 +188,7 @@ Otherwise, the standard format with 11 bit idenfier is used.</string>
<x>0</x>
<y>0</y>
<width>551</width>
- <height>21</height>
+ <height>19</height>
</rect>
</property>
<widget class="QMenu" name="menuCalls">
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index f9f28cc..53836b0 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.cpp
+++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp
@@ -449,6 +449,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
canfd_frame frame;
frame.len = newData.payload().size();
frame.can_id = canId;
+ frame.flags = newData.hasBitrateSwitch() ? CANFD_BRS : 0;
::memcpy(frame.data, newData.payload().constData(), frame.len);
bytesWritten = ::write(canSocket, &frame, sizeof(frame));
@@ -676,6 +677,8 @@ void SocketCanBackend::readSocket()
bufferedFrame.setFrameType(QCanBusFrame::RemoteRequestFrame);
if (frame.can_id & CAN_ERR_FLAG)
bufferedFrame.setFrameType(QCanBusFrame::ErrorFrame);
+ if (frame.flags & CANFD_BRS)
+ bufferedFrame.setBitrateSwitch(true);
bufferedFrame.setFrameId(frame.can_id & CAN_EFF_MASK);
diff --git a/src/serialbus/doc/src/socketcan.qdoc b/src/serialbus/doc/src/socketcan.qdoc
index 919955d..f5aec83 100644
--- a/src/serialbus/doc/src/socketcan.qdoc
+++ b/src/serialbus/doc/src/socketcan.qdoc
@@ -47,6 +47,8 @@
This section assumes, that the device driver is already loaded
(most likely automatically when connecting the CAN hardware).
+ \section3 Default settings
+
To set the device can0 to a bitrate of 250 kBit/s:
\code
sudo ip link set up can0 type can bitrate 250000
@@ -56,6 +58,13 @@
the following command can be used:
\code
sudo ip link set up can0 type can bitrate 250000 restart-ms 100
+
+ \section3 CAN FD settings
+
+ To set the device can0 to an arbitration bitrate of 500 kBit/s and a data
+ bitrate of 4 MBit/s (for frames with bitrate switch flag):
+ \code
+ sudo ip link set can0 up type can bitrate 500000 dbitrate 4000000 fd on
\endcode
\section2 Setting up a virtual CAN bus
@@ -73,10 +82,10 @@
the \l{https://github.com/linux-can/can-utils}{can-utils} package:
\code
- # Display received CAN messages
- candump vcan0
+ # Display received CAN messages with absolute timestamps and flags
+ candump -ta -x vcan0
- # Send a CAN message
+ # Send a CAN FD message with flags BRS and EFI set
cansend vcan0 123##3112233445566778899aabbccddeeff
# Generate random CAN messages
@@ -163,6 +172,11 @@
\li This configuration option determines whether CANFD frames may be sent or received.
By default, this option is disabled. It controls the CAN_RAW_FD_FRAMES
option of the CAN socket.
+ \row
+ \li QCanBusDevice::DataBitRateKey
+ \li This configuration is not supported by the socketcan plugin. However
+ it is possible to set the data rate when configuring the CAN network interface
+ using the \c {ip link} command.
\endtable
For example:
diff --git a/src/serialbus/qcanbusdevice.cpp b/src/serialbus/qcanbusdevice.cpp
index bfded26..1acf98a 100644
--- a/src/serialbus/qcanbusdevice.cpp
+++ b/src/serialbus/qcanbusdevice.cpp
@@ -102,9 +102,18 @@ QT_BEGIN_NAMESPACE
\value ReceiveOwnKey This key defines whether this CAN device receives its own send frames.
This can be used to check if the transmission was successful.
The expected value for this key is \c bool.
- \value BitRateKey This key defines the bitrate in bits per second.
+ \value BitRateKey This key defines the CAN bitrate in bits per second. With CAN FD,
+ the payload can be transmitted at a higher data bitrate,
+ if \l QCanBusFrame::hasBitrateSwitch() is set. In this case,
+ \c QCanBusDevice::BitRateKey is only used for the CAN ID arbitration
+ phase. See also \c QCanBusDevice::DataBitRateKey
\value CanFdKey This key defines whether sending and receiving of CAN FD frames
should be enabled. The expected value for this key is \c bool.
+ \value DataBitRateKey This key defines the CAN FD payload bitrate in bits per second.
+ CAN FD allows to transmit the payload of frames with
+ \l QCanBusFrame::hasBitrateSwitch() flag at a higher data bitrate,
+ after the arbitration phase at the nominal bitrate is finished.
+ See also \c QCanBusDevice::BitRateKey
\value UserKey This key defines the range where custom keys start. Its most
common purpose is to permit platform-specific configuration
options.
diff --git a/src/serialbus/qcanbusdevice.h b/src/serialbus/qcanbusdevice.h
index 607fa25..0b9d91d 100644
--- a/src/serialbus/qcanbusdevice.h
+++ b/src/serialbus/qcanbusdevice.h
@@ -77,6 +77,7 @@ public:
ReceiveOwnKey,
BitRateKey,
CanFdKey,
+ DataBitRateKey,
UserKey = 30
};
Q_ENUM(ConfigurationKey)
diff --git a/src/serialbus/qcanbusframe.cpp b/src/serialbus/qcanbusframe.cpp
index 6bde751..26e1964 100644
--- a/src/serialbus/qcanbusframe.cpp
+++ b/src/serialbus/qcanbusframe.cpp
@@ -148,6 +148,21 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \enum QCanBusFrame::Version
+ \internal
+
+ This enum describes the version of the QCanBusFrame.
+
+ With newer Qt versions, new features may be added to QCanBusFrame. To support serializing and
+ deserializing of frames with different features, the version needs to be incremented every
+ time a new feature appears. This enum describes, at which Qt version a specific QCanBusFrame
+ version appeared.
+
+ \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
+*/
+
+/*!
\enum QCanBusFrame::FrameType
This enum describes the type of the CAN frame.
@@ -253,6 +268,26 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QCanBusFrame::hasBitrateSwitch() const
+ \since 5.9
+
+ Returns \c true if the CAN uses \e {Flexible Data-Rate} with \e {Bitrate Switch},
+ to transfer the payload data at a higher data bitrate.
+
+ \sa setBitrateSwitch() QCanBusDevice::DataBitRateKey
+*/
+
+/*!
+ \fn void QCanBusFrame::setBitrateSwitch(bool bitrateSwitch)
+ \since 5.9
+
+ Set the \e {Flexible Data-Rate} flag \e {Bitrate Switch} flag to \a bitrateSwitch.
+ The data field of frames with this flag is transferred at a higher data bitrate.
+
+ \sa hasBitrateSwitch() QCanBusDevice::DataBitRateKey
+*/
+
+/*!
\class QCanBusFrame::TimeStamp
\inmodule QtSerialBus
\since 5.8
@@ -361,6 +396,8 @@ QDataStream &operator<<(QDataStream &out, const QCanBusFrame &frame)
const QCanBusFrame::TimeStamp stamp = frame.timeStamp();
out << stamp.seconds();
out << stamp.microSeconds();
+ if (frame.version >= QCanBusFrame::Version::Qt_5_9)
+ out << frame.hasBitrateSwitch();
return out;
}
@@ -376,6 +413,7 @@ QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame)
quint8 version;
bool extendedFrameFormat;
bool flexibleDataRate;
+ bool bitrateSwitch = false;
QByteArray payload;
qint64 seconds;
qint64 microSeconds;
@@ -383,12 +421,16 @@ QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame)
in >> frameId >> frameType >> version >> extendedFrameFormat >> flexibleDataRate
>> payload >> seconds >> microSeconds;
+ if (version >= QCanBusFrame::Version::Qt_5_9)
+ in >> bitrateSwitch;
+
frame.setFrameId(frameId);
frame.version = version;
frame.setFrameType(static_cast<QCanBusFrame::FrameType>(frameType));
frame.setExtendedFrameFormat(extendedFrameFormat);
frame.setFlexibleDataRateFormat(flexibleDataRate);
+ frame.setBitrateSwitch(bitrateSwitch);
frame.setPayload(payload);
frame.setTimeStamp(QCanBusFrame::TimeStamp(seconds, microSeconds));
diff --git a/src/serialbus/qcanbusframe.h b/src/serialbus/qcanbusframe.h
index 486d996..2c32cd8 100644
--- a/src/serialbus/qcanbusframe.h
+++ b/src/serialbus/qcanbusframe.h
@@ -74,9 +74,12 @@ public:
explicit QCanBusFrame(FrameType type = DataFrame) Q_DECL_NOTHROW :
isExtendedFrame(0x0),
- version(0x0),
- isFlexibleDataRate(0x0)
+ version(Qt_5_9),
+ isFlexibleDataRate(0x0),
+ isBitrateSwitch(0x0),
+ reserved0(0x0)
{
+ Q_UNUSED(reserved0);
memset(reserved, 0, sizeof(reserved));
setFrameId(0x0);
setFrameType(type);
@@ -103,8 +106,10 @@ public:
explicit QCanBusFrame(quint32 identifier, const QByteArray &data) :
format(DataFrame),
isExtendedFrame(0x0),
- version(0x0),
+ version(Qt_5_9),
isFlexibleDataRate(data.length() > 8 ? 0x1 : 0x0),
+ isBitrateSwitch(0x0),
+ reserved0(0x0),
load(data)
{
memset(reserved, 0, sizeof(reserved));
@@ -221,6 +226,16 @@ public:
void setFlexibleDataRateFormat(bool isFlexibleData) Q_DECL_NOTHROW
{
isFlexibleDataRate = (isFlexibleData & 0x1);
+ if (!isFlexibleData)
+ isBitrateSwitch = 0x0;
+ }
+
+ bool hasBitrateSwitch() const Q_DECL_NOTHROW { return (isBitrateSwitch & 0x1); }
+ void setBitrateSwitch(bool bitrateSwitch) Q_DECL_NOTHROW
+ {
+ isBitrateSwitch = (bitrateSwitch & 0x1);
+ if (bitrateSwitch)
+ isFlexibleDataRate = 0x1;
}
#ifndef QT_NO_DATASTREAM
@@ -229,6 +244,11 @@ public:
#endif
private:
+ enum Version {
+ Qt_5_8 = 0x0,
+ Qt_5_9 = 0x1
+ };
+
quint32 canId:29; // acts as container for error codes too
quint8 format:3; // max of 8 frame types
@@ -237,8 +257,11 @@ private:
quint8 isValidFrameId:1;
quint8 isFlexibleDataRate:1;
+ quint8 isBitrateSwitch:1;
+ quint8 reserved0:7;
+
// reserved for future use
- quint8 reserved[3];
+ quint8 reserved[2];
QByteArray load;
TimeStamp stamp;
diff --git a/tests/auto/qcanbusframe/tst_qcanbusframe.cpp b/tests/auto/qcanbusframe/tst_qcanbusframe.cpp
index 78f35da..4decffa 100644
--- a/tests/auto/qcanbusframe/tst_qcanbusframe.cpp
+++ b/tests/auto/qcanbusframe/tst_qcanbusframe.cpp
@@ -48,6 +48,7 @@ private slots:
void id();
void payload();
void timeStamp();
+ void bitRateSwitch();
void tst_isValid_data();
void tst_isValid();
@@ -180,6 +181,47 @@ void tst_QCanBusFrame::timeStamp()
QCOMPARE(timeStamp.microSeconds(), 1);
}
+void tst_QCanBusFrame::bitRateSwitch()
+{
+ QCanBusFrame frame(QCanBusFrame::DataFrame);
+ QVERIFY(!frame.hasBitrateSwitch());
+
+ // set CAN FD does not set BRS
+ frame.setFlexibleDataRateFormat(true);
+ QVERIFY(frame.hasFlexibleDataRateFormat());
+ QVERIFY(!frame.hasBitrateSwitch());
+
+ // set BRS keeps CAN FD
+ frame.setBitrateSwitch(true);
+ QVERIFY(frame.hasFlexibleDataRateFormat());
+ QVERIFY(frame.hasBitrateSwitch());
+
+ // clear BRS keeps CAN FD
+ frame.setBitrateSwitch(false);
+ QVERIFY(frame.hasFlexibleDataRateFormat());
+ QVERIFY(!frame.hasBitrateSwitch());
+
+ // clear CAN FD
+ frame.setFlexibleDataRateFormat(false);
+ QVERIFY(!frame.hasFlexibleDataRateFormat());
+ QVERIFY(!frame.hasBitrateSwitch());
+
+ // set BRS sets CAN FD
+ frame.setBitrateSwitch(true);
+ QVERIFY(frame.hasFlexibleDataRateFormat());
+ QVERIFY(frame.hasBitrateSwitch());
+
+ // clear CAN FD clears BRS
+ frame.setFlexibleDataRateFormat(false);
+ QVERIFY(!frame.hasFlexibleDataRateFormat());
+ QVERIFY(!frame.hasBitrateSwitch());
+
+ // default constructed CAN FD frame has no BRS
+ const QCanBusFrame frame2(0x123, QByteArray(10, 0x55));
+ QVERIFY(frame2.hasFlexibleDataRateFormat());
+ QVERIFY(!frame2.hasBitrateSwitch());
+}
+
void tst_QCanBusFrame::tst_isValid_data()
{
QTest::addColumn<QCanBusFrame::FrameType>("frameType");
@@ -346,33 +388,37 @@ void tst_QCanBusFrame::streaming_data()
QTest::addColumn<qint64>("microSeconds");
QTest::addColumn<bool>("isExtended");
QTest::addColumn<bool>("isFlexibleDataRate");
+ QTest::addColumn<bool>("isBitrateSwitch");
QTest::addColumn<QCanBusFrame::FrameType>("frameType");
QTest::newRow("emptyFrame") << quint32(0) << QByteArray()
<< qint64(0) << qint64(0)
- << false << false << QCanBusFrame::DataFrame;
+ << false << false << false << QCanBusFrame::DataFrame;
QTest::newRow("fullFrame1") << quint32(123) << QByteArray("abcde1")
<< qint64(456) << qint64(784)
- << true << false << QCanBusFrame::DataFrame;
+ << true << false << false << QCanBusFrame::DataFrame;
QTest::newRow("fullFrame2") << quint32(123) << QByteArray("abcde2")
<< qint64(457) << qint64(785)
- << false << false << QCanBusFrame::DataFrame;
+ << false << false << false << QCanBusFrame::DataFrame;
QTest::newRow("fullFrameFD") << quint32(123) << QByteArray("abcdfd")
<< qint64(457) << qint64(785)
- << false << true << QCanBusFrame::DataFrame;
+ << false << true << false << QCanBusFrame::DataFrame;
+ QTest::newRow("fullFrameBRS") << quint32(123) << QByteArray("abcdfd")
+ << qint64(457) << qint64(785)
+ << false << true << true << QCanBusFrame::DataFrame;
QTest::newRow("fullFrame3") << quint32(123) << QByteArray("abcde3")
<< qint64(458) << qint64(786)
- << true << false << QCanBusFrame::RemoteRequestFrame;
+ << true << false << false << QCanBusFrame::RemoteRequestFrame;
QTest::newRow("fullFrame4") << quint32(123) << QByteArray("abcde4")
<< qint64(459) << qint64(787)
- << false << false << QCanBusFrame::RemoteRequestFrame;
+ << false << false << false << QCanBusFrame::RemoteRequestFrame;
QTest::newRow("fullFrame5") << quint32(123) << QByteArray("abcde5")
<< qint64(460) << qint64(789)
- << true << false << QCanBusFrame::ErrorFrame;
+ << true << false << false << QCanBusFrame::ErrorFrame;
QTest::newRow("fullFrame6") << quint32(123) << QByteArray("abcde6")
<< qint64(453) << qint64(788)
- << false << false << QCanBusFrame::ErrorFrame;
+ << false << false << false << QCanBusFrame::ErrorFrame;
}
void tst_QCanBusFrame::streaming()
@@ -383,6 +429,7 @@ void tst_QCanBusFrame::streaming()
QFETCH(qint64, microSeconds);
QFETCH(bool, isExtended);
QFETCH(bool, isFlexibleDataRate);
+ QFETCH(bool, isBitrateSwitch);
QFETCH(QCanBusFrame::FrameType, frameType);
QCanBusFrame originalFrame(frameId, payload);
@@ -391,6 +438,7 @@ void tst_QCanBusFrame::streaming()
originalFrame.setExtendedFrameFormat(isExtended);
originalFrame.setFlexibleDataRateFormat(isFlexibleDataRate);
+ originalFrame.setBitrateSwitch(isBitrateSwitch);
originalFrame.setFrameType(frameType);
QByteArray buffer;
@@ -413,6 +461,8 @@ void tst_QCanBusFrame::streaming()
originalFrame.hasExtendedFrameFormat());
QCOMPARE(restoredFrame.hasFlexibleDataRateFormat(),
originalFrame.hasFlexibleDataRateFormat());
+ QCOMPARE(restoredFrame.hasBitrateSwitch(),
+ originalFrame.hasBitrateSwitch());
}
void tst_QCanBusFrame::tst_error()