summaryrefslogtreecommitdiffstats
path: root/src/plugins/canbus
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/canbus')
-rw-r--r--src/plugins/canbus/peakcan/peakcan_symbols_p.h51
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend.cpp4
-rw-r--r--src/plugins/canbus/socketcan/libsocketcan.cpp193
-rw-r--r--src/plugins/canbus/socketcan/libsocketcan.h72
-rw-r--r--src/plugins/canbus/socketcan/socketcan.pro2
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp20
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.h5
7 files changed, 325 insertions, 22 deletions
diff --git a/src/plugins/canbus/peakcan/peakcan_symbols_p.h b/src/plugins/canbus/peakcan/peakcan_symbols_p.h
index 9ab2e67..3470df2 100644
--- a/src/plugins/canbus/peakcan/peakcan_symbols_p.h
+++ b/src/plugins/canbus/peakcan/peakcan_symbols_p.h
@@ -267,21 +267,28 @@
#define PCAN_TYPE_DNG_SJA_EPP 0x06U // PCAN-Dongle EPP SJA1000
// Type definitions
-#define TPCANHandle quint16 // Represents a PCAN hardware channel handle
-#define TPCANStatus quint32 // Represents a PCAN status/error code
-#define TPCANParameter quint8 // Represents a PCAN parameter to be read or set
-#define TPCANDevice quint8 // Represents a PCAN device
-#define TPCANMessageType quint8 // Represents the type of a PCAN message
-#define TPCANType quint8 // Represents the type of PCAN hardware to be initialized
-#define TPCANMode quint8 // Represents a PCAN filter mode
-#define TPCANBaudrate quint16 // Represents a PCAN Baud rate register value
-#define TPCANBitrateFD char * // Represents a PCAN-FD bit rate string
-#define TPCANTimestampFD quint64 // Represents a timestamp of a received PCAN FD message
+#ifdef Q_OS_MACOS
+#define TPCANLong quint64
+#define TPCANLongToFrameID(a) static_cast<quint32>(a)
+#else
+#define TPCANLong quint32
+#define TPCANLongToFrameID(a) a
+#endif
+#define TPCANHandle quint16 // Represents a PCAN hardware channel handle
+#define TPCANStatus TPCANLong // Represents a PCAN status/error code
+#define TPCANParameter quint8 // Represents a PCAN parameter to be read or set
+#define TPCANDevice quint8 // Represents a PCAN device
+#define TPCANMessageType quint8 // Represents the type of a PCAN message
+#define TPCANType quint8 // Represents the type of PCAN hardware to be initialized
+#define TPCANMode quint8 // Represents a PCAN filter mode
+#define TPCANBaudrate quint16 // Represents a PCAN Baud rate register value
+#define TPCANBitrateFD char * // Represents a PCAN-FD bit rate string
+#define TPCANTimestampFD quint64 // Represents a timestamp of a received PCAN FD message
// Represents a PCAN message
typedef struct tagTPCANMsg
{
- quint32 ID; // 11/29-bit message identifier
+ TPCANLong ID; // 11/29-bit message identifier
TPCANMessageType MSGTYPE; // Type of the message
quint8 LEN; // Data Length Code of the message (0..8)
quint8 DATA[8]; // Data of the message (DATA[0]..DATA[7])
@@ -291,15 +298,15 @@ typedef struct tagTPCANMsg
// Total Microseconds = micros + 1000 * millis + 0xFFFFFFFF * 1000 * millis_overflow
typedef struct tagTPCANTimestamp
{
- quint32 millis; // Base-value: milliseconds: 0.. 2^32-1
- quint16 millis_overflow; // Roll-arounds of millis
- quint16 micros; // Microseconds: 0..999
+ TPCANLong millis; // Base-value: milliseconds: 0.. 2^32-1
+ quint16 millis_overflow; // Roll-arounds of millis
+ quint16 micros; // Microseconds: 0..999
} TPCANTimestamp;
// Represents a PCAN message from a FD capable hardware
typedef struct tagTPCANMsgFD
{
- quint32 ID; // 11/29-bit message identifier
+ TPCANLong ID; // 11/29-bit message identifier
TPCANMessageType MSGTYPE; // Type of the message
quint8 DLC; // Data Length Code of the message (0..15)
quint8 DATA[64]; // Data of the message (DATA[0]..DATA[63])
@@ -314,7 +321,7 @@ typedef struct tagTPCANMsgFD
if (!symbolName) \
return false;
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Initialize, TPCANHandle, TPCANBaudrate, TPCANType, quint32, quint16)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Initialize, TPCANHandle, TPCANBaudrate, TPCANType, TPCANLong, quint16)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_InitializeFD, TPCANHandle, TPCANBitrateFD)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Uninitialize, TPCANHandle)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Reset, TPCANHandle)
@@ -323,15 +330,19 @@ GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Read, TPCANHandle, TPCANMsg *, TPCANTi
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_ReadFD, TPCANHandle, TPCANMsgFD *, TPCANTimestampFD *)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Write, TPCANHandle, TPCANMsg *)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_WriteFD, TPCANHandle, TPCANMsgFD *)
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_FilterMessages, TPCANHandle, quint32, quint32, TPCANMode)
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetValue, TPCANHandle, TPCANParameter, void *, quint32)
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_SetValue, TPCANHandle, TPCANParameter, void *, quint32)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_FilterMessages, TPCANHandle, TPCANLong, TPCANLong, TPCANMode)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetValue, TPCANHandle, TPCANParameter, void *, TPCANLong)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_SetValue, TPCANHandle, TPCANParameter, void *, TPCANLong)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetErrorText, TPCANStatus, quint16, char *)
inline bool resolveSymbols(QLibrary *pcanLibrary)
{
if (!pcanLibrary->isLoaded()) {
- pcanLibrary->setFileName(QStringLiteral("pcanbasic"));
+ #ifdef Q_OS_MACOS
+ pcanLibrary->setFileName(QStringLiteral("PCBUSB"));
+ #else
+ pcanLibrary->setFileName(QStringLiteral("pcanbasic"));
+ #endif
if (!pcanLibrary->load())
return false;
}
diff --git a/src/plugins/canbus/peakcan/peakcanbackend.cpp b/src/plugins/canbus/peakcan/peakcanbackend.cpp
index f8932e9..2f5e2d0 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend.cpp
+++ b/src/plugins/canbus/peakcan/peakcanbackend.cpp
@@ -611,7 +611,7 @@ void PeakCanBackendPrivate::startRead()
continue;
const int size = dlcToSize(static_cast<CanFrameDlc>(message.DLC));
- QCanBusFrame frame(message.ID,
+ QCanBusFrame frame(TPCANLongToFrameID(message.ID),
QByteArray(reinterpret_cast<const char *>(message.DATA), size));
frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(static_cast<qint64>(timestamp)));
frame.setExtendedFrameFormat(message.MSGTYPE & PCAN_MESSAGE_EXTENDED);
@@ -641,7 +641,7 @@ void PeakCanBackendPrivate::startRead()
continue;
const int size = static_cast<int>(message.LEN);
- QCanBusFrame frame(message.ID,
+ QCanBusFrame frame(TPCANLongToFrameID(message.ID),
QByteArray(reinterpret_cast<const char *>(message.DATA), size));
const quint64 millis = timestamp.millis + Q_UINT64_C(0xFFFFFFFF) * timestamp.millis_overflow;
const quint64 micros = Q_UINT64_C(1000) * millis + timestamp.micros;
diff --git a/src/plugins/canbus/socketcan/libsocketcan.cpp b/src/plugins/canbus/socketcan/libsocketcan.cpp
new file mode 100644
index 0000000..ca63391
--- /dev/null
+++ b/src/plugins/canbus/socketcan/libsocketcan.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Andre Hartmann <aha_1980@gmx.de>
+** 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 "libsocketcan.h"
+
+#include <QtCore/qloggingcategory.h>
+
+#if QT_CONFIG(library)
+# include <QtCore/qlibrary.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_SOCKETCAN)
+
+#define GENERATE_SYMBOL(returnType, symbolName, ...) \
+ typedef returnType (*fp_##symbolName)(__VA_ARGS__); \
+ static fp_##symbolName symbolName = nullptr;
+
+#define RESOLVE_SYMBOL(symbolName) \
+ symbolName = reinterpret_cast<fp_##symbolName>(library->resolve(#symbolName)); \
+ if (!symbolName) \
+ return false;
+
+struct can_bittiming {
+ quint32 bitrate = 0; /* Bit-rate in bits/second */
+ quint32 sample_point = 0; /* Sample point in one-tenth of a percent */
+ quint32 tq = 0; /* Time quanta (TQ) in nanoseconds */
+ quint32 prop_seg = 0; /* Propagation segment in TQs */
+ quint32 phase_seg1 = 0; /* Phase buffer segment 1 in TQs */
+ quint32 phase_seg2 = 0; /* Phase buffer segment 2 in TQs */
+ quint32 sjw = 0; /* Synchronization jump width in TQs */
+ quint32 brp = 0; /* Bit-rate prescaler */
+};
+
+GENERATE_SYMBOL(int, can_do_restart, const char * /* name */)
+GENERATE_SYMBOL(int, can_do_stop, const char * /* name */)
+GENERATE_SYMBOL(int, can_do_start, const char * /* name */)
+GENERATE_SYMBOL(int, can_set_bitrate, const char * /* name */, quint32 /* bitrate */)
+GENERATE_SYMBOL(int, can_get_bittiming, const char * /* name */, struct can_bittiming * /* bt */)
+
+LibSocketCan::LibSocketCan(QString *errorString)
+{
+#if QT_CONFIG(library)
+ auto resolveSymbols = [](QLibrary *library) {
+ if (!library->isLoaded()) {
+ library->setFileName(QStringLiteral("socketcan"));
+ if (!library->load())
+ return false;
+ }
+
+ RESOLVE_SYMBOL(can_do_start);
+ RESOLVE_SYMBOL(can_do_stop);
+ RESOLVE_SYMBOL(can_do_restart);
+ RESOLVE_SYMBOL(can_set_bitrate);
+ RESOLVE_SYMBOL(can_get_bittiming);
+
+ return true;
+ };
+
+ QLibrary lib;
+ if (Q_UNLIKELY(!resolveSymbols(&lib))) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "%ls", qUtf16Printable(lib.errorString()));
+ if (errorString)
+ *errorString = lib.errorString();
+ }
+#else
+ const QString error =
+ QObject::tr("Cannot load library libsocketcan as Qt was built without QLibrary.");
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "%ls", qUtf16Printable(error));
+ if (errorString)
+ *errorString = error;
+#endif
+}
+
+/*!
+ Brings the CAN \a interface up.
+
+ \internal
+ \note Requires appropriate permissions.
+*/
+bool LibSocketCan::start(const QString &interface)
+{
+ if (!::can_do_start) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_do_start() is not available.");
+ return false;
+ }
+
+ return ::can_do_start(interface.toLatin1().constData()) == 0;
+}
+
+/*!
+ Brings the CAN \a interface down.
+
+ \internal
+ \note Requires appropriate permissions.
+*/
+bool LibSocketCan::stop(const QString &interface)
+{
+ if (!::can_do_stop) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_do_stop() is not available.");
+ return false;
+ }
+
+ return ::can_do_stop(interface.toLatin1().constData()) == 0;
+}
+
+/*!
+ Performs a CAN controller reset on the CAN \a interface.
+
+ \internal
+ \note Reset can only be triggerd if the controller is in bus off
+ and the auto restart not turned on.
+ \note Requires appropriate permissions.
+ */
+bool LibSocketCan::restart(const QString &interface)
+{
+ if (!::can_do_restart) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_do_restart() is not available.");
+ return false;
+ }
+
+ return ::can_do_restart(interface.toLatin1().constData()) == 0;
+}
+
+/*!
+ Returns the configured bitrate for \a interface.
+ \internal
+*/
+quint32 LibSocketCan::bitrate(const QString &interface) const
+{
+ if (!::can_get_bittiming) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_get_bittiming() is not available.");
+ return 0;
+ }
+
+ struct can_bittiming bt;
+ if (::can_get_bittiming(interface.toLatin1().constData(), &bt) == 0)
+ return bt.bitrate;
+
+ return 0;
+}
+
+/*!
+ Sets the bitrate for the CAN \a interface.
+
+ \internal
+ \note Requires appropriate permissions.
+ */
+bool LibSocketCan::setBitrate(const QString &interface, quint32 bitrate)
+{
+ if (!::can_set_bitrate) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_set_bitrate() is not available.");
+ return false;
+ }
+
+ return ::can_set_bitrate(interface.toLatin1().constData(), bitrate) == 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/canbus/socketcan/libsocketcan.h b/src/plugins/canbus/socketcan/libsocketcan.h
new file mode 100644
index 0000000..91229ee
--- /dev/null
+++ b/src/plugins/canbus/socketcan/libsocketcan.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Andre Hartmann <aha_1980@gmx.de>
+** 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 LIBSOCKETCAN_H
+#define LIBSOCKETCAN_H
+
+#include <QtCore/qglobal.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+class LibSocketCan final
+{
+public:
+ explicit LibSocketCan(QString *errorString = nullptr);
+
+ bool start(const QString &interface);
+ bool stop(const QString &interface);
+ bool restart(const QString &interface);
+
+ quint32 bitrate(const QString &interface) const;
+ bool setBitrate(const QString &interface, quint32 bitrate);
+};
+
+QT_END_NAMESPACE
+
+#endif // LIBSOCKETCAN_H
diff --git a/src/plugins/canbus/socketcan/socketcan.pro b/src/plugins/canbus/socketcan/socketcan.pro
index 20a2c5d..cd731fd 100644
--- a/src/plugins/canbus/socketcan/socketcan.pro
+++ b/src/plugins/canbus/socketcan/socketcan.pro
@@ -3,9 +3,11 @@ TARGET = qtsocketcanbus
QT = core serialbus
HEADERS += \
+ libsocketcan.h \
socketcanbackend.h
SOURCES += \
+ libsocketcan.cpp \
main.cpp \
socketcanbackend.cpp
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index 74b0d1d..cac1db5 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.cpp
+++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp
@@ -36,6 +36,10 @@
#include "socketcanbackend.h"
+#include "libsocketcan.h"
+
+#include <QtSerialBus/qcanbusdevice.h>
+
#include <QtCore/qdatastream.h>
#include <QtCore/qdebug.h>
#include <QtCore/qdiriterator.h>
@@ -181,6 +185,14 @@ QList<QCanBusDeviceInfo> SocketCanBackend::interfaces()
SocketCanBackend::SocketCanBackend(const QString &name) :
canSocketName(name)
{
+ QString errorString;
+ libSocketCan.reset(new LibSocketCan(&errorString));
+ if (Q_UNLIKELY(!errorString.isEmpty())) {
+ qCInfo(QT_CANBUS_PLUGINS_SOCKETCAN,
+ "Cannot load library libsocketcan, some functionality will not be available.\n%ls",
+ qUtf16Printable(errorString));
+ }
+
resetConfigurations();
}
@@ -200,6 +212,8 @@ void SocketCanBackend::resetConfigurations()
QVariant::fromValue(QCanBusFrame::FrameErrors(QCanBusFrame::AnyError)));
QCanBusDevice::setConfigurationParameter(
QCanBusDevice::CanFdKey, false);
+ QCanBusDevice::setConfigurationParameter(
+ QCanBusDevice::BitRateKey, 500000);
}
bool SocketCanBackend::open()
@@ -345,6 +359,12 @@ bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &valu
success = true;
break;
}
+ case QCanBusDevice::BitRateKey:
+ {
+ const quint32 bitRate = value.toUInt();
+ libSocketCan->setBitrate(canSocketName, bitRate);
+ break;
+ }
default:
setError(tr("SocketCanBackend: No such configuration as %1 in SocketCanBackend").arg(key),
QCanBusDevice::CanBusError::ConfigurationError);
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.h b/src/plugins/canbus/socketcan/socketcanbackend.h
index b49d267..1392251 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.h
+++ b/src/plugins/canbus/socketcan/socketcanbackend.h
@@ -52,8 +52,12 @@
#include <linux/can.h>
#include <sys/time.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
+class LibSocketCan;
+
class SocketCanBackend : public QCanBusDevice
{
Q_OBJECT
@@ -89,6 +93,7 @@ private:
qint64 canSocket = -1;
QSocketNotifier *notifier = nullptr;
+ std::unique_ptr<LibSocketCan> libSocketCan;
QString canSocketName;
bool canFdOptionEnabled = false;
};