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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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