1// Copyright (C) 2017 Ford Motor Company.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef PASSTHRUCAN_J2534PASSTHRU_H
5#define PASSTHRUCAN_J2534PASSTHRU_H
6
7#include <QByteArray>
8#include <QLibrary>
9#include <QLoggingCategory>
10#include <QObject>
11#include <QString>
12
13#ifdef Q_OS_WIN32
14# define J2534_API __stdcall
15#else
16# define J2534_API
17#endif
18
19Q_DECLARE_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_PASSTHRU)
20
21namespace J2534 {
22
23class Message;
24
25extern "C" {
26
27typedef long (J2534_API *PassThruOpenFunc)(const void *pName, ulong *pDeviceId);
28typedef long (J2534_API *PassThruCloseFunc)(ulong deviceId);
29typedef long (J2534_API *PassThruConnectFunc)(ulong deviceId, ulong protocolId, ulong flags,
30 ulong baudRate, ulong *pChannelId);
31typedef long (J2534_API *PassThruDisconnectFunc)(ulong channelId);
32typedef long (J2534_API *PassThruReadMsgsFunc)(ulong channelId, Message *pMsg,
33 ulong *pNumMsgs, ulong timeout);
34typedef long (J2534_API *PassThruWriteMsgsFunc)(ulong channelId, const Message *pMsg,
35 ulong *pNumMsgs, ulong timeout);
36typedef long (J2534_API *PassThruStartMsgFilterFunc)(ulong channelID, ulong filterType,
37 const Message *pMaskMsg,
38 const Message *pPatternMsg,
39 const Message *pFlowControlMsg,
40 ulong *pFilterId);
41typedef long (J2534_API *PassThruGetLastErrorFunc)(char *pErrorDescription);
42typedef long (J2534_API *PassThruIoctlFunc)(ulong channelId, ulong ioctlId,
43 const void *pInput, void *pOutput);
44} // extern "C"
45
46enum class Protocol : uint {
47 J1850VPW = 1,
48 J1850PWM,
49 ISO9141,
50 ISO14230,
51 CAN,
52 ISO15765,
53 SCIAEngine,
54 SCIATrans,
55 SCIBEngine,
56 SCIBTrans
57};
58
59class Message
60{
61public:
62 static const ulong maxSize = 4128;
63
64 enum RxStatusBit {
65 InTxMsgType = 1 << 0,
66 InStartOfMessage = 1 << 1,
67 InRxBreak = 1 << 2,
68 InTxIndication = 1 << 3,
69 InISO15765PaddingError = 1 << 4,
70 InISO15765AddrType = 1 << 7,
71 InCAN29BitID = 1 << 8
72 };
73 Q_DECLARE_FLAGS(RxStatus, RxStatusBit)
74
75 enum TxFlag {
76 OutISO15765FramePad = 1 << 6,
77 OutISO15765AddrType = 1 << 7,
78 OutCAN29BitID = 1 << 8,
79 OutWaitP3MinOnly = 1 << 9
80 };
81 Q_DECLARE_FLAGS(TxFlags, TxFlag)
82
83 Message();
84 explicit Message(Protocol proto);
85
86 Protocol protocolId() const { return Protocol(m_protocolId); }
87 void setProtocolId(Protocol proto) { m_protocolId = uint(proto); }
88
89 RxStatus rxStatus() const { return RxStatus(uint(m_rxStatus)); }
90 void setRxStatus(RxStatus status) { m_rxStatus = uint(status); }
91
92 TxFlags txFlags() const { return TxFlags(uint(m_txFlags)); }
93 void setTxFlags(TxFlags flags) { m_txFlags = uint(flags); }
94
95 ulong timestamp() const { return m_timestamp; }
96 void setTimestamp(ulong stamp) { m_timestamp = stamp; }
97
98 ulong size() const { return m_dataSize; }
99 void setSize(ulong dataSize) { m_dataSize = dataSize; }
100
101 ulong extraDataIndex() const { return m_extraDataIndex; }
102 void setExtraDataIndex(ulong index) { m_extraDataIndex = index; }
103
104 char *data() { return m_data; }
105 const char *data() const { return m_data; }
106
107private:
108 ulong m_protocolId = 0;
109 ulong m_rxStatus = 0;
110 ulong m_txFlags = 0;
111 ulong m_timestamp = 0;
112 ulong m_dataSize = 0;
113 ulong m_extraDataIndex = 0;
114 char m_data[maxSize];
115};
116
117Q_DECLARE_OPERATORS_FOR_FLAGS(Message::RxStatus)
118Q_DECLARE_OPERATORS_FOR_FLAGS(Message::TxFlags)
119
120class Config
121{
122public:
123 enum Parameter {
124 DataRate = 1,
125
126 Loopback = 3,
127 NodeAddress,
128 NetworkLine,
129 P1Min,
130 P1Max,
131 P2Min,
132 P2Max,
133 P3Min,
134 P3Max,
135 P4Min,
136 P4Max,
137 W1,
138 W2,
139 W3,
140 W4,
141 W5,
142 Tidle,
143 Tinil,
144 Twup,
145 Parity,
146 BitSamplePoint,
147 SyncJumpWidth,
148 W0,
149 T1Max,
150 T2Max,
151 T4Max,
152 T5Max,
153 ISO15765BS,
154 ISO15765STmin,
155 DataBits,
156 FiveBaudMod,
157 BSTx,
158 STminTx,
159 T3Max,
160 ISO15765WFTMax,
161
162 CanMixedFormat = 0x8000,
163 J1962Pins,
164
165 SWCANHSDataRate = 0x8010,
166 SWCANSpeedchangeEnable,
167 SWCANResSwitch,
168
169 ActiveChannels = 0x8020,
170 SampleRate,
171 SamplesPerReading,
172 ReadingsPerMsg,
173 AveragingMethod,
174 SampleResolution,
175 InputRangeLow,
176 InputRangeHigh
177 };
178
179 Config() : m_parameter(0), m_value(0) {}
180 explicit Config(Parameter param, ulong val = 0) : m_parameter(param), m_value(val) {}
181
182 Parameter parameter() const { return Parameter(m_parameter); }
183 ulong value() const { return m_value; }
184
185private:
186 ulong m_parameter;
187 ulong m_value;
188};
189
190/**
191 * @brief J2534 pass-through interface, version 04.04.
192 * @internal
193 * @see http://www.drewtech.com/support/passthru.html
194 */
195class PassThru : public QObject
196{
197 Q_OBJECT
198 Q_DISABLE_COPY(PassThru)
199public:
200 typedef ulong Handle;
201
202 enum Status {
203 LoadFailed = -1,
204 NoError = 0,
205 NotSupported,
206 InvalidChannelID,
207 InvalidProtocolID,
208 NullParameter,
209 InvalidIoctlValue,
210 InvalidFlags,
211 Failed,
212 DeviceNotConnected,
213 Timeout,
214 InvalidMsg,
215 InvalidTimeInterval,
216 ExceededLimit,
217 InvalidMsgID,
218 DeviceInUse,
219 InvalidIoctlID,
220 BufferEmpty,
221 BufferFull,
222 BufferOverflow,
223 PinInvalid,
224 ChannelInUse,
225 MsgProtocolID,
226 InvalidFilterID,
227 NoFlowControl,
228 NotUnique,
229 InvalidBaudrate,
230 InvalidDeviceID
231 };
232
233 enum ConnectFlag {
234 CAN29BitID = 1 << 8,
235 ISO9141NoChecksum = 1 << 9,
236 CANIDBoth = 1 << 11,
237 ISO9141KLineOnly = 1 << 12
238 };
239 Q_DECLARE_FLAGS(ConnectFlags, ConnectFlag)
240
241 enum FilterType {
242 PassFilter = 1,
243 BlockFilter,
244 FlowControlFilter
245 };
246
247 enum ClearTarget {
248 TxBuffer = 7,
249 RxBuffer,
250 PeriodicMsgs,
251 MsgFilters
252 };
253
254 explicit PassThru(const QString &libraryPath, QObject *parent = nullptr);
255 virtual ~PassThru();
256
257 Status open(const QByteArray &name, Handle *deviceId);
258 Status close(Handle deviceId);
259 Status connect(Handle deviceId, Protocol protocolId, ConnectFlags flags,
260 uint baudRate, Handle *channelId);
261 Status disconnect(Handle channelId);
262 Status readMsgs(Handle channelId, Message *msgs, ulong *numMsgs, uint timeout = 0);
263 Status writeMsgs(Handle channelId, const Message *msgs, ulong *numMsgs, uint timeout = 0);
264 Status startMsgFilter(Handle channelId, FilterType filterType,
265 const Message &maskMsg, const Message &patternMsg);
266 Status setConfig(Handle channelId, const Config *params, ulong numParams = 1);
267 Status clear(Handle channelId, ClearTarget target);
268
269 Status lastError() const { return m_lastError; }
270 QString lastErrorString() const;
271
272private:
273 Status handleResult(long statusCode);
274
275 template <typename Func>
276 Func resolveApiFunction(Func *funcPtr, const char *name) {
277 *funcPtr = reinterpret_cast<Func>(m_libJ2534.resolve(symbol: name));
278 return *funcPtr;
279 }
280
281 QLibrary m_libJ2534;
282 PassThruOpenFunc m_ptOpen = nullptr;
283 PassThruCloseFunc m_ptClose = nullptr;
284 PassThruConnectFunc m_ptConnect = nullptr;
285 PassThruDisconnectFunc m_ptDisconnect = nullptr;
286 PassThruReadMsgsFunc m_ptReadMsgs = nullptr;
287 PassThruWriteMsgsFunc m_ptWriteMsgs = nullptr;
288 PassThruStartMsgFilterFunc m_ptStartMsgFilter = nullptr;
289 PassThruGetLastErrorFunc m_ptGetLastError = nullptr;
290 PassThruIoctlFunc m_ptIoctl = nullptr;
291 QString m_lastErrorString;
292 Status m_lastError = NoError;
293};
294
295Q_DECLARE_OPERATORS_FOR_FLAGS(PassThru::ConnectFlags)
296
297} // namespace J2534
298
299#endif // PASSTHRUCAN_J2534PASSTHRU_H
300

source code of qtserialbus/src/plugins/canbus/passthrucan/j2534passthru.h