summaryrefslogtreecommitdiffstats
path: root/src/plugins/canbus
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/canbus')
-rw-r--r--src/plugins/canbus/canbus.pro1
-rw-r--r--src/plugins/canbus/peakcan/main.cpp4
-rw-r--r--src/plugins/canbus/peakcan/peakcan_symbols_p.h15
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend.cpp168
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend_p.h3
-rw-r--r--src/plugins/canbus/socketcan/main.cpp3
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp17
-rw-r--r--src/plugins/canbus/tinycan/main.cpp4
-rw-r--r--src/plugins/canbus/tinycan/tinycan_symbols_p.h15
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend.cpp51
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend_p.h2
-rw-r--r--src/plugins/canbus/vectorcan/main.cpp69
-rw-r--r--src/plugins/canbus/vectorcan/plugin.json3
-rw-r--r--src/plugins/canbus/vectorcan/vectorcan.pro19
-rw-r--r--src/plugins/canbus/vectorcan/vectorcan_symbols_p.h484
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend.cpp490
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend.h77
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend_p.h94
18 files changed, 1336 insertions, 183 deletions
diff --git a/src/plugins/canbus/canbus.pro b/src/plugins/canbus/canbus.pro
index 342a8b7..a2e5304 100644
--- a/src/plugins/canbus/canbus.pro
+++ b/src/plugins/canbus/canbus.pro
@@ -5,3 +5,4 @@ config_socketcan {
}
SUBDIRS += peakcan tinycan
+win32:SUBDIRS += vectorcan
diff --git a/src/plugins/canbus/peakcan/main.cpp b/src/plugins/canbus/peakcan/main.cpp
index f76127d..00b4d36 100644
--- a/src/plugins/canbus/peakcan/main.cpp
+++ b/src/plugins/canbus/peakcan/main.cpp
@@ -51,11 +51,13 @@ class PeakCanBusPlugin : public QObject, public QCanBusFactory
public:
- QCanBusDevice *createDevice(const QString &interfaceName) const
+ QCanBusDevice *createDevice(const QString &interfaceName, QString *errorMessage) const override
{
QString errorReason;
if (!PeakCanBackend::canCreate(&errorReason)) {
qWarning("%ls", qUtf16Printable(errorReason));
+ if (errorMessage)
+ *errorMessage = errorReason;
return nullptr;
}
diff --git a/src/plugins/canbus/peakcan/peakcan_symbols_p.h b/src/plugins/canbus/peakcan/peakcan_symbols_p.h
index cb90599..456be17 100644
--- a/src/plugins/canbus/peakcan/peakcan_symbols_p.h
+++ b/src/plugins/canbus/peakcan/peakcan_symbols_p.h
@@ -258,7 +258,7 @@ typedef struct tagTPCANTimestamp
static fp_##symbolName symbolName;
#define RESOLVE_SYMBOL(symbolName) \
- symbolName = (fp_##symbolName)resolveSymbol(pcanLibrary, #symbolName); \
+ symbolName = (fp_##symbolName)pcanLibrary->resolve(#symbolName); \
if (!symbolName) \
return false;
@@ -273,23 +273,12 @@ GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetValue, TPCANHandle, TPCANParameter,
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_SetValue, TPCANHandle, TPCANParameter, void *, quint32)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetErrorText, TPCANStatus, quint16, char *)
-inline QFunctionPointer resolveSymbol(QLibrary *pcanLibrary, const char *symbolName)
-{
- QFunctionPointer symbolFunctionPointer = pcanLibrary->resolve(symbolName);
- if (!symbolFunctionPointer)
- qWarning("Failed to resolve the pcanbasic symbol: %s", symbolName);
-
- return symbolFunctionPointer;
-}
-
inline bool resolveSymbols(QLibrary *pcanLibrary)
{
if (!pcanLibrary->isLoaded()) {
pcanLibrary->setFileName(QStringLiteral("pcanbasic"));
- if (!pcanLibrary->load()) {
- qWarning("Failed to load the library: %s", qPrintable(pcanLibrary->fileName()));
+ if (!pcanLibrary->load())
return false;
- }
}
RESOLVE_SYMBOL(CAN_Initialize)
diff --git a/src/plugins/canbus/peakcan/peakcanbackend.cpp b/src/plugins/canbus/peakcan/peakcanbackend.cpp
index 3f5d2c0..d8ddf76 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend.cpp
+++ b/src/plugins/canbus/peakcan/peakcanbackend.cpp
@@ -214,13 +214,28 @@ bool PeakCanBackendPrivate::open()
return false;
}
- if (!acquireReadNotification()) {
- const TPCANStatus st = ::CAN_Uninitialize(channelIndex);
- if (st != PCAN_ERROR_OK)
- q->setError(systemErrorString(st), QCanBusDevice::ConnectionError);
+#if defined(Q_OS_WIN32)
+ if (readHandle == INVALID_HANDLE_VALUE) {
+ readHandle = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ if (!readHandle) {
+ q->setError(qt_error_string(::GetLastError()), QCanBusDevice::ConnectionError);
+ return false;
+ }
+ }
+#endif
+
+ const TPCANStatus err = ::CAN_SetValue(channelIndex, PCAN_RECEIVE_EVENT, &readHandle, sizeof(readHandle));
+ if (err != PCAN_ERROR_OK) {
+ q->setError(systemErrorString(err), QCanBusDevice::ConnectionError);
return false;
}
+ writeNotifier = new WriteNotifier(this, q);
+ writeNotifier->setInterval(0);
+
+ readNotifier = new ReadNotifier(this, q);
+ readNotifier->setEnabled(true);
+
isOpen = true;
return true;
}
@@ -229,18 +244,31 @@ void PeakCanBackendPrivate::close()
{
Q_Q(PeakCanBackend);
- enableWriteNotification(false);
- releaseReadNotification();
+ delete readNotifier;
+ readNotifier = nullptr;
- if (writeNotifier) {
- delete writeNotifier;
- writeNotifier = nullptr;
- }
+ delete writeNotifier;
+ writeNotifier = nullptr;
+
+ quint32 value = 0;
+ const TPCANStatus err = ::CAN_SetValue(channelIndex, PCAN_RECEIVE_EVENT, &value, sizeof(value));
+ if (err != PCAN_ERROR_OK)
+ emit q->setError(systemErrorString(err), QCanBusDevice::ConnectionError);
const TPCANStatus st = ::CAN_Uninitialize(channelIndex);
if (st != PCAN_ERROR_OK)
q->setError(systemErrorString(st), QCanBusDevice::ConnectionError);
+#if defined(Q_OS_WIN32)
+ if (readHandle && (readHandle != INVALID_HANDLE_VALUE)) {
+ if (!::CloseHandle(readHandle))
+ q->setError(qt_error_string(::GetLastError()), QCanBusDevice::ConnectionError);
+ readHandle = INVALID_HANDLE_VALUE;
+ }
+#else
+ readHandle = -1;
+#endif
+
isOpen = false;
}
@@ -260,37 +288,37 @@ bool PeakCanBackendPrivate::setConfigurationParameter(int key, const QVariant &v
static int channelIndexFromName(const QString &interfaceName)
{
- if (interfaceName == QStringLiteral("usbbus1"))
+ if (interfaceName == QStringLiteral("usb0"))
return PCAN_USBBUS1;
- else if (interfaceName == QStringLiteral("usbbus2"))
+ else if (interfaceName == QStringLiteral("usb1"))
return PCAN_USBBUS2;
- else if (interfaceName == QStringLiteral("usbbus3"))
+ else if (interfaceName == QStringLiteral("usb2"))
return PCAN_USBBUS3;
- else if (interfaceName == QStringLiteral("usbbus4"))
+ else if (interfaceName == QStringLiteral("usb3"))
return PCAN_USBBUS4;
- else if (interfaceName == QStringLiteral("usbbus5"))
+ else if (interfaceName == QStringLiteral("usb4"))
return PCAN_USBBUS5;
- else if (interfaceName == QStringLiteral("usbbus6"))
+ else if (interfaceName == QStringLiteral("usb5"))
return PCAN_USBBUS6;
- else if (interfaceName == QStringLiteral("usbbus7"))
+ else if (interfaceName == QStringLiteral("usb6"))
return PCAN_USBBUS7;
- else if (interfaceName == QStringLiteral("usbbus8"))
+ else if (interfaceName == QStringLiteral("usb7"))
return PCAN_USBBUS8;
- else if (interfaceName == QStringLiteral("pcibus1"))
+ else if (interfaceName == QStringLiteral("pci0"))
return PCAN_PCIBUS1;
- else if (interfaceName == QStringLiteral("pcibus2"))
+ else if (interfaceName == QStringLiteral("pci1"))
return PCAN_PCIBUS2;
- else if (interfaceName == QStringLiteral("pcibus3"))
+ else if (interfaceName == QStringLiteral("pci2"))
return PCAN_PCIBUS3;
- else if (interfaceName == QStringLiteral("pcibus4"))
+ else if (interfaceName == QStringLiteral("pci3"))
return PCAN_PCIBUS4;
- else if (interfaceName == QStringLiteral("pcibus5"))
+ else if (interfaceName == QStringLiteral("pci4"))
return PCAN_PCIBUS5;
- else if (interfaceName == QStringLiteral("pcibus6"))
+ else if (interfaceName == QStringLiteral("pci5"))
return PCAN_PCIBUS6;
- else if (interfaceName == QStringLiteral("pcibus7"))
+ else if (interfaceName == QStringLiteral("pci6"))
return PCAN_PCIBUS7;
- else if (interfaceName == QStringLiteral("pcibus8"))
+ else if (interfaceName == QStringLiteral("pci7"))
return PCAN_PCIBUS8;
else // TODO: Add other indexes here
return PCAN_NONEBUS;
@@ -317,30 +345,12 @@ QString PeakCanBackendPrivate::systemErrorString(int errorCode)
return QString::fromLatin1(buffer);
}
-void PeakCanBackendPrivate::enableWriteNotification(bool enable)
-{
- Q_Q(PeakCanBackend);
-
- if (writeNotifier) {
- if (enable) {
- if (!writeNotifier->isActive())
- writeNotifier->start();
- } else {
- writeNotifier->stop();
- }
- } else if (enable) {
- writeNotifier = new WriteNotifier(this, q);
- writeNotifier->setInterval(0);
- writeNotifier->start();
- }
-}
-
void PeakCanBackendPrivate::startWrite()
{
Q_Q(PeakCanBackend);
if (!q->hasOutgoingFrames()) {
- enableWriteNotification(false);
+ writeNotifier->stop();
return;
}
@@ -365,62 +375,8 @@ void PeakCanBackendPrivate::startWrite()
else
emit q->framesWritten(qint64(1));
- if (q->hasOutgoingFrames())
- enableWriteNotification(true);
-}
-
-bool PeakCanBackendPrivate::acquireReadNotification()
-{
- Q_Q(PeakCanBackend);
-
-#if defined(Q_OS_WIN32)
- if (readHandle == INVALID_HANDLE_VALUE) {
- readHandle = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
- if (!readHandle) {
- q->setError(qt_error_string(::GetLastError()), QCanBusDevice::ReadError);
- return false;
- }
- }
-#endif
-
- const TPCANStatus st = ::CAN_SetValue(channelIndex, PCAN_RECEIVE_EVENT,
- &readHandle, sizeof(readHandle));
- if (st != PCAN_ERROR_OK) {
- q->setError(systemErrorString(st), QCanBusDevice::ReadError);
- return false;
- }
-
- if (!readNotifier) {
- readNotifier = new ReadNotifier(this, q);
- readNotifier->setEnabled(true);
- }
-
- return true;
-}
-
-void PeakCanBackendPrivate::releaseReadNotification()
-{
- Q_Q(PeakCanBackend);
-
- quint32 value = 0;
- const TPCANStatus st = ::CAN_SetValue(channelIndex, PCAN_RECEIVE_EVENT, &value, sizeof(value));
- if (st != PCAN_ERROR_OK)
- q->setError(systemErrorString(st), QCanBusDevice::ConnectionError);
-
- if (readNotifier) {
- delete readNotifier;
- readNotifier = nullptr;
- }
-
-#if defined(Q_OS_WIN32)
- if (readHandle && (readHandle != INVALID_HANDLE_VALUE)) {
- if (!::CloseHandle(readHandle))
- q->setError(qt_error_string(::GetLastError()), QCanBusDevice::ConnectionError);
- readHandle = INVALID_HANDLE_VALUE;
- }
-#else
- readHandle = -1;
-#endif
+ if (q->hasOutgoingFrames() && !writeNotifier->isActive())
+ writeNotifier->start();
}
void PeakCanBackendPrivate::startRead()
@@ -444,12 +400,12 @@ void PeakCanBackendPrivate::startRead()
QCanBusFrame frame(message.ID, QByteArray(reinterpret_cast<const char *>(message.DATA), int(message.LEN)));
const quint64 millis = timestamp.millis + Q_UINT64_C(0xFFFFFFFF) * timestamp.millis_overflow;
- const quint64 micros = Q_UINT64_C(1000) * (millis % 1000) + timestamp.micros;
- frame.setTimeStamp(QCanBusFrame::TimeStamp(millis / 1000, micros));
+ const quint64 micros = Q_UINT64_C(1000) * millis + timestamp.micros;
+ frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(micros));
frame.setExtendedFrameFormat(message.MSGTYPE & PCAN_MESSAGE_EXTENDED);
frame.setFrameType((message.MSGTYPE & PCAN_MESSAGE_RTR) ? QCanBusFrame::RemoteRequestFrame : QCanBusFrame::DataFrame);
- newFrames.append(frame);
+ newFrames.append(std::move(frame));
}
q->enqueueReceivedFrames(newFrames);
@@ -563,7 +519,9 @@ bool PeakCanBackend::writeFrame(const QCanBusFrame &newData)
}
enqueueOutgoingFrame(newData);
- d->enableWriteNotification(true);
+
+ if (!d->writeNotifier->isActive())
+ d->writeNotifier->start();
return true;
}
diff --git a/src/plugins/canbus/peakcan/peakcanbackend_p.h b/src/plugins/canbus/peakcan/peakcanbackend_p.h
index 88f39f5..9222b83 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend_p.h
+++ b/src/plugins/canbus/peakcan/peakcanbackend_p.h
@@ -75,10 +75,7 @@ public:
void setupChannel(const QString &interfaceName);
void setupDefaultConfigurations();
QString systemErrorString(int errorCode);
- void enableWriteNotification(bool enable);
void startWrite();
- bool acquireReadNotification();
- void releaseReadNotification();
void startRead();
bool verifyBitRate(int bitrate);
diff --git a/src/plugins/canbus/socketcan/main.cpp b/src/plugins/canbus/socketcan/main.cpp
index e83b569..eb13cea 100644
--- a/src/plugins/canbus/socketcan/main.cpp
+++ b/src/plugins/canbus/socketcan/main.cpp
@@ -53,8 +53,9 @@ class SocketCanBusPlugin : public QObject, public QCanBusFactory
public:
- QCanBusDevice *createDevice(const QString &interfaceName) const
+ QCanBusDevice *createDevice(const QString &interfaceName, QString *errorMessage) const override
{
+ Q_UNUSED(errorMessage);
auto device = new SocketCanBackend(interfaceName);
return device;
}
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index 60f36f9..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;
@@ -594,16 +594,13 @@ void SocketCanBackend::readSocket()
if (ioctl(canSocket, SIOCGSTAMP, &timeStamp) < 0) {
setError(qt_error_string(errno),
QCanBusDevice::CanBusError::ReadError);
- timeStamp.tv_sec = 0;
- timeStamp.tv_usec = 0;
+ memset(&timeStamp, 0, sizeof(timeStamp));
}
- QCanBusFrame::TimeStamp stamp;
- stamp.setSeconds(timeStamp.tv_sec);
- stamp.setMicroSeconds(timeStamp.tv_usec);
-
+ 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);
@@ -615,10 +612,10 @@ void SocketCanBackend::readSocket()
bufferedFrame.setFrameId(frame.can_id & CAN_EFF_MASK);
- QByteArray load(reinterpret_cast<char *>(frame.data), frame.len);
+ const QByteArray load(reinterpret_cast<char *>(frame.data), frame.len);
bufferedFrame.setPayload(load);
- newFrames.append(bufferedFrame);
+ newFrames.append(std::move(bufferedFrame));
}
enqueueReceivedFrames(newFrames);
diff --git a/src/plugins/canbus/tinycan/main.cpp b/src/plugins/canbus/tinycan/main.cpp
index e8a084c..fe988ba 100644
--- a/src/plugins/canbus/tinycan/main.cpp
+++ b/src/plugins/canbus/tinycan/main.cpp
@@ -51,11 +51,13 @@ class TinyCanBusPlugin : public QObject, public QCanBusFactory
public:
- QCanBusDevice *createDevice(const QString &interfaceName) const
+ QCanBusDevice *createDevice(const QString &interfaceName, QString *errorMessage) const override
{
QString errorReason;
if (!TinyCanBackend::canCreate(&errorReason)) {
qWarning("%ls", qUtf16Printable(errorReason));
+ if (errorMessage)
+ *errorMessage = errorReason;
return nullptr;
}
diff --git a/src/plugins/canbus/tinycan/tinycan_symbols_p.h b/src/plugins/canbus/tinycan/tinycan_symbols_p.h
index 5ad149c..6e05b92 100644
--- a/src/plugins/canbus/tinycan/tinycan_symbols_p.h
+++ b/src/plugins/canbus/tinycan/tinycan_symbols_p.h
@@ -285,7 +285,7 @@ typedef void (DRV_CALLBACK_TYPE *CanRxEventCallback)(
static fp_##symbolName symbolName;
#define RESOLVE_SYMBOL(symbolName) \
- symbolName = (fp_##symbolName)resolveSymbol(mhstcanLibrary, #symbolName); \
+ symbolName = (fp_##symbolName)mhstcanLibrary->resolve(#symbolName); \
if (!symbolName) \
return false;
@@ -317,23 +317,12 @@ GENERATE_SYMBOL_VARIABLE(void, CanSetRxEventCallback, CanRxEventCallback)
GENERATE_SYMBOL_VARIABLE(void, CanSetEvents, quint16)
GENERATE_SYMBOL_VARIABLE(quint32, CanEventStatus, void)
-inline QFunctionPointer resolveSymbol(QLibrary *mhstcanLibrary, const char *symbolName)
-{
- QFunctionPointer symbolFunctionPointer = mhstcanLibrary->resolve(symbolName);
- if (!symbolFunctionPointer)
- qWarning("Failed to resolve the mhstcan symbol: %s", symbolName);
-
- return symbolFunctionPointer;
-}
-
inline bool resolveSymbols(QLibrary *mhstcanLibrary)
{
if (!mhstcanLibrary->isLoaded()) {
mhstcanLibrary->setFileName(QStringLiteral("mhstcan"));
- if (!mhstcanLibrary->load()) {
- qWarning("Failed to load the library: %s", qPrintable(mhstcanLibrary->fileName()));
+ if (!mhstcanLibrary->load())
return false;
- }
}
RESOLVE_SYMBOL(CanInitDriver)
diff --git a/src/plugins/canbus/tinycan/tinycanbackend.cpp b/src/plugins/canbus/tinycan/tinycanbackend.cpp
index 2cee2d0..0961813 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend.cpp
+++ b/src/plugins/canbus/tinycan/tinycanbackend.cpp
@@ -197,6 +197,9 @@ bool TinyCanBackendPrivate::open()
}
}
+ writeNotifier = new WriteNotifier(this, q);
+ writeNotifier->setInterval(0);
+
isOpen = true;
return true;
}
@@ -205,6 +208,9 @@ void TinyCanBackendPrivate::close()
{
Q_Q(TinyCanBackend);
+ delete writeNotifier;
+ writeNotifier = nullptr;
+
const int ret = ::CanDeviceClose(channelIndex);
if (ret < 0)
q->setError(systemErrorString(ret), QCanBusDevice::CanBusError::ConnectionError);
@@ -299,9 +305,9 @@ QString TinyCanBackendPrivate::systemErrorString(int errorCode)
static int channelIndexFromName(const QString &interfaceName)
{
- if (interfaceName == QStringLiteral("channela"))
+ if (interfaceName == QStringLiteral("can0.0"))
return INDEX_CAN_KANAL_A;
- else if (interfaceName == QStringLiteral("channelb"))
+ else if (interfaceName == QStringLiteral("can0.1"))
return INDEX_CAN_KANAL_B;
else
return INDEX_INVALID;
@@ -320,30 +326,12 @@ void TinyCanBackendPrivate::setupDefaultConfigurations()
q->setConfigurationParameter(QCanBusDevice::BitRateKey, 500000);
}
-void TinyCanBackendPrivate::enableWriteNotification(bool enable)
-{
- Q_Q(TinyCanBackend);
-
- if (writeNotifier) {
- if (enable) {
- if (!writeNotifier->isActive())
- writeNotifier->start();
- } else {
- writeNotifier->stop();
- }
- } else if (enable) {
- writeNotifier = new WriteNotifier(this, q);
- writeNotifier->setInterval(0);
- writeNotifier->start();
- }
-}
-
void TinyCanBackendPrivate::startWrite()
{
Q_Q(TinyCanBackend);
if (!q->hasOutgoingFrames()) {
- enableWriteNotification(false);
+ writeNotifier->stop();
return;
}
@@ -372,16 +360,8 @@ void TinyCanBackendPrivate::startWrite()
emit q->framesWritten(messagesToWrite);
}
- if (q->hasOutgoingFrames())
- enableWriteNotification(true);
-}
-
-bool TinyCanBackendPrivate::enableReadNotification()
-{
- ::CanSetRxEventCallback(&canRxEventCallback);
- ::CanSetEvents(EVENT_ENABLE_RX_MESSAGES);
-
- return true;
+ if (q->hasOutgoingFrames() && !writeNotifier->isActive())
+ writeNotifier->start();
}
// this method is called from the different thread!
@@ -431,7 +411,7 @@ void TinyCanBackendPrivate::startRead()
else
frame.setFrameType(QCanBusFrame::DataFrame);
- newFrames.append(frame);
+ newFrames.append(std::move(frame));
}
q->enqueueReceivedFrames(newFrames);
@@ -448,7 +428,8 @@ void TinyCanBackendPrivate::startupDriver()
return;
}
- enableReadNotification();
+ ::CanSetRxEventCallback(&canRxEventCallback);
+ ::CanSetEvents(EVENT_ENABLE_RX_MESSAGES);
} else if (driverRefCount < 0) {
qCritical("Wrong reference counter: %d", driverRefCount);
@@ -578,7 +559,9 @@ bool TinyCanBackend::writeFrame(const QCanBusFrame &newData)
}
enqueueOutgoingFrame(newData);
- d->enableWriteNotification(true);
+
+ if (!d->writeNotifier->isActive())
+ d->writeNotifier->start();
return true;
}
diff --git a/src/plugins/canbus/tinycan/tinycanbackend_p.h b/src/plugins/canbus/tinycan/tinycanbackend_p.h
index 14630dd..18c82ef 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend_p.h
+++ b/src/plugins/canbus/tinycan/tinycanbackend_p.h
@@ -70,9 +70,7 @@ public:
QString systemErrorString(int errorCode);
void setupChannel(const QString &interfaceName);
void setupDefaultConfigurations();
- void enableWriteNotification(bool enable);
void startWrite();
- bool enableReadNotification();
void startRead();
void startupDriver();
void cleanupDriver();
diff --git a/src/plugins/canbus/vectorcan/main.cpp b/src/plugins/canbus/vectorcan/main.cpp
new file mode 100644
index 0000000..7be88b9
--- /dev/null
+++ b/src/plugins/canbus/vectorcan/main.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtSerialBus module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "vectorcanbackend.h"
+
+#include <QtSerialBus/qcanbus.h>
+#include <QtSerialBus/qcanbusdevice.h>
+#include <QtSerialBus/qcanbusfactory.h>
+
+QT_BEGIN_NAMESPACE
+
+class VectorCanBusPlugin : public QObject, public QCanBusFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QCanBusFactory" FILE "plugin.json")
+ Q_INTERFACES(QCanBusFactory)
+
+public:
+ QCanBusDevice *createDevice(const QString &interfaceName, QString *errorMessage) const override
+ {
+ QString errorReason;
+ if (!VectorCanBackend::canCreate(&errorReason)) {
+ qWarning("%s", qPrintable(errorReason));
+ if (errorMessage)
+ *errorMessage = errorReason;
+ return nullptr;
+ }
+
+ auto device = new VectorCanBackend(interfaceName);
+ return device;
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/canbus/vectorcan/plugin.json b/src/plugins/canbus/vectorcan/plugin.json
new file mode 100644
index 0000000..de0002c
--- /dev/null
+++ b/src/plugins/canbus/vectorcan/plugin.json
@@ -0,0 +1,3 @@
+{
+ "Key": "vectorcan"
+}
diff --git a/src/plugins/canbus/vectorcan/vectorcan.pro b/src/plugins/canbus/vectorcan/vectorcan.pro
new file mode 100644
index 0000000..a43c061
--- /dev/null
+++ b/src/plugins/canbus/vectorcan/vectorcan.pro
@@ -0,0 +1,19 @@
+TARGET = qtvectorcanbus
+
+QT = core-private serialbus
+
+HEADERS += \
+ vectorcanbackend.h \
+ vectorcanbackend_p.h \
+ vectorcan_symbols_p.h
+
+SOURCES += \
+ main.cpp \
+ vectorcanbackend.cpp
+
+DISTFILES = plugin.json
+
+PLUGIN_TYPE = canbus
+PLUGIN_EXTENDS = serialbus
+PLUGIN_CLASS_NAME = VectorCanBusPlugin
+load(qt_plugin)
diff --git a/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h b/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h
new file mode 100644
index 0000000..429f50e
--- /dev/null
+++ b/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h
@@ -0,0 +1,484 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtSerialBus module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VECTORCAN_SYMBOLS_P_H
+#define VECTORCAN_SYMBOLS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifdef LINK_LIBVECTORCAN
+
+extern "C"
+{
+#include <vxlapi.h>
+}
+
+#else
+
+#include <QtCore/qlibrary.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qdebug.h>
+
+#ifdef Q_OS_WIN32
+# include <windows.h>
+#else
+# error "Unsupported platform"
+#endif
+
+// transceiver types: CAN Cab
+#define XL_TRANSCEIVER_TYPE_NONE 0x0000
+#define XL_TRANSCEIVER_TYPE_CAN_251 0x0001
+#define XL_TRANSCEIVER_TYPE_CAN_252 0x0002
+#define XL_TRANSCEIVER_TYPE_CAN_DNOPTO 0x0003
+#define XL_TRANSCEIVER_TYPE_CAN_SWC_PROTO 0x0005 // Prototype. Driver may latch-up.
+#define XL_TRANSCEIVER_TYPE_CAN_SWC 0x0006
+#define XL_TRANSCEIVER_TYPE_CAN_EVA 0x0007
+#define XL_TRANSCEIVER_TYPE_CAN_FIBER 0x0008
+#define XL_TRANSCEIVER_TYPE_CAN_1054_OPTO 0x000B // 1054 with optical isolation
+#define XL_TRANSCEIVER_TYPE_CAN_SWC_OPTO 0x000C // SWC with optical isolation
+#define XL_TRANSCEIVER_TYPE_CAN_B10011S 0x000D // B10011S truck-and-trailer
+#define XL_TRANSCEIVER_TYPE_CAN_1050 0x000E // 1050
+#define XL_TRANSCEIVER_TYPE_CAN_1050_OPTO 0x000F // 1050 with optical isolation
+#define XL_TRANSCEIVER_TYPE_CAN_1041 0x0010 // 1041
+#define XL_TRANSCEIVER_TYPE_CAN_1041_OPTO 0x0011 // 1041 with optical isolation
+#define XL_TRANSCEIVER_TYPE_LIN_6258_OPTO 0x0017 // Vector LINcab 6258opto with transceiver Infineon TLE6258
+#define XL_TRANSCEIVER_TYPE_LIN_6259_OPTO 0x0019 // Vector LINcab 6259opto with transceiver Infineon TLE6259
+#define XL_TRANSCEIVER_TYPE_DAIO_8444_OPTO 0x001D // Vector IOcab 8444 (8 dig.Inp.; 4 dig.Outp.; 4 ana.Inp.; 4 ana.Outp.)
+#define XL_TRANSCEIVER_TYPE_CAN_1041A_OPTO 0x0021 // 1041A with optical isolation
+#define XL_TRANSCEIVER_TYPE_LIN_6259_MAG 0x0023 // LIN transceiver 6259, with transceiver Infineon TLE6259, magnetically isolated, stress functionality
+#define XL_TRANSCEIVER_TYPE_LIN_7259_MAG 0x0025 // LIN transceiver 7259, with transceiver Infineon TLE7259, magnetically isolated, stress functionality
+#define XL_TRANSCEIVER_TYPE_LIN_7269_MAG 0x0027 // LIN transceiver 7269, with transceiver Infineon TLE7269, magnetically isolated, stress functionality
+#define XL_TRANSCEIVER_TYPE_CAN_1054_MAG 0x0033 // TJA1054, magnetically isolated, with selectable termination resistor (via 4th IO line)
+#define XL_TRANSCEIVER_TYPE_CAN_251_MAG 0x0035 // 82C250/251 or equivalent, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_CAN_1050_MAG 0x0037 // TJA1050, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_CAN_1040_MAG 0x0039 // TJA1040, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_CAN_1041A_MAG 0x003B // TJA1041A, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_TWIN_CAN_1041A_MAG 0x0080 // TWINcab with two TJA1041, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_TWIN_LIN_7269_MAG 0x0081 // TWINcab with two 7259, Infineon TLE7259, magnetically isolated, stress functionality
+#define XL_TRANSCEIVER_TYPE_TWIN_CAN_1041AV2_MAG 0x0082 // TWINcab with two TJA1041, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_TWIN_CAN_1054_1041A_MAG 0x0083 // TWINcab with TJA1054A and TJA1041A with magnetic isolation
+// transceiver types: CAN PiggyBack
+#define XL_TRANSCEIVER_TYPE_PB_CAN_251 0x0101
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1054 0x0103
+#define XL_TRANSCEIVER_TYPE_PB_CAN_251_OPTO 0x0105
+#define XL_TRANSCEIVER_TYPE_PB_CAN_SWC 0x010B
+// 0x010D not supported, 0x010F, 0x0111, 0x0113 reserved for future use!!
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1054_OPTO 0x0115
+#define XL_TRANSCEIVER_TYPE_PB_CAN_SWC_OPTO 0x0117
+#define XL_TRANSCEIVER_TYPE_PB_CAN_TT_OPTO 0x0119
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1050 0x011B
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1050_OPTO 0x011D
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1041 0x011F
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1041_OPTO 0x0121
+#define XL_TRANSCEIVER_TYPE_PB_LIN_6258_OPTO 0x0129 // LIN piggy back with transceiver Infineon TLE6258
+#define XL_TRANSCEIVER_TYPE_PB_LIN_6259_OPTO 0x012B // LIN piggy back with transceiver Infineon TLE6259
+#define XL_TRANSCEIVER_TYPE_PB_LIN_6259_MAG 0x012D // LIN piggy back with transceiver Infineon TLE6259, magnetically isolated, stress functionality
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1041A_OPTO 0x012F // CAN transceiver 1041A
+#define XL_TRANSCEIVER_TYPE_PB_LIN_7259_MAG 0x0131 // LIN piggy back with transceiver Infineon TLE7259, magnetically isolated, stress functionality
+#define XL_TRANSCEIVER_TYPE_PB_LIN_7269_MAG 0x0133 // LIN piggy back with transceiver Infineon TLE7269, magnetically isolated, stress functionality
+#define XL_TRANSCEIVER_TYPE_PB_CAN_251_MAG 0x0135 // 82C250/251 or compatible, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1050_MAG 0x0136 // TJA 1050, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1040_MAG 0x0137 // TJA 1040, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1041A_MAG 0x0138 // TJA 1041A, magnetically isolated
+#define XL_TRANSCEIVER_TYPE_PB_DAIO_8444_OPTO 0x0139 // optically isolated IO piggy
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1054_MAG 0x013B // TJA1054, magnetically isolated, with selectable termination resistor (via 4th IO line)
+#define XL_TRANSCEIVER_TYPE_CAN_1051_CAP_FIX 0x013C // TJA1051 - fixed transceiver on e.g. 16xx/8970
+#define XL_TRANSCEIVER_TYPE_DAIO_1021_FIX 0x013D // Onboard IO of VN1630/VN1640
+#define XL_TRANSCEIVER_TYPE_LIN_7269_CAP_FIX 0x013E // TLE7269 - fixed transceiver on 1611
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1051_CAP 0x013F // TJA 1051, capacitive isolated
+#define XL_TRANSCEIVER_TYPE_PB_CAN_SWC_7356_CAP 0x0140 // Single Wire NCV7356, capacitive isolated
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1055_CAP 0x0141 // TJA1055, capacitive isolated, with selectable termination resistor (via 4th IO line)
+#define XL_TRANSCEIVER_TYPE_PB_CAN_1057_CAP 0x0142 // TJA 1057, capacitive isolated
+// transceiver types: FlexRay PiggyBacks
+#define XL_TRANSCEIVER_TYPE_PB_FR_1080 0x0201 // TJA 1080
+#define XL_TRANSCEIVER_TYPE_PB_FR_1080_MAG 0x0202 // TJA 1080 magnetically isolated piggy
+#define XL_TRANSCEIVER_TYPE_PB_FR_1080A_MAG 0x0203 // TJA 1080A magnetically isolated piggy
+#define XL_TRANSCEIVER_TYPE_PB_FR_1082_CAP 0x0204 // TJA 1082 capacitive isolated piggy
+#define XL_TRANSCEIVER_TYPE_PB_FRC_1082_CAP 0x0205 // TJA 1082 capacitive isolated piggy with CANpiggy form factor
+
+#define XL_TRANSCEIVER_TYPE_ETH_BCM54810_FIX 0x0230 // Onboard Broadcom PHY on VN5610
+
+// IOpiggy 8642
+#define XL_TRANSCEIVER_TYPE_PB_DAIO_8642 0x0280 // Iopiggy for VN8900
+
+// transceiver Operation Modes
+#define XL_TRANSCEIVER_LINEMODE_NA ((quint32)0x0000)
+#define XL_TRANSCEIVER_LINEMODE_TWO_LINE ((quint32)0x0001)
+#define XL_TRANSCEIVER_LINEMODE_CAN_H ((quint32)0x0002)
+#define XL_TRANSCEIVER_LINEMODE_CAN_L ((quint32)0x0003)
+#define XL_TRANSCEIVER_LINEMODE_SWC_SLEEP ((quint32)0x0004) // SWC Sleep Mode.
+#define XL_TRANSCEIVER_LINEMODE_SWC_NORMAL ((quint32)0x0005) // SWC Normal Mode.
+#define XL_TRANSCEIVER_LINEMODE_SWC_FAST ((quint32)0x0006) // SWC High-Speed Mode.
+#define XL_TRANSCEIVER_LINEMODE_SWC_WAKEUP ((quint32)0x0007) // SWC Wakeup Mode.
+#define XL_TRANSCEIVER_LINEMODE_SLEEP ((quint32)0x0008)
+#define XL_TRANSCEIVER_LINEMODE_NORMAL ((quint32)0x0009)
+#define XL_TRANSCEIVER_LINEMODE_STDBY ((quint32)0x000a) // Standby for those who support it
+#define XL_TRANSCEIVER_LINEMODE_TT_CAN_H ((quint32)0x000b) // truck & trailer: operating mode single wire using CAN high
+#define XL_TRANSCEIVER_LINEMODE_TT_CAN_L ((quint32)0x000c) // truck & trailer: operating mode single wire using CAN low
+#define XL_TRANSCEIVER_LINEMODE_EVA_00 ((quint32)0x000d) // CANcab Eva
+#define XL_TRANSCEIVER_LINEMODE_EVA_01 ((quint32)0x000e) // CANcab Eva
+#define XL_TRANSCEIVER_LINEMODE_EVA_10 ((quint32)0x000f) // CANcab Eva
+#define XL_TRANSCEIVER_LINEMODE_EVA_11 ((quint32)0x0010) // CANcab Eva
+
+// transceiver Status Flags (not all used, but for compatibility reasons)
+#define XL_TRANSCEIVER_STATUS_PRESENT ((quint32)0x0001)
+#define XL_TRANSCEIVER_STATUS_POWER ((quint32)0x0002)
+#define XL_TRANSCEIVER_STATUS_MEMBLANK ((quint32)0x0004)
+#define XL_TRANSCEIVER_STATUS_MEMCORRUPT ((quint32)0x0008)
+#define XL_TRANSCEIVER_STATUS_POWER_GOOD ((quint32)0x0010)
+#define XL_TRANSCEIVER_STATUS_EXT_POWER_GOOD ((quint32)0x0020)
+#define XL_TRANSCEIVER_STATUS_NOT_SUPPORTED ((quint32)0x0040)
+
+// common event tags
+#define XL_RECEIVE_MSG ((quint16)0x0001)
+#define XL_CHIP_STATE ((quint16)0x0004)
+#define XL_TRANSCEIVER_INFO ((quint16)0x0006)
+#define XL_TRANSCEIVER (XL_TRANSCEIVER_INFO)
+#define XL_TIMER_EVENT ((quint16)0x0008)
+#define XL_TIMER (XL_TIMER_EVENT)
+#define XL_TRANSMIT_MSG ((quint16)0x000A)
+#define XL_SYNC_PULSE ((quint16)0x000B)
+#define XL_APPLICATION_NOTIFICATION ((quint16)0x000F)
+
+// CAN/CAN-FD event tags Rx
+#define XL_CAN_EV_TAG_RX_OK ((quint16)0x0400)
+#define XL_CAN_EV_TAG_RX_ERROR ((quint16)0x0401)
+#define XL_CAN_EV_TAG_TX_ERROR ((quint16)0x0402)
+#define XL_CAN_EV_TAG_TX_REQUEST ((quint16)0x0403)
+#define XL_CAN_EV_TAG_TX_OK ((quint16)0x0404)
+#define XL_CAN_EV_TAG_CHIP_STATE ((quint16)0x0409)
+
+// CAN/CAN-FD event tags Tx
+#define XL_CAN_EV_TAG_TX_MSG ((quint16)0x0440)
+#define XL_CAN_EV_TAG_TX_ERRFR ((quint16)0x0441)
+
+// Bus types
+#define XL_BUS_TYPE_NONE 0x00000000
+#define XL_BUS_TYPE_CAN 0x00000001
+
+#include <pshpack1.h>
+typedef quint64 XLaccess;
+typedef HANDLE XLhandle;
+
+// message flags
+#ifndef MAX_MSG_LEN
+#define MAX_MSG_LEN 8
+#endif
+
+// interface version for our events
+#define XL_INTERFACE_VERSION_V2 2
+#define XL_INTERFACE_VERSION_V3 3
+#define XL_INTERFACE_VERSION_V4 4
+//current version
+#define XL_INTERFACE_VERSION XL_INTERFACE_VERSION_V3
+
+#define XL_CAN_EXT_MSG_ID 0x80000000
+
+#define XL_CAN_MSG_FLAG_ERROR_FRAME 0x01
+#define XL_CAN_MSG_FLAG_OVERRUN 0x02 // Overrun in Driver or CAN Controller, previous msgs have been lost.
+#define XL_CAN_MSG_FLAG_NERR 0x04 // Line Error on Lowspeed
+#define XL_CAN_MSG_FLAG_WAKEUP 0x08 // High Voltage Message on Single Wire CAN
+#define XL_CAN_MSG_FLAG_REMOTE_FRAME 0x10
+#define XL_CAN_MSG_FLAG_RESERVED_1 0x20
+#define XL_CAN_MSG_FLAG_TX_COMPLETED 0x40 // Message Transmitted
+#define XL_CAN_MSG_FLAG_TX_REQUEST 0x80 // Transmit Message stored into Controller
+#define XL_CAN_MSG_FLAG_SRR_BIT_DOM 0x0200 // SRR bit in CAN message is dominant
+
+#define XL_EVENT_FLAG_OVERRUN 0x01 // Used in XLevent.flags
+
+// structure for XL_RECEIVE_MSG, XL_TRANSMIT_MSG (32 bytes)
+struct s_xl_can_msg {
+ unsigned long id;
+ quint16 flags;
+ quint16 dlc;
+ quint64 res1;
+ quint8 data[MAX_MSG_LEN];
+ quint64 res2;
+};
+static_assert(sizeof(s_xl_can_msg) == 32, "Invalid size of s_xl_can_msg structure");
+
+// defines for SET_OUTPUT_MODE
+#define XL_OUTPUT_MODE_SILENT 0 // switch CAN trx into default silent mode
+#define XL_OUTPUT_MODE_NORMAL 1 // switch CAN trx into normal mode
+#define XL_OUTPUT_MODE_TX_OFF 2 // switch CAN trx into silent mode with tx pin off
+#define XL_OUTPUT_MODE_SJA_1000_SILENT 3 // switch CAN trx into SJA1000 silent mode
+
+// Transceiver modes
+#define XL_TRANSCEIVER_EVENT_ERROR 1
+#define XL_TRANSCEIVER_EVENT_CHANGED 2
+
+// basic bus message structure
+union s_xl_tag_data {
+ struct s_xl_can_msg msg;
+};
+
+// event type definition (48 bytes)
+typedef struct s_xl_event {
+ quint8 tag;
+ quint8 chanIndex;
+ quint16 transId;
+ quint16 portHandle;
+ quint8 flags; // e.g. XL_EVENT_FLAG_OVERRUN
+ quint8 reserved;
+ quint64 timeStamp;
+ union s_xl_tag_data tagData; // 32 bytes
+} XLevent;
+static_assert(sizeof(s_xl_event) == 48, "Invalid size of s_xl_event structure");
+
+// build a channels mask from the channels index
+#define XL_CHANNEL_MASK(x) (quint64(1) << (x))
+
+#define XL_MAX_APPNAME 32
+
+// driver status
+typedef qint16 XLstatus;
+
+#define XL_SUCCESS 0
+#define XL_PENDING 1
+
+#define XL_ERR_QUEUE_IS_EMPTY 10
+#define XL_ERR_QUEUE_IS_FULL 11
+#define XL_ERR_TX_NOT_POSSIBLE 12
+#define XL_ERR_NO_LICENSE 14
+#define XL_ERR_WRONG_PARAMETER 101
+#define XL_ERR_TWICE_REGISTER 110
+#define XL_ERR_INVALID_CHAN_INDEX 111
+#define XL_ERR_INVALID_ACCESS 112
+#define XL_ERR_PORT_IS_OFFLINE 113
+#define XL_ERR_CHAN_IS_ONLINE 116
+#define XL_ERR_NOT_IMPLEMENTED 117
+#define XL_ERR_INVALID_PORT 118
+#define XL_ERR_HW_NOT_READY 120
+#define XL_ERR_CMD_TIMEOUT 121
+#define XL_ERR_HW_NOT_PRESENT 129
+#define XL_ERR_NOTIFY_ALREADY_ACTIVE 131
+#define XL_ERR_NO_RESOURCES 152
+#define XL_ERR_WRONG_CHIP_TYPE 153
+#define XL_ERR_WRONG_COMMAND 154
+#define XL_ERR_INVALID_HANDLE 155
+#define XL_ERR_RESERVED_NOT_ZERO 157
+#define XL_ERR_INIT_ACCESS_MISSING 158
+#define XL_ERR_CANNOT_OPEN_DRIVER 201
+#define XL_ERR_WRONG_BUS_TYPE 202
+#define XL_ERR_DLL_NOT_FOUND 203
+#define XL_ERR_INVALID_CHANNEL_MASK 204
+#define XL_ERR_NOT_SUPPORTED 205
+// special stream defines
+#define XL_ERR_CONNECTION_BROKEN 210
+#define XL_ERR_CONNECTION_CLOSED 211
+#define XL_ERR_INVALID_STREAM_NAME 212
+#define XL_ERR_CONNECTION_FAILED 213
+#define XL_ERR_STREAM_NOT_FOUND 214
+#define XL_ERR_STREAM_NOT_CONNECTED 215
+#define XL_ERR_QUEUE_OVERRUN 216
+#define XL_ERROR 255
+
+// defines for xlGetDriverConfig structures
+#define XL_MAX_LENGTH 31
+#define XL_CONFIG_MAX_CHANNELS 64
+
+// flags for channelCapabilities
+#define XL_CHANNEL_FLAG_TIME_SYNC_RUNNING 0x00000001
+#define XL_CHANNEL_FLAG_CANFD_SUPPORT 0x20000000
+
+// activate - channel flags
+#define XL_ACTIVATE_NONE 0
+#define XL_ACTIVATE_RESET_CLOCK 8
+
+#define XL_BUS_COMPATIBLE_CAN XL_BUS_TYPE_CAN
+
+// the following bus types can be used with the current cab / piggy
+#define XL_BUS_ACTIVE_CAP_CAN (XL_BUS_COMPATIBLE_CAN << 16)
+
+// acceptance filter
+#define XL_CAN_STD 01 // flag for standard ID's
+#define XL_CAN_EXT 02 // flag for extended ID's
+
+typedef struct {
+ quint32 busType;
+ union {
+ struct {
+ quint32 bitRate;
+ quint8 sjw;
+ quint8 tseg1;
+ quint8 tseg2;
+ quint8 sam;
+ quint8 outputMode;
+ } can;
+ quint8 raw[32];
+ } data;
+} XLbusParams;
+
+// porthandle
+#define XL_INVALID_PORTHANDLE (-1)
+typedef long XLportHandle, *pXLportHandle;
+
+// defines for FPGA core types (fpgaCoreCapabilities)
+#define XL_FPGA_CORE_TYPE_NONE 0
+#define XL_FPGA_CORE_TYPE_CAN 1
+
+// defines for special DeviceStatus
+#define XL_SPECIAL_DEVICE_STAT_FPGA_UPDATE_DONE 0x01 // automatic driver FPGA flashing done
+
+typedef struct s_xl_channel_config {
+ char name[XL_MAX_LENGTH + 1];
+ quint8 hwType; // HWTYPE_xxxx (see above)
+ quint8 hwIndex; // Index of the hardware (same type) (0,1,...)
+ quint8 hwChannel; // Index of the channel (same hardware) (0,1,...)
+ quint16 transceiverType; // TRANSCEIVER_TYPE_xxxx (see above)
+ quint16 transceiverState; // transceiver state (XL_TRANSCEIVER_STATUS...)
+ quint16 configError; // XL_CHANNEL_CONFIG_ERROR_XXX (see above)
+ quint8 channelIndex; // Global channel index (0,1,...)
+ quint64 channelMask; // Global channel mask (=1<<channelIndex)
+ quint32 channelCapabilities; // capabilities which are supported (e.g CHANNEL_FLAG_XXX)
+ quint32 channelBusCapabilities; // what buses are supported and which are possible to be activated (e.g. XXX_BUS_ACTIVE_CAP_CAN)
+
+ // channel
+ quint8 isOnBus; // The channel is on bus
+ quint32 connectedBusType; // currently selected bus
+ XLbusParams busParams;
+
+ quint32 driverVersion;
+ quint32 interfaceVersion; // version of interface with driver
+ quint32 raw_data[10];
+
+ quint32 serialNumber;
+ quint32 articleNumber;
+
+ char transceiverName[XL_MAX_LENGTH + 1]; // name for CANcab or another transceiver
+
+ quint32 specialCabFlags; // XL_SPECIAL_CAB_LIN_RECESSIVE_STRESS, XL_SPECIAL_CAB_LIN_DOMINANT_TIMEOUT flags
+ quint32 dominantTimeout; // Dominant Timeout in us.
+ quint8 dominantRecessiveDelay; // Delay in us.
+ quint8 recessiveDominantDelay; // Delay in us.
+ quint8 connectionInfo; // XL_CONNECTION_INFO_XXX
+ quint8 currentlyAvailableTimestamps; // XL_CURRENTLY_AVAILABLE_TIMESTAMP...
+ quint16 minimalSupplyVoltage; // Minimal Supply Voltage of the Cab/Piggy in 1/100 V
+ quint16 maximalSupplyVoltage; // Maximal Supply Voltage of the Cab/Piggy in 1/100 V
+ quint32 maximalBaudrate; // Maximal supported LIN baudrate
+ quint8 fpgaCoreCapabilities; // e.g.: XL_FPGA_CORE_TYPE_XXX
+ quint8 specialDeviceStatus; // e.g.: XL_SPECIAL_DEVICE_STAT_XXX
+ quint16 channelBusActiveCapabilities; // like channelBusCapabilities (but without core dependencies)
+ quint16 breakOffset; // compensation for edge asymmetry in ns
+ quint16 delimiterOffset; // compensation for edgdfde asymmetry in ns
+ quint32 reserved[3];
+} XLchannelConfig, *pXLchannelConfig;
+
+typedef struct s_xl_driver_config {
+ quint32 dllVersion;
+ quint32 channelCount; // total number of channels
+ quint32 reserved[10];
+ XLchannelConfig channel[XL_CONFIG_MAX_CHANNELS]; // [channelCount]
+} XLdriverConfig, *pXLdriverConfig;
+
+// structure for the acceptance filter
+typedef struct _XLacc_filt {
+ quint8 isSet;
+ unsigned long code;
+ unsigned long mask; // relevant = 1
+} XLaccFilt;
+
+// structure for the acceptance filter of one CAN chip
+typedef struct _XLacceptance {
+ XLaccFilt std;
+ XLaccFilt xtd;
+} XLacceptance;
+
+// defines for xlSetGlobalTimeSync
+#define XL_SET_TIMESYNC_NO_CHANGE ((unsigned long)0)
+#define XL_SET_TIMESYNC_ON ((unsigned long)1)
+#define XL_SET_TIMESYNC_OFF ((unsigned long)2)
+
+#include <poppack.h>
+
+#define GENERATE_SYMBOL_VARIABLE(returnType, symbolName, ...) \
+ typedef returnType (WINAPI *fp_##symbolName)(__VA_ARGS__); \
+ static fp_##symbolName symbolName;
+
+#define RESOLVE_SYMBOL(symbolName) \
+ symbolName = (fp_##symbolName)vectorcanLibrary->resolve(#symbolName); \
+ if (!symbolName) \
+ return false;
+
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlOpenDriver, void)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlCloseDriver, void)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlGetDriverConfig, XLdriverConfig *)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlOpenPort, XLportHandle *, char *, XLaccess, XLaccess *, quint32, quint32, quint32)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlClosePort, XLportHandle)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlActivateChannel, XLportHandle, XLaccess, quint32, quint32)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlDeactivateChannel, XLportHandle, XLaccess)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanSetChannelBitrate, XLportHandle, XLaccess, quint32)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanTransmit, XLportHandle, XLaccess, quint32 *, void *)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlReceive, XLportHandle, quint32 *, XLevent *)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlSetNotification, XLportHandle, XLhandle *, int)
+GENERATE_SYMBOL_VARIABLE(char *, xlGetErrorString, XLstatus)
+
+inline bool resolveSymbols(QLibrary *vectorcanLibrary)
+{
+ if (!vectorcanLibrary->isLoaded()) {
+ vectorcanLibrary->setFileName(QStringLiteral("vxlapi"));
+ if (!vectorcanLibrary->load())
+ return false;
+ }
+
+ RESOLVE_SYMBOL(xlOpenDriver)
+ RESOLVE_SYMBOL(xlCloseDriver)
+ RESOLVE_SYMBOL(xlGetDriverConfig)
+ RESOLVE_SYMBOL(xlOpenPort)
+ RESOLVE_SYMBOL(xlClosePort)
+ RESOLVE_SYMBOL(xlActivateChannel)
+ RESOLVE_SYMBOL(xlDeactivateChannel)
+ RESOLVE_SYMBOL(xlCanSetChannelBitrate)
+ RESOLVE_SYMBOL(xlCanTransmit)
+ RESOLVE_SYMBOL(xlReceive)
+ RESOLVE_SYMBOL(xlSetNotification)
+ RESOLVE_SYMBOL(xlGetErrorString)
+
+ return true;
+}
+
+#endif
+
+#endif // VECTORCAN_SYMBOLS_P_H
diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend.cpp b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
new file mode 100644
index 0000000..005b726
--- /dev/null
+++ b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
@@ -0,0 +1,490 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtSerialBus module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "vectorcanbackend.h"
+#include "vectorcanbackend_p.h"
+#include "vectorcan_symbols_p.h"
+
+#include <QtSerialBus/qcanbusdevice.h>
+
+#include <QtCore/qtimer.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qwineventnotifier.h>
+#include <QtCore/qcoreapplication.h>
+
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef LINK_LIBVECTORCAN
+Q_GLOBAL_STATIC(QLibrary, vectorcanLibrary)
+#endif
+
+bool VectorCanBackend::canCreate(QString *errorReason)
+{
+#ifdef LINK_LIBVECTORCAN
+ return true;
+#else
+ static bool symbolsResolved = resolveSymbols(vectorcanLibrary());
+ if (!symbolsResolved) {
+ *errorReason = vectorcanLibrary()->errorString();
+ return false;
+ }
+ return true;
+#endif
+}
+
+static int driverRefCount = 0;
+
+class ReadNotifier : public QWinEventNotifier
+{
+ // no Q_OBJECT macro!
+public:
+ explicit ReadNotifier(VectorCanBackendPrivate *d, QObject *parent)
+ : QWinEventNotifier(parent)
+ , dptr(d)
+ {
+ setHandle(dptr->readHandle);
+ }
+
+protected:
+ bool event(QEvent *e) override
+ {
+ if (e->type() == QEvent::WinEventAct) {
+ dptr->startRead();
+ return true;
+ }
+ return QWinEventNotifier::event(e);
+ }
+
+private:
+ VectorCanBackendPrivate *dptr;
+};
+
+class WriteNotifier : public QTimer
+{
+ // no Q_OBJECT macro!
+public:
+ WriteNotifier(VectorCanBackendPrivate *d, QObject *parent)
+ : QTimer(parent)
+ , dptr(d)
+ {
+ setInterval(0);
+ }
+
+protected:
+ void timerEvent(QTimerEvent *e) override
+ {
+ if (e->timerId() == timerId()) {
+ dptr->startWrite();
+ return;
+ }
+ QTimer::timerEvent(e);
+ }
+
+private:
+ VectorCanBackendPrivate *dptr;
+};
+
+
+VectorCanBackendPrivate::VectorCanBackendPrivate(VectorCanBackend *q)
+ : q_ptr(q)
+ , portHandle(XL_INVALID_PORTHANDLE)
+{
+ startupDriver();
+}
+
+VectorCanBackendPrivate::~VectorCanBackendPrivate()
+{
+ cleanupDriver();
+}
+
+bool VectorCanBackendPrivate::open()
+{
+ Q_Q(VectorCanBackend);
+
+ {
+ XLaccess permissionMask = channelMask;
+ const quint32 queueSize = 256;
+ const XLstatus status = ::xlOpenPort(&portHandle,
+ const_cast<char *>(qPrintable(qApp->applicationName())),
+ channelMask, &permissionMask, queueSize,
+ XL_INTERFACE_VERSION, XL_BUS_TYPE_CAN);
+
+ if (status != XL_SUCCESS || portHandle == XL_INVALID_PORTHANDLE) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::ConnectionError);
+ return false;
+ }
+ }
+
+ {
+ const XLstatus status = ::xlActivateChannel(portHandle, channelMask,
+ XL_BUS_TYPE_CAN, XL_ACTIVATE_RESET_CLOCK);
+ if (status != XL_SUCCESS) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::CanBusError::ConnectionError);
+ return false;
+ }
+ }
+
+ {
+ const int queueLevel = 1;
+ const XLstatus status = ::xlSetNotification(portHandle, &readHandle, queueLevel);
+ if (status != XL_SUCCESS) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::ConnectionError);
+ return false;
+ }
+ }
+
+ readNotifier = new ReadNotifier(this, q);
+ readNotifier->setEnabled(true);
+
+ writeNotifier = new WriteNotifier(this, q);
+
+ return true;
+}
+
+void VectorCanBackendPrivate::close()
+{
+ Q_Q(VectorCanBackend);
+
+ delete readNotifier;
+ readNotifier = nullptr;
+
+ delete writeNotifier;
+ writeNotifier = nullptr;
+
+ {
+ const XLstatus status = ::xlDeactivateChannel(portHandle, channelMask);
+ if (status != XL_SUCCESS) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::CanBusError::ConfigurationError);
+ }
+ }
+
+ {
+ const XLstatus status = ::xlClosePort(portHandle);
+ if (status != XL_SUCCESS) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::ConnectionError);
+ }
+ }
+
+ portHandle = XL_INVALID_PORTHANDLE;
+}
+
+bool VectorCanBackendPrivate::setConfigurationParameter(int key, const QVariant &value)
+{
+ Q_Q(VectorCanBackend);
+
+ switch (key) {
+ case QCanBusDevice::BitRateKey:
+ return setBitRate(value.toUInt());
+ default:
+ q->setError(VectorCanBackend::tr("Unsupported configuration key"),
+ QCanBusDevice::ConfigurationError);
+ return false;
+ }
+}
+
+void VectorCanBackendPrivate::setupChannel(const QString &interfaceName)
+{
+ if (interfaceName.startsWith(QStringLiteral("can"))) {
+ const QStringRef ref = interfaceName.midRef(3);
+ bool ok = false;
+ const int channelIndex = ref.toInt(&ok);
+ if (ok && (channelIndex >= 0 && channelIndex < XL_CONFIG_MAX_CHANNELS)) {
+ channelMask = XL_CHANNEL_MASK((channelIndex));
+ return;
+ }
+ }
+
+ qCritical() << "Unable to parse the channel from an interface";
+}
+
+void VectorCanBackendPrivate::setupDefaultConfigurations()
+{
+ Q_Q(VectorCanBackend);
+
+ q->setConfigurationParameter(QCanBusDevice::BitRateKey, 500000);
+}
+
+QString VectorCanBackendPrivate::systemErrorString(int errorCode) const
+{
+ if (const char *string = ::xlGetErrorString(errorCode))
+ return QString::fromUtf8(string);
+ return VectorCanBackend::tr("Unable to retrieve an error string");
+}
+
+void VectorCanBackendPrivate::startWrite()
+{
+ Q_Q(VectorCanBackend);
+
+ if (!q->hasOutgoingFrames()) {
+ writeNotifier->stop();
+ return;
+ }
+
+ 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;
+
+ msg.id = frame.frameId();
+ if (frame.hasExtendedFrameFormat())
+ msg.id |= XL_CAN_EXT_MSG_ID;
+
+ 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));
+
+ quint32 eventCount = 1;
+ const XLstatus status = ::xlCanTransmit(portHandle, channelMask,
+ &eventCount, &event);
+ if (status != XL_SUCCESS) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::WriteError);
+ } else {
+ emit q->framesWritten(qint64(eventCount));
+ }
+
+ if (q->hasOutgoingFrames())
+ writeNotifier->start();
+}
+
+void VectorCanBackendPrivate::startRead()
+{
+ Q_Q(VectorCanBackend);
+
+ QVector<QCanBusFrame> newFrames;
+
+ for (;;) {
+ quint32 eventCount = 1;
+ XLevent event;
+ ::memset(&event, 0, sizeof(event));
+
+ const XLstatus status = ::xlReceive(portHandle, &eventCount, &event);
+ if (status != XL_SUCCESS) {
+ if (status != XL_ERR_QUEUE_IS_EMPTY) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::ReadError);
+ }
+ break;
+ }
+
+ if (event.tag != XL_RECEIVE_MSG || event.portHandle != portHandle)
+ continue;
+
+ const s_xl_can_msg &msg = event.tagData.msg;
+
+ QCanBusFrame frame(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.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);
+}
+
+void VectorCanBackendPrivate::startupDriver()
+{
+ Q_Q(VectorCanBackend);
+
+ if (driverRefCount == 0) {
+ const XLstatus status = ::xlOpenDriver();
+ if (status != XL_SUCCESS) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::CanBusError::ConnectionError);
+ return;
+ }
+ } else if (driverRefCount < 0) {
+ qCritical("Wrong reference counter: %d", driverRefCount);
+ return;
+ }
+
+ ++driverRefCount;
+}
+
+void VectorCanBackendPrivate::cleanupDriver()
+{
+ --driverRefCount;
+
+ if (driverRefCount < 0) {
+ qCritical("Wrong reference counter: %d", driverRefCount);
+ driverRefCount = 0;
+ } else if (driverRefCount == 0) {
+ ::xlCloseDriver();
+ }
+}
+
+bool VectorCanBackendPrivate::setBitRate(quint32 bitrate)
+{
+ Q_Q(VectorCanBackend);
+
+ if (q->state() != QCanBusDevice::UnconnectedState) {
+ const XLstatus status = ::xlCanSetChannelBitrate(portHandle, channelMask, bitrate);
+ if (status != XL_SUCCESS) {
+ q->setError(systemErrorString(status),
+ QCanBusDevice::CanBusError::ConfigurationError);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+VectorCanBackend::VectorCanBackend(const QString &name, QObject *parent)
+ : QCanBusDevice(parent)
+ , d_ptr(new VectorCanBackendPrivate(this))
+{
+ Q_D(VectorCanBackend);
+
+ d->setupChannel(name);
+ d->setupDefaultConfigurations();
+}
+
+VectorCanBackend::~VectorCanBackend()
+{
+ if (state() == ConnectedState)
+ close();
+
+ delete d_ptr;
+}
+
+bool VectorCanBackend::open()
+{
+ Q_D(VectorCanBackend);
+
+ if (!d->open()) {
+ close(); // sets UnconnectedState
+ return false;
+ }
+
+ const auto keys = configurationKeys();
+ for (int key : keys) {
+ const QVariant param = configurationParameter(key);
+ const bool success = d->setConfigurationParameter(key, param);
+ if (!success) {
+ qWarning() << "Cannot apply parameter:" << key
+ << "with value:" << param;
+ }
+ }
+
+ setState(QCanBusDevice::ConnectedState);
+ return true;
+}
+
+void VectorCanBackend::close()
+{
+ Q_D(VectorCanBackend);
+
+ d->close();
+
+ setState(QCanBusDevice::UnconnectedState);
+}
+
+void VectorCanBackend::setConfigurationParameter(int key, const QVariant &value)
+{
+ Q_D(VectorCanBackend);
+
+ if (d->setConfigurationParameter(key, value))
+ QCanBusDevice::setConfigurationParameter(key, value);
+}
+
+bool VectorCanBackend::writeFrame(const QCanBusFrame &newData)
+{
+ Q_D(VectorCanBackend);
+
+ if (state() != QCanBusDevice::ConnectedState)
+ return false;
+
+ if (!newData.isValid()) {
+ setError(tr("Cannot write invalid QCanBusFrame"),
+ QCanBusDevice::WriteError);
+ return false;
+ }
+
+ if (newData.frameType() != QCanBusFrame::DataFrame
+ && newData.frameType() != QCanBusFrame::RemoteRequestFrame
+ && newData.frameType() != QCanBusFrame::ErrorFrame) {
+ setError(tr("Unable to write a frame with unacceptable type"),
+ QCanBusDevice::WriteError);
+ return false;
+ }
+
+ // CAN FD frame format not implemented at this stage
+ if (newData.payload().size() > MAX_MSG_LEN) {
+ setError(tr("CAN FD frame format not supported."),
+ QCanBusDevice::WriteError);
+ return false;
+ }
+
+ enqueueOutgoingFrame(newData);
+
+ if (!d->writeNotifier->isActive())
+ d->writeNotifier->start();
+
+ return true;
+}
+
+// TODO: Implement me
+QString VectorCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
+{
+ Q_UNUSED(errorFrame);
+
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend.h b/src/plugins/canbus/vectorcan/vectorcanbackend.h
new file mode 100644
index 0000000..89966ed
--- /dev/null
+++ b/src/plugins/canbus/vectorcan/vectorcanbackend.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtSerialBus module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VECTORCANBACKEND_H
+#define VECTORCANBACKEND_H
+
+#include <QtSerialBus/qcanbusframe.h>
+#include <QtSerialBus/qcanbusdevice.h>
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class VectorCanBackendPrivate;
+
+class VectorCanBackend : public QCanBusDevice
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(VectorCanBackend)
+ Q_DISABLE_COPY(VectorCanBackend)
+public:
+ explicit VectorCanBackend(const QString &name, QObject *parent = nullptr);
+ ~VectorCanBackend() override;
+
+ bool open() override;
+ void close() override;
+
+ void setConfigurationParameter(int key, const QVariant &value) override;
+
+ bool writeFrame(const QCanBusFrame &newData) override;
+
+ QString interpretErrorFrame(const QCanBusFrame &errorFrame) override;
+
+ static bool canCreate(QString *errorReason);
+
+private:
+ VectorCanBackendPrivate * const d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // VECTORCANBACKEND_H
diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend_p.h b/src/plugins/canbus/vectorcan/vectorcanbackend_p.h
new file mode 100644
index 0000000..dbb3903
--- /dev/null
+++ b/src/plugins/canbus/vectorcan/vectorcanbackend_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtSerialBus module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VECTORCANBACKEND_P_H
+#define VECTORCANBACKEND_P_H
+
+#include "vectorcanbackend.h"
+
+#if defined(Q_OS_WIN32)
+# include <qt_windows.h>
+#else
+# error "Unsupported platform" // other stuff
+#endif
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QWinEventNotifier;
+class QTimer;
+
+class VectorCanBackendPrivate
+{
+ Q_DECLARE_PUBLIC(VectorCanBackend)
+public:
+ VectorCanBackendPrivate(VectorCanBackend *q);
+ ~VectorCanBackendPrivate();
+
+ bool open();
+ void close();
+ bool setConfigurationParameter(int key, const QVariant &value);
+ void setupChannel(const QString &interfaceName);
+ void setupDefaultConfigurations();
+ QString systemErrorString(int errorCode) const;
+ void startWrite();
+ void startRead();
+ void startupDriver();
+ void cleanupDriver();
+ bool setBitRate(quint32 bitrate);
+
+ VectorCanBackend * const q_ptr;
+
+ long portHandle;
+ quint64 channelMask = 0;
+ HANDLE readHandle = INVALID_HANDLE_VALUE;
+ QTimer *writeNotifier = nullptr;
+ QWinEventNotifier *readNotifier = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // VECTORCANBACKEND_P_H