1 | // Copyright (C) 2017 The Qt Company Ltd. |
2 | // Copyright (C) 2021 Andre Hartmann <aha_1980@gmx.de> |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QCANBUSDEVICE_H |
6 | #define QCANBUSDEVICE_H |
7 | |
8 | #include <QtCore/qobject.h> |
9 | #include <QtSerialBus/qcanbusframe.h> |
10 | #include <QtSerialBus/qcanbusdeviceinfo.h> |
11 | |
12 | #include <functional> |
13 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | class QCanBusDevicePrivate; |
17 | |
18 | class Q_SERIALBUS_EXPORT QCanBusDevice : public QObject |
19 | { |
20 | Q_OBJECT |
21 | Q_DECLARE_PRIVATE(QCanBusDevice) |
22 | Q_DISABLE_COPY(QCanBusDevice) |
23 | |
24 | public: |
25 | enum CanBusError { |
26 | NoError, |
27 | ReadError, |
28 | WriteError, |
29 | ConnectionError, |
30 | ConfigurationError, |
31 | UnknownError, |
32 | OperationError, |
33 | TimeoutError |
34 | }; |
35 | Q_ENUM(CanBusError) |
36 | |
37 | enum CanBusDeviceState { |
38 | UnconnectedState, |
39 | ConnectingState, |
40 | ConnectedState, |
41 | ClosingState |
42 | }; |
43 | Q_ENUM(CanBusDeviceState) |
44 | |
45 | enum class CanBusStatus { |
46 | Unknown, |
47 | Good, |
48 | Warning, |
49 | Error, |
50 | BusOff |
51 | }; |
52 | Q_ENUM(CanBusStatus) |
53 | |
54 | enum ConfigurationKey { |
55 | RawFilterKey = 0, |
56 | ErrorFilterKey, |
57 | LoopbackKey, |
58 | ReceiveOwnKey, |
59 | BitRateKey, |
60 | CanFdKey, |
61 | DataBitRateKey, |
62 | ProtocolKey, |
63 | UserKey = 30 |
64 | }; |
65 | Q_ENUM(ConfigurationKey) |
66 | |
67 | struct Filter |
68 | { |
69 | friend constexpr bool operator==(const Filter &a, const Filter &b) noexcept |
70 | { |
71 | return a.frameId == b.frameId && a.frameIdMask == b.frameIdMask |
72 | && a.type == b.type && a.format == b.format; |
73 | } |
74 | |
75 | friend constexpr bool operator!=(const Filter &a, const Filter &b) noexcept |
76 | { |
77 | return !operator==(a, b); |
78 | } |
79 | |
80 | enum FormatFilter { |
81 | MatchBaseFormat = 0x0001, |
82 | MatchExtendedFormat = 0x0002, |
83 | MatchBaseAndExtendedFormat = 0x0003, |
84 | }; |
85 | Q_DECLARE_FLAGS(FormatFilters, FormatFilter) |
86 | |
87 | QCanBusFrame::FrameId frameId = 0; |
88 | QCanBusFrame::FrameId frameIdMask = 0; |
89 | QCanBusFrame::FrameType type = QCanBusFrame::InvalidFrame; |
90 | FormatFilter format = MatchBaseAndExtendedFormat; |
91 | }; |
92 | |
93 | explicit QCanBusDevice(QObject *parent = nullptr); |
94 | |
95 | virtual void setConfigurationParameter(ConfigurationKey key, const QVariant &value); |
96 | QVariant configurationParameter(ConfigurationKey key) const; |
97 | QList<ConfigurationKey> configurationKeys() const; |
98 | |
99 | virtual bool writeFrame(const QCanBusFrame &frame) = 0; |
100 | QCanBusFrame readFrame(); |
101 | QList<QCanBusFrame> readAllFrames(); |
102 | qint64 framesAvailable() const; |
103 | qint64 framesToWrite() const; |
104 | |
105 | virtual void resetController(); |
106 | virtual bool hasBusStatus() const; |
107 | virtual CanBusStatus busStatus(); |
108 | |
109 | enum Direction { |
110 | Input = 1, |
111 | Output = 2, |
112 | AllDirections = Input | Output |
113 | }; |
114 | Q_DECLARE_FLAGS(Directions, Direction) |
115 | void clear(Directions direction = Direction::AllDirections); |
116 | |
117 | virtual bool waitForFramesWritten(int msecs); |
118 | virtual bool waitForFramesReceived(int msecs); |
119 | |
120 | bool connectDevice(); |
121 | void disconnectDevice(); |
122 | |
123 | CanBusDeviceState state() const; |
124 | |
125 | CanBusError error() const; |
126 | QString errorString() const; |
127 | |
128 | virtual QString interpretErrorFrame(const QCanBusFrame &errorFrame) = 0; |
129 | virtual QCanBusDeviceInfo deviceInfo() const; |
130 | |
131 | Q_SIGNALS: |
132 | void errorOccurred(QCanBusDevice::CanBusError); |
133 | void framesReceived(); |
134 | void framesWritten(qint64 framesCount); |
135 | void stateChanged(QCanBusDevice::CanBusDeviceState state); |
136 | |
137 | protected: |
138 | void setState(QCanBusDevice::CanBusDeviceState newState); |
139 | void setError(const QString &errorText, QCanBusDevice::CanBusError); |
140 | void clearError(); |
141 | |
142 | void enqueueReceivedFrames(const QList<QCanBusFrame> &newFrames); |
143 | |
144 | void enqueueOutgoingFrame(const QCanBusFrame &newFrame); |
145 | QCanBusFrame dequeueOutgoingFrame(); |
146 | bool hasOutgoingFrames() const; |
147 | |
148 | virtual bool open() = 0; |
149 | virtual void close() = 0; |
150 | |
151 | static QCanBusDeviceInfo createDeviceInfo(const QString &plugin, |
152 | const QString &name, |
153 | bool isVirtual, |
154 | bool isFlexibleDataRateCapable); |
155 | static QCanBusDeviceInfo createDeviceInfo(const QString &plugin, |
156 | const QString &name, |
157 | const QString &serialNumber, |
158 | const QString &description, |
159 | const QString &alias, |
160 | int channel, |
161 | bool isVirtual, |
162 | bool isFlexibleDataRateCapable); |
163 | }; |
164 | |
165 | Q_DECLARE_TYPEINFO(QCanBusDevice::CanBusError, Q_PRIMITIVE_TYPE); |
166 | Q_DECLARE_TYPEINFO(QCanBusDevice::CanBusDeviceState, Q_PRIMITIVE_TYPE); |
167 | Q_DECLARE_TYPEINFO(QCanBusDevice::ConfigurationKey, Q_PRIMITIVE_TYPE); |
168 | Q_DECLARE_TYPEINFO(QCanBusDevice::Filter, Q_PRIMITIVE_TYPE); |
169 | Q_DECLARE_TYPEINFO(QCanBusDevice::Filter::FormatFilter, Q_PRIMITIVE_TYPE); |
170 | |
171 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCanBusDevice::Filter::FormatFilters) |
172 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCanBusDevice::Directions) |
173 | |
174 | QT_END_NAMESPACE |
175 | |
176 | Q_DECLARE_METATYPE(QCanBusDevice::Filter::FormatFilter) |
177 | Q_DECLARE_METATYPE(QList<QCanBusDevice::Filter>) |
178 | |
179 | #endif // QCANBUSDEVICE_H |
180 | |