// Copyright (C) 2017 Ford Motor Company. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef PASSTHRUCAN_J2534PASSTHRU_H #define PASSTHRUCAN_J2534PASSTHRU_H #include #include #include #include #include #ifdef Q_OS_WIN32 # define J2534_API __stdcall #else # define J2534_API #endif Q_DECLARE_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_PASSTHRU) namespace J2534 { class Message; extern "C" { typedef long (J2534_API *PassThruOpenFunc)(const void *pName, ulong *pDeviceId); typedef long (J2534_API *PassThruCloseFunc)(ulong deviceId); typedef long (J2534_API *PassThruConnectFunc)(ulong deviceId, ulong protocolId, ulong flags, ulong baudRate, ulong *pChannelId); typedef long (J2534_API *PassThruDisconnectFunc)(ulong channelId); typedef long (J2534_API *PassThruReadMsgsFunc)(ulong channelId, Message *pMsg, ulong *pNumMsgs, ulong timeout); typedef long (J2534_API *PassThruWriteMsgsFunc)(ulong channelId, const Message *pMsg, ulong *pNumMsgs, ulong timeout); typedef long (J2534_API *PassThruStartMsgFilterFunc)(ulong channelID, ulong filterType, const Message *pMaskMsg, const Message *pPatternMsg, const Message *pFlowControlMsg, ulong *pFilterId); typedef long (J2534_API *PassThruGetLastErrorFunc)(char *pErrorDescription); typedef long (J2534_API *PassThruIoctlFunc)(ulong channelId, ulong ioctlId, const void *pInput, void *pOutput); } // extern "C" enum class Protocol : uint { J1850VPW = 1, J1850PWM, ISO9141, ISO14230, CAN, ISO15765, SCIAEngine, SCIATrans, SCIBEngine, SCIBTrans }; class Message { public: static const ulong maxSize = 4128; enum RxStatusBit { InTxMsgType = 1 << 0, InStartOfMessage = 1 << 1, InRxBreak = 1 << 2, InTxIndication = 1 << 3, InISO15765PaddingError = 1 << 4, InISO15765AddrType = 1 << 7, InCAN29BitID = 1 << 8 }; Q_DECLARE_FLAGS(RxStatus, RxStatusBit) enum TxFlag { OutISO15765FramePad = 1 << 6, OutISO15765AddrType = 1 << 7, OutCAN29BitID = 1 << 8, OutWaitP3MinOnly = 1 << 9 }; Q_DECLARE_FLAGS(TxFlags, TxFlag) Message(); explicit Message(Protocol proto); Protocol protocolId() const { return Protocol(m_protocolId); } void setProtocolId(Protocol proto) { m_protocolId = uint(proto); } RxStatus rxStatus() const { return RxStatus(uint(m_rxStatus)); } void setRxStatus(RxStatus status) { m_rxStatus = uint(status); } TxFlags txFlags() const { return TxFlags(uint(m_txFlags)); } void setTxFlags(TxFlags flags) { m_txFlags = uint(flags); } ulong timestamp() const { return m_timestamp; } void setTimestamp(ulong stamp) { m_timestamp = stamp; } ulong size() const { return m_dataSize; } void setSize(ulong dataSize) { m_dataSize = dataSize; } ulong extraDataIndex() const { return m_extraDataIndex; } void setExtraDataIndex(ulong index) { m_extraDataIndex = index; } char *data() { return m_data; } const char *data() const { return m_data; } private: ulong m_protocolId = 0; ulong m_rxStatus = 0; ulong m_txFlags = 0; ulong m_timestamp = 0; ulong m_dataSize = 0; ulong m_extraDataIndex = 0; char m_data[maxSize]; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Message::RxStatus) Q_DECLARE_OPERATORS_FOR_FLAGS(Message::TxFlags) class Config { public: enum Parameter { DataRate = 1, Loopback = 3, NodeAddress, NetworkLine, P1Min, P1Max, P2Min, P2Max, P3Min, P3Max, P4Min, P4Max, W1, W2, W3, W4, W5, Tidle, Tinil, Twup, Parity, BitSamplePoint, SyncJumpWidth, W0, T1Max, T2Max, T4Max, T5Max, ISO15765BS, ISO15765STmin, DataBits, FiveBaudMod, BSTx, STminTx, T3Max, ISO15765WFTMax, CanMixedFormat = 0x8000, J1962Pins, SWCANHSDataRate = 0x8010, SWCANSpeedchangeEnable, SWCANResSwitch, ActiveChannels = 0x8020, SampleRate, SamplesPerReading, ReadingsPerMsg, AveragingMethod, SampleResolution, InputRangeLow, InputRangeHigh }; Config() : m_parameter(0), m_value(0) {} explicit Config(Parameter param, ulong val = 0) : m_parameter(param), m_value(val) {} Parameter parameter() const { return Parameter(m_parameter); } ulong value() const { return m_value; } private: ulong m_parameter; ulong m_value; }; /** * @brief J2534 pass-through interface, version 04.04. * @internal * @see http://www.drewtech.com/support/passthru.html */ class PassThru : public QObject { Q_OBJECT Q_DISABLE_COPY(PassThru) public: typedef ulong Handle; enum Status { LoadFailed = -1, NoError = 0, NotSupported, InvalidChannelID, InvalidProtocolID, NullParameter, InvalidIoctlValue, InvalidFlags, Failed, DeviceNotConnected, Timeout, InvalidMsg, InvalidTimeInterval, ExceededLimit, InvalidMsgID, DeviceInUse, InvalidIoctlID, BufferEmpty, BufferFull, BufferOverflow, PinInvalid, ChannelInUse, MsgProtocolID, InvalidFilterID, NoFlowControl, NotUnique, InvalidBaudrate, InvalidDeviceID }; enum ConnectFlag { CAN29BitID = 1 << 8, ISO9141NoChecksum = 1 << 9, CANIDBoth = 1 << 11, ISO9141KLineOnly = 1 << 12 }; Q_DECLARE_FLAGS(ConnectFlags, ConnectFlag) enum FilterType { PassFilter = 1, BlockFilter, FlowControlFilter }; enum ClearTarget { TxBuffer = 7, RxBuffer, PeriodicMsgs, MsgFilters }; explicit PassThru(const QString &libraryPath, QObject *parent = nullptr); virtual ~PassThru(); Status open(const QByteArray &name, Handle *deviceId); Status close(Handle deviceId); Status connect(Handle deviceId, Protocol protocolId, ConnectFlags flags, uint baudRate, Handle *channelId); Status disconnect(Handle channelId); Status readMsgs(Handle channelId, Message *msgs, ulong *numMsgs, uint timeout = 0); Status writeMsgs(Handle channelId, const Message *msgs, ulong *numMsgs, uint timeout = 0); Status startMsgFilter(Handle channelId, FilterType filterType, const Message &maskMsg, const Message &patternMsg); Status setConfig(Handle channelId, const Config *params, ulong numParams = 1); Status clear(Handle channelId, ClearTarget target); Status lastError() const { return m_lastError; } QString lastErrorString() const; private: Status handleResult(long statusCode); template Func resolveApiFunction(Func *funcPtr, const char *name) { *funcPtr = reinterpret_cast(m_libJ2534.resolve(name)); return *funcPtr; } QLibrary m_libJ2534; PassThruOpenFunc m_ptOpen = nullptr; PassThruCloseFunc m_ptClose = nullptr; PassThruConnectFunc m_ptConnect = nullptr; PassThruDisconnectFunc m_ptDisconnect = nullptr; PassThruReadMsgsFunc m_ptReadMsgs = nullptr; PassThruWriteMsgsFunc m_ptWriteMsgs = nullptr; PassThruStartMsgFilterFunc m_ptStartMsgFilter = nullptr; PassThruGetLastErrorFunc m_ptGetLastError = nullptr; PassThruIoctlFunc m_ptIoctl = nullptr; QString m_lastErrorString; Status m_lastError = NoError; }; Q_DECLARE_OPERATORS_FOR_FLAGS(PassThru::ConnectFlags) } // namespace J2534 #endif // PASSTHRUCAN_J2534PASSTHRU_H