1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtSerialBus module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "socketcanbackend.h"
38
39#include "libsocketcan.h"
40
41#include <QtSerialBus/qcanbusdevice.h>
42
43#include <QtCore/qdatastream.h>
44#include <QtCore/qdebug.h>
45#include <QtCore/qdiriterator.h>
46#include <QtCore/qfile.h>
47#include <QtCore/qloggingcategory.h>
48#include <QtCore/qsocketnotifier.h>
49
50#include <linux/can/error.h>
51#include <linux/can/raw.h>
52#include <linux/sockios.h>
53#include <errno.h>
54#include <unistd.h>
55#include <net/if.h>
56#include <sys/ioctl.h>
57#include <sys/time.h>
58
59#ifndef CANFD_MTU
60// CAN FD support was added by Linux kernel 3.6
61// For prior kernels we redefine the missing defines here
62// they are taken from linux/can/raw.h & linux/can.h
63
64enum {
65 CAN_RAW_FD_FRAMES = 5
66};
67
68#define CAN_MAX_DLEN 8
69#define CANFD_MAX_DLEN 64
70struct canfd_frame {
71 canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
72 __u8 len; /* frame payload length in byte */
73 __u8 flags; /* additional flags for CAN FD */
74 __u8 __res0; /* reserved / padding */
75 __u8 __res1; /* reserved / padding */
76 __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
77};
78#define CAN_MTU (sizeof(struct can_frame))
79#define CANFD_MTU (sizeof(struct canfd_frame))
80
81#endif
82
83#ifndef CANFD_BRS
84# define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
85#endif
86#ifndef CANFD_ESI
87# define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
88#endif
89
90QT_BEGIN_NAMESPACE
91
92Q_DECLARE_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_SOCKETCAN)
93
94const char sysClassNetC[] = "/sys/class/net/";
95const char interfaceC[] = "/device/interface";
96const char devIdC[] = "/dev_id";
97const char flagsC[] = "/flags";
98const char mtuC[] = "/mtu";
99const char typeC[] = "/type";
100const char virtualC[] = "virtual";
101
102enum {
103 CanFlexibleDataRateMtu = 72,
104 TypeSocketCan = 280,
105 DeviceIsActive = 1
106};
107
108static QByteArray fileContent(const QString &fileName)
109{
110 QFile file(fileName);
111 if (!file.open(QIODevice::ReadOnly))
112 return QByteArray();
113
114 return file.readAll().trimmed();
115}
116
117static bool isFlexibleDataRateCapable(const QString &canDevice)
118{
119 const QString path = QLatin1String(sysClassNetC) + canDevice + QLatin1String(mtuC);
120 const int mtu = fileContent(path).toInt();
121 return mtu == CanFlexibleDataRateMtu;
122}
123
124static bool isVirtual(const QString &canDevice)
125{
126 const QFileInfo fi(QLatin1String(sysClassNetC) + canDevice);
127 return fi.canonicalPath().contains(QLatin1String(virtualC));
128}
129
130static quint32 flags(const QString &canDevice)
131{
132 const QString path = QLatin1String(sysClassNetC) + canDevice + QLatin1String(flagsC);
133 const quint32 result = fileContent(path).toUInt(nullptr, 0);
134 return result;
135}
136
137static QString deviceDescription(const QString &canDevice)
138{
139 const QString path = QLatin1String(sysClassNetC) + canDevice + QLatin1String(interfaceC);
140 const QByteArray content = fileContent(path);
141 if (content.isEmpty() && isVirtual(canDevice))
142 return QStringLiteral("Virtual CAN");
143
144 return QString::fromUtf8(content);
145}
146
147static int deviceChannel(const QString &canDevice)
148{
149 const QString path = QLatin1String(sysClassNetC) + canDevice + QLatin1String(devIdC);
150 const QByteArray content = fileContent(path);
151 return content.toInt(nullptr, 0);
152}
153
154QList<QCanBusDeviceInfo> SocketCanBackend::interfaces()
155{
156 QList<QCanBusDeviceInfo> result;
157 QDirIterator it(sysClassNetC,
158 QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot,
159 QDirIterator::Subdirectories);
160
161 while (it.hasNext()) {
162 const QString dirEntry = it.next();
163 if (fileContent(dirEntry + QLatin1String(typeC)).toInt() != TypeSocketCan)
164 continue;
165
166 const QString deviceName = dirEntry.mid(strlen(sysClassNetC));
167 if (!(flags(deviceName) & DeviceIsActive))
168 continue;
169
170 const QString serial;
171 const QString description = deviceDescription(deviceName);
172 const int channel = deviceChannel(deviceName);
173 result.append(std::move(createDeviceInfo(deviceName, serial, description,
174 channel, isVirtual(deviceName),
175 isFlexibleDataRateCapable(deviceName))));
176 }
177
178 std::sort(result.begin(), result.end(),
179 [](const QCanBusDeviceInfo &a, const QCanBusDeviceInfo &b) {
180 return a.name() < b.name();
181 });
182
183 return result;
184}
185
186SocketCanBackend::SocketCanBackend(const QString &name) :
187 canSocketName(name)
188{
189 QString errorString;
190 libSocketCan.reset(new LibSocketCan(&errorString));
191 if (Q_UNLIKELY(!errorString.isEmpty())) {
192 qCInfo(QT_CANBUS_PLUGINS_SOCKETCAN,
193 "Cannot load library libsocketcan, some functionality will not be available.\n%ls",
194 qUtf16Printable(errorString));
195 }
196
197 resetConfigurations();
198
199 std::function<void()> f = std::bind(&SocketCanBackend::resetController, this);
200 setResetControllerFunction(f);
201
202 if (hasBusStatus()) {
203 // Only register busStatus when libsocketcan is available
204 // QCanBusDevice::hasBusStatus() will return false otherwise
205 std::function<CanBusStatus()> g = std::bind(&SocketCanBackend::busStatus, this);
206 setCanBusStatusGetter(g);
207 }
208}
209
210SocketCanBackend::~SocketCanBackend()
211{
212 close();
213}
214
215void SocketCanBackend::resetConfigurations()
216{
217 QCanBusDevice::setConfigurationParameter(
218 QCanBusDevice::LoopbackKey, true);
219 QCanBusDevice::setConfigurationParameter(
220 QCanBusDevice::ReceiveOwnKey, false);
221 QCanBusDevice::setConfigurationParameter(
222 QCanBusDevice::ErrorFilterKey,
223 QVariant::fromValue(QCanBusFrame::FrameErrors(QCanBusFrame::AnyError)));
224 QCanBusDevice::setConfigurationParameter(
225 QCanBusDevice::CanFdKey, false);
226 QCanBusDevice::setConfigurationParameter(
227 QCanBusDevice::BitRateKey, 500000);
228}
229
230bool SocketCanBackend::open()
231{
232 if (canSocket == -1) {
233 if (!connectSocket()) {
234 close(); // sets UnconnectedState
235 return false;
236 }
237 }
238
239 setState(QCanBusDevice::ConnectedState);
240 return true;
241}
242
243void SocketCanBackend::close()
244{
245 ::close(canSocket);
246 canSocket = -1;
247
248 setState(QCanBusDevice::UnconnectedState);
249}
250
251bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &value)
252{
253 bool success = false;
254
255 switch (key) {
256 case QCanBusDevice::LoopbackKey:
257 {
258 const int loopback = value.toBool() ? 1 : 0;
259 if (Q_UNLIKELY(setsockopt(canSocket, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
260 &loopback, sizeof(loopback)) < 0)) {
261 setError(qt_error_string(errno),
262 QCanBusDevice::CanBusError::ConfigurationError);
263 break;
264 }
265 success = true;
266 break;
267 }
268 case QCanBusDevice::ReceiveOwnKey:
269 {
270 const int receiveOwnMessages = value.toBool() ? 1 : 0;
271 if (Q_UNLIKELY(setsockopt(canSocket, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
272 &receiveOwnMessages, sizeof(receiveOwnMessages)) < 0)) {
273 setError(qt_error_string(errno),
274 QCanBusDevice::CanBusError::ConfigurationError);
275 break;
276 }
277 success = true;
278 break;
279 }
280 case QCanBusDevice::ErrorFilterKey:
281 {
282 const int errorMask = value.value<QCanBusFrame::FrameErrors>();
283 if (Q_UNLIKELY(setsockopt(canSocket, SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
284 &errorMask, sizeof(errorMask)) < 0)) {
285 setError(qt_error_string(errno),
286 QCanBusDevice::CanBusError::ConfigurationError);
287 break;
288 }
289 success = true;
290 break;
291 }
292 case QCanBusDevice::RawFilterKey:
293 {
294 const QList<QCanBusDevice::Filter> filterList
295 = value.value<QList<QCanBusDevice::Filter> >();
296 if (!value.isValid() || filterList.isEmpty()) {
297 // permit every frame - no restrictions (filter reset)
298 can_filter filters = {0, 0};
299 socklen_t s = sizeof(can_filter);
300 if (Q_UNLIKELY(setsockopt(canSocket, SOL_CAN_RAW, CAN_RAW_FILTER,
301 &filters, s) != 0)) {
302 qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Cannot unset socket filters.");
303 setError(qt_error_string(errno),
304 QCanBusDevice::CanBusError::ConfigurationError);
305 break;
306 }
307 success = true;
308 break;
309 }
310
311 QVector<can_filter> filters;
312 filters.resize(filterList.size());
313 for (int i = 0; i < filterList.size(); i++) {
314 const QCanBusDevice::Filter f = filterList.at(i);
315 can_filter filter = { f.frameId, f.frameIdMask };
316
317 // frame type filter
318 switch (f.type) {
319 default:
320 // any other type cannot be filtered upon
321 setError(tr("Cannot set filter for frame type: %1").arg(f.type),
322 QCanBusDevice::CanBusError::ConfigurationError);
323 return false;
324 case QCanBusFrame::InvalidFrame:
325 break;
326 case QCanBusFrame::DataFrame:
327 filter.can_mask |= CAN_RTR_FLAG;
328 break;
329 case QCanBusFrame::ErrorFrame:
330 filter.can_mask |= CAN_ERR_FLAG;
331 filter.can_id |= CAN_ERR_FLAG;
332 break;
333 case QCanBusFrame::RemoteRequestFrame:
334 filter.can_mask |= CAN_RTR_FLAG;
335 filter.can_id |= CAN_RTR_FLAG;
336 break;
337 }
338
339 // frame format filter
340 if ((f.format & QCanBusDevice::Filter::MatchBaseAndExtendedFormat)
341 == QCanBusDevice::Filter::MatchBaseAndExtendedFormat) {
342 // nothing
343 } else if (f.format & QCanBusDevice::Filter::MatchBaseFormat) {
344 filter.can_mask |= CAN_EFF_FLAG;
345 } else if (f.format & QCanBusDevice::Filter::MatchExtendedFormat) {
346 filter.can_mask |= CAN_EFF_FLAG;
347 filter.can_id |= CAN_EFF_FLAG;
348 }
349
350 filters[i] = filter;
351 }
352 if (Q_UNLIKELY(setsockopt(canSocket, SOL_CAN_RAW, CAN_RAW_FILTER,
353 filters.constData(), sizeof(filters[0]) * filters.size()) < 0)) {
354 setError(qt_error_string(errno),
355 QCanBusDevice::CanBusError::ConfigurationError);
356 break;
357 }
358 success = true;
359 break;
360 }
361 case QCanBusDevice::CanFdKey:
362 {
363 const int fd_frames = value.toBool() ? 1 : 0;
364 if (Q_UNLIKELY(setsockopt(canSocket, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
365 &fd_frames, sizeof(fd_frames)) < 0)) {
366 setError(qt_error_string(errno),
367 QCanBusDevice::CanBusError::ConfigurationError);
368 break;
369 }
370 success = true;
371 break;
372 }
373 case QCanBusDevice::BitRateKey:
374 {
375 const quint32 bitRate = value.toUInt();
376 libSocketCan->setBitrate(canSocketName, bitRate);
377 break;
378 }
379 default:
380 setError(tr("SocketCanBackend: No such configuration as %1 in SocketCanBackend").arg(key),
381 QCanBusDevice::CanBusError::ConfigurationError);
382 break;
383 }
384
385 return success;
386}
387
388bool SocketCanBackend::connectSocket()
389{
390 struct ifreq interface;
391
392 if (Q_UNLIKELY((canSocket = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, protocol)) < 0)) {
393 setError(qt_error_string(errno),
394 QCanBusDevice::CanBusError::ConnectionError);
395 return false;
396 }
397
398 qstrncpy(interface.ifr_name, canSocketName.toLatin1().constData(), sizeof(interface.ifr_name));
399 if (Q_UNLIKELY(ioctl(canSocket, SIOCGIFINDEX, &interface) < 0)) {
400 setError(qt_error_string(errno),
401 QCanBusDevice::CanBusError::ConnectionError);
402 return false;
403 }
404
405 m_address.can_family = AF_CAN;
406 m_address.can_ifindex = interface.ifr_ifindex;
407
408 if (Q_UNLIKELY(bind(canSocket, reinterpret_cast<struct sockaddr *>(&m_address), sizeof(m_address)) < 0)) {
409 setError(qt_error_string(errno),
410 QCanBusDevice::CanBusError::ConnectionError);
411 return false;
412 }
413
414 m_iov.iov_base = &m_frame;
415 m_msg.msg_name = &m_address;
416 m_msg.msg_iov = &m_iov;
417 m_msg.msg_iovlen = 1;
418 m_msg.msg_control = &m_ctrlmsg;
419
420 delete notifier;
421
422 notifier = new QSocketNotifier(canSocket, QSocketNotifier::Read, this);
423 connect(notifier, &QSocketNotifier::activated,
424 this, &SocketCanBackend::readSocket);
425
426 //apply all stored configurations
427 const auto keys = configurationKeys();
428 for (int key : keys) {
429 const QVariant param = configurationParameter(key);
430 bool success = applyConfigurationParameter(key, param);
431 if (Q_UNLIKELY(!success)) {
432 qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Cannot apply parameter: %d with value: %ls.",
433 key, qUtf16Printable(param.toString()));
434 }
435 }
436
437 return true;
438}
439
440void SocketCanBackend::setConfigurationParameter(int key, const QVariant &value)
441{
442 if (key == QCanBusDevice::RawFilterKey) {
443 //verify valid/supported filters
444
445 const auto filters = value.value<QList<QCanBusDevice::Filter> >();
446 for (QCanBusDevice::Filter f : filters) {
447 switch (f.type) {
448 case QCanBusFrame::UnknownFrame:
449
450 default:
451 setError(tr("Cannot set filter for frame type: %1").arg(f.type),
452 QCanBusDevice::CanBusError::ConfigurationError);
453 return;
454 case QCanBusFrame::InvalidFrame:
455 case QCanBusFrame::DataFrame:
456 case QCanBusFrame::ErrorFrame:
457 case QCanBusFrame::RemoteRequestFrame:
458 break;
459 }
460
461 if (f.frameId > 0x1FFFFFFFU) {
462 setError(tr("FrameId %1 larger than 29 bit.").arg(f.frameId),
463 QCanBusDevice::CanBusError::ConfigurationError);
464 return;
465 }
466 }
467 } else if (key == QCanBusDevice::ProtocolKey) {
468 bool ok = false;
469 const int newProtocol = value.toInt(&ok);
470 if (Q_UNLIKELY(!ok || (newProtocol < 0))) {
471 const QString errorString = tr("Cannot set protocol to value %1.").arg(value.toString());
472 setError(errorString, QCanBusDevice::ConfigurationError);
473 qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "%ls", qUtf16Printable(errorString));
474 return;
475 }
476 protocol = newProtocol;
477 }
478 // connected & params not applyable/invalid
479 if (canSocket != -1 && !applyConfigurationParameter(key, value))
480 return;
481
482 QCanBusDevice::setConfigurationParameter(key, value);
483
484 // we need to check CAN FD option a lot -> cache it and avoid QVector lookup
485 if (key == QCanBusDevice::CanFdKey)
486 canFdOptionEnabled = value.toBool();
487}
488
489bool SocketCanBackend::writeFrame(const QCanBusFrame &newData)
490{
491 if (state() != ConnectedState)
492 return false;
493
494 if (Q_UNLIKELY(!newData.isValid())) {
495 setError(tr("Cannot write invalid QCanBusFrame"), QCanBusDevice::WriteError);
496 return false;
497 }
498
499 canid_t canId = newData.frameId();
500 if (newData.hasExtendedFrameFormat())
501 canId |= CAN_EFF_FLAG;
502
503 if (newData.frameType() == QCanBusFrame::RemoteRequestFrame) {
504 canId |= CAN_RTR_FLAG;
505 } else if (newData.frameType() == QCanBusFrame::ErrorFrame) {
506 canId = static_cast<canid_t>((newData.error() & QCanBusFrame::AnyError));
507 canId |= CAN_ERR_FLAG;
508 }
509
510 if (Q_UNLIKELY(!canFdOptionEnabled && newData.hasFlexibleDataRateFormat())) {
511 const QString error = tr("Cannot write CAN FD frame because CAN FD option is not enabled.");
512 qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "%ls", qUtf16Printable(error));
513 setError(error, QCanBusDevice::WriteError);
514 return false;
515 }
516
517 qint64 bytesWritten = 0;
518 if (newData.hasFlexibleDataRateFormat()) {
519 canfd_frame frame;
520 ::memset(&frame, 0, sizeof(frame));
521 frame.len = newData.payload().size();
522 frame.can_id = canId;
523 frame.flags = newData.hasBitrateSwitch() ? CANFD_BRS : 0;
524 frame.flags |= newData.hasErrorStateIndicator() ? CANFD_ESI : 0;
525 ::memcpy(frame.data, newData.payload().constData(), frame.len);
526
527 bytesWritten = ::write(canSocket, &frame, sizeof(frame));
528 } else {
529 can_frame frame;
530 ::memset(&frame, 0, sizeof(frame));
531 frame.can_dlc = newData.payload().size();
532 frame.can_id = canId;
533 ::memcpy(frame.data, newData.payload().constData(), frame.can_dlc);
534
535 bytesWritten = ::write(canSocket, &frame, sizeof(frame));
536 }
537
538 if (Q_UNLIKELY(bytesWritten < 0)) {
539 setError(qt_error_string(errno),
540 QCanBusDevice::CanBusError::WriteError);
541 return false;
542 }
543
544 emit framesWritten(1);
545
546 return true;
547}
548
549QString SocketCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
550{
551 if (errorFrame.frameType() != QCanBusFrame::ErrorFrame)
552 return QString();
553
554 // the payload may contain the error details
555 const QByteArray data = errorFrame.payload();
556 QString errorMsg;
557
558 if (errorFrame.error() & QCanBusFrame::TransmissionTimeoutError)
559 errorMsg += QStringLiteral("TX timout\n");
560
561 if (errorFrame.error() & QCanBusFrame::MissingAcknowledgmentError)
562 errorMsg += QStringLiteral("Received no ACK on transmission\n");
563
564 if (errorFrame.error() & QCanBusFrame::BusOffError)
565 errorMsg += QStringLiteral("Bus off\n");
566
567 if (errorFrame.error() & QCanBusFrame::BusError)
568 errorMsg += QStringLiteral("Bus error\n");
569
570 if (errorFrame.error() & QCanBusFrame::ControllerRestartError)
571 errorMsg += QStringLiteral("Controller restarted\n");
572
573 if (errorFrame.error() & QCanBusFrame::UnknownError)
574 errorMsg += QStringLiteral("Unknown error\n");
575
576 if (errorFrame.error() & QCanBusFrame::LostArbitrationError) {
577 errorMsg += QStringLiteral("Lost arbitration:\n");
578 if (data.size() >= 1) {
579 errorMsg += QString::number(data.at(0), 16);
580 errorMsg += QStringLiteral(" bit\n");
581 }
582 }
583
584 if (errorFrame.error() & QCanBusFrame::ControllerError) {
585 errorMsg += QStringLiteral("Controller problem:\n");
586 if (data.size() >= 2) {
587 char b = data.at(1) ;
588 if (b & CAN_ERR_CRTL_RX_OVERFLOW)
589 errorMsg += QStringLiteral(" RX buffer overflow\n");
590 if (b & CAN_ERR_CRTL_TX_OVERFLOW)
591 errorMsg += QStringLiteral(" TX buffer overflow\n");
592 if (b & CAN_ERR_CRTL_RX_WARNING)
593 errorMsg += QStringLiteral(" reached warning level for RX errors\n");
594 if (b & CAN_ERR_CRTL_TX_WARNING)
595 errorMsg += QStringLiteral(" reached warning level for TX errors\n");
596 if (b & CAN_ERR_CRTL_RX_PASSIVE)
597 errorMsg += QStringLiteral(" reached error passive status RX\n");
598 if (b & CAN_ERR_CRTL_TX_PASSIVE)
599 errorMsg += QStringLiteral(" reached error passive status TX\n");
600
601 if (b == CAN_ERR_CRTL_UNSPEC)
602 errorMsg += QStringLiteral(" Unspecified error\n");
603 }
604 }
605
606 if (errorFrame.error() & QCanBusFrame::TransceiverError) {
607 errorMsg = QStringLiteral("Transceiver status:");
608 if (data.size() >= 5) {
609 char b = data.at(4);
610 if (b & CAN_ERR_TRX_CANH_NO_WIRE)
611 errorMsg += QStringLiteral(" CAN-transceiver CANH no wire\n");
612 if (b & CAN_ERR_TRX_CANH_SHORT_TO_BAT)
613 errorMsg += QStringLiteral(" CAN-transceiver CANH short to bat\n");
614 if (b & CAN_ERR_TRX_CANH_SHORT_TO_VCC)
615 errorMsg += QStringLiteral(" CAN-transceiver CANH short to vcc\n");
616 if (b & CAN_ERR_TRX_CANH_SHORT_TO_GND)
617 errorMsg += QStringLiteral(" CAN-transceiver CANH short to ground\n");
618 if (b & CAN_ERR_TRX_CANL_NO_WIRE)
619 errorMsg += QStringLiteral(" CAN-transceiver CANL no wire\n");
620 if (b & CAN_ERR_TRX_CANL_SHORT_TO_BAT)
621 errorMsg += QStringLiteral(" CAN-transceiver CANL short to bat\n");
622 if (b & CAN_ERR_TRX_CANL_SHORT_TO_VCC)
623 errorMsg += QStringLiteral(" CAN-transceiver CANL short to vcc\n");
624 if (b & CAN_ERR_TRX_CANL_SHORT_TO_GND)
625 errorMsg += QStringLiteral(" CAN-transceiver CANL short to ground\n");
626 if (b & CAN_ERR_TRX_CANL_SHORT_TO_CANH)
627 errorMsg += QStringLiteral(" CAN-transceiver CANL short to CANH\n");
628
629 if (b == CAN_ERR_TRX_UNSPEC)
630 errorMsg += QStringLiteral(" unspecified\n");
631 }
632
633 }
634
635 if (errorFrame.error() & QCanBusFrame::ProtocolViolationError) {
636 errorMsg += QStringLiteral("Protocol violation:\n");
637 if (data.size() > 3) {
638 char b = data.at(2);
639 if (b & CAN_ERR_PROT_BIT)
640 errorMsg += QStringLiteral(" single bit error\n");
641 if (b & CAN_ERR_PROT_FORM)
642 errorMsg += QStringLiteral(" frame format error\n");
643 if (b & CAN_ERR_PROT_STUFF)
644 errorMsg += QStringLiteral(" bit stuffing error\n");
645 if (b & CAN_ERR_PROT_BIT0)
646 errorMsg += QStringLiteral(" unable to send dominant bit\n");
647 if (b & CAN_ERR_PROT_BIT1)
648 errorMsg += QStringLiteral(" unable to send recessive bit\n");
649 if (b & CAN_ERR_PROT_OVERLOAD)
650 errorMsg += QStringLiteral(" bus overload\n");
651 if (b & CAN_ERR_PROT_ACTIVE)
652 errorMsg += QStringLiteral(" active error announcement\n");
653 if (b & CAN_ERR_PROT_TX)
654 errorMsg += QStringLiteral(" error occurred on transmission\n");
655
656 if (b == CAN_ERR_PROT_UNSPEC)
657 errorMsg += QStringLiteral(" unspecified\n");
658 }
659 if (data.size() > 4) {
660 char b = data.at(3);
661 if (b == CAN_ERR_PROT_LOC_SOF)
662 errorMsg += QStringLiteral(" start of frame\n");
663 if (b == CAN_ERR_PROT_LOC_ID28_21)
664 errorMsg += QStringLiteral(" ID bits 28 - 21 (SFF: 10 - 3)\n");
665 if (b == CAN_ERR_PROT_LOC_ID20_18)
666 errorMsg += QStringLiteral(" ID bits 20 - 18 (SFF: 2 - 0 )\n");
667 if (b == CAN_ERR_PROT_LOC_SRTR)
668 errorMsg += QStringLiteral(" substitute RTR (SFF: RTR)\n");
669 if (b == CAN_ERR_PROT_LOC_IDE)
670 errorMsg += QStringLiteral(" identifier extension\n");
671 if (b == CAN_ERR_PROT_LOC_ID17_13)
672 errorMsg += QStringLiteral(" ID bits 17-13\n");
673 if (b == CAN_ERR_PROT_LOC_ID12_05)
674 errorMsg += QStringLiteral(" ID bits 12-5\n");
675 if (b == CAN_ERR_PROT_LOC_ID04_00)
676 errorMsg += QStringLiteral(" ID bits 4-0\n");
677 if (b == CAN_ERR_PROT_LOC_RTR)
678 errorMsg += QStringLiteral(" RTR\n");
679 if (b == CAN_ERR_PROT_LOC_RES1)
680 errorMsg += QStringLiteral(" reserved bit 1\n");
681 if (b == CAN_ERR_PROT_LOC_RES0)
682 errorMsg += QStringLiteral(" reserved bit 0\n");
683 if (b == CAN_ERR_PROT_LOC_DLC)
684 errorMsg += QStringLiteral(" data length code\n");
685 if (b == CAN_ERR_PROT_LOC_DATA)
686 errorMsg += QStringLiteral(" data section\n");
687 if (b == CAN_ERR_PROT_LOC_CRC_SEQ)
688 errorMsg += QStringLiteral(" CRC sequence\n");
689 if (b == CAN_ERR_PROT_LOC_CRC_DEL)
690 errorMsg += QStringLiteral(" CRC delimiter\n");
691 if (b == CAN_ERR_PROT_LOC_ACK)
692 errorMsg += QStringLiteral(" ACK slot\n");
693 if (b == CAN_ERR_PROT_LOC_ACK_DEL)
694 errorMsg += QStringLiteral(" ACK delimiter\n");
695 if (b == CAN_ERR_PROT_LOC_EOF)
696 errorMsg += QStringLiteral(" end of frame\n");
697 if (b == CAN_ERR_PROT_LOC_INTERM)
698 errorMsg += QStringLiteral(" Intermission\n");
699
700 if (b == CAN_ERR_PROT_LOC_UNSPEC)
701 errorMsg += QStringLiteral(" unspecified\n");
702 }
703 }
704
705 // cut trailing \n
706 if (!errorMsg.isEmpty())
707 errorMsg.chop(1);
708
709 return errorMsg;
710}
711
712void SocketCanBackend::readSocket()
713{
714 QVector<QCanBusFrame> newFrames;
715
716 for (;;) {
717 ::memset(&m_frame, 0, sizeof(m_frame));
718 m_iov.iov_len = sizeof(m_frame);
719 m_msg.msg_namelen = sizeof(m_addr);
720 m_msg.msg_controllen = sizeof(m_ctrlmsg);
721 m_msg.msg_flags = 0;
722
723 const int bytesReceived = ::recvmsg(canSocket, &m_msg, 0);
724
725 if (bytesReceived <= 0) {
726 break;
727 } else if (Q_UNLIKELY(bytesReceived != CANFD_MTU && bytesReceived != CAN_MTU)) {
728 setError(tr("ERROR SocketCanBackend: incomplete CAN frame"),
729 QCanBusDevice::CanBusError::ReadError);
730 continue;
731 } else if (Q_UNLIKELY(m_frame.len > bytesReceived - offsetof(canfd_frame, data))) {
732 setError(tr("ERROR SocketCanBackend: invalid CAN frame length"),
733 QCanBusDevice::CanBusError::ReadError);
734 continue;
735 }
736
737 struct timeval timeStamp;
738 if (Q_UNLIKELY(ioctl(canSocket, SIOCGSTAMP, &timeStamp) < 0)) {
739 setError(qt_error_string(errno),
740 QCanBusDevice::CanBusError::ReadError);
741 ::memset(&timeStamp, 0, sizeof(timeStamp));
742 }
743
744 const QCanBusFrame::TimeStamp stamp(timeStamp.tv_sec, timeStamp.tv_usec);
745 QCanBusFrame bufferedFrame;
746 bufferedFrame.setTimeStamp(stamp);
747 bufferedFrame.setFlexibleDataRateFormat(bytesReceived == CANFD_MTU);
748
749 bufferedFrame.setExtendedFrameFormat(m_frame.can_id & CAN_EFF_FLAG);
750 Q_ASSERT(m_frame.len <= CANFD_MAX_DLEN);
751
752 if (m_frame.can_id & CAN_RTR_FLAG)
753 bufferedFrame.setFrameType(QCanBusFrame::RemoteRequestFrame);
754 if (m_frame.can_id & CAN_ERR_FLAG)
755 bufferedFrame.setFrameType(QCanBusFrame::ErrorFrame);
756 if (m_frame.flags & CANFD_BRS)
757 bufferedFrame.setBitrateSwitch(true);
758 if (m_frame.flags & CANFD_ESI)
759 bufferedFrame.setErrorStateIndicator(true);
760 if (m_msg.msg_flags & MSG_CONFIRM)
761 bufferedFrame.setLocalEcho(true);
762
763 bufferedFrame.setFrameId(m_frame.can_id & CAN_EFF_MASK);
764
765 const QByteArray load(reinterpret_cast<char *>(m_frame.data), m_frame.len);
766 bufferedFrame.setPayload(load);
767
768 newFrames.append(std::move(bufferedFrame));
769 }
770
771 enqueueReceivedFrames(newFrames);
772}
773
774void SocketCanBackend::resetController()
775{
776 libSocketCan->restart(canSocketName);
777}
778
779bool SocketCanBackend::hasBusStatus() const
780{
781 return libSocketCan->hasBusStatus();
782}
783
784QCanBusDevice::CanBusStatus SocketCanBackend::busStatus() const
785{
786 return libSocketCan->busStatus(canSocketName);
787}
788
789QT_END_NAMESPACE
790