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 "qcanbusframe.h"
38 
39 #include <QtCore/qdatastream.h>
40 
41 QT_BEGIN_NAMESPACE
42 
43 /*!
44     \class QCanBusFrame
45     \inmodule QtSerialBus
46     \since 5.8
47 
48     \brief QCanBusFrame is a container class representing a single CAN frame.
49 
50     \l QCanBusDevice can use QCanBusFrame for read and write operations. It contains the frame
51     identifier and the data payload. QCanBusFrame contains the timestamp of the moment it was read.
52 
53     \sa QCanBusFrame::TimeStamp
54 */
55 
56 /*!
57     \fn QCanBusFrame::QCanBusFrame(QCanBusFrame::FrameType type = DataFrame)
58 
59     Constructs a CAN frame of the specified \a type.
60 */
61 
62 /*!
63     \fn QCanBusFrame::QCanBusFrame(quint32 identifier, const QByteArray &data)
64 
65     Constructs a CAN frame using \a identifier as the frame identifier and \a data as the payload.
66 */
67 
68 /*!
69     \fn bool QCanBusFrame::isValid() const
70 
71     Returns \c false if the \l frameType() is \l InvalidFrame,
72     the \l hasExtendedFrameFormat() is not set although \l frameId() is longer than 11 bit or
73     the payload is longer than the maximal permitted payload length of 64 byte if \e {Flexible
74     Data-Rate} mode is enabled or 8 byte if it is disabled. If \l frameType() is \l RemoteRequestFrame
75     and the \e {Flexible Data-Rate} mode is enabled at the same time \c false is also returned.
76 
77     Otherwise this function returns \c true.
78 */
79 
80 /*!
81     \fn QCanBusFrame::setFrameId(quint32 newFrameId)
82 
83     Sets the identifier of the CAN frame to \a newFrameId.
84 
85     The maximum size of a CAN frame identifier is 11 bits, which can be
86     extended up to 29 bits by supporting the \e {CAN extended frame format}.
87     The \e {CAN extended frame format} setting is automatically set when a
88     \a newFrameId with more than 11 bits in size is given.
89 
90     When the format is extended and a \a newFrameId with up to 11 bits or less
91     is passed, the \e {CAN extended frame format} setting is \b not changed.
92 
93     \sa frameId(), hasExtendedFrameFormat()
94 */
95 
96 /*!
97     \fn QCanBusFrame::setPayload(const QByteArray &data)
98 
99     Sets \a data as the payload for the CAN frame. The maximum size of payload is 8 bytes, which can
100     be extended up to 64 bytes by supporting \e {Flexible Data-Rate}. If \a data contains more than
101     8 byte the \e {Flexible Data-Rate} flag is automatically set. Flexible Data-Rate has to be
102     enabled on the \l QCanBusDevice by setting the \l QCanBusDevice::CanFdKey.
103 
104     Frames of type \l RemoteRequestFrame (RTR) do not have a payload. However they have to
105     provide an indication of the responses expected payload length. To set the length expection it
106     is necessary to set a fake payload whose length matches the expected payload length of the
107     response. One way of doing this might be as follows:
108 
109     \code
110         QCanBusFrame frame(QCanBusFrame::RemoteRequestFrame);
111         int expectedResponseLength = ...;
112         frame.setPayload(QByteArray(expectedResponseLength, 0));
113     \endcode
114 
115     \sa payload(), hasFlexibleDataRateFormat()
116 */
117 
118 /*!
119     \fn QCanBusFrame::setTimeStamp(TimeStamp ts)
120 
121     Sets \a ts as the timestamp for the CAN frame. Usually, this function is not needed, because the
122     timestamp is created during the read operation and not needed during the write operation.
123 
124     \sa QCanBusFrame::TimeStamp
125 */
126 
127 /*!
128     \fn quint32 QCanBusFrame::frameId() const
129 
130     Returns the CAN frame identifier. If the CAN frame uses the
131     extended frame format, the identifier has a maximum of 29 bits;
132     otherwise 11 bits.
133 
134     If the frame is of \l ErrorFrame type, this ID is always 0.
135 
136     \sa setFrameId(), hasExtendedFrameFormat()
137 */
138 
139 /*!
140     \fn bool QCanBusFrame::hasExtendedFrameFormat() const
141 
142     Returns \c true if the CAN frame uses a 29bit identifier;
143     otherwise \c false, implying an 11bit identifier.
144 
145     \sa setExtendedFrameFormat(), frameId()
146 */
147 
148 /*!
149     \fn  void QCanBusFrame::setExtendedFrameFormat(bool isExtended)
150 
151     Sets the extended frame format flag to \a isExtended.
152 
153     \sa hasExtendedFrameFormat()
154 */
155 
156 /*!
157     \enum QCanBusFrame::Version
158     \internal
159 
160     This enum describes the version of the QCanBusFrame.
161 
162     With newer Qt versions, new features may be added to QCanBusFrame. To support serializing and
163     deserializing of frames with different features, the version needs to be incremented every
164     time a new feature appears. This enum describes, at which Qt version a specific QCanBusFrame
165     version appeared.
166 
167     \value Qt_5_8               This frame is the initial version introduced in Qt 5.8
168     \value Qt_5_9               This frame version was introduced in Qt 5.9
169 */
170 
171 /*!
172     \enum QCanBusFrame::FrameType
173 
174     This enum describes the type of the CAN frame.
175 
176     \value UnknownFrame         The frame type is unknown.
177     \value DataFrame            This value represents a data frame.
178     \value ErrorFrame           This value represents an error frame.
179     \value RemoteRequestFrame   This value represents a remote request.
180     \value InvalidFrame         This value represents an invalid frame.
181                                 This type is used for error reporting.
182 
183     \sa setFrameType()
184 */
185 
186 /*!
187     \enum QCanBusFrame::FrameError
188 
189     This enum describes the possible error types.
190 
191     \value NoError                      No error has occurred.
192     \value TransmissionTimeoutError     The transmission has timed out.
193     \value LostArbitrationError         The frame could not be sent due to lost
194                                         arbitration on the bus.
195     \value ControllerError              The controller encountered an error.
196     \value ProtocolViolationError       A protocol violation has occurred.
197     \value TransceiverError             A transceiver error occurred
198     \value MissingAcknowledgmentError   The transmission received no
199                                         acknowledgment.
200     \value BusOffError                  The CAN bus is offline.
201     \value BusError                     A CAN bus error occurred.
202     \value ControllerRestartError       The controller restarted.
203     \value UnknownError                 An unknown error has occurred.
204     \value AnyError                     Matches every other error type.
205 */
206 
207 /*!
208     \fn FrameType QCanBusFrame::frameType() const
209 
210     Returns the type of the frame.
211 
212     \sa setFrameType()
213 */
214 
215 /*!
216     \fn void QCanBusFrame::setFrameType(FrameType newType)
217 
218     Sets the type of the frame to \a newType.
219 
220     \sa frameType()
221 */
222 
223 /*!
224     \fn QByteArray QCanBusFrame::payload() const
225 
226     Returns the data payload of the frame.
227 
228     \sa setPayload()
229 */
230 
231 /*!
232     \fn TimeStamp QCanBusFrame::timeStamp() const
233 
234     Returns the timestamp of the frame.
235 
236     \sa QCanBusFrame::TimeStamp, QCanBusFrame::setTimeStamp()
237 */
238 
239 /*!
240     \fn FrameErrors QCanBusFrame::error() const
241 
242     Returns the error of the current error frame. If the frame
243     is not an \l ErrorFrame, this function returns \l NoError.
244 
245     \sa setError()
246 */
247 
248 /*!
249     \fn void QCanBusFrame::setError(FrameErrors error)
250 
251     Sets the frame's \a error type. This function does nothing if
252     \l frameType() is not an \l ErrorFrame.
253 
254     \sa error()
255 */
256 
257 /*!
258     \fn bool QCanBusFrame::hasFlexibleDataRateFormat() const
259 
260     Returns \c true if the CAN frame uses \e {Flexible Data-Rate} which allows up to 64 data bytes,
261     otherwise \c false, implying at most 8 byte of payload.
262 
263     \sa setFlexibleDataRateFormat(), payload()
264 */
265 
266 /*!
267     \fn  void QCanBusFrame::setFlexibleDataRateFormat(bool isFlexibleData)
268 
269     Sets the \e {Flexible Data-Rate} flag to \a isFlexibleData. Those frames can be sent using
270     a higher speed on supporting controllers. Additionally the payload length limit is raised to
271     64 byte.
272 
273     \sa hasFlexibleDataRateFormat()
274 */
275 
276 /*!
277     \fn QCanBusFrame::hasBitrateSwitch() const
278     \since 5.9
279 
280     Returns \c true if the CAN uses \e {Flexible Data-Rate} with \e {Bitrate Switch},
281     to transfer the payload data at a higher data bitrate.
282 
283     \sa setBitrateSwitch() QCanBusDevice::DataBitRateKey
284 */
285 
286 /*!
287     \fn void QCanBusFrame::setBitrateSwitch(bool bitrateSwitch)
288     \since 5.9
289 
290     Set the \e {Flexible Data-Rate} flag \e {Bitrate Switch} flag to \a bitrateSwitch.
291     The data field of frames with this flag is transferred at a higher data bitrate.
292 
293     \sa hasBitrateSwitch() QCanBusDevice::DataBitRateKey
294 */
295 
296 /*!
297     \fn QCanBusFrame::hasErrorStateIndicator() const
298     \since 5.9
299 
300     Returns \c true if the CAN uses \e {Flexible Data-Rate} with \e {Error State Indicator} set.
301 
302     This flag is set by the transmitter's CAN FD hardware to indicate the transmitter's error state.
303 
304     \sa setErrorStateIndicator()
305 */
306 
307 /*!
308     \fn void QCanBusFrame::setErrorStateIndicator(bool errorStateIndicator)
309     \since 5.9
310 
311     Set the \e {Flexible Data-Rate} flag \e {Error State Indicator} flag to \a errorStateIndicator.
312 
313     When sending CAN FD frames, this flag is automatically set by the CAN FD hardware.
314     \c QCanBusFrame::setErrorStateIndicator() should only be used for application testing,
315     e.g. on virtual CAN FD busses.
316 
317     \sa hasErrorStateIndicator()
318 */
319 
320 /*!
321     \fn QCanBusFrame::hasLocalEcho() const
322     \since 5.10
323 
324     Returns \c true if the frame is a local echo frame, i.e. a frame that is received as echo when
325     the frame with the same content was successfully sent to the CAN bus. This flag is set for
326     frames sent by the application itself as well as for frames sent by other applications running
327     on the same system.
328 
329     QCanBusDevice::ReceiveOwnKey must be set to true to receive echo frames.
330 
331     \sa setLocalEcho()
332     \sa QCanBusDevice::ReceiveOwnKey
333     \sa QCanBusDevice::LoopbackKey
334 */
335 
336 /*!
337     \fn void QCanBusFrame::setLocalEcho(bool echo)
338     \since 5.10
339 
340     Set the \e {Local Echo} flag to \a echo.
341 
342     When sending CAN bus frames with QCanBusDevice::ReceiveOwnKey enabled, all successfully sent
343     frames are echoed to the receive queue and marked as local echo frames.
344     \c QCanBusFrame::setLocalEcho should therefore only be used for application testing,
345     e.g. on virtual CAN busses.
346 
347     \sa hasLocalEcho()
348 */
349 
350 /*!
351     \class QCanBusFrame::TimeStamp
352     \inmodule QtSerialBus
353     \since 5.8
354 
355     \brief The TimeStamp class provides timestamp information with microsecond precision.
356 */
357 
358 /*!
359     \fn QCanBusFrame::TimeStamp::TimeStamp(qint64 s, qint64 usec)
360 
361     Constructs a TimeStamp in seconds, \a s, and microseconds, \a usec.
362 
363     \note The TimeStamp is not normalized, i.e. microseconds greater 1000000 are not
364     converted to seconds.
365 */
366 
367 /*!
368     \fn static TimeStamp QCanBusFrame::TimeStamp::fromMicroSeconds(qint64 usec)
369 
370     Constructs a normalized TimeStamp from microseconds \a usec.
371 
372     The created TimeStamp is normalized, i.e. microseconds greater 1000000 are converted
373     to seconds.
374 */
375 
376 /*!
377     \fn qint64 QCanBusFrame::TimeStamp::seconds() const
378 
379     Returns the seconds of the timestamp.
380 */
381 
382 /*!
383     \fn qint64 QCanBusFrame::TimeStamp::microSeconds() const
384 
385     Returns the microseconds of the timestamp.
386 */
387 
388 /*!
389     Returns the CAN frame as a formatted string.
390 
391     The output contains the CAN identifier in hexadecimal format, right
392     adjusted to 32 bit, followed by the data length in square brackets
393     and the payload in hexadecimal format.
394 
395     Standard identifiers are filled with spaces while extended identifiers
396     are filled with zeros.
397 
398     Typical outputs are:
399 
400     \code
401         (Error)                                  - error frame
402              7FF   [1]  01                       - data frame with standard identifier
403         1FFFFFFF   [8]  01 23 45 67 89 AB CD EF  - data frame with extended identifier
404              400  [10]  01 23 45 67 ... EF 01 23 - CAN FD frame
405              123   [5]  Remote Request           - remote frame with standard identifier
406         00000234   [0]  Remote Request           - remote frame with extended identifier
407     \endcode
408 */
toString() const409 QString QCanBusFrame::toString() const
410 {
411     const FrameType type = frameType();
412 
413     switch (type) {
414     case InvalidFrame:
415         return QStringLiteral("(Invalid)");
416     case ErrorFrame:
417         return QStringLiteral("(Error)");
418     case UnknownFrame:
419         return QStringLiteral("(Unknown)");
420     default:
421         break;
422     }
423 
424     const char * const idFormat = hasExtendedFrameFormat() ? "%08X" : "     %03X";
425     const char * const dlcFormat = hasFlexibleDataRateFormat() ? "  [%02d]" : "   [%d]";
426     QString result;
427     result.append(QString::asprintf(idFormat, static_cast<uint>(frameId())));
428     result.append(QString::asprintf(dlcFormat, payload().size()));
429 
430     if (type == RemoteRequestFrame) {
431         result.append(QLatin1String("  Remote Request"));
432     } else if (!payload().isEmpty()) {
433         const QByteArray data = payload().toHex(' ').toUpper();
434         result.append(QLatin1String("  "));
435         result.append(QLatin1String(data));
436     }
437 
438     return result;
439 }
440 
441 #ifndef QT_NO_DATASTREAM
442 
443 /*! \relates QCanBusFrame
444 
445     Writes a \a frame to the stream (\a out) and returns a reference
446     to the it.
447 */
operator <<(QDataStream & out,const QCanBusFrame & frame)448 QDataStream &operator<<(QDataStream &out, const QCanBusFrame &frame)
449 {
450     out << frame.frameId();
451     out << static_cast<quint8>(frame.frameType());
452     out << static_cast<quint8>(frame.version);
453     out << frame.hasExtendedFrameFormat();
454     out << frame.hasFlexibleDataRateFormat();
455     out << frame.payload();
456     const QCanBusFrame::TimeStamp stamp = frame.timeStamp();
457     out << stamp.seconds();
458     out << stamp.microSeconds();
459     if (frame.version >= QCanBusFrame::Version::Qt_5_9)
460         out << frame.hasBitrateSwitch() << frame.hasErrorStateIndicator();
461     if (frame.version >= QCanBusFrame::Version::Qt_5_10)
462         out << frame.hasLocalEcho();
463     return out;
464 }
465 
466 /*! \relates QCanBusFrame
467 
468     Reads a \a frame from the stream (\a in) and returns a
469     reference to the it.
470 */
operator >>(QDataStream & in,QCanBusFrame & frame)471 QDataStream &operator>>(QDataStream &in, QCanBusFrame &frame)
472 {
473     quint32 frameId;
474     quint8 frameType;
475     quint8 version;
476     bool extendedFrameFormat;
477     bool flexibleDataRate;
478     bool bitrateSwitch = false;
479     bool errorStateIndicator = false;
480     bool localEcho = false;
481     QByteArray payload;
482     qint64 seconds;
483     qint64 microSeconds;
484 
485     in >> frameId >> frameType >> version >> extendedFrameFormat >> flexibleDataRate
486        >> payload >> seconds >> microSeconds;
487 
488     if (version >= QCanBusFrame::Version::Qt_5_9)
489         in >> bitrateSwitch >> errorStateIndicator;
490 
491     if (version >= QCanBusFrame::Version::Qt_5_10)
492         in >> localEcho;
493 
494     frame.setFrameId(frameId);
495     frame.version = version;
496 
497     frame.setFrameType(static_cast<QCanBusFrame::FrameType>(frameType));
498     frame.setExtendedFrameFormat(extendedFrameFormat);
499     frame.setFlexibleDataRateFormat(flexibleDataRate);
500     frame.setBitrateSwitch(bitrateSwitch);
501     frame.setErrorStateIndicator(errorStateIndicator);
502     frame.setLocalEcho(localEcho);
503     frame.setPayload(payload);
504 
505     frame.setTimeStamp(QCanBusFrame::TimeStamp(seconds, microSeconds));
506 
507     return in;
508 }
509 
510 #endif // QT_NO_DATASTREAM
511 
512 QT_END_NAMESPACE
513