summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Shaw <andy.shaw@qt.io>2019-11-14 09:57:49 +0100
committerAndy Shaw <andy.shaw@qt.io>2020-02-13 14:37:36 +0100
commit421dad73cc993f2af4573a709607690feb28729b (patch)
tree964195cdb9c450f99e4cec77ae86377c4f06c5e1
parent8c2a9138ffb00fdab49ab3ef128e4b1c92eb880c (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.h125
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend.cpp287
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend_p.h5
-rw-r--r--src/serialbus/doc/src/vectorcan.qdoc9
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: