diff options
-rw-r--r-- | examples/serialbus/can/mainwindow.cpp | 1 | ||||
-rw-r--r-- | src/plugins/canbus/socketcan/socketcanbackend.cpp | 5 | ||||
-rw-r--r-- | src/serialbus/qcanbusframe.cpp | 36 | ||||
-rw-r--r-- | src/serialbus/qcanbusframe.h | 33 | ||||
-rw-r--r-- | src/tools/canbusutil/canbusutil.cpp | 14 | ||||
-rw-r--r-- | src/tools/canbusutil/canbusutil.h | 2 | ||||
-rw-r--r-- | tests/auto/qcanbusframe/tst_qcanbusframe.cpp | 95 |
7 files changed, 134 insertions, 52 deletions
diff --git a/examples/serialbus/can/mainwindow.cpp b/examples/serialbus/can/mainwindow.cpp index 5da9387..b3b3a87 100644 --- a/examples/serialbus/can/mainwindow.cpp +++ b/examples/serialbus/can/mainwindow.cpp @@ -232,6 +232,7 @@ void MainWindow::sendMessage() const frame.setFrameId(id); frame.setExtendedFrameFormat(m_ui->effBox->checkState()); + frame.setFlexibleDataRateFormat(m_ui->fdBox->checkState()); if (m_ui->remoteFrame->isChecked()) frame.setFrameType(QCanBusFrame::RemoteRequestFrame); diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp index c9781d1..8974279 100644 --- a/src/plugins/canbus/socketcan/socketcanbackend.cpp +++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp @@ -368,7 +368,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData) qWarning() << QString("payload (%1 bytes) is too large for chosen frame size of " "maximal %2 bytes. Frame is discarded."). arg(payloadSize).arg(canFdOptionEnabled ? CANFD_MAX_DLEN : CAN_MAX_DLEN); - if (!canFdOptionEnabled && payloadSize <= CANFD_MAX_DLEN) + if (!canFdOptionEnabled && newData.hasFlexibleDataRateFormat()) setError(tr("Sending CAN FD frame although CAN FD option not enabled."), QCanBusDevice::WriteError); else @@ -378,7 +378,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData) } qint64 bytesWritten = 0; - if (canFdOptionEnabled) { + if (newData.hasFlexibleDataRateFormat()) { canfd_frame frame; frame.len = newData.payload().size(); frame.can_id = canId; @@ -600,6 +600,7 @@ void SocketCanBackend::readSocket() const QCanBusFrame::TimeStamp stamp(timeStamp.tv_sec, timeStamp.tv_usec); QCanBusFrame bufferedFrame; bufferedFrame.setTimeStamp(stamp); + bufferedFrame.setFlexibleDataRateFormat(bytesReceived == CANFD_MTU); bufferedFrame.setExtendedFrameFormat(frame.can_id & CAN_EFF_FLAG); Q_ASSERT(frame.len <= CANFD_MAX_DLEN); diff --git a/src/serialbus/qcanbusframe.cpp b/src/serialbus/qcanbusframe.cpp index 9892446..1787c4c 100644 --- a/src/serialbus/qcanbusframe.cpp +++ b/src/serialbus/qcanbusframe.cpp @@ -72,7 +72,9 @@ QT_BEGIN_NAMESPACE Returns \c false if the \l frameType() is \l InvalidFrame, the \l hasExtendedFrameFormat() is not set although \l frameId() is longer than 11 bit or - the payload is longer than the maximal permitted payload length of 64 byte. + the payload is longer than the maximal permitted payload length of 64 byte if \e {Flexible + Data-Rate} mode is enabled or 8 byte if it is disabled. If \l frameType() is \l RemoteRequestFrame + and the \e {Flexible Data-Rate} mode is enabled at the same time \c false is also returned. Otherwise this function returns \c true. */ @@ -91,7 +93,8 @@ QT_BEGIN_NAMESPACE \fn QCanBusFrame::setPayload(const QByteArray &data) Sets \a data as the payload for the CAN frame. The maximum size of payload is 8 bytes, which can - be extended up to 64 bytes by supporting \e {Flexible Data-Rate}. Flexible Data-Rate has to be + be extended up to 64 bytes by supporting \e {Flexible Data-Rate}. If \a data contains more than + 8 byte the \e {Flexible Data-Rate} flag is automatically set. Flexible Data-Rate has to be enabled on the \l QCanBusDevice by setting the \l QCanBusDevice::CanFdKey. Frames of type \l RemoteRequestFrame (RTR) do not have a payload. However they have to @@ -105,8 +108,7 @@ QT_BEGIN_NAMESPACE frame.setPayload(QByteArray(expectedResponseLength, 0)); \endcode - - \sa payload() + \sa payload(), hasFlexibleDataRateFormat() */ /*! @@ -235,6 +237,25 @@ QT_BEGIN_NAMESPACE */ /*! + \fn bool QCanBusFrame::hasFlexibleDataRateFormat() const + + Returns \c true if the CAN frame uses \e {Flexible Data-Rate} which allows up to 64 data bytes, + otherwise \c false, implying at most 8 byte of payload. + + \sa setFlexibleDataRateFormat(), payload() +*/ + +/*! + \fn void QCanBusFrame::setFlexibleDataRateFormat(bool isFlexibleData) + + Sets the \e {Flexible Data-Rate} flag to \a isFlexibleData. Those frames can be sent using + a higher speed on supporting controllers. Additionally the payload length limit is raised to + 64 byte. + + \sa hasFlexibleDataRateFormat() +*/ + +/*! \class QCanBusFrame::TimeStamp \inmodule QtSerialBus \since 5.6 @@ -310,7 +331,7 @@ QString QCanBusFrame::toString() const return QStringLiteral("(Unknown)"); const char *idFormat = hasExtendedFrameFormat() ? "%08X" : " %03X"; - const char *dlcFormat = payload().size() < 10 ? " [%d]" : " [%d]"; + const char *dlcFormat = hasFlexibleDataRateFormat() ? " [%02d]" : " [%d]"; QString result; result.append(QString::asprintf(idFormat, static_cast<uint>(frameId()))); result.append(QString::asprintf(dlcFormat, payload().size())); @@ -345,6 +366,7 @@ QDataStream &operator<<(QDataStream &out, const QCanBusFrame &frame) out << static_cast<quint8>(frame.frameType()); out << static_cast<quint8>(frame.version); out << frame.hasExtendedFrameFormat(); + out << frame.hasFlexibleDataRateFormat(); out << frame.payload(); const QCanBusFrame::TimeStamp stamp = frame.timeStamp(); out << stamp.seconds(); @@ -363,11 +385,12 @@ QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame) quint8 frameType; quint8 version; bool extendedFrameFormat; + bool flexibleDataRate; QByteArray payload; qint64 seconds; qint64 microSeconds; - in >> frameId >> frameType >> version >> extendedFrameFormat + in >> frameId >> frameType >> version >> extendedFrameFormat >> flexibleDataRate >> payload >> seconds >> microSeconds; frame.setFrameId(frameId); @@ -375,6 +398,7 @@ QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame) frame.setFrameType(static_cast<QCanBusFrame::FrameType>(frameType)); frame.setExtendedFrameFormat(extendedFrameFormat); + frame.setFlexibleDataRateFormat(flexibleDataRate); frame.setPayload(payload); frame.setTimeStamp(QCanBusFrame::TimeStamp(seconds, microSeconds)); diff --git a/src/serialbus/qcanbusframe.h b/src/serialbus/qcanbusframe.h index 1fae2e4..7f3a2be 100644 --- a/src/serialbus/qcanbusframe.h +++ b/src/serialbus/qcanbusframe.h @@ -74,7 +74,8 @@ public: explicit QCanBusFrame(FrameType type = DataFrame) Q_DECL_NOTHROW : isExtendedFrame(0x0), - version(0x0) + version(0x0), + isFlexibleDataRate(0x0) { setFrameId(0x0); setFrameType(type); @@ -102,9 +103,9 @@ public: format(DataFrame), isExtendedFrame(0x0), version(0x0), + isFlexibleDataRate(data.length() > 8 ? 0x1 : 0x0), load(data) { - Q_UNUSED(extra); Q_UNUSED(reserved); setFrameId(identifier); @@ -122,9 +123,16 @@ public: if (!isValidFrameId) return false; - // maximum permitted payload size in CAN FD - if (load.length() > 64) - return false; + // maximum permitted payload size in CAN or CAN FD + if (isFlexibleDataRate) { + if (load.length() > 64) + return false; + if (format == RemoteRequestFrame) + return false; + } else { + if (load.length() > 8) + return false; + } return true; } @@ -182,7 +190,12 @@ public: } } - void setPayload(const QByteArray &data) { load = data; } + void setPayload(const QByteArray &data) + { + load = data; + if (data.length() > 8) + isFlexibleDataRate = 0x1; + } void setTimeStamp(TimeStamp ts) Q_DECL_NOTHROW { stamp = ts; } QByteArray payload() const { return load; } @@ -204,6 +217,12 @@ public: QString toString() const; + bool hasFlexibleDataRateFormat() const Q_DECL_NOTHROW { return (isFlexibleDataRate & 0x1); } + void setFlexibleDataRateFormat(bool isFlexibleData) Q_DECL_NOTHROW + { + isFlexibleDataRate = (isFlexibleData & 0x1); + } + #ifndef QT_NO_DATASTREAM friend Q_SERIALBUS_EXPORT QDataStream &operator<<(QDataStream &, const QCanBusFrame &); friend Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &, QCanBusFrame &); @@ -216,7 +235,7 @@ private: quint8 isExtendedFrame:1; quint8 version:5; quint8 isValidFrameId:1; - quint8 extra: 1; // unused + quint8 isFlexibleDataRate:1; // reserved for future use quint8 reserved[3]; diff --git a/src/tools/canbusutil/canbusutil.cpp b/src/tools/canbusutil/canbusutil.cpp index 9c8995d..d614583 100644 --- a/src/tools/canbusutil/canbusutil.cpp +++ b/src/tools/canbusutil/canbusutil.cpp @@ -97,11 +97,8 @@ bool CanBusUtil::parseDataField(qint32 &id, QString &payload) return true; } -bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame, - bool &fdFrame) +bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame) { - fdFrame = false; - if (!payload.isEmpty() && payload.at(0).toUpper() == 'R') { bool validPayloadLength = false; @@ -127,7 +124,7 @@ bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame, return validPayloadLength; } else if (!payload.isEmpty() && payload.at(0) == '#') { - fdFrame = true; + frame->setFlexibleDataRateFormat(true); payload = payload.mid(1); } @@ -144,7 +141,7 @@ bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame, QByteArray bytes = QByteArray::fromHex(payload.toLatin1()); - const int maxSize = fdFrame ? 64 : 8; + const int maxSize = frame->hasFlexibleDataRateFormat() ? 64 : 8; if (bytes.size() > maxSize) { m_output << "Warning: Truncating payload at max. size of " << maxSize << " bytes." << endl; bytes.truncate(maxSize); @@ -182,13 +179,12 @@ bool CanBusUtil::sendData() { qint32 id; QString payload; - bool fdFrame; QCanBusFrame frame; if (parseDataField(id, payload) == false) return false; - if (setFrameFromPayload(payload, &frame, fdFrame) == false) + if (setFrameFromPayload(payload, &frame) == false) return false; if (id < 0 || id > 0x1FFFFFFF) { // 29 bits @@ -198,7 +194,7 @@ bool CanBusUtil::sendData() frame.setFrameId(id); - if (fdFrame) + if (frame.hasFlexibleDataRateFormat()) m_canDevice->setConfigurationParameter(QCanBusDevice::CanFdKey, true); return m_canDevice->writeFrame(frame); diff --git a/src/tools/canbusutil/canbusutil.h b/src/tools/canbusutil/canbusutil.h index dd1ce26..e17fe7b 100644 --- a/src/tools/canbusutil/canbusutil.h +++ b/src/tools/canbusutil/canbusutil.h @@ -62,7 +62,7 @@ public: private: bool parseDataField(qint32 &id, QString &payload); - bool setFrameFromPayload(QString payload, QCanBusFrame *frame, bool &fdFrame); + bool setFrameFromPayload(QString payload, QCanBusFrame *frame); bool connectCanDevice(); bool startListeningOnCanDevice(); bool sendData(); diff --git a/tests/auto/qcanbusframe/tst_qcanbusframe.cpp b/tests/auto/qcanbusframe/tst_qcanbusframe.cpp index 56fe064..78f35da 100644 --- a/tests/auto/qcanbusframe/tst_qcanbusframe.cpp +++ b/tests/auto/qcanbusframe/tst_qcanbusframe.cpp @@ -70,31 +70,39 @@ void tst_QCanBusFrame::constructors() QCanBusFrame frame1; QCanBusFrame frame2(123, "tst"); QCanBusFrame frame3(123456, "tst"); + QCanBusFrame frame4(1234, "tst tst tst"); QCanBusFrame::TimeStamp timeStamp1; QCanBusFrame::TimeStamp timeStamp2(5, 5); QVERIFY(frame1.payload().isEmpty()); QVERIFY(!frame1.frameId()); + QVERIFY(!frame1.hasFlexibleDataRateFormat()); + QVERIFY(!frame1.hasExtendedFrameFormat()); + QCOMPARE(frame1.frameType(), QCanBusFrame::DataFrame); QVERIFY(!frame2.payload().isEmpty()); QVERIFY(frame2.frameId()); + QVERIFY(!frame2.hasFlexibleDataRateFormat()); + QVERIFY(!frame2.hasExtendedFrameFormat()); + QCOMPARE(frame2.frameType(), QCanBusFrame::DataFrame); QVERIFY(!frame3.payload().isEmpty()); QVERIFY(frame3.frameId()); + QVERIFY(!frame3.hasFlexibleDataRateFormat()); + QVERIFY(frame3.hasExtendedFrameFormat()); + QCOMPARE(frame3.frameType(), QCanBusFrame::DataFrame); + + QVERIFY(!frame4.payload().isEmpty()); + QVERIFY(frame4.frameId()); + QVERIFY(frame4.hasFlexibleDataRateFormat()); + QVERIFY(!frame4.hasExtendedFrameFormat()); + QCOMPARE(frame4.frameType(), QCanBusFrame::DataFrame); QVERIFY(!timeStamp1.seconds()); QVERIFY(!timeStamp1.microSeconds()); QVERIFY(timeStamp2.seconds()); QVERIFY(timeStamp2.microSeconds()); - - QVERIFY(frame1.hasExtendedFrameFormat() == false); - QVERIFY(frame2.hasExtendedFrameFormat() == false); - QVERIFY(frame3.hasExtendedFrameFormat() == true); - - QCOMPARE(frame1.frameType(), QCanBusFrame::DataFrame); - QCOMPARE(frame2.frameType(), QCanBusFrame::DataFrame); - QCOMPARE(frame3.frameType(), QCanBusFrame::DataFrame); } void tst_QCanBusFrame::id() @@ -138,6 +146,15 @@ void tst_QCanBusFrame::payload() QVERIFY(frame.payload().isEmpty()); frame.setPayload("test"); QCOMPARE(frame.payload().data(), "test"); + QVERIFY(!frame.hasFlexibleDataRateFormat()); + // setting long payload should automatically set hasFlexibleDataRateFormat() + frame.setPayload("testtesttest"); + QCOMPARE(frame.payload().data(), "testtesttest"); + QVERIFY(frame.hasFlexibleDataRateFormat()); + // setting short payload should not change hasFlexibleDataRateFormat() + frame.setPayload("test"); + QCOMPARE(frame.payload().data(), "test"); + QVERIFY(frame.hasFlexibleDataRateFormat()); } void tst_QCanBusFrame::timeStamp() @@ -170,40 +187,53 @@ void tst_QCanBusFrame::tst_isValid_data() QTest::addColumn<QByteArray>("payload"); QTest::addColumn<uint>("id"); QTest::addColumn<bool>("extended"); + QTest::addColumn<bool>("flexibleData"); QTest::newRow("invalid frame") << QCanBusFrame::InvalidFrame << false - << QByteArray() << 0u << false; + << QByteArray() << 0u << false << false; QTest::newRow("data frame") << QCanBusFrame::DataFrame << true - << QByteArray() << 0u << false; + << QByteArray() << 0u << false << false; QTest::newRow("error frame") << QCanBusFrame::ErrorFrame << true - << QByteArray() << 0u << false; + << QByteArray() << 0u << false << false; QTest::newRow("remote request frame") << QCanBusFrame::RemoteRequestFrame << true - << QByteArray() << 0u << false; + << QByteArray() << 0u << false << false; + QTest::newRow("remote request CAN FD frame") + << QCanBusFrame::RemoteRequestFrame << false + << QByteArray() << 0u << false << true; QTest::newRow("unknown frame") << QCanBusFrame::UnknownFrame << true - << QByteArray() << 0u << false; + << QByteArray() << 0u << false << false; QTest::newRow("data frame CAN max payload") << QCanBusFrame::DataFrame << true - << QByteArray(8, 0) << 0u << false; + << QByteArray(8, 0) << 0u << false << false; QTest::newRow("data frame CAN FD max payload") << QCanBusFrame::DataFrame << true - << QByteArray(64, 0) << 0u << false; + << QByteArray(64, 0) << 0u << false << true; QTest::newRow("data frame CAN too much payload") << QCanBusFrame::DataFrame << false - << QByteArray(65, 0) << 0u << false; + << QByteArray(65, 0) << 0u << false << false; QTest::newRow("data frame short id") << QCanBusFrame::DataFrame << true - << QByteArray(8, 0) << (1u << 11) - 1 << false; + << QByteArray(8, 0) << (1u << 11) - 1 << false << false; QTest::newRow("data frame long id") << QCanBusFrame::DataFrame << true - << QByteArray(8, 0) << (1u << 11) << true; + << QByteArray(8, 0) << (1u << 11) << true << false; QTest::newRow("data frame bad long id") << QCanBusFrame::DataFrame << false - << QByteArray(8, 0) << (1u << 11) << false; + << QByteArray(8, 0) << (1u << 11) << false << false; + QTest::newRow("data frame CAN too long payload") + << QCanBusFrame::DataFrame << false + << QByteArray(9, 0) << 512u << false << false; + QTest::newRow("data frame CAN FD long payload") + << QCanBusFrame::DataFrame << true + << QByteArray(9, 0) << 512u << false << true; + QTest::newRow("data frame CAN FD too long payload") + << QCanBusFrame::DataFrame << false + << QByteArray(65, 0) << 512u << false << true; } void tst_QCanBusFrame::tst_isValid() @@ -213,16 +243,19 @@ void tst_QCanBusFrame::tst_isValid() QFETCH(QByteArray, payload); QFETCH(uint, id); QFETCH(bool, extended); + QFETCH(bool, flexibleData); QCanBusFrame frame(frameType); frame.setPayload(payload); frame.setFrameId(id); frame.setExtendedFrameFormat(extended); + frame.setFlexibleDataRateFormat(flexibleData); QCOMPARE(frame.isValid(), isValid); QCOMPARE(frame.frameType(), frameType); QCOMPARE(frame.payload(), payload); QCOMPARE(frame.frameId(), id); QCOMPARE(frame.hasExtendedFrameFormat(), extended); + QCOMPARE(frame.hasFlexibleDataRateFormat(), flexibleData); frame.setFrameType(QCanBusFrame::InvalidFrame); QCOMPARE(frame.isValid(), false); @@ -280,7 +313,7 @@ void tst_QCanBusFrame::tst_toString_data() QTest::newRow("short data frame FD") << QCanBusFrame::DataFrame << 0x123u << false << QByteArray::fromHex("001122334455667788") - << QString(" 123 [9] 00 11 22 33 44 55 66 77 88"); + << QString(" 123 [09] 00 11 22 33 44 55 66 77 88"); QTest::newRow("long data frame FD") << QCanBusFrame::DataFrame << 0x123u << false << QByteArray::fromHex("00112233445566778899") @@ -312,30 +345,34 @@ void tst_QCanBusFrame::streaming_data() QTest::addColumn<qint64>("seconds"); QTest::addColumn<qint64>("microSeconds"); QTest::addColumn<bool>("isExtended"); + QTest::addColumn<bool>("isFlexibleDataRate"); QTest::addColumn<QCanBusFrame::FrameType>("frameType"); QTest::newRow("emptyFrame") << quint32(0) << QByteArray() << qint64(0) << qint64(0) - << false << QCanBusFrame::DataFrame; + << false << false << QCanBusFrame::DataFrame; QTest::newRow("fullFrame1") << quint32(123) << QByteArray("abcde1") << qint64(456) << qint64(784) - << true << QCanBusFrame::DataFrame; + << true << false << QCanBusFrame::DataFrame; QTest::newRow("fullFrame2") << quint32(123) << QByteArray("abcde2") << qint64(457) << qint64(785) - << false << QCanBusFrame::DataFrame; + << false << false << QCanBusFrame::DataFrame; + QTest::newRow("fullFrameFD") << quint32(123) << QByteArray("abcdfd") + << qint64(457) << qint64(785) + << false << true << QCanBusFrame::DataFrame; QTest::newRow("fullFrame3") << quint32(123) << QByteArray("abcde3") << qint64(458) << qint64(786) - << true << QCanBusFrame::RemoteRequestFrame; + << true << false << QCanBusFrame::RemoteRequestFrame; QTest::newRow("fullFrame4") << quint32(123) << QByteArray("abcde4") << qint64(459) << qint64(787) - << false << QCanBusFrame::RemoteRequestFrame; + << false << false << QCanBusFrame::RemoteRequestFrame; QTest::newRow("fullFrame5") << quint32(123) << QByteArray("abcde5") << qint64(460) << qint64(789) - << true << QCanBusFrame::ErrorFrame; + << true << false << QCanBusFrame::ErrorFrame; QTest::newRow("fullFrame6") << quint32(123) << QByteArray("abcde6") << qint64(453) << qint64(788) - << false << QCanBusFrame::ErrorFrame; + << false << false << QCanBusFrame::ErrorFrame; } void tst_QCanBusFrame::streaming() @@ -345,6 +382,7 @@ void tst_QCanBusFrame::streaming() QFETCH(qint64, seconds); QFETCH(qint64, microSeconds); QFETCH(bool, isExtended); + QFETCH(bool, isFlexibleDataRate); QFETCH(QCanBusFrame::FrameType, frameType); QCanBusFrame originalFrame(frameId, payload); @@ -352,6 +390,7 @@ void tst_QCanBusFrame::streaming() originalFrame.setTimeStamp(originalStamp); originalFrame.setExtendedFrameFormat(isExtended); + originalFrame.setFlexibleDataRateFormat(isFlexibleDataRate); originalFrame.setFrameType(frameType); QByteArray buffer; @@ -372,6 +411,8 @@ void tst_QCanBusFrame::streaming() QCOMPARE(restoredFrame.frameType(), originalFrame.frameType()); QCOMPARE(restoredFrame.hasExtendedFrameFormat(), originalFrame.hasExtendedFrameFormat()); + QCOMPARE(restoredFrame.hasFlexibleDataRateFormat(), + originalFrame.hasFlexibleDataRateFormat()); } void tst_QCanBusFrame::tst_error() |