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#ifndef QCANBUSFRAME_H
38#define QCANBUSFRAME_H
39
40#include <QtCore/qmetatype.h>
41#include <QtCore/qobject.h>
42#include <QtSerialBus/qtserialbusglobal.h>
43
44QT_BEGIN_NAMESPACE
45
46class QDataStream;
47
48class Q_SERIALBUS_EXPORT QCanBusFrame
49{
50public:
51 class TimeStamp {
52 public:
53 Q_DECL_CONSTEXPR TimeStamp(qint64 s = 0, qint64 usec = 0) Q_DECL_NOTHROW
54 : secs(s), usecs(usec) {}
55
56 Q_DECL_CONSTEXPR static TimeStamp fromMicroSeconds(qint64 usec) Q_DECL_NOTHROW
57 { return TimeStamp(usec / 1000000, usec % 1000000); }
58
59 Q_DECL_CONSTEXPR qint64 seconds() const Q_DECL_NOTHROW { return secs; }
60 Q_DECL_CONSTEXPR qint64 microSeconds() const Q_DECL_NOTHROW { return usecs; }
61
62 private:
63 qint64 secs;
64 qint64 usecs;
65 };
66
67 enum FrameType {
68 UnknownFrame = 0x0,
69 DataFrame = 0x1,
70 ErrorFrame = 0x2,
71 RemoteRequestFrame = 0x3,
72 InvalidFrame = 0x4
73 };
74
75 explicit QCanBusFrame(FrameType type = DataFrame) Q_DECL_NOTHROW :
76 isExtendedFrame(0x0),
77 version(Qt_5_10),
78 isFlexibleDataRate(0x0),
79 isBitrateSwitch(0x0),
80 isErrorStateIndicator(0x0),
81 isLocalEcho(0x0),
82 reserved0(0x0)
83 {
84 Q_UNUSED(reserved0);
85 ::memset(s: reserved, c: 0, n: sizeof(reserved));
86 setFrameId(0x0);
87 setFrameType(type);
88 }
89
90 enum FrameError {
91 NoError = 0,
92 TransmissionTimeoutError = (1 << 0),
93 LostArbitrationError = (1 << 1),
94 ControllerError = (1 << 2),
95 ProtocolViolationError = (1 << 3),
96 TransceiverError = (1 << 4),
97 MissingAcknowledgmentError = (1 << 5),
98 BusOffError = (1 << 6),
99 BusError = (1 << 7),
100 ControllerRestartError = (1 << 8),
101 UnknownError = (1 << 9),
102 AnyError = 0x1FFFFFFFU
103 //only 29 bits usable
104 };
105 Q_DECLARE_FLAGS(FrameErrors, FrameError)
106 Q_FLAGS(FrameErrors)
107
108 explicit QCanBusFrame(quint32 identifier, const QByteArray &data) :
109 format(DataFrame),
110 isExtendedFrame(0x0),
111 version(Qt_5_10),
112 isFlexibleDataRate(data.length() > 8 ? 0x1 : 0x0),
113 isBitrateSwitch(0x0),
114 isErrorStateIndicator(0x0),
115 isLocalEcho(0x0),
116 reserved0(0x0),
117 load(data)
118 {
119 ::memset(s: reserved, c: 0, n: sizeof(reserved));
120 setFrameId(identifier);
121 }
122
123 bool isValid() const Q_DECL_NOTHROW
124 {
125 if (format == InvalidFrame)
126 return false;
127
128 // long id used, but extended flag not set
129 if (!isExtendedFrame && (canId & 0x1FFFF800U))
130 return false;
131
132 if (!isValidFrameId)
133 return false;
134
135 // maximum permitted payload size in CAN or CAN FD
136 const int length = load.length();
137 if (isFlexibleDataRate) {
138 if (format == RemoteRequestFrame)
139 return false;
140
141 return length <= 8 || length == 12 || length == 16 || length == 20
142 || length == 24 || length == 32 || length == 48 || length == 64;
143 }
144
145 return length <= 8;
146 }
147
148 FrameType frameType() const Q_DECL_NOTHROW
149 {
150 switch (format) {
151 case 0x1: return DataFrame;
152 case 0x2: return ErrorFrame;
153 case 0x3: return RemoteRequestFrame;
154 case 0x4: return InvalidFrame;
155 // no default to trigger warning
156 }
157
158 return UnknownFrame;
159 }
160
161 void setFrameType(FrameType newFormat) Q_DECL_NOTHROW
162 {
163 switch (newFormat) {
164 case DataFrame:
165 format = 0x1; return;
166 case ErrorFrame:
167 format = 0x2; return;
168 case RemoteRequestFrame:
169 format = 0x3; return;
170 case UnknownFrame:
171 format = 0x0; return;
172 case InvalidFrame:
173 format = 0x4; return;
174 }
175 }
176
177 bool hasExtendedFrameFormat() const Q_DECL_NOTHROW { return (isExtendedFrame & 0x1); }
178 void setExtendedFrameFormat(bool isExtended) Q_DECL_NOTHROW
179 {
180 isExtendedFrame = (isExtended & 0x1);
181 }
182
183 quint32 frameId() const Q_DECL_NOTHROW
184 {
185 if (Q_UNLIKELY(format == ErrorFrame))
186 return 0;
187 return (canId & 0x1FFFFFFFU);
188 }
189 void setFrameId(quint32 newFrameId)
190 {
191 if (Q_LIKELY(newFrameId < 0x20000000U)) {
192 isValidFrameId = true;
193 canId = newFrameId;
194 setExtendedFrameFormat(isExtendedFrame || (newFrameId & 0x1FFFF800U));
195 } else {
196 isValidFrameId = false;
197 canId = 0;
198 }
199 }
200
201 void setPayload(const QByteArray &data)
202 {
203 load = data;
204 if (data.length() > 8)
205 isFlexibleDataRate = 0x1;
206 }
207 void setTimeStamp(TimeStamp ts) Q_DECL_NOTHROW { stamp = ts; }
208
209 QByteArray payload() const { return load; }
210 TimeStamp timeStamp() const Q_DECL_NOTHROW { return stamp; }
211
212 FrameErrors error() const Q_DECL_NOTHROW
213 {
214 if (format != ErrorFrame)
215 return NoError;
216
217 return FrameErrors(canId & 0x1FFFFFFFU);
218 }
219 void setError(FrameErrors e)
220 {
221 if (format != ErrorFrame)
222 return;
223 canId = (e & AnyError);
224 }
225
226 QString toString() const;
227
228 bool hasFlexibleDataRateFormat() const Q_DECL_NOTHROW { return (isFlexibleDataRate & 0x1); }
229 void setFlexibleDataRateFormat(bool isFlexibleData) Q_DECL_NOTHROW
230 {
231 isFlexibleDataRate = (isFlexibleData & 0x1);
232 if (!isFlexibleData) {
233 isBitrateSwitch = 0x0;
234 isErrorStateIndicator = 0x0;
235 }
236 }
237
238 bool hasBitrateSwitch() const Q_DECL_NOTHROW { return (isBitrateSwitch & 0x1); }
239 void setBitrateSwitch(bool bitrateSwitch) Q_DECL_NOTHROW
240 {
241 isBitrateSwitch = (bitrateSwitch & 0x1);
242 if (bitrateSwitch)
243 isFlexibleDataRate = 0x1;
244 }
245
246 bool hasErrorStateIndicator() const Q_DECL_NOTHROW { return (isErrorStateIndicator & 0x1); }
247 void setErrorStateIndicator(bool errorStateIndicator) Q_DECL_NOTHROW
248 {
249 isErrorStateIndicator = (errorStateIndicator & 0x1);
250 if (errorStateIndicator)
251 isFlexibleDataRate = 0x1;
252 }
253 bool hasLocalEcho() const Q_DECL_NOTHROW { return (isLocalEcho & 0x1); }
254 void setLocalEcho(bool localEcho) Q_DECL_NOTHROW
255 {
256 isLocalEcho = (localEcho & 0x1);
257 }
258
259#ifndef QT_NO_DATASTREAM
260 friend Q_SERIALBUS_EXPORT QDataStream &operator<<(QDataStream &, const QCanBusFrame &);
261 friend Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &, QCanBusFrame &);
262#endif
263
264private:
265 enum Version {
266 Qt_5_8 = 0x0,
267 Qt_5_9 = 0x1,
268 Qt_5_10 = 0x2
269 };
270
271 quint32 canId:29; // acts as container for error codes too
272 quint8 format:3; // max of 8 frame types
273
274 quint8 isExtendedFrame:1;
275 quint8 version:5;
276 quint8 isValidFrameId:1;
277 quint8 isFlexibleDataRate:1;
278
279 quint8 isBitrateSwitch:1;
280 quint8 isErrorStateIndicator:1;
281 quint8 isLocalEcho:1;
282 quint8 reserved0:5;
283
284 // reserved for future use
285 quint8 reserved[2];
286
287 QByteArray load;
288 TimeStamp stamp;
289};
290
291Q_DECLARE_TYPEINFO(QCanBusFrame, Q_MOVABLE_TYPE);
292Q_DECLARE_TYPEINFO(QCanBusFrame::FrameError, Q_PRIMITIVE_TYPE);
293Q_DECLARE_TYPEINFO(QCanBusFrame::FrameType, Q_PRIMITIVE_TYPE);
294Q_DECLARE_TYPEINFO(QCanBusFrame::TimeStamp, Q_PRIMITIVE_TYPE);
295
296Q_DECLARE_OPERATORS_FOR_FLAGS(QCanBusFrame::FrameErrors)
297
298#ifndef QT_NO_DATASTREAM
299Q_SERIALBUS_EXPORT QDataStream &operator<<(QDataStream &, const QCanBusFrame &);
300Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &, QCanBusFrame &);
301#endif
302
303QT_END_NAMESPACE
304
305Q_DECLARE_METATYPE(QCanBusFrame::FrameType)
306Q_DECLARE_METATYPE(QCanBusFrame::FrameErrors)
307
308#endif // QCANBUSFRAME_H
309

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