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 44 QT_BEGIN_NAMESPACE 45 46 class QDataStream; 47 48 class Q_SERIALBUS_EXPORT QCanBusFrame 49 { 50 public: 51 class TimeStamp { 52 public: 53 Q_DECL_CONSTEXPR TimeStamp(qint64 s = 0, qint64 usec = 0) Q_DECL_NOTHROW secs(s)54 : secs(s), usecs(usec) {} 55 fromMicroSeconds(qint64 usec)56 Q_DECL_CONSTEXPR static TimeStamp fromMicroSeconds(qint64 usec) Q_DECL_NOTHROW 57 { return TimeStamp(usec / 1000000, usec % 1000000); } 58 seconds()59 Q_DECL_CONSTEXPR qint64 seconds() const Q_DECL_NOTHROW { return secs; } microSeconds()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(reserved, 0, 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 }; Q_DECLARE_FLAGS(FrameErrors,FrameError)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(reserved, 0, sizeof(reserved)); 120 setFrameId(identifier); 121 } 122 isValid()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 frameType()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 setFrameType(FrameType newFormat)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 hasExtendedFrameFormat()177 bool hasExtendedFrameFormat() const Q_DECL_NOTHROW { return (isExtendedFrame & 0x1); } setExtendedFrameFormat(bool isExtended)178 void setExtendedFrameFormat(bool isExtended) Q_DECL_NOTHROW 179 { 180 isExtendedFrame = (isExtended & 0x1); 181 } 182 frameId()183 quint32 frameId() const Q_DECL_NOTHROW 184 { 185 if (Q_UNLIKELY(format == ErrorFrame)) 186 return 0; 187 return (canId & 0x1FFFFFFFU); 188 } setFrameId(quint32 newFrameId)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 setPayload(const QByteArray & data)201 void setPayload(const QByteArray &data) 202 { 203 load = data; 204 if (data.length() > 8) 205 isFlexibleDataRate = 0x1; 206 } setTimeStamp(TimeStamp ts)207 void setTimeStamp(TimeStamp ts) Q_DECL_NOTHROW { stamp = ts; } 208 payload()209 QByteArray payload() const { return load; } timeStamp()210 TimeStamp timeStamp() const Q_DECL_NOTHROW { return stamp; } 211 error()212 FrameErrors error() const Q_DECL_NOTHROW 213 { 214 if (format != ErrorFrame) 215 return NoError; 216 217 return FrameErrors(canId & 0x1FFFFFFFU); 218 } setError(FrameErrors e)219 void setError(FrameErrors e) 220 { 221 if (format != ErrorFrame) 222 return; 223 canId = (e & AnyError); 224 } 225 226 QString toString() const; 227 hasFlexibleDataRateFormat()228 bool hasFlexibleDataRateFormat() const Q_DECL_NOTHROW { return (isFlexibleDataRate & 0x1); } setFlexibleDataRateFormat(bool isFlexibleData)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 hasBitrateSwitch()238 bool hasBitrateSwitch() const Q_DECL_NOTHROW { return (isBitrateSwitch & 0x1); } setBitrateSwitch(bool bitrateSwitch)239 void setBitrateSwitch(bool bitrateSwitch) Q_DECL_NOTHROW 240 { 241 isBitrateSwitch = (bitrateSwitch & 0x1); 242 if (bitrateSwitch) 243 isFlexibleDataRate = 0x1; 244 } 245 hasErrorStateIndicator()246 bool hasErrorStateIndicator() const Q_DECL_NOTHROW { return (isErrorStateIndicator & 0x1); } setErrorStateIndicator(bool errorStateIndicator)247 void setErrorStateIndicator(bool errorStateIndicator) Q_DECL_NOTHROW 248 { 249 isErrorStateIndicator = (errorStateIndicator & 0x1); 250 if (errorStateIndicator) 251 isFlexibleDataRate = 0x1; 252 } hasLocalEcho()253 bool hasLocalEcho() const Q_DECL_NOTHROW { return (isLocalEcho & 0x1); } setLocalEcho(bool localEcho)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 264 private: 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 291 Q_DECLARE_TYPEINFO(QCanBusFrame, Q_MOVABLE_TYPE); 292 Q_DECLARE_TYPEINFO(QCanBusFrame::FrameError, Q_PRIMITIVE_TYPE); 293 Q_DECLARE_TYPEINFO(QCanBusFrame::FrameType, Q_PRIMITIVE_TYPE); 294 Q_DECLARE_TYPEINFO(QCanBusFrame::TimeStamp, Q_PRIMITIVE_TYPE); 295 296 Q_DECLARE_OPERATORS_FOR_FLAGS(QCanBusFrame::FrameErrors) 297 298 #ifndef QT_NO_DATASTREAM 299 Q_SERIALBUS_EXPORT QDataStream &operator<<(QDataStream &, const QCanBusFrame &); 300 Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &, QCanBusFrame &); 301 #endif 302 303 QT_END_NAMESPACE 304 305 Q_DECLARE_METATYPE(QCanBusFrame::FrameType) 306 Q_DECLARE_METATYPE(QCanBusFrame::FrameErrors) 307 308 #endif // QCANBUSFRAME_H 309