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

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