summaryrefslogtreecommitdiffstats
path: root/src/plugins/canbus/socketcan/libsocketcan.cpp
diff options
context:
space:
mode:
authorAndre Hartmann <aha_1980@gmx.de>2016-08-11 20:19:06 +0200
committerAndré Hartmann <aha_1980@gmx.de>2019-02-22 18:47:37 +0000
commit6ddb74e8165fc9658ab57ff5a3e09eb23ad9c69e (patch)
tree3944ab8ed5c5523d30e2f25bee7946447fe3484b /src/plugins/canbus/socketcan/libsocketcan.cpp
parenteb85cebadb546dafe7c87db931164491ad5cca89 (diff)
SocketCAN: Set and get bitrate by loading libsocketcan dynamically
Can be extended for further functions from this library also. [ChangeLog][Plugins][SocketCAN] If libsocketcan is available, the CAN bus bitrate can be get and set at runtime. Fixes: QTBUG-54296 Change-Id: Ie677ddb5cf4ee9f99927973d837ef7a2810a2b37 Reviewed-by: Rolf Eike Beer <eb@emlix.com> Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
Diffstat (limited to 'src/plugins/canbus/socketcan/libsocketcan.cpp')
-rw-r--r--src/plugins/canbus/socketcan/libsocketcan.cpp193
1 files changed, 193 insertions, 0 deletions
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