summaryrefslogtreecommitdiffstats
path: root/src/plugins/canbus/socketcan
diff options
context:
space:
mode:
authorAndre Hartmann <aha_1980@gmx.de>2017-02-02 15:21:04 +0100
committerAndré Hartmann <aha_1980@gmx.de>2017-07-04 05:49:54 +0000
commite23f4ced90381925406bd854dd3b3d1eeb478d87 (patch)
tree9dfc9fd27982c42e76fbdc9816cc6e00932a6e77 /src/plugins/canbus/socketcan
parente257664ae65ce5c51c7edac0a1a9ffaba4baea70 (diff)
QCanBusFrame: Introduce local echo flag
Inspiration for change after reading the SocketCAN mailing list thread: https://marc.info/?l=linux-can&m=147438437202356&w=2 The main usage is, to verify at application stage, that and when a frame was really sent on the bus. For architectures like SocketCAN, where multiple applications can connect to one CAN bus on the same system, this flag also indicates frames that are sent by an other local running application (i.e. not coming from the real bus). Implementations done for SystecCAN, VectorCAN and SocketCAN plugin. PCAN Basic does not seem to have support for this flag. For SocketCAN, see section "4.1.7 RAW socket returned message flags" in https://www.kernel.org/doc/Documentation/networking/can.txt for reference. [ChangeLog][QCanBusFrame] Added local echo flag to mark all echo frames that are generated by the hardware on successful transmission to CAN bus as such. Change-Id: I66d4ce1ec6dfd0a0b994a7b7a9de1a5f503fcb70 Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src/plugins/canbus/socketcan')
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp42
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.h13
2 files changed, 39 insertions, 16 deletions
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index 27a847d..a26070a 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.cpp
+++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp
@@ -325,7 +325,6 @@ bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &valu
bool SocketCanBackend::connectSocket()
{
- struct sockaddr_can address;
struct ifreq interface;
if (Q_UNLIKELY((canSocket = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)) < 0)) {
@@ -341,15 +340,21 @@ bool SocketCanBackend::connectSocket()
return false;
}
- address.can_family = AF_CAN;
- address.can_ifindex = interface.ifr_ifindex;
+ m_address.can_family = AF_CAN;
+ m_address.can_ifindex = interface.ifr_ifindex;
- if (Q_UNLIKELY(bind(canSocket, reinterpret_cast<struct sockaddr *>(&address), sizeof(address)) < 0)) {
+ if (Q_UNLIKELY(bind(canSocket, reinterpret_cast<struct sockaddr *>(&m_address), sizeof(m_address)) < 0)) {
setError(qt_error_string(errno),
QCanBusDevice::CanBusError::ConnectionError);
return false;
}
+ m_iov.iov_base = &m_frame;
+ m_msg.msg_name = &m_address;
+ m_msg.msg_iov = &m_iov;
+ m_msg.msg_iovlen = 1;
+ m_msg.msg_control = &m_ctrlmsg;
+
delete notifier;
notifier = new QSocketNotifier(canSocket, QSocketNotifier::Read, this);
@@ -637,10 +642,13 @@ void SocketCanBackend::readSocket()
QVector<QCanBusFrame> newFrames;
for (;;) {
- struct canfd_frame frame;
- int bytesReceived;
+ memset(&m_frame, 0, sizeof(m_frame));
+ m_iov.iov_len = sizeof(m_frame);
+ m_msg.msg_namelen = sizeof(m_addr);
+ m_msg.msg_controllen = sizeof(m_ctrlmsg);
+ m_msg.msg_flags = 0;
- bytesReceived = ::read(canSocket, &frame, sizeof(frame));
+ const int bytesReceived = ::recvmsg(canSocket, &m_msg, 0);
if (bytesReceived <= 0) {
break;
@@ -648,7 +656,7 @@ void SocketCanBackend::readSocket()
setError(tr("ERROR SocketCanBackend: incomplete CAN frame"),
QCanBusDevice::CanBusError::ReadError);
continue;
- } else if (Q_UNLIKELY(frame.len > bytesReceived - offsetof(canfd_frame, data))) {
+ } else if (Q_UNLIKELY(m_frame.len > bytesReceived - offsetof(canfd_frame, data))) {
setError(tr("ERROR SocketCanBackend: invalid CAN frame length"),
QCanBusDevice::CanBusError::ReadError);
continue;
@@ -666,21 +674,23 @@ void SocketCanBackend::readSocket()
bufferedFrame.setTimeStamp(stamp);
bufferedFrame.setFlexibleDataRateFormat(bytesReceived == CANFD_MTU);
- bufferedFrame.setExtendedFrameFormat(frame.can_id & CAN_EFF_FLAG);
- Q_ASSERT(frame.len <= CANFD_MAX_DLEN);
+ bufferedFrame.setExtendedFrameFormat(m_frame.can_id & CAN_EFF_FLAG);
+ Q_ASSERT(m_frame.len <= CANFD_MAX_DLEN);
- if (frame.can_id & CAN_RTR_FLAG)
+ if (m_frame.can_id & CAN_RTR_FLAG)
bufferedFrame.setFrameType(QCanBusFrame::RemoteRequestFrame);
- if (frame.can_id & CAN_ERR_FLAG)
+ if (m_frame.can_id & CAN_ERR_FLAG)
bufferedFrame.setFrameType(QCanBusFrame::ErrorFrame);
- if (frame.flags & CANFD_BRS)
+ if (m_frame.flags & CANFD_BRS)
bufferedFrame.setBitrateSwitch(true);
- if (frame.flags & CANFD_ESI)
+ if (m_frame.flags & CANFD_ESI)
bufferedFrame.setErrorStateIndicator(true);
+ if (m_msg.msg_flags & MSG_CONFIRM)
+ bufferedFrame.setLocalEcho(true);
- bufferedFrame.setFrameId(frame.can_id & CAN_EFF_MASK);
+ bufferedFrame.setFrameId(m_frame.can_id & CAN_EFF_MASK);
- const QByteArray load(reinterpret_cast<char *>(frame.data), frame.len);
+ const QByteArray load(reinterpret_cast<char *>(m_frame.data), m_frame.len);
bufferedFrame.setPayload(load);
newFrames.append(std::move(bufferedFrame));
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.h b/src/plugins/canbus/socketcan/socketcanbackend.h
index 70c47c8..50976b1 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.h
+++ b/src/plugins/canbus/socketcan/socketcanbackend.h
@@ -45,6 +45,12 @@
#include <QtCore/qstring.h>
#include <QtCore/qvariant.h>
+// The order of the following includes is mandatory, because some
+// distributions use sa_family_t in can.h without including socket.h
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <linux/can.h>
+
QT_BEGIN_NAMESPACE
class SocketCanBackend : public QCanBusDevice
@@ -73,6 +79,13 @@ private:
bool connectSocket();
bool applyConfigurationParameter(int key, const QVariant &value);
+ canfd_frame m_frame;
+ sockaddr_can m_address;
+ msghdr m_msg;
+ iovec m_iov;
+ sockaddr_can m_addr;
+ char m_ctrlmsg[CMSG_SPACE(sizeof(timeval)) + CMSG_SPACE(sizeof(__u32))];
+
qint64 canSocket = -1;
QSocketNotifier *notifier = nullptr;
QString canSocketName;