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 "qcanbusdevice.h"
38 #include "qcanbusdevice_p.h"
39 #include "qcanbusdeviceinfo_p.h"
40 
41 #include "qcanbusframe.h"
42 
43 #include <QtCore/qdebug.h>
44 #include <QtCore/qdatastream.h>
45 #include <QtCore/qeventloop.h>
46 #include <QtCore/qloggingcategory.h>
47 #include <QtCore/qscopedvaluerollback.h>
48 #include <QtCore/qtimer.h>
49 
50 QT_BEGIN_NAMESPACE
51 
52 Q_LOGGING_CATEGORY(QT_CANBUS, "qt.canbus")
53 
54 /*!
55     \class QCanBusDevice
56     \inmodule QtSerialBus
57     \since 5.8
58 
59     \brief The QCanBusDevice class is the interface class for CAN bus.
60 
61     QCanBusDevice communicates with a CAN plugin providing users with a convenient API.
62     The CAN plugin must be specified during the object creation.
63 */
64 
65 /*!
66     \enum QCanBusDevice::CanBusError
67     This enum describes all the possible error conditions.
68 
69     \value NoError              No errors have occurred.
70     \value ReadError            An error occurred during a read operation.
71     \value WriteError           An error occurred during a write operation.
72     \value ConnectionError      An error occurred when attempting to open the plugin.
73     \value ConfigurationError   An error occurred when attempting to set a configuration
74                                 parameter.
75     \value UnknownError         An unknown error occurred.
76     \value OperationError       An operation was attempted while the device was in
77                                 a state that did not permit it. This enum was introduced
78                                 in Qt 5.14.
79     \value TimeoutError         An timeout occurred while waiting for frames written or
80                                 received. This enum was introduced in Qt 5.14.
81 */
82 
83 /*!
84     \enum QCanBusDevice::CanBusDeviceState
85     This enum describes all possible device states.
86 
87     \value UnconnectedState The device is disconnected.
88     \value ConnectingState  The device is being connected.
89     \value ConnectedState   The device is connected to the CAN bus.
90     \value ClosingState     The device is being closed.
91 */
92 
93 /*!
94     \enum QCanBusDevice::ConfigurationKey
95     This enum describes the possible configuration options for
96     the CAN bus connection.
97 
98     \value RawFilterKey     This configuration determines the type of CAN bus frames
99                             that the current device accepts. The expected value
100                             is \c QList<QCanBusDevice::Filter>. Passing an empty list clears
101                             all previously set filters including default filters. For more details
102                             see \l QCanBusDevice::Filter.
103     \value ErrorFilterKey   This key defines the type of error that should be
104                             forwarded via the current connection. The associated
105                             value should be of type \l QCanBusFrame::FrameErrors.
106     \value LoopbackKey      This key defines whether the CAN bus device should operate in loopback
107                             mode. Loopback means, whenever a CAN frame is transmitted on the CAN
108                             bus, a local echo of this frame is sent to all applications connected to
109                             this CAN device. The expected value for this key is \c bool.
110     \value ReceiveOwnKey    This key defines whether this CAN device receives its own send frames.
111                             This can be used to check if the transmission was successful.
112                             The expected value for this key is \c bool.
113     \value BitRateKey       This key defines the CAN bitrate in bits per second. With CAN FD,
114                             the payload can be transmitted at a higher data bitrate,
115                             if \l QCanBusFrame::hasBitrateSwitch() is set. In this case,
116                             \c QCanBusDevice::BitRateKey is only used for the CAN ID arbitration
117                             phase. See also \c QCanBusDevice::DataBitRateKey
118     \value CanFdKey         This key defines whether sending and receiving of CAN FD frames
119                             should be enabled. The expected value for this key is \c bool.
120     \value DataBitRateKey   This key defines the CAN FD payload bitrate in bits per second.
121                             CAN FD allows to transmit the payload of frames with
122                             \l QCanBusFrame::hasBitrateSwitch() flag at a higher data bitrate,
123                             after the arbitration phase at the nominal bitrate is finished.
124                             This enum value was introduced in Qt 5.9.
125                             See also \c QCanBusDevice::BitRateKey
126     \value ProtocolKey      This key allows to specify another protocol. For now, this
127                             parameter can only be set and used in the SocketCAN plugin.
128                             This enum value was introduced in Qt 5.14.
129     \value UserKey          This key defines the range where custom keys start. Its most
130                             common purpose is to permit platform-specific configuration
131                             options.
132 
133     \sa configurationParameter()
134 */
135 
136 /*!
137     \class QCanBusDevice::Filter
138     \inmodule QtSerialBus
139     \since 5.8
140 
141     \brief The QCanBusDevice::Filter struct defines a filter for CAN bus frames.
142 
143     A list of QCanBusDevice::Filter instances is passed to
144     \l QCanBusDevice::setConfigurationParameter() to enable filtering. If a received CAN frame
145     matches at least one of the filters in the list, the QCanBusDevice will accept it.
146 
147     The example below demonstrates how to use the struct:
148 
149     \snippet snippetmain.cpp Filter Examples
150 */
151 
152 /*!
153     \fn bool operator==(const QCanBusDevice::Filter &a, const QCanBusDevice::Filter &b)
154     \relates QCanBusDevice::Filter
155 
156     Returns true, if the filter \a a is equal to the filter \a b,
157     otherwise returns false.
158 */
159 
160 /*!
161     \fn bool operator!=(const QCanBusDevice::Filter &a, const QCanBusDevice::Filter &b)
162     \relates QCanBusDevice::Filter
163 
164     Returns true, if the filter \a a is not equal to the filter \a b,
165     otherwise returns false.
166 */
167 
168 /*!
169     \enum QCanBusDevice::Filter::FormatFilter
170     This enum describes the format pattern, which is used to filter incoming
171     CAN bus frames.
172 
173     \value MatchBaseFormat              The CAN bus frame must use the base frame format
174                                         (11 bit identifier).
175     \value MatchExtendedFormat          The CAN bus frame must use the extended frame format
176                                         (29 bit identifier).
177     \value MatchBaseAndExtendedFormat   The CAN bus frame can have a base or an extended
178                                         frame format.
179 */
180 
181 /*!
182     \variable QCanBusDevice::Filter::frameId
183 
184     \brief The frame id used to filter the incoming frames.
185 
186     The frameId is used in conjunction with \a frameIdMask.
187     The matching is successful if the following evaluates to \c true:
188 
189     \code
190         (receivedFrameId & frameIdMask) == (frameId & frameIdMask)
191     \endcode
192 
193     By default this field is set to \c 0x0.
194 
195     \sa frameIdMask
196 */
197 
198 /*!
199     \variable QCanBusDevice::Filter::frameIdMask
200 
201     \brief The bit mask that is applied to the frame id of the filter and the received frame.
202 
203     The two frame ids are matching if the following evaluates to \c true:
204 
205     \code
206         (receivedFrameId & frameIdMask) == (frameId & frameIdMask)
207     \endcode
208 
209     By default this field is set to \c 0x0.
210 
211     \sa frameId
212 */
213 
214 /*!
215     \variable QCanBusDevice::Filter::type
216 
217     \brief The type of the frame to be filtered.
218 
219     Any CAN bus frame type can be matched by setting this variable
220     to \l QCanBusFrame::InvalidFrame. The filter object is invalid if
221     type is equal to \l QCanBusFrame::UnknownFrame.
222 
223     By default this field is set to \l QCanBusFrame::InvalidFrame.
224 
225     \sa QCanBusFrame::FrameType
226 */
227 
228 /*!
229     \variable QCanBusDevice::Filter::format
230 
231     \brief The frame format of the matching CAN bus frame.
232 
233     By default this field is set to \l QCanBusDevice::Filter::MatchBaseAndExtendedFormat.
234 */
235 
236 /*!
237     \fn void QCanBusDevice::errorOccurred(CanBusError)
238 
239     This signal is emitted when an error occurs.
240 */
241 
242 /*!
243     Constructs a serial bus device with the specified \a parent.
244 */
QCanBusDevice(QObject * parent)245 QCanBusDevice::QCanBusDevice(QObject *parent) :
246     QObject(*new QCanBusDevicePrivate, parent)
247 {
248 }
249 
250 
251 /*!
252     Sets the human readable description of the last device error to
253     \a errorText. \a errorId categorizes the type of error.
254 
255     CAN bus implementations must use this function to update the device's
256     error state.
257 
258     \sa error(), errorOccurred(), clearError()
259 */
setError(const QString & errorText,CanBusError errorId)260 void QCanBusDevice::setError(const QString &errorText, CanBusError errorId)
261 {
262     Q_D(QCanBusDevice);
263 
264     d->errorText = errorText;
265     d->lastError = errorId;
266 
267     emit errorOccurred(errorId);
268 }
269 
270 /*!
271     \since 5.14
272     Clears the error id and the human readable description of the last
273     device error.
274 
275     CAN bus implementations must use this function to update the device's
276     error state.
277 
278     \sa error(), errorOccurred(), setError()
279 */
clearError()280 void QCanBusDevice::clearError()
281 {
282     Q_D(QCanBusDevice);
283 
284     d->errorText.clear();
285     d->lastError = NoError;
286 }
287 
288 /*!
289     Appends \a newFrames to the internal list of frames which can be
290     accessed using \l readFrame() and emits the \l framesReceived()
291     signal.
292 
293     Subclasses must call this function when they receive frames.
294 
295 */
enqueueReceivedFrames(const QVector<QCanBusFrame> & newFrames)296 void QCanBusDevice::enqueueReceivedFrames(const QVector<QCanBusFrame> &newFrames)
297 {
298     Q_D(QCanBusDevice);
299 
300     if (Q_UNLIKELY(newFrames.isEmpty()))
301         return;
302 
303     d->incomingFramesGuard.lock();
304     d->incomingFrames.append(newFrames);
305     d->incomingFramesGuard.unlock();
306     emit framesReceived();
307 }
308 
309 /*!
310     Appends \a newFrame to the internal list of outgoing frames which
311     can be accessed by \l writeFrame().
312 
313     Subclasses must call this function when they write a new frame.
314 */
enqueueOutgoingFrame(const QCanBusFrame & newFrame)315 void QCanBusDevice::enqueueOutgoingFrame(const QCanBusFrame &newFrame)
316 {
317     Q_D(QCanBusDevice);
318 
319     d->outgoingFrames.append(newFrame);
320 }
321 
322 /*!
323     Returns the next \l QCanBusFrame from the internal list of outgoing frames;
324     otherwise returns an invalid QCanBusFrame. The returned frame is removed
325     from the internal list.
326 */
dequeueOutgoingFrame()327 QCanBusFrame QCanBusDevice::dequeueOutgoingFrame()
328 {
329     Q_D(QCanBusDevice);
330 
331     if (Q_UNLIKELY(d->outgoingFrames.isEmpty()))
332         return QCanBusFrame(QCanBusFrame::InvalidFrame);
333     return d->outgoingFrames.takeFirst();
334 }
335 
336 /*!
337     Returns \c true if the internal list of outgoing frames is not
338     empty; otherwise returns \c false.
339 */
hasOutgoingFrames() const340 bool QCanBusDevice::hasOutgoingFrames() const
341 {
342     Q_D(const QCanBusDevice);
343 
344     return !d->outgoingFrames.isEmpty();
345 }
346 
347 /*!
348  * \since 5.14
349  * Called from the derived plugin to register a function \a resetter which performs the
350  * CAN controller hardware reset when resetController() is called.
351  */
setResetControllerFunction(std::function<void ()> resetter)352 void QCanBusDevice::setResetControllerFunction(std::function<void()> resetter)
353 {
354     Q_D(QCanBusDevice);
355 
356     d->m_resetControllerFunction = std::move(resetter);
357 }
358 
359 /*!
360  * \since 5.14
361  * Called from the derived plugin to register a function \a busStatusGetter
362  * which returns the CAN controller bus status when busStatus() is called.
363  */
setCanBusStatusGetter(std::function<CanBusStatus ()> busStatusGetter)364 void QCanBusDevice::setCanBusStatusGetter(std::function<CanBusStatus()> busStatusGetter)
365 {
366     Q_D(QCanBusDevice);
367 
368     d->m_busStatusGetter = std::move(busStatusGetter);
369 }
370 
371 /*!
372     Sets the configuration parameter \a key for the CAN bus connection
373     to \a value. The potential keys are represented by \l ConfigurationKey.
374 
375     A parameter can be unset by setting an invalid \l QVariant.
376     Unsetting a parameter implies that the configuration is reset to
377     its default setting.
378 
379     \note In most cases, configuration changes only take effect
380     after a reconnect.
381 
382     \sa configurationParameter()
383 */
setConfigurationParameter(int key,const QVariant & value)384 void QCanBusDevice::setConfigurationParameter(int key, const QVariant &value)
385 {
386     Q_D(QCanBusDevice);
387 
388     for (int i = 0; i < d->configOptions.size(); i++) {
389         if (d->configOptions.at(i).first == key) {
390             if (value.isValid()) {
391                 ConfigEntry entry = d->configOptions.at(i);
392                 entry.second = value;
393                 d->configOptions.replace(i, entry);
394             } else {
395                 d->configOptions.remove(i);
396             }
397             return;
398         }
399     }
400 
401     if (!value.isValid())
402         return;
403 
404     ConfigEntry newEntry(key, value);
405     d->configOptions.append(newEntry);
406 }
407 
408 /*!
409     Returns the current value assigned to the \l ConfigurationKey \a key; otherwise
410     an invalid \l QVariant.
411 
412     \sa setConfigurationParameter(), configurationKeys()
413 */
configurationParameter(int key) const414 QVariant QCanBusDevice::configurationParameter(int key) const
415 {
416     Q_D(const QCanBusDevice);
417 
418     for (const ConfigEntry &e : d->configOptions) {
419         if (e.first == key)
420             return e.second;
421     }
422 
423     return QVariant();
424 }
425 
426 /*!
427     Returns the list of keys used by the CAN bus connection.
428 
429     The the meaning of the keys is equivalent to \l ConfigurationKey.
430     If a key is not explicitly mentioned the platform's
431     default setting for the relevant key is used.
432 */
configurationKeys() const433 QVector<int> QCanBusDevice::configurationKeys() const
434 {
435     Q_D(const QCanBusDevice);
436 
437     QVector<int> result;
438     for (const ConfigEntry &e : d->configOptions)
439         result.append(e.first);
440 
441     return result;
442 }
443 
444 /*!
445     Returns the last error that has occurred. The error value is always set to last error that
446     occurred and it is never reset.
447 
448     \sa errorString()
449 */
error() const450 QCanBusDevice::CanBusError QCanBusDevice::error() const
451 {
452     return d_func()->lastError;
453 }
454 
455 /*!
456     Returns a human-readable description of the last device error that occurred.
457 
458     \sa error()
459 */
errorString() const460 QString QCanBusDevice::errorString() const
461 {
462     Q_D(const QCanBusDevice);
463 
464     if (d->lastError == QCanBusDevice::NoError)
465         return QString();
466 
467     return d->errorText;
468 }
469 
470 /*!
471     Returns the number of available frames. If no frames are available,
472     this function returns 0.
473 
474     \sa clear(), readFrame(), readAllFrames()
475 */
framesAvailable() const476 qint64 QCanBusDevice::framesAvailable() const
477 {
478     return d_func()->incomingFrames.size();
479 }
480 
481 /*!
482     For buffered devices, this function returns the number of frames waiting to be written.
483     For unbuffered devices, this function always returns zero.
484 
485     \note There may be additional buffering in the CAN driver and CAN hardware layer.
486     Therefore, if this function returns zero, that does not mean all CAN frames are
487     already written to the CAN bus.
488 
489     \sa clear(), writeFrame()
490 */
framesToWrite() const491 qint64 QCanBusDevice::framesToWrite() const
492 {
493     return d_func()->outgoingFrames.size();
494 }
495 
496 /*!
497     \since 5.14
498 
499     Performs a CAN controller reset to release the CAN controller from
500     bus off state, if possible.
501 
502     \note CAN controller resets disturb the running communication and
503     may take up to one second to complete. Only call this function to
504     recover from bus errors.
505 
506     \note This function may not be implemented in all CAN plugins.
507     Please refer to the plugins help pages for more information.
508 
509     \sa busStatus()
510 */
resetController()511 void QCanBusDevice::resetController()
512 {
513     if (d_func()->m_resetControllerFunction) {
514         d_func()->m_resetControllerFunction();
515     } else {
516         const char error[] = QT_TRANSLATE_NOOP("QCanBusDevice",
517                 "This CAN bus plugin does not support hardware controller reset.");
518         qCWarning(QT_CANBUS, error);
519         setError(tr(error), QCanBusDevice::CanBusError::ConfigurationError);
520     }
521 }
522 
523 /*!
524     \since 5.14
525 
526     Return true, if the CAN plugin supports requesting the CAN bus status.
527 
528     \sa busStatus()
529  */
hasBusStatus() const530 bool QCanBusDevice::hasBusStatus() const
531 {
532     return d_func()->m_busStatusGetter != nullptr;
533 }
534 
535 /*!
536     \since 5.14
537     \enum QCanBusDevice::CanBusStatus
538 
539     This enum describes possible CAN bus status values.
540 
541     \value Unknown  The CAN bus status is unknown
542                     (e.g. not supported by the CAN plugin).
543     \value Good     The CAN controller is fully operational
544     \value Warning  The CAN controller is in warning status
545     \value Error    The CAN controller is in error status
546                     (no longer sending CAN frames)
547     \value BusOff   The CAN controller is in bus off status
548                     (disconnected from the CAN bus)
549 */
550 
551 /*!
552     \since 5.14
553 
554     Returns the current CAN bus status. If the status cannot be requested,
555     QCanBusDevice::UnknownStatus is returned.
556 
557     \note This function may not be implemented in all CAN plugins.
558     Please refer to the plugins help pages for more information.
559     The function hasBusStatus() can be used at runtime to check if
560     the used CAN plugin has support for requesting the CAN bus status.
561 
562     \sa hasBusStatus(), resetController()
563 */
busStatus() const564 QCanBusDevice::CanBusStatus QCanBusDevice::busStatus() const
565 {
566     if (d_func()->m_busStatusGetter)
567         return d_func()->m_busStatusGetter();
568 
569     return QCanBusDevice::CanBusStatus::Unknown;
570 }
571 
572 /*!
573     \since 5.12
574     \enum QCanBusDevice::Direction
575 
576     This enum describes possible data transmission directions.
577 
578     \value Input            Input direction.
579     \value Output           Output direction.
580     \value AllDirections    Both directions, input and output.
581 */
582 
583 /*!
584     \since 5.12
585     Clears the devices input or output buffers, depending on \a direction.
586 
587     This function only operates on QCanBusDevice buffers. Frames that are
588     already written to the CAN driver or CAN hardware layer, or that are
589     not yet read from these layers, are not cleared by this function.
590 
591     \note Clearing the output buffers is only possible for buffered devices.
592 
593     \sa framesAvailable(), readFrame(), framesToWrite(), writeFrame(),
594 */
clear(QCanBusDevice::Directions direction)595 void QCanBusDevice::clear(QCanBusDevice::Directions direction)
596 {
597     Q_D(QCanBusDevice);
598 
599     if (Q_UNLIKELY(d->state != ConnectedState)) {
600         const QString error = tr("Cannot clear buffers as device is not connected.");
601         qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
602         setError(error, CanBusError::OperationError);
603         return;
604     }
605 
606     clearError();
607 
608     if (direction & Direction::Input) {
609         QMutexLocker(&d->incomingFramesGuard);
610         d->incomingFrames.clear();
611     }
612 
613     if (direction & Direction::Output)
614         d->outgoingFrames.clear();
615 }
616 
617 /*!
618     For buffered devices, this function waits until all buffered frames
619     have been written to the device and the \l framesWritten() signal has been emitted,
620     or until \a msecs milliseconds have passed. If \a msecs is -1,
621     this function will not time out. For unbuffered devices, it returns immediately with \c false
622     as \l writeFrame() does not require a write buffer.
623 
624     Returns \c true if the \l framesWritten() signal is emitted;
625     otherwise returns \c false (i.e. if the operation timed out, or if an error occurred).
626 
627     \note This function will start a local event loop. This may lead to scenarios whereby
628     other application slots may be called while the execution of this function scope is blocking.
629     To avoid problems, the signals for this class should not be connected to slots.
630     Similarly this function must never be called in response to the \l framesWritten()
631     or \l errorOccurred() signals.
632 
633     \sa waitForFramesReceived()
634  */
waitForFramesWritten(int msecs)635 bool QCanBusDevice::waitForFramesWritten(int msecs)
636 {
637     // do not enter this function recursively
638     if (Q_UNLIKELY(d_func()->waitForWrittenEntered)) {
639         qCWarning(QT_CANBUS, "QCanBusDevice::waitForFramesWritten() must not be called "
640                              "recursively. Check that no slot containing waitForFramesReceived() "
641                              "is called in response to framesWritten(qint64) or "
642                              "errorOccurred(CanBusError) signals.");
643         setError(tr("QCanBusDevice::waitForFramesWritten() must not be called recursively."),
644                  CanBusError::OperationError);
645         return false;
646     }
647 
648     if (Q_UNLIKELY(d_func()->state != ConnectedState)) {
649         const QString error = tr("Cannot wait for frames written as device is not connected.");
650         qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
651         setError(error, CanBusError::OperationError);
652         return false;
653     }
654 
655     if (!framesToWrite())
656         return false; // nothing pending, nothing to wait upon
657 
658     QScopedValueRollback<bool> guard(d_func()->waitForWrittenEntered);
659     d_func()->waitForWrittenEntered = true;
660 
661     enum { Written = 0, Error, Timeout };
662     QEventLoop loop;
663     connect(this, &QCanBusDevice::framesWritten, &loop, [&]() { loop.exit(Written); });
664     connect(this, &QCanBusDevice::errorOccurred, &loop, [&]() { loop.exit(Error); });
665     if (msecs >= 0)
666         QTimer::singleShot(msecs, &loop, [&]() { loop.exit(Timeout); });
667 
668     int result = Written;
669     while (framesToWrite() > 0) {
670         // wait till all written or time out
671         result = loop.exec(QEventLoop::ExcludeUserInputEvents);
672         if (Q_UNLIKELY(result == Timeout)) {
673             const QString error = tr("Timeout (%1 ms) during wait for frames written.").arg(msecs);
674             setError(error, CanBusError::TimeoutError);
675             qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
676         }
677 
678         if (result > Written)
679             return false;
680     }
681 
682     clearError();
683     return true;
684 }
685 
686 /*!
687     Blocks until new frames are available for reading and the \l framesReceived()
688     signal has been emitted, or until \a msecs milliseconds have passed. If
689     \a msecs is \c -1, this function will not time out.
690 
691     Returns \c true if new frames are available for reading and the \l framesReceived()
692     signal is emitted; otherwise returns \c false (if the operation timed out
693     or if an error occurred).
694 
695     \note This function will start a local event loop. This may lead to scenarios whereby
696     other application slots may be called while the execution of this function scope is blocking.
697     To avoid problems, the signals for this class should not be connected to slots.
698     Similarly this function must never be called in response to the \l framesReceived()
699     or \l errorOccurred() signals.
700 
701     \sa waitForFramesWritten()
702  */
waitForFramesReceived(int msecs)703 bool QCanBusDevice::waitForFramesReceived(int msecs)
704 {
705     // do not enter this function recursively
706     if (Q_UNLIKELY(d_func()->waitForReceivedEntered)) {
707         qCWarning(QT_CANBUS, "QCanBusDevice::waitForFramesReceived() must not be called "
708                              "recursively. Check that no slot containing waitForFramesReceived() "
709                              "is called in response to framesReceived() or "
710                              "errorOccurred(CanBusError) signals.");
711         setError(tr("QCanBusDevice::waitForFramesReceived() must not be called recursively."),
712                  CanBusError::OperationError);
713         return false;
714     }
715 
716     if (Q_UNLIKELY(d_func()->state != ConnectedState)) {
717         const QString error = tr("Cannot wait for frames received as device is not connected.");
718         qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
719         setError(error, CanBusError::OperationError);
720         return false;
721     }
722 
723     QScopedValueRollback<bool> guard(d_func()->waitForReceivedEntered);
724     d_func()->waitForReceivedEntered = true;
725 
726     enum { Received = 0, Error, Timeout };
727     QEventLoop loop;
728     connect(this, &QCanBusDevice::framesReceived, &loop, [&]() { loop.exit(Received); });
729     connect(this, &QCanBusDevice::errorOccurred, &loop, [&]() { loop.exit(Error); });
730     if (msecs >= 0)
731         QTimer::singleShot(msecs, &loop, [&]() { loop.exit(Timeout); });
732 
733     int result = loop.exec(QEventLoop::ExcludeUserInputEvents);
734 
735     if (Q_UNLIKELY(result == Timeout)) {
736         const QString error = tr("Timeout (%1 ms) during wait for frames received.").arg(msecs);
737         setError(error, CanBusError::TimeoutError);
738         qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
739     }
740 
741     if (result == Received)
742         clearError();
743     return result == Received;
744 }
745 
746 /*!
747     \fn bool QCanBusDevice::open()
748 
749     This function is called by connectDevice(). Subclasses must provide
750     an implementation which returns \c true if the CAN bus connection
751     could be established; otherwise \c false. The QCanBusDevice implementation
752     ensures upon entry of this function that the device's \l state() is set
753     to \l QCanBusDevice::ConnectingState already.
754 
755     The implementation must ensure that upon success the instance's \l state()
756     is set to \l QCanBusDevice::ConnectedState; otherwise
757     \l QCanBusDevice::UnconnectedState. \l setState() must be used to set the new
758     device state.
759 
760     The custom implementation is responsible for opening the socket, instanciation
761     of a potentially required \l QSocketNotifier and the application of custom and default
762     \l QCanBusDevice::configurationParameter().
763 
764     \sa connectDevice()
765 */
766 
767 /*!
768     \fn void QCanBusDevice::close()
769 
770     This function is responsible for closing the CAN bus connection.
771     The implementation must ensure that the instance's
772     \l state() is set to \l QCanBusDevice::UnconnectedState.
773 
774     This function's most important task is to close the socket to the CAN device
775     and to call \l QCanBusDevice::setState().
776 
777     \sa disconnectDevice()
778 */
779 
780 /*!
781     \fn void QCanBusDevice::framesReceived()
782 
783     This signal is emitted when one or more frames have been received.
784     The frames should be read using \l readFrame() and \l framesAvailable().
785 */
786 
787 /*!
788     Returns the next \l QCanBusFrame from the queue; otherwise returns
789     an empty QCanBusFrame. The returned frame is removed from the queue.
790 
791     The queue operates according to the FIFO principle.
792 
793     \sa clear(), framesAvailable(), readAllFrames()
794 */
readFrame()795 QCanBusFrame QCanBusDevice::readFrame()
796 {
797     Q_D(QCanBusDevice);
798 
799     if (Q_UNLIKELY(d->state != ConnectedState)) {
800         const QString error = tr("Cannot read frame as device is not connected.");
801         qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
802         setError(error, CanBusError::OperationError);
803         return QCanBusFrame(QCanBusFrame::InvalidFrame);
804     }
805 
806     clearError();
807 
808     QMutexLocker locker(&d->incomingFramesGuard);
809 
810     if (Q_UNLIKELY(d->incomingFrames.isEmpty()))
811         return QCanBusFrame(QCanBusFrame::InvalidFrame);
812 
813     return d->incomingFrames.takeFirst();
814 }
815 
816 /*!
817     \since 5.12
818     Returns all \l{QCanBusFrame}s from the queue; otherwise returns
819     an empty QVector. The returned frames are removed from the queue.
820 
821     The queue operates according to the FIFO principle.
822 
823     \sa clear(), framesAvailable(), readFrame()
824 */
readAllFrames()825 QVector<QCanBusFrame> QCanBusDevice::readAllFrames()
826 {
827     Q_D(QCanBusDevice);
828 
829     if (Q_UNLIKELY(d->state != ConnectedState)) {
830         const QString error = tr("Cannot read frame as device is not connected.");
831         qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
832         setError(error, CanBusError::OperationError);
833         return QVector<QCanBusFrame>();
834     }
835 
836     clearError();
837 
838     QMutexLocker locker(&d->incomingFramesGuard);
839 
840     QVector<QCanBusFrame> result;
841     result.swap(d->incomingFrames);
842     return result;
843 }
844 
845 /*!
846     \fn void QCanBusDevice::framesWritten(qint64 framesCount)
847 
848     This signal is emitted every time a payload of frames has been
849     written to the CAN bus. The \a framesCount argument is set to
850     the number of frames that were written in this payload.
851 */
852 
853 /*!
854     \fn bool QCanBusDevice::writeFrame(const QCanBusFrame &frame)
855 
856     Writes \a frame to the CAN bus and returns \c true on success;
857     otherwise \c false.
858 
859     On some platforms, the frame may be put into a queue and the return
860     value may only indicate a successful insertion into the queue.
861     The actual frame will be send later on. Therefore the \l framesWritten()
862     signal is the final confirmation that the frame has been handed off to
863     the transport layer. If an error occurs the \l errorOccurred() is emitted.
864 
865     As per CAN bus specification, frames of type
866     \l {QCanBusFrame::RemoteRequestFrame} {remote transfer request (RTR)}
867     do not have a payload, but a length from 0 to 8 (including). This length
868     indicates the expected response payload length from the remote party.
869     Therefore when sending a RTR frame using this function it may still
870     be required to set an arbitrary payload on \a frame. The length of
871     the arbitrary payload is what is set as size expectation for the RTR frame.
872 
873     \sa QCanBusFrame::setPayload()
874 */
875 
876 /*!
877     \fn QString QCanBusDevice::interpretErrorFrame(const QCanBusFrame &frame)
878 
879     Interprets \a frame as error frame and returns a human readable
880     description of the error.
881 
882     If \a frame is not an error frame, the returned string is empty.
883 */
884 
885 /*!
886     Connects the device to the CAN bus. Returns \c true on success;
887     otherwise \c false.
888 
889     This function calls \l open() as part of its implementation.
890 
891     \sa disconnectDevice()
892 */
connectDevice()893 bool QCanBusDevice::connectDevice()
894 {
895     Q_D(QCanBusDevice);
896 
897     if (Q_UNLIKELY(d->state != QCanBusDevice::UnconnectedState)) {
898         const char error[] = QT_TRANSLATE_NOOP("QCanBusDevice",
899                                 "Can not connect an already connected device.");
900         qCWarning(QT_CANBUS, error);
901         setError(tr(error), QCanBusDevice::ConnectionError);
902         return false;
903     }
904 
905     setState(ConnectingState);
906 
907     if (!open()) {
908         setState(UnconnectedState);
909         return false;
910     }
911 
912     clearError();
913 
914     //Connected is set by backend -> might be delayed by event loop
915     return true;
916 }
917 
918 
919 /*!
920     Disconnects the device from the CAN bus.
921 
922     This function calls \l close() as part of its implementation.
923 
924     \note This function should only be called, if connectDevice()
925     returned \c true.
926 
927     \sa connectDevice()
928 */
disconnectDevice()929 void QCanBusDevice::disconnectDevice()
930 {
931     Q_D(QCanBusDevice);
932 
933     if (Q_UNLIKELY(d->state == QCanBusDevice::UnconnectedState
934             || d->state == QCanBusDevice::ClosingState)) {
935         qCWarning(QT_CANBUS, "Can not disconnect an unconnected device.");
936         return;
937     }
938 
939     setState(QCanBusDevice::ClosingState);
940 
941     //Unconnected is set by backend -> might be delayed by event loop
942     close();
943 }
944 
945 /*!
946     \fn void QCanBusDevice::stateChanged(QCanBusDevice::CanBusDeviceState state)
947 
948     This signal is emitted every time the state of the device changes.
949     The new state is represented by \a state.
950 
951     \sa setState(), state()
952 */
953 
954 /*!
955     Returns the current state of the device.
956 
957     \sa setState(), stateChanged()
958 */
state() const959 QCanBusDevice::CanBusDeviceState QCanBusDevice::state() const
960 {
961     return d_func()->state;
962 }
963 
964 /*!
965     Sets the state of the device to \a newState. CAN bus implementations
966     must use this function to update the device state.
967 */
setState(QCanBusDevice::CanBusDeviceState newState)968 void QCanBusDevice::setState(QCanBusDevice::CanBusDeviceState newState)
969 {
970     Q_D(QCanBusDevice);
971 
972     if (newState == d->state)
973         return;
974 
975     d->state = newState;
976     emit stateChanged(newState);
977 }
978 
979 /*!
980  * Returns a QCanBusDeviceInfo created from the given parameters \a name,
981  * \a isVirtual, and \a isFlexibleDataRateCapable.
982  * \internal
983  */
createDeviceInfo(const QString & name,bool isVirtual,bool isFlexibleDataRateCapable)984 QCanBusDeviceInfo QCanBusDevice::createDeviceInfo(const QString &name, bool isVirtual,
985                                                   bool isFlexibleDataRateCapable)
986 {
987     return createDeviceInfo(name, QString(), QString(), 0, isVirtual, isFlexibleDataRateCapable);
988 }
989 
990 /*!
991     \since 5.11
992     Returns a QCanBusDeviceInfo created from the given parameters \a name,
993     \a serialNumber, \a description, \a channel, \a isVirtual, and \a
994     isFlexibleDataRateCapable.
995     \internal
996  */
createDeviceInfo(const QString & name,const QString & serialNumber,const QString & description,int channel,bool isVirtual,bool isFlexibleDataRateCapable)997 QCanBusDeviceInfo QCanBusDevice::createDeviceInfo(const QString &name, const QString &serialNumber,
998                                                   const QString &description, int channel,
999                                                   bool isVirtual, bool isFlexibleDataRateCapable)
1000 {
1001     QScopedPointer<QCanBusDeviceInfoPrivate> info(new QCanBusDeviceInfoPrivate);
1002     info->name = name;
1003     info->serialNumber = serialNumber;
1004     info->description = description;
1005     info->channel = channel;
1006     info->hasFlexibleDataRate = isFlexibleDataRateCapable;
1007     info->isVirtual = isVirtual;
1008     return QCanBusDeviceInfo(*info.take());
1009 }
1010 
1011 QT_END_NAMESPACE
1012