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
41QT_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*/
409QString 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(s: QString::asprintf(format: idFormat, static_cast<uint>(frameId())));
428 result.append(s: QString::asprintf(format: dlcFormat, payload().size()));
429
430 if (type == RemoteRequestFrame) {
431 result.append(s: QLatin1String(" Remote Request"));
432 } else if (!payload().isEmpty()) {
433 const QByteArray data = payload().toHex(separator: ' ').toUpper();
434 result.append(s: QLatin1String(" "));
435 result.append(s: 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*/
448QDataStream &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*/
471QDataStream &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
512QT_END_NAMESPACE
513

source code of qtserialbus/src/serialbus/qcanbusframe.cpp