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 | */ |
409 | 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(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 | */ |
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 | */ |
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 | |