summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/serialbus/can/mainwindow.h2
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend.cpp23
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp39
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.h24
-rw-r--r--src/plugins/canbus/systeccan/systeccanbackend.cpp12
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend.cpp9
-rw-r--r--src/plugins/canbus/vectorcan/vectorcan_symbols_p.h125
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend.cpp284
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend_p.h5
-rw-r--r--src/serialbus/doc/src/vectorcan.qdoc9
-rw-r--r--src/serialbus/qmodbustcpclient_p.h2
12 files changed, 391 insertions, 145 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 16c30a1..96f7a81 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.14.2
+MODULE_VERSION = 5.15.0
diff --git a/examples/serialbus/can/mainwindow.h b/examples/serialbus/can/mainwindow.h
index febe72d..2a7bbf0 100644
--- a/examples/serialbus/can/mainwindow.h
+++ b/examples/serialbus/can/mainwindow.h
@@ -51,7 +51,7 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
-#include <QCanBusDevice> // for CanBusError
+#include <QCanBusDevice>
#include <QMainWindow>
diff --git a/src/plugins/canbus/peakcan/peakcanbackend.cpp b/src/plugins/canbus/peakcan/peakcanbackend.cpp
index 5a17b22..6e1af1c 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend.cpp
+++ b/src/plugins/canbus/peakcan/peakcanbackend.cpp
@@ -344,7 +344,7 @@ bool PeakCanBackendPrivate::open()
if (readHandle == INVALID_HANDLE_VALUE) {
readHandle = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (Q_UNLIKELY(!readHandle)) {
- const QString errorString = qt_error_string(::GetLastError());
+ const QString errorString = qt_error_string(int(::GetLastError()));
qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot create receive event handler: %ls",
qUtf16Printable(errorString));
q->setError(errorString, QCanBusDevice::ConnectionError);
@@ -404,7 +404,7 @@ void PeakCanBackendPrivate::close()
#if defined(Q_OS_WIN32)
if (readHandle && (readHandle != INVALID_HANDLE_VALUE)) {
- const QString errorString = qt_error_string(::GetLastError());
+ const QString errorString = qt_error_string(int(::GetLastError()));
if (Q_UNLIKELY(!::CloseHandle(readHandle))) {
qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot close read handle: %ls",
qUtf16Printable(errorString));
@@ -561,8 +561,7 @@ void PeakCanBackendPrivate::startWrite()
if (isFlexibleDatarateEnabled) {
const int size = payload.size();
- TPCANMsgFD message;
- ::memset(&message, 0, sizeof(message));
+ TPCANMsgFD message = {};
message.ID = frame.frameId();
message.DLC = sizeToDlc(size);
message.MSGTYPE = frame.hasExtendedFrameFormat() ? PCAN_MESSAGE_EXTENDED
@@ -583,9 +582,7 @@ void PeakCanBackendPrivate::startWrite()
qCWarning(QT_CANBUS_PLUGINS_PEAKCAN(), errorString);
q->setError(PeakCanBackend::tr(errorString), QCanBusDevice::WriteError);
} else {
- TPCANMsg message;
- ::memset(&message, 0, sizeof(message));
-
+ TPCANMsg message = {};
message.ID = frame.frameId();
message.LEN = static_cast<quint8>(payload.size());
message.MSGTYPE = frame.hasExtendedFrameFormat() ? PCAN_MESSAGE_EXTENDED
@@ -619,10 +616,8 @@ void PeakCanBackendPrivate::startRead()
for (;;) {
if (isFlexibleDatarateEnabled) {
- TPCANMsgFD message;
- ::memset(&message, 0, sizeof(message));
- TPCANTimestampFD timestamp;
- ::memset(&timestamp, 0, sizeof(timestamp));
+ TPCANMsgFD message = {};
+ TPCANTimestampFD timestamp = {};
const TPCANStatus st = ::CAN_ReadFD(channelIndex, &message, &timestamp);
if (st != PCAN_ERROR_OK) {
@@ -649,10 +644,8 @@ void PeakCanBackendPrivate::startRead()
newFrames.append(std::move(frame));
} else {
- TPCANMsg message;
- ::memset(&message, 0, sizeof(message));
- TPCANTimestamp timestamp;
- ::memset(&timestamp, 0, sizeof(timestamp));
+ TPCANMsg message = {};
+ TPCANTimestamp timestamp = {};
const TPCANStatus st = ::CAN_Read(channelIndex, &message, &timestamp);
if (st != PCAN_ERROR_OK) {
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index 2ed1310..572fef8 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.cpp
+++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp
@@ -56,30 +56,6 @@
#include <sys/ioctl.h>
#include <sys/time.h>
-#ifndef CANFD_MTU
-// CAN FD support was added by Linux kernel 3.6
-// For prior kernels we redefine the missing defines here
-// they are taken from linux/can/raw.h & linux/can.h
-
-enum {
- CAN_RAW_FD_FRAMES = 5
-};
-
-#define CAN_MAX_DLEN 8
-#define CANFD_MAX_DLEN 64
-struct canfd_frame {
- canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
- __u8 len; /* frame payload length in byte */
- __u8 flags; /* additional flags for CAN FD */
- __u8 __res0; /* reserved / padding */
- __u8 __res1; /* reserved / padding */
- __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
-};
-#define CAN_MTU (sizeof(struct can_frame))
-#define CANFD_MTU (sizeof(struct canfd_frame))
-
-#endif
-
#ifndef CANFD_BRS
# define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
#endif
@@ -516,8 +492,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
qint64 bytesWritten = 0;
if (newData.hasFlexibleDataRateFormat()) {
- canfd_frame frame;
- ::memset(&frame, 0, sizeof(frame));
+ canfd_frame frame = {};
frame.len = newData.payload().size();
frame.can_id = canId;
frame.flags = newData.hasBitrateSwitch() ? CANFD_BRS : 0;
@@ -526,8 +501,7 @@ bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
bytesWritten = ::write(canSocket, &frame, sizeof(frame));
} else {
- can_frame frame;
- ::memset(&frame, 0, sizeof(frame));
+ can_frame frame = {};
frame.can_dlc = newData.payload().size();
frame.can_id = canId;
::memcpy(frame.data, newData.payload().constData(), frame.can_dlc);
@@ -714,7 +688,7 @@ void SocketCanBackend::readSocket()
QVector<QCanBusFrame> newFrames;
for (;;) {
- ::memset(&m_frame, 0, sizeof(m_frame));
+ m_frame = {};
m_iov.iov_len = sizeof(m_frame);
m_msg.msg_namelen = sizeof(m_addr);
m_msg.msg_controllen = sizeof(m_ctrlmsg);
@@ -734,11 +708,11 @@ void SocketCanBackend::readSocket()
continue;
}
- struct timeval timeStamp;
+ struct timeval timeStamp = {};
if (Q_UNLIKELY(ioctl(canSocket, SIOCGSTAMP, &timeStamp) < 0)) {
setError(qt_error_string(errno),
QCanBusDevice::CanBusError::ReadError);
- ::memset(&timeStamp, 0, sizeof(timeStamp));
+ timeStamp = {};
}
const QCanBusFrame::TimeStamp stamp(timeStamp.tv_sec, timeStamp.tv_usec);
@@ -778,6 +752,9 @@ void SocketCanBackend::resetController()
bool SocketCanBackend::hasBusStatus() const
{
+ if (isVirtual(canSocketName.toLatin1()))
+ return false;
+
return libSocketCan->hasBusStatus();
}
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.h b/src/plugins/canbus/socketcan/socketcanbackend.h
index 0497244..b6cb5ef 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.h
+++ b/src/plugins/canbus/socketcan/socketcanbackend.h
@@ -54,6 +54,30 @@
#include <memory>
+#ifndef CANFD_MTU
+// CAN FD support was added by Linux kernel 3.6
+// For prior kernels we redefine the missing defines here
+// they are taken from linux/can/raw.h & linux/can.h
+
+enum {
+ CAN_RAW_FD_FRAMES = 5
+};
+
+#define CAN_MAX_DLEN 8
+#define CANFD_MAX_DLEN 64
+struct canfd_frame {
+ canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
+ __u8 len; /* frame payload length in byte */
+ __u8 flags; /* additional flags for CAN FD */
+ __u8 __res0; /* reserved / padding */
+ __u8 __res1; /* reserved / padding */
+ __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
+};
+#define CAN_MTU (sizeof(struct can_frame))
+#define CANFD_MTU (sizeof(struct canfd_frame))
+
+#endif
+
QT_BEGIN_NAMESPACE
class LibSocketCan;
diff --git a/src/plugins/canbus/systeccan/systeccanbackend.cpp b/src/plugins/canbus/systeccan/systeccanbackend.cpp
index a7de557..e5bb09b 100644
--- a/src/plugins/canbus/systeccan/systeccanbackend.cpp
+++ b/src/plugins/canbus/systeccan/systeccanbackend.cpp
@@ -202,8 +202,7 @@ bool SystecCanBackendPrivate::open()
const int bitrate = q->configurationParameter(QCanBusDevice::BitRateKey).toInt();
const bool receiveOwn = q->configurationParameter(QCanBusDevice::ReceiveOwnKey).toBool();
- tUcanInitCanParam param;
- ::memset(&param, 0, sizeof(param));
+ tUcanInitCanParam param = {};
param.m_dwSize = sizeof(param);
param.m_bMode = receiveOwn ? kUcanModeTxEcho : kUcanModeNormal;
param.m_bOCR = USBCAN_OCR_DEFAULT;
@@ -373,8 +372,7 @@ void SystecCanBackendPrivate::startWrite()
const QCanBusFrame frame = q->dequeueOutgoingFrame();
const QByteArray payload = frame.payload();
- tCanMsgStruct message;
- ::memset(&message, 0, sizeof(message));
+ tCanMsgStruct message = {};
message.m_dwID = frame.frameId();
message.m_bDLC = quint8(payload.size());
@@ -403,8 +401,7 @@ void SystecCanBackendPrivate::readAllReceivedMessages()
QVector<QCanBusFrame> newFrames;
for (;;) {
- tCanMsgStruct message;
- ::memset(&message, 0, sizeof(message));
+ tCanMsgStruct message = {};
const UCANRET result = ::UcanReadCanMsgEx(handle, &channel, &message, nullptr);
if (result == USBCAN_WARN_NODATA)
@@ -463,8 +460,7 @@ QCanBusDevice::CanBusStatus SystecCanBackendPrivate::busStatus()
{
Q_Q(SystecCanBackend);
- tStatusStruct status;
- ::memset(&status, 0, sizeof(status));
+ tStatusStruct status = {};
const UCANRET result = ::UcanGetStatus(handle, &status);
if (Q_UNLIKELY(result != USBCAN_SUCCESSFUL)) {
diff --git a/src/plugins/canbus/tinycan/tinycanbackend.cpp b/src/plugins/canbus/tinycan/tinycanbackend.cpp
index fdd5aaa..62da66d 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend.cpp
+++ b/src/plugins/canbus/tinycan/tinycanbackend.cpp
@@ -352,8 +352,7 @@ void TinyCanBackendPrivate::startWrite()
const QCanBusFrame frame = q->dequeueOutgoingFrame();
const QByteArray payload = frame.payload();
- TCanMsg message;
- ::memset(&message, 0, sizeof(message));
+ TCanMsg message = {};
if (Q_UNLIKELY(payload.size() > int(sizeof(message.Data.Bytes)))) {
qCWarning(QT_CANBUS_PLUGINS_TINYCAN, "Cannot write frame with payload size %d.", payload.size());
@@ -389,16 +388,14 @@ void TinyCanBackendPrivate::startRead()
if (!::CanReceiveGetCount(channelIndex))
break;
- TCanMsg message;
- ::memset(&message, 0, sizeof(message));
+ TCanMsg message = {};
const int messagesToRead = 1;
const int ret = ::CanReceive(channelIndex, &message, messagesToRead);
if (Q_UNLIKELY(ret < 0)) {
q->setError(systemErrorString(ret), QCanBusDevice::CanBusError::ReadError);
- TDeviceStatus status;
- ::memset(&status, 0, sizeof(status));
+ TDeviceStatus status = {};
if (::CanGetDeviceStatus(channelIndex, &status) < 0) {
q->setError(systemErrorString(ret), QCanBusDevice::CanBusError::ReadError);
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..550f744 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,16 @@ bool VectorCanBackendPrivate::open()
return false;
}
}
+ if (usesCanFd && arbBitRate != 0) {
+ XLcanFdConf 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 +269,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 +297,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 +343,47 @@ void VectorCanBackendPrivate::startWrite()
const QCanBusFrame frame = q->dequeueOutgoingFrame();
const QByteArray payload = frame.payload();
- XLevent event;
- ::memset(&event, 0, sizeof(event));
-
- event.tag = XL_TRANSMIT_MSG;
-
- s_xl_can_msg &msg = event.tagData.msg;
+ quint32 eventCount = 1;
+ XLstatus status = XL_ERROR;
+ if (usesCanFd) {
+ XLcanTxEvent event = {};
+
+ event.tag = XL_CAN_EV_TAG_TX_MSG;
+ XL_CAN_TX_MSG &msg = event.tagData.canMsg;
+
+ 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));
+
+ status = ::xlCanTransmitEx(portHandle, channelMask, eventCount, &eventCount, &event);
+ } else {
+ XLevent event = {};
+ event.tag = XL_TRANSMIT_MSG;
+ 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();
+ 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));
+ 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));
- quint32 eventCount = 1;
- const XLstatus status = ::xlCanTransmit(portHandle, channelMask,
- &eventCount, &event);
+ status = ::xlCanTransmit(portHandle, channelMask, &eventCount, &event);
+ }
if (Q_UNLIKELY(status != XL_SUCCESS)) {
q->setError(systemErrorString(status),
QCanBusDevice::WriteError);
@@ -344,38 +403,64 @@ 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 = {};
+
+ 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;
+ }
+ 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 = {};
+
+ 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;
}
- 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 +510,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 +626,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 +661,51 @@ 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 = {};
+
+ 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;
+ }
- 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_CAN_EV_TAG_CHIP_STATE))
+ busStatus = event.tagData.canChipState.busStatus;
- 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;
+ } else {
+ quint32 eventCount = 1;
+ XLevent 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:
diff --git a/src/serialbus/qmodbustcpclient_p.h b/src/serialbus/qmodbustcpclient_p.h
index 649b48e..4c574a1 100644
--- a/src/serialbus/qmodbustcpclient_p.h
+++ b/src/serialbus/qmodbustcpclient_p.h
@@ -87,7 +87,7 @@ public:
});
QObject::connect(m_socket,
- QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), q,
+ &QAbstractSocket::errorOccurred, q,
[this](QAbstractSocket::SocketError /*error*/)
{
Q_Q(QModbusTcpClient);