diff options
author | Andy Shaw <andy.shaw@qt.io> | 2019-11-14 09:57:49 +0100 |
---|---|---|
committer | Andy Shaw <andy.shaw@qt.io> | 2020-02-13 14:37:36 +0100 |
commit | 421dad73cc993f2af4573a709607690feb28729b (patch) | |
tree | 964195cdb9c450f99e4cec77ae86377c4f06c5e1 | |
parent | 8c2a9138ffb00fdab49ab3ef128e4b1c92eb880c (diff) |
VectorCAN: Add support for using CAN FD
[ChangeLog][VectorCAN] Added CAN FD support to the VectorCAN plugin.
Change-Id: I7e72dafd13bb16b2db636a133502f0bdbc7a2ba6
Reviewed-by: André Hartmann <aha_1980@gmx.de>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
-rw-r--r-- | src/plugins/canbus/vectorcan/vectorcan_symbols_p.h | 125 | ||||
-rw-r--r-- | src/plugins/canbus/vectorcan/vectorcanbackend.cpp | 287 | ||||
-rw-r--r-- | src/plugins/canbus/vectorcan/vectorcanbackend_p.h | 5 | ||||
-rw-r--r-- | src/serialbus/doc/src/vectorcan.qdoc | 9 |
4 files changed, 346 insertions, 80 deletions
diff --git a/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h b/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h index 9d6e841..4e8c9d4 100644 --- a/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h +++ b/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h @@ -228,6 +228,8 @@ typedef HANDLE XLhandle; #define XL_EVENT_FLAG_OVERRUN 0x01 // Used in XLevent.flags +#define XL_CAN_MAX_DATA_LEN 64 + // structure for XL_RECEIVE_MSG, XL_TRANSMIT_MSG (32 bytes) struct s_xl_can_msg { unsigned long id; @@ -256,6 +258,9 @@ static_assert(sizeof(s_xl_can_msg) == 32, "Invalid size of s_xl_can_msg structur #define XL_CAN_STATE_FLAG_SJA_MODE 0x00000001 +#define XL_CANFD_RX_EVENT_HEADER_SIZE 32 +#define XL_CANFD_MAX_EVENT_SIZE 128 + // CAN Chip status struct s_xl_chip_state { unsigned char busStatus; @@ -285,6 +290,86 @@ typedef struct s_xl_event { } XLevent; static_assert(sizeof(s_xl_event) == 48, "Invalid size of s_xl_event structure"); +typedef struct { + quint32 id; + quint32 flags; + quint32 crc; + quint8 reserved1[12]; + quint16 totalBitCnt; + quint8 dlc; + quint8 reserved[5]; + quint8 data[XL_CAN_MAX_DATA_LEN]; +} XL_CAN_EV_RX_MSG; + +typedef struct { + quint32 canId; + quint32 msgFlags; + quint8 dlc; + quint8 reserved1; + quint16 reserved; + quint8 data[XL_CAN_MAX_DATA_LEN]; +} XL_CAN_EV_TX_REQUEST; + +typedef struct { + quint8 errorCode; + quint8 reserved[95]; +} XL_CAN_EV_ERROR; + +typedef struct { + quint8 busStatus; + quint8 txErrorCounter; + quint8 rxErrorCounter; + quint8 reserved; + quint32 reserved0; +} XL_CAN_EV_CHIP_STATE; + +typedef struct s_xl_sync_pulse_ev { + quint32 triggerSource; + quint32 reserved; + quint64 time; +} XL_SYNC_PULSE_EV; + +typedef XL_SYNC_PULSE_EV XL_CAN_EV_SYNC_PULSE; + +typedef struct { + quint32 size; + quint16 tag; + quint16 channelIndex; + quint32 userHandle; + quint16 flagsChip; + quint16 reserved0; + quint64 reserved1; + quint64 timeStamp; + union { + quint8 raw[XL_CANFD_MAX_EVENT_SIZE - XL_CANFD_RX_EVENT_HEADER_SIZE]; + XL_CAN_EV_RX_MSG canRxOkMsg; + XL_CAN_EV_RX_MSG canTxOkMsg; + XL_CAN_EV_TX_REQUEST canTxRequest; + XL_CAN_EV_ERROR canError; + XL_CAN_EV_CHIP_STATE canChipState; + XL_CAN_EV_SYNC_PULSE canSyncPulse; + } tagData; +} XLcanRxEvent; + +typedef struct { + quint32 id; + quint32 flags; + quint16 dlc; + quint16 reserved[7]; + quint16 data[XL_CAN_MAX_DATA_LEN]; +} XL_CAN_TX_MSG; + +typedef struct { + quint32 tag; + quint32 transId; + quint32 channelIndex; + quint32 reserved[3]; + union { + XL_CAN_TX_MSG canMsg; + } tagData; +} XLcanTxEvent; + + // build a channels mask from the channels index #define XL_CHANNEL_MASK(x) (quint64(1) << (x)) @@ -354,6 +439,22 @@ typedef qint16 XLstatus; #define XL_CAN_STD 01 // flag for standard ID's #define XL_CAN_EXT 02 // flag for extended ID's +#define XL_CAN_TXMSG_FLAG_EDL 0x0001 // extended data length +#define XL_CAN_TXMSG_FLAG_BRS 0x0002 // baud rate switch +#define XL_CAN_TXMSG_FLAG_RTR 0x0010 // remote transmission request +#define XL_CAN_TXMSG_FLAG_HIGHPRIO 0x0080 // high priority message - clears all send buffers - then transmits +#define XL_CAN_TXMSG_FLAG_WAKEUP 0x0200 // generate a wakeup message + +#define XL_CAN_RXMSG_FLAG_EDL 0x0001 // extended data length +#define XL_CAN_RXMSG_FLAG_BRS 0x0002 // baud rate switch +#define XL_CAN_RXMSG_FLAG_ESI 0x0004 // error state indicator +#define XL_CAN_RXMSG_FLAG_RTR 0x0010 // remote transmission request +#define XL_CAN_RXMSG_FLAG_EF 0x0200 // error frame (only posssible in XL_CAN_EV_TX_REQUEST/XL_CAN_EV_TX_REMOVED) +#define XL_CAN_RXMSG_FLAG_ARB_LOST 0x0400 // Arbitration Lost + // set if the receiving node tried to transmit a message but lost arbitration process +#define XL_CAN_RXMSG_FLAG_WAKEUP 0x2000 // high voltage message on single wire CAN +#define XL_CAN_RXMSG_FLAG_TE 0x4000 // 1: transceiver error detected + typedef struct { quint32 busType; union { @@ -447,6 +548,21 @@ typedef struct _XLacceptance { XLaccFilt xtd; } XLacceptance; +typedef struct s_XLcanFdConf { + unsigned int arbitrationBitRate; + unsigned int sjwAbr; + unsigned int tseg1Abr; + unsigned int tseg2Abr; + unsigned int dataBitRate; + unsigned int sjwDbr; + unsigned int tseg1Dbr; + unsigned int tseg2Dbr; + unsigned char reserved; + unsigned char options; + unsigned char reserved1[2]; + unsigned int reserved2; +} XLcanFdConf; + // defines for xlSetGlobalTimeSync #define XL_SET_TIMESYNC_NO_CHANGE ((unsigned long)0) #define XL_SET_TIMESYNC_ON ((unsigned long)1) @@ -476,6 +592,10 @@ GENERATE_SYMBOL_VARIABLE(XLstatus, xlReceive, XLportHandle, quint32 *, XLevent * GENERATE_SYMBOL_VARIABLE(XLstatus, xlSetNotification, XLportHandle, XLhandle *, int) GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanRequestChipState, XLportHandle, XLaccess) GENERATE_SYMBOL_VARIABLE(char *, xlGetErrorString, XLstatus) +GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanFdSetConfiguration, XLportHandle, XLaccess, XLcanFdConf *) +GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanReceive, XLportHandle, XLcanRxEvent *) +GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanTransmitEx, XLportHandle, XLaccess, quint32, quint32 *, XLcanTxEvent *) +GENERATE_SYMBOL_VARIABLE(XLaccess, xlGetChannelMask, int, int, int) inline bool resolveVectorCanSymbols(QLibrary *vectorcanLibrary) { @@ -502,7 +622,10 @@ inline bool resolveVectorCanSymbols(QLibrary *vectorcanLibrary) RESOLVE_SYMBOL(xlSetNotification) RESOLVE_SYMBOL(xlCanRequestChipState) RESOLVE_SYMBOL(xlGetErrorString) - + RESOLVE_SYMBOL(xlCanFdSetConfiguration) + RESOLVE_SYMBOL(xlCanTransmitEx) + RESOLVE_SYMBOL(xlCanReceive) + RESOLVE_SYMBOL(xlGetChannelMask) return true; } diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend.cpp b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp index 0382d66..c4d87e2 100644 --- a/src/plugins/canbus/vectorcan/vectorcanbackend.cpp +++ b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp @@ -170,12 +170,19 @@ bool VectorCanBackendPrivate::open() Q_Q(VectorCanBackend); { + XLdriverConfig config; + if (Q_UNLIKELY(::xlGetDriverConfig(&config) != XL_SUCCESS)) { + q->setError(VectorCanBackend::tr("Unable to get driver configuration"), + QCanBusDevice::CanBusError::ConnectionError); + return false; + } + channelMask = config.channel[channelIndex].channelMask; XLaccess permissionMask = channelMask; - const quint32 queueSize = 256; + const quint32 queueSize = usesCanFd ? 8192 : 256; const XLstatus status = ::xlOpenPort(&portHandle, const_cast<char *>(qPrintable(qApp->applicationName())), channelMask, &permissionMask, queueSize, - XL_INTERFACE_VERSION, XL_BUS_TYPE_CAN); + usesCanFd ? XL_INTERFACE_VERSION_V4 : XL_INTERFACE_VERSION, XL_BUS_TYPE_CAN); if (Q_UNLIKELY(status != XL_SUCCESS || portHandle == XL_INVALID_PORTHANDLE)) { q->setError(systemErrorString(status), QCanBusDevice::ConnectionError); @@ -183,6 +190,17 @@ bool VectorCanBackendPrivate::open() return false; } } + if (usesCanFd && arbBitRate != 0) { + XLcanFdConf xlfdconf; + ::memset(&xlfdconf, 0, sizeof(xlfdconf)); + xlfdconf.dataBitRate = (dataBitRate != 0) ? dataBitRate : arbBitRate; + xlfdconf.arbitrationBitRate = arbBitRate; + + const XLstatus status = ::xlCanFdSetConfiguration(portHandle, channelMask, &xlfdconf); + if (Q_UNLIKELY(status != XL_SUCCESS)) + qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, + "Unable to change the configuration for an open channel"); + } { const XLstatus status = ::xlActivateChannel(portHandle, channelMask, @@ -252,6 +270,25 @@ bool VectorCanBackendPrivate::setConfigurationParameter(int key, const QVariant case QCanBusDevice::ReceiveOwnKey: transmitEcho = value.toBool(); return true; + case QCanBusDevice::DataBitRateKey: + return setDataBitRate(value.toUInt()); + case QCanBusDevice::CanFdKey: + { + if (value.toBool()) { + XLdriverConfig config; + if (Q_UNLIKELY(::xlGetDriverConfig(&config) == XL_SUCCESS)) { + if (config.channel[channelIndex].channelCapabilities & XL_CHANNEL_FLAG_CANFD_SUPPORT) { + usesCanFd = true; + return true; + } + } + q->setError(VectorCanBackend::tr("Unable to set CAN FD"), + QCanBusDevice::CanBusError::ConfigurationError); + return false; + } + usesCanFd = false; + return true; + } default: q->setError(VectorCanBackend::tr("Unsupported configuration key"), QCanBusDevice::ConfigurationError); @@ -261,13 +298,18 @@ bool VectorCanBackendPrivate::setConfigurationParameter(int key, const QVariant void VectorCanBackendPrivate::setupChannel(const QString &interfaceName) { + Q_Q(VectorCanBackend); if (Q_LIKELY(interfaceName.startsWith(QStringLiteral("can")))) { const QStringRef ref = interfaceName.midRef(3); bool ok = false; - const int channelIndex = ref.toInt(&ok); + channelIndex = ref.toInt(&ok); if (ok && (channelIndex >= 0 && channelIndex < XL_CONFIG_MAX_CHANNELS)) { - channelMask = XL_CHANNEL_MASK((channelIndex)); + channelMask = xlGetChannelMask(-1, channelIndex, 0); return; + } else { + channelIndex = -1; + q->setError(VectorCanBackend::tr("Unable to setup channel with interface name %1") + .arg(interfaceName), QCanBusDevice::CanBusError::ConfigurationError); } } @@ -302,29 +344,49 @@ void VectorCanBackendPrivate::startWrite() const QCanBusFrame frame = q->dequeueOutgoingFrame(); const QByteArray payload = frame.payload(); - XLevent event; - ::memset(&event, 0, sizeof(event)); + quint32 eventCount = 1; + XLstatus status = XL_ERROR; + if (usesCanFd) { + XLcanTxEvent event; + ::memset(&event, 0, sizeof(event)); - event.tag = XL_TRANSMIT_MSG; + event.tag = XL_CAN_EV_TAG_TX_MSG; + XL_CAN_TX_MSG &msg = event.tagData.canMsg; - s_xl_can_msg &msg = event.tagData.msg; + msg.id = frame.frameId(); + if (frame.hasExtendedFrameFormat()) + msg.id |= XL_CAN_EXT_MSG_ID; - msg.id = frame.frameId(); - if (frame.hasExtendedFrameFormat()) - msg.id |= XL_CAN_EXT_MSG_ID; + msg.dlc = payload.size(); + if (frame.hasFlexibleDataRateFormat()) + msg.flags = XL_CAN_TXMSG_FLAG_EDL; + if (frame.frameType() == QCanBusFrame::RemoteRequestFrame) + msg.flags |= XL_CAN_TXMSG_FLAG_RTR; // we do not care about the payload + else + ::memcpy(msg.data, payload.constData(), sizeof(msg.data)); - msg.dlc = payload.size(); + status = ::xlCanTransmitEx(portHandle, channelMask, eventCount, &eventCount, &event); + } else { + XLevent event; + ::memset(&event, 0, sizeof(event)); + event.tag = XL_TRANSMIT_MSG; + s_xl_can_msg &msg = event.tagData.msg; - if (frame.frameType() == QCanBusFrame::RemoteRequestFrame) - msg.flags |= XL_CAN_MSG_FLAG_REMOTE_FRAME; // we do not care about the payload - else if (frame.frameType() == QCanBusFrame::ErrorFrame) - msg.flags |= XL_CAN_MSG_FLAG_ERROR_FRAME; // we do not care about the payload - else - ::memcpy(msg.data, payload.constData(), sizeof(msg.data)); + msg.id = frame.frameId(); + if (frame.hasExtendedFrameFormat()) + msg.id |= XL_CAN_EXT_MSG_ID; - quint32 eventCount = 1; - const XLstatus status = ::xlCanTransmit(portHandle, channelMask, - &eventCount, &event); + msg.dlc = payload.size(); + + if (frame.frameType() == QCanBusFrame::RemoteRequestFrame) + msg.flags |= XL_CAN_MSG_FLAG_REMOTE_FRAME; // we do not care about the payload + else if (frame.frameType() == QCanBusFrame::ErrorFrame) + msg.flags |= XL_CAN_MSG_FLAG_ERROR_FRAME; // we do not care about the payload + else + ::memcpy(msg.data, payload.constData(), sizeof(msg.data)); + + status = ::xlCanTransmit(portHandle, channelMask, &eventCount, &event); + } if (Q_UNLIKELY(status != XL_SUCCESS)) { q->setError(systemErrorString(status), QCanBusDevice::WriteError); @@ -344,38 +406,66 @@ void VectorCanBackendPrivate::startRead() for (;;) { quint32 eventCount = 1; - XLevent event; - ::memset(&event, 0, sizeof(event)); - - const XLstatus status = ::xlReceive(portHandle, &eventCount, &event); - if (Q_UNLIKELY(status != XL_SUCCESS)) { - if (status != XL_ERR_QUEUE_IS_EMPTY) { - q->setError(systemErrorString(status), - QCanBusDevice::ReadError); + if (usesCanFd) { + XLcanRxEvent event; + ::memset(&event, 0, sizeof(event)); + + const XLstatus status = ::xlCanReceive(portHandle, &event); + if (Q_UNLIKELY(status != XL_SUCCESS)) { + if (status != XL_ERR_QUEUE_IS_EMPTY) { + q->setError(systemErrorString(status), QCanBusDevice::ReadError); + } + break; } - break; + if (event.tag != XL_CAN_EV_TAG_RX_OK) + continue; + + const XL_CAN_EV_RX_MSG &msg = event.tagData.canRxOkMsg; + + QCanBusFrame frame(msg.id & ~XL_CAN_EXT_MSG_ID, + QByteArray(reinterpret_cast<const char *>(msg.data), int(msg.dlc))); + frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(event.timeStamp / 1000)); + frame.setExtendedFrameFormat(msg.id & XL_CAN_RXMSG_FLAG_EDL); + frame.setFrameType((msg.flags & XL_CAN_RXMSG_FLAG_RTR) + ? QCanBusFrame::RemoteRequestFrame + : (msg.flags & XL_CAN_RXMSG_FLAG_EF) + ? QCanBusFrame::ErrorFrame + : QCanBusFrame::DataFrame); + + newFrames.append(std::move(frame)); + } else { + XLevent event; + ::memset(&event, 0, sizeof(event)); + + const XLstatus status = ::xlReceive(portHandle, &eventCount, &event); + if (Q_UNLIKELY(status != XL_SUCCESS)) { + if (status != XL_ERR_QUEUE_IS_EMPTY) { + q->setError(systemErrorString(status), + QCanBusDevice::ReadError); + } + break; + } + if (event.tag != XL_RECEIVE_MSG) + continue; + + const s_xl_can_msg &msg = event.tagData.msg; + + if ((msg.flags & XL_CAN_MSG_FLAG_TX_COMPLETED) && !transmitEcho) + continue; + + QCanBusFrame frame(msg.id & ~XL_CAN_EXT_MSG_ID, + QByteArray(reinterpret_cast<const char *>(msg.data), int(msg.dlc))); + frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(event.timeStamp / 1000)); + frame.setExtendedFrameFormat(msg.id & XL_CAN_EXT_MSG_ID); + frame.setLocalEcho(msg.flags & XL_CAN_MSG_FLAG_TX_COMPLETED); + frame.setFrameType((msg.flags & XL_CAN_MSG_FLAG_REMOTE_FRAME) + ? QCanBusFrame::RemoteRequestFrame + : (msg.flags & XL_CAN_MSG_FLAG_ERROR_FRAME) + ? QCanBusFrame::ErrorFrame + : QCanBusFrame::DataFrame); + + newFrames.append(std::move(frame)); } - - if (event.tag != XL_RECEIVE_MSG) - continue; - - const s_xl_can_msg &msg = event.tagData.msg; - - if ((msg.flags & XL_CAN_MSG_FLAG_TX_COMPLETED) && !transmitEcho) - continue; - - QCanBusFrame frame(msg.id & ~XL_CAN_EXT_MSG_ID, - QByteArray(reinterpret_cast<const char *>(msg.data), int(msg.dlc))); - frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(event.timeStamp / 1000)); - frame.setExtendedFrameFormat(msg.id & XL_CAN_EXT_MSG_ID); - frame.setLocalEcho(msg.flags & XL_CAN_MSG_FLAG_TX_COMPLETED); - frame.setFrameType((msg.flags & XL_CAN_MSG_FLAG_REMOTE_FRAME) - ? QCanBusFrame::RemoteRequestFrame - : (msg.flags & XL_CAN_MSG_FLAG_ERROR_FRAME) - ? QCanBusFrame::ErrorFrame - : QCanBusFrame::DataFrame); - - newFrames.append(std::move(frame)); } q->enqueueReceivedFrames(newFrames); @@ -425,19 +515,40 @@ void VectorCanBackendPrivate::cleanupDriver() bool VectorCanBackendPrivate::setBitRate(quint32 bitrate) { Q_Q(VectorCanBackend); - - if (q->state() != QCanBusDevice::UnconnectedState) { + if (!usesCanFd && q->state() != QCanBusDevice::UnconnectedState) { const XLstatus status = ::xlCanSetChannelBitrate(portHandle, channelMask, bitrate); + arbBitRate = bitrate; if (Q_UNLIKELY(status != XL_SUCCESS)) { q->setError(systemErrorString(status), QCanBusDevice::CanBusError::ConfigurationError); return false; } + } else if (arbBitRate != bitrate) { + arbBitRate = bitrate; } return true; } +bool VectorCanBackendPrivate::setDataBitRate(quint32 bitrate) +{ + if (!usesCanFd) { + qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, + "Cannot set data bit rate in CAN 2.0 mode, this is only available with CAN FD"); + return false; + } + if (dataBitRate != bitrate) { + if (bitrate >= 25000) { // Minimum + dataBitRate = bitrate; + } else { + qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, + "Cannot set data bit rate to less than 25000 which is the minimum"); + return false; + } + } + return true; +} + VectorCanBackend::VectorCanBackend(const QString &name, QObject *parent) : QCanBusDevice(parent) , d_ptr(new VectorCanBackendPrivate(this)) @@ -520,9 +631,8 @@ bool VectorCanBackend::writeFrame(const QCanBusFrame &newData) return false; } - // CAN FD frame format not implemented at this stage - if (Q_UNLIKELY(newData.hasFlexibleDataRateFormat())) { - setError(tr("CAN FD frame format not supported."), + if (!d->usesCanFd && newData.hasFlexibleDataRateFormat()) { + setError(tr("Unable to write a flexible data rate format frame without CAN FD enabled."), QCanBusDevice::WriteError); return false; } @@ -556,34 +666,53 @@ QCanBusDevice::CanBusStatus VectorCanBackend::busStatus() return QCanBusDevice::CanBusStatus::Unknown; } - quint32 eventCount = 1; - XLevent event; - ::memset(&event, 0, sizeof(event)); + quint8 busStatus = 0; + if (d->usesCanFd) { + XLcanRxEvent event; + ::memset(&event, 0, sizeof(event)); - const XLstatus receiveStatus = ::xlReceive(d->portHandle, &eventCount, &event); - if (Q_UNLIKELY(receiveStatus != XL_SUCCESS)) { - const QString errorString = d->systemErrorString(receiveStatus); - qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Can not query CAN bus status: %ls.", - qUtf16Printable(errorString)); - setError(errorString, QCanBusDevice::CanBusError::ReadError); - return QCanBusDevice::CanBusStatus::Unknown; - } + const XLstatus receiveStatus = ::xlCanReceive(d->portHandle, &event); + if (Q_UNLIKELY(receiveStatus != XL_SUCCESS)) { + const QString errorString = d->systemErrorString(receiveStatus); + qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Can not query CAN bus status: %ls.", + qUtf16Printable(errorString)); + setError(errorString, QCanBusDevice::CanBusError::ReadError); + return QCanBusDevice::CanBusStatus::Unknown; + } - if (Q_LIKELY(event.tag == XL_CHIP_STATE)) { - switch (event.tagData.chipState.busStatus) { - case XL_CHIPSTAT_BUSOFF: - return QCanBusDevice::CanBusStatus::BusOff; - case XL_CHIPSTAT_ERROR_PASSIVE: - return QCanBusDevice::CanBusStatus::Error; - case XL_CHIPSTAT_ERROR_WARNING: - return QCanBusDevice::CanBusStatus::Warning; - case XL_CHIPSTAT_ERROR_ACTIVE: - return QCanBusDevice::CanBusStatus::Good; + if (Q_LIKELY(event.tag == XL_CAN_EV_TAG_CHIP_STATE)) + busStatus = event.tagData.canChipState.busStatus; + + } else { + quint32 eventCount = 1; + XLevent event; + ::memset(&event, 0, sizeof(event)); + + const XLstatus receiveStatus = ::xlReceive(d->portHandle, &eventCount, &event); + if (Q_UNLIKELY(receiveStatus != XL_SUCCESS)) { + const QString errorString = d->systemErrorString(receiveStatus); + qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Can not query CAN bus status: %ls.", + qUtf16Printable(errorString)); + setError(errorString, QCanBusDevice::CanBusError::ReadError); + return QCanBusDevice::CanBusStatus::Unknown; } + + if (Q_LIKELY(event.tag == XL_CHIP_STATE)) + busStatus = event.tagData.chipState.busStatus; + } + + switch (busStatus) { + case XL_CHIPSTAT_BUSOFF: + return QCanBusDevice::CanBusStatus::BusOff; + case XL_CHIPSTAT_ERROR_PASSIVE: + return QCanBusDevice::CanBusStatus::Error; + case XL_CHIPSTAT_ERROR_WARNING: + return QCanBusDevice::CanBusStatus::Warning; + case XL_CHIPSTAT_ERROR_ACTIVE: + return QCanBusDevice::CanBusStatus::Good; } - qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Unknown CAN bus status: %u", - uint(event.tagData.chipState.busStatus)); + qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Unknown CAN bus status: %u", busStatus); return QCanBusDevice::CanBusStatus::Unknown; } diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend_p.h b/src/plugins/canbus/vectorcan/vectorcanbackend_p.h index 3eafb0c..b8116a6 100644 --- a/src/plugins/canbus/vectorcan/vectorcanbackend_p.h +++ b/src/plugins/canbus/vectorcan/vectorcanbackend_p.h @@ -81,6 +81,7 @@ public: void startupDriver(); static void cleanupDriver(); bool setBitRate(quint32 bitrate); + bool setDataBitRate(quint32 bitrate); VectorCanBackend * const q_ptr; @@ -90,6 +91,10 @@ public: HANDLE readHandle = INVALID_HANDLE_VALUE; QTimer *writeNotifier = nullptr; QWinEventNotifier *readNotifier = nullptr; + quint32 dataBitRate = 0; + quint32 arbBitRate = 0; + int channelIndex = -1; + bool usesCanFd = false; }; QT_END_NAMESPACE diff --git a/src/serialbus/doc/src/vectorcan.qdoc b/src/serialbus/doc/src/vectorcan.qdoc index 70b6521..0d2921b 100644 --- a/src/serialbus/doc/src/vectorcan.qdoc +++ b/src/serialbus/doc/src/vectorcan.qdoc @@ -105,6 +105,15 @@ bus immediately appear in the receive buffer. This can be used to check if sending was successful. If this option is enabled, the therefore received frames are marked with QCanBusFrame::hasLocalEcho() + \row + \li QCanBusDevice::CanFdKey + \li Enable the use of CAN FD on the CAN bus connection. If this option is enabled, then + it is not possible to receive your own CAN frames being sent, so setting + QCanBusDevice::ReceiveOwnKey to true has no effect. Since Qt 5.15. + \row + \li QCanBusDevice::DataBitRateKey + \li Determines the data bit rate of the CAN bus connection. This is only available when + \l QCanBusDevice::CanFdKey is set to true. Since Qt 5.15. \endtable VectorCAN supports the following additional functions: |