mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-09-21 00:18:38 +02:00
Compare commits
4
Commits
07e4eca14a
...
3a6501d116
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a6501d116 | ||
|
|
34875129ee | ||
|
|
236c6ad089 | ||
|
|
cf58f819cb |
@@ -234,10 +234,14 @@ set(SRC_FILES
|
|||||||
communication/message/ethernetstatusmessage.cpp
|
communication/message/ethernetstatusmessage.cpp
|
||||||
communication/message/networkmutexmessage.cpp
|
communication/message/networkmutexmessage.cpp
|
||||||
communication/message/clientidmessage.cpp
|
communication/message/clientidmessage.cpp
|
||||||
|
communication/message/mfgconfigmessage.cpp
|
||||||
communication/message/transmitmessage.cpp
|
communication/message/transmitmessage.cpp
|
||||||
|
|
||||||
|
|
||||||
communication/message/spiportkeymessage.cpp
|
communication/message/spiportkeymessage.cpp
|
||||||
communication/message/genericapidatamessage.cpp
|
communication/message/genericapidatamessage.cpp
|
||||||
communication/message/genericapistatusmessage.cpp
|
communication/message/genericapistatusmessage.cpp
|
||||||
|
communication/message/iso15765message.cpp
|
||||||
communication/packet/flexraypacket.cpp
|
communication/packet/flexraypacket.cpp
|
||||||
communication/packet/canpacket.cpp
|
communication/packet/canpacket.cpp
|
||||||
communication/packet/a2bpacket.cpp
|
communication/packet/a2bpacket.cpp
|
||||||
|
|||||||
@@ -545,15 +545,13 @@ int LegacyDLLExport icsneoGetTimeStampForMsg(void* hObject, icsSpyMessage* pMsg,
|
|||||||
void LegacyDLLExport icsneoGetISO15765Status(void* hObject, int lNetwork, int lClearTxStatus, int lClearRxStatus,
|
void LegacyDLLExport icsneoGetISO15765Status(void* hObject, int lNetwork, int lClearTxStatus, int lClearRxStatus,
|
||||||
int* lTxStatus, int* lRxStatus)
|
int* lTxStatus, int* lRxStatus)
|
||||||
{
|
{
|
||||||
// TODO Implement
|
// Not supported
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LegacyDLLExport icsneoSetISO15765RxParameters(void* hObject, int lNetwork, int lEnable, spyFilterLong* pFF_CFMsgFilter,
|
void LegacyDLLExport icsneoSetISO15765RxParameters(void* hObject, int lNetwork, int lEnable, spyFilterLong* pFF_CFMsgFilter,
|
||||||
icsSpyMessage* pTxMsg, int lCFTimeOutMs, int lFlowCBlockSize, int lUsesExtendedAddressing, int lUseHardwareIfPresent)
|
icsSpyMessage* pTxMsg, int lCFTimeOutMs, int lFlowCBlockSize, int lUsesExtendedAddressing, int lUseHardwareIfPresent)
|
||||||
{
|
{
|
||||||
// TODO Implement
|
// Not supported
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int LegacyDLLExport icsneoGetRTC(void* hObject, icsSpyTime* time)
|
int LegacyDLLExport icsneoGetRTC(void* hObject, icsSpyTime* time)
|
||||||
@@ -835,26 +833,25 @@ int LegacyDLLExport icsneoGetErrorInfo(int lErrorNumber, char* szErrorDescriptio
|
|||||||
//ISO15765-2 Functions
|
//ISO15765-2 Functions
|
||||||
int LegacyDLLExport icsneoISO15765_EnableNetworks(void* hObject, unsigned long ulNetworks)
|
int LegacyDLLExport icsneoISO15765_EnableNetworks(void* hObject, unsigned long ulNetworks)
|
||||||
{
|
{
|
||||||
// TODO Implement
|
// Not supported
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LegacyDLLExport icsneoISO15765_DisableNetworks(void* hObject)
|
int LegacyDLLExport icsneoISO15765_DisableNetworks(void* hObject)
|
||||||
{
|
{
|
||||||
// TODO Implement
|
// Not supported
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LegacyDLLExport icsneoISO15765_TransmitMessage(void* hObject, unsigned long ulNetworkID, stCM_ISO157652_TxMessage* pMsg,
|
int LegacyDLLExport icsneoISO15765_TransmitMessage(void* hObject, unsigned long ulNetworkID, stCM_ISO157652_TxMessage* pMsg, unsigned long ulBlockingTimeout)
|
||||||
unsigned long ulBlockingTimeout)
|
|
||||||
{
|
{
|
||||||
// TODO Implement
|
// Not supported
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LegacyDLLExport icsneoISO15765_ReceiveMessage(void* hObject, int ulNetworkID, stCM_ISO157652_RxMessage* pMsg)
|
int LegacyDLLExport icsneoISO15765_ReceiveMessage(void* hObject, int ulNetworkID, stCM_ISO157652_RxMessage* pMsg)
|
||||||
{
|
{
|
||||||
// TODO Implement
|
// Not supported
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1285,10 +1282,11 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
neodevice_t* device = reinterpret_cast<neodevice_t*>(hObject);
|
neodevice_t* device = reinterpret_cast<neodevice_t*>(hObject);
|
||||||
|
const auto& cmd = static_cast<icsneo::J2534Command>(*CmdBuf);
|
||||||
|
|
||||||
switch (*CmdBuf)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case J2534NVCMD_SetNetworkBaudRate:
|
case icsneo::J2534Command::SetNetworkBaudRate:
|
||||||
|
|
||||||
pTmp = (uint64_t *)&CmdBuf[1];
|
pTmp = (uint64_t *)&CmdBuf[1];
|
||||||
NetworkID = (uint16_t)*pTmp;
|
NetworkID = (uint16_t)*pTmp;
|
||||||
@@ -1298,7 +1296,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
|||||||
iRetVal = 0;
|
iRetVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case J2534NVCMD_GetNetworkBaudRate:
|
case icsneo::J2534Command::GetNetworkBaudRate:
|
||||||
{
|
{
|
||||||
pTmp = (uint64_t *)&CmdBuf[1];
|
pTmp = (uint64_t *)&CmdBuf[1];
|
||||||
NetworkID = (uint16_t)*pTmp;
|
NetworkID = (uint16_t)*pTmp;
|
||||||
@@ -1311,7 +1309,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
|||||||
*pTmp = static_cast<uint64_t>(ret);
|
*pTmp = static_cast<uint64_t>(ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case J2534NVCMD_SetCANFDRate:
|
case icsneo::J2534Command::SetCANFDRate:
|
||||||
|
|
||||||
pTmp = (uint64_t *)&CmdBuf[1];
|
pTmp = (uint64_t *)&CmdBuf[1];
|
||||||
NetworkID = (uint16_t)*pTmp;
|
NetworkID = (uint16_t)*pTmp;
|
||||||
@@ -1322,7 +1320,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
|||||||
iRetVal = 0;
|
iRetVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case J2534NVCMD_GetCANFDRate:
|
case icsneo::J2534Command::GetCANFDRate:
|
||||||
|
|
||||||
pTmp = (uint64_t *)&CmdBuf[1];
|
pTmp = (uint64_t *)&CmdBuf[1];
|
||||||
NetworkID = (uint16_t)*pTmp;
|
NetworkID = (uint16_t)*pTmp;
|
||||||
@@ -1332,7 +1330,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
|||||||
*pTmp = icsneo_getFDBaudrate(device, NetworkID);
|
*pTmp = icsneo_getFDBaudrate(device, NetworkID);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case J2534NVCMD_GetCANFDTermination:
|
case icsneo::J2534Command::GetCANFDTermination:
|
||||||
|
|
||||||
pTmp = (uint64_t *)&CmdBuf[1];
|
pTmp = (uint64_t *)&CmdBuf[1];
|
||||||
NetworkID = (uint16_t)*pTmp;
|
NetworkID = (uint16_t)*pTmp;
|
||||||
@@ -1368,7 +1366,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case J2534NVCMD_SetCANFDTermination:
|
case icsneo::J2534Command::SetCANFDTermination:
|
||||||
|
|
||||||
pTmp = (uint64_t *)&CmdBuf[1];
|
pTmp = (uint64_t *)&CmdBuf[1];
|
||||||
NetworkID = (uint16_t)*pTmp;
|
NetworkID = (uint16_t)*pTmp;
|
||||||
@@ -1422,11 +1420,9 @@ int LegacyDLLExport icsneoEnableBusVoltageMonitor(void* hObject, unsigned int en
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LegacyDLLExport icsneoISO15765_TransmitMessageEx(void* hObject,
|
int LegacyDLLExport icsneoISO15765_TransmitMessageEx(void* hObject, unsigned long ulNetworkID, ISO15765_2015_TxMessage* pMsg, unsigned long ulBlockingTimeout)
|
||||||
unsigned long ulNetworkID,
|
|
||||||
ISO15765_2015_TxMessage* pMsg,
|
|
||||||
unsigned long ulBlockingTimeout)
|
|
||||||
{
|
{
|
||||||
|
// Not supported
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||||
#include "icsneo/communication/message/networkmutexmessage.h"
|
#include "icsneo/communication/message/networkmutexmessage.h"
|
||||||
#include "icsneo/communication/message/clientidmessage.h"
|
#include "icsneo/communication/message/clientidmessage.h"
|
||||||
|
#include "icsneo/communication/message/mfgconfigmessage.h"
|
||||||
#include "icsneo/communication/message/spiportkeymessage.h"
|
#include "icsneo/communication/message/spiportkeymessage.h"
|
||||||
#include "icsneo/communication/message/genericapidatamessage.h"
|
#include "icsneo/communication/message/genericapidatamessage.h"
|
||||||
#include "icsneo/communication/message/genericapistatusmessage.h"
|
#include "icsneo/communication/message/genericapistatusmessage.h"
|
||||||
@@ -43,6 +44,7 @@
|
|||||||
#include "icsneo/communication/packet/i2cpacket.h"
|
#include "icsneo/communication/packet/i2cpacket.h"
|
||||||
#include "icsneo/communication/packet/scriptstatuspacket.h"
|
#include "icsneo/communication/packet/scriptstatuspacket.h"
|
||||||
#include "icsneo/communication/packet/linpacket.h"
|
#include "icsneo/communication/packet/linpacket.h"
|
||||||
|
#include "icsneo/communication/message/iso15765message.h"
|
||||||
#include "icsneo/communication/packet/componentversionpacket.h"
|
#include "icsneo/communication/packet/componentversionpacket.h"
|
||||||
#include "icsneo/communication/packet/supportedfeaturespacket.h"
|
#include "icsneo/communication/packet/supportedfeaturespacket.h"
|
||||||
#include "icsneo/communication/packet/mdiopacket.h"
|
#include "icsneo/communication/packet/mdiopacket.h"
|
||||||
@@ -371,6 +373,9 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
|||||||
);
|
);
|
||||||
protoapi::Id protoId = protoapi::getProtoId(responseBody.data(), responseBody.size());
|
protoapi::Id protoId = protoapi::getProtoId(responseBody.data(), responseBody.size());
|
||||||
switch(protoId) {
|
switch(protoId) {
|
||||||
|
case protoapi::Id::MfgConfig:
|
||||||
|
result = MfgConfigMessage::DecodeToMessage(responseBody);
|
||||||
|
return true;
|
||||||
case protoapi::Id::NetworkMutex:
|
case protoapi::Id::NetworkMutex:
|
||||||
result = NetworkMutexMessage::DecodeToMessage(responseBody);
|
result = NetworkMutexMessage::DecodeToMessage(responseBody);
|
||||||
return true;
|
return true;
|
||||||
@@ -475,6 +480,14 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case Command::J2534Command: {
|
||||||
|
result = J2534CommandMessage::decodeToMessage(packet->data);
|
||||||
|
if(!result) {
|
||||||
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
auto msg = std::make_shared<Main51Message>();
|
auto msg = std::make_shared<Main51Message>();
|
||||||
msg->command = Command(packet->data[0]);
|
msg->command = Command(packet->data[0]);
|
||||||
|
|||||||
@@ -0,0 +1,337 @@
|
|||||||
|
#include "icsneo/communication/message/iso15765message.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace icsneo;
|
||||||
|
|
||||||
|
std::shared_ptr<J2534CommandMessage> J2534CommandMessage::decodeToMessage(const std::vector<uint8_t>& data) {
|
||||||
|
if(data.size() < 2)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto msg = std::make_shared<J2534CommandMessage>((J2534Command)data[1]);
|
||||||
|
if(data.size() > 2)
|
||||||
|
msg->setArgumentData(std::vector<uint8_t>(data.begin() + 2, data.end()));
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t J2534CommandMessage::read16LE(size_t o) const {
|
||||||
|
return (uint16_t)((uint16_t)argumentData[o] | ((uint16_t)argumentData[o + 1] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2534CommandMessage::write16LE(size_t o, uint16_t v) {
|
||||||
|
argumentData[o] = (uint8_t)(v & 0xFF);
|
||||||
|
argumentData[o + 1] = (uint8_t)((v >> 8) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t J2534CommandMessage::read16BE(size_t o) const {
|
||||||
|
return (uint16_t)(((uint16_t)argumentData[o] << 8) | argumentData[o + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2534CommandMessage::write16BE(size_t o, uint16_t v) {
|
||||||
|
argumentData[o] = (uint8_t)((v >> 8) & 0xFF);
|
||||||
|
argumentData[o + 1] = (uint8_t)(v & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2534CommandMessage::writeBits16LE(size_t o, unsigned bitPos, unsigned bitCount, uint32_t value) {
|
||||||
|
const uint16_t mask = (uint16_t)(((1u << bitCount) - 1u) << bitPos);
|
||||||
|
uint16_t word = read16LE(o);
|
||||||
|
word = (uint16_t)((word & ~mask) | (((value << bitPos) & mask)));
|
||||||
|
write16LE(o, word);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t J2534CommandMessage::read32LE(size_t o) const {
|
||||||
|
return (uint32_t)argumentData[o]
|
||||||
|
| ((uint32_t)argumentData[o + 1] << 8)
|
||||||
|
| ((uint32_t)argumentData[o + 2] << 16)
|
||||||
|
| ((uint32_t)argumentData[o + 3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2534CommandMessage::write32LE(size_t o, uint32_t v) {
|
||||||
|
argumentData[o] = (uint8_t)(v & 0xFF);
|
||||||
|
argumentData[o + 1] = (uint8_t)((v >> 8) & 0xFF);
|
||||||
|
argumentData[o + 2] = (uint8_t)((v >> 16) & 0xFF);
|
||||||
|
argumentData[o + 3] = (uint8_t)((v >> 24) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t J2534CommandMessage::read32BE(size_t o) const {
|
||||||
|
return ((uint32_t)argumentData[o] << 24) | ((uint32_t)argumentData[o + 1] << 16)
|
||||||
|
| ((uint32_t)argumentData[o + 2] << 8) | (uint32_t)argumentData[o + 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2534CommandMessage::write32BE(size_t o, uint32_t v) {
|
||||||
|
argumentData[o] = (uint8_t)((v >> 24) & 0xFF);
|
||||||
|
argumentData[o + 1] = (uint8_t)((v >> 16) & 0xFF);
|
||||||
|
argumentData[o + 2] = (uint8_t)((v >> 8) & 0xFF);
|
||||||
|
argumentData[o + 3] = (uint8_t)(v & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
J2534_RxCanFilter J2534SetupCanRxFilteringMessage::getRxCanFilter() const {
|
||||||
|
constexpr size_t filterSize = sizeof(J2534_RxCanFilter::fb);
|
||||||
|
J2534_RxCanFilter filter = {};
|
||||||
|
if(argumentData.size() >= (10 + filterSize))
|
||||||
|
{
|
||||||
|
filter.idx = (argumentData[2] << 8) | argumentData[3];
|
||||||
|
filter.enabled = (argumentData[4] << 8) | argumentData[5];
|
||||||
|
filter.filterCount = (argumentData[6] << 8) | argumentData[7];
|
||||||
|
filter.fb = *((MessageFilterBytes*)(argumentData.data() + 8));
|
||||||
|
filter.networkId = (argumentData[8 + filterSize] << 8) | argumentData[9 + filterSize];
|
||||||
|
}
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2534SetupCanRxFilteringMessage::setRxCanFilter(const J2534_RxCanFilter& filter) {
|
||||||
|
argumentData.resize(10 + sizeof(filter.fb));
|
||||||
|
argumentData[2] = (filter.idx >> 8) & 0xFF;
|
||||||
|
argumentData[3] = filter.idx & 0xFF;
|
||||||
|
argumentData[4] = (filter.enabled >> 8) & 0xFF;
|
||||||
|
argumentData[5] = filter.enabled & 0xFF;
|
||||||
|
argumentData[6] = (filter.filterCount >> 8) & 0xFF;
|
||||||
|
argumentData[7] = filter.filterCount & 0xFF;
|
||||||
|
*((MessageFilterBytes*)(argumentData.data() + 8)) = filter.fb;
|
||||||
|
argumentData[8 + sizeof(filter.fb)] = (filter.networkId >> 8) & 0xFF;
|
||||||
|
argumentData[9 + sizeof(filter.fb)] = filter.networkId & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
J2534SetupIso15765FlowControlMessage::J2534SetupIso15765FlowControlMessage()
|
||||||
|
: J2534CommandMessage(J2534Command::SetupIso15765RxFilter) {
|
||||||
|
argumentData.resize(MessageSize);
|
||||||
|
// Bytes [0..1] were populated by the base constructor. Everything else starts at zero
|
||||||
|
// (matches the previous behavior which zeroed the flt region and left the rest of the
|
||||||
|
// caller-supplied struct as-is; typical callers value-initialized their struct too).
|
||||||
|
for(size_t i = 2; i < MessageSize; ++i)
|
||||||
|
argumentData[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2534SetupIso15765FlowControlMessage::rebuildFilterBytes(void) {
|
||||||
|
// Zero the 28-byte flt region.
|
||||||
|
for(size_t i = 0; i < FltSize; ++i)
|
||||||
|
argumentData[FltOffset + i] = 0;
|
||||||
|
|
||||||
|
const uint32_t id = read32LE(IdOffset);
|
||||||
|
const uint32_t idMask = read32LE(IdMaskOffset);
|
||||||
|
const bool is29Bit = getFlagBit(FlagId29BitEnable);
|
||||||
|
const bool extAddr = getFlagBit(FlagExtAddressEnable);
|
||||||
|
const uint8_t extAddrByte = argumentData[ExtAddrOffset];
|
||||||
|
|
||||||
|
// CoreMiniMessageFilterBytes has an interleaved layout:
|
||||||
|
// uiFilterMask0 at flt+0, uiFilterID0 at flt+2
|
||||||
|
// uiFilterMask1 at flt+4, uiFilterID1 at flt+6
|
||||||
|
// uiFilterMask2 at flt+8, uiFilterID2 at flt+10
|
||||||
|
// datalink.uiFilterMask3 at flt+12, datalink.uiFilterID3 at flt+14
|
||||||
|
//
|
||||||
|
// CoreMiniMsgBitsCAN bit layout within each 16-bit unit:
|
||||||
|
// unit0: IDE(bit0), SRR(bit1), SID(bits2-12), NETWORKINDEX(bits13-15)
|
||||||
|
// unit1: EID(bits0-11), TXMSG(bit12), ...
|
||||||
|
// unit2: DLC(bits0-3), ..., RTR(bit9), EID2(bits10-15)
|
||||||
|
const size_t MaskUnit0 = FltOffset + 0;
|
||||||
|
const size_t MaskUnit1 = FltOffset + 4;
|
||||||
|
const size_t MaskUnit2 = FltOffset + 8;
|
||||||
|
const size_t ValueUnit0 = FltOffset + 2;
|
||||||
|
const size_t ValueUnit1 = FltOffset + 6;
|
||||||
|
const size_t ValueUnit2 = FltOffset + 10;
|
||||||
|
|
||||||
|
// filter arbid: pMask->IDE = 1
|
||||||
|
writeBits16LE(MaskUnit0, /*bit*/0, /*width*/1, 1);
|
||||||
|
|
||||||
|
if(is29Bit) {
|
||||||
|
// pValue->IDE = 1; pValue->SID = (id >> 18) & 0x7FF
|
||||||
|
writeBits16LE(ValueUnit0, 0, 1, 1);
|
||||||
|
writeBits16LE(ValueUnit0, 2, 11, (id >> 18) & 0x7FF);
|
||||||
|
// pValue->EID = (id >> 6) & 0xFFF
|
||||||
|
writeBits16LE(ValueUnit1, 0, 12, (id >> 6) & 0xFFF);
|
||||||
|
// pValue->EID2 = id & 0x3F
|
||||||
|
writeBits16LE(ValueUnit2, 10, 6, id & 0x3F);
|
||||||
|
// pMask->SID = (id_mask >> 18) & 0x7FF
|
||||||
|
writeBits16LE(MaskUnit0, 2, 11, (idMask >> 18) & 0x7FF);
|
||||||
|
// pMask->EID = (id_mask >> 6) & 0xFFF (overlaps pValue->{IDE,SID} storage)
|
||||||
|
writeBits16LE(MaskUnit1, 0, 12, (idMask >> 6) & 0xFFF);
|
||||||
|
// pMask->EID2 = id_mask & 0x3F (overlaps pValue->EID storage)
|
||||||
|
writeBits16LE(MaskUnit2, 10, 6, idMask & 0x3F);
|
||||||
|
} else {
|
||||||
|
// pValue->IDE = 0 (already zero); pValue->SID = id
|
||||||
|
writeBits16LE(ValueUnit0, 2, 11, id & 0x7FF);
|
||||||
|
// pMask->SID = id_mask
|
||||||
|
writeBits16LE(MaskUnit0, 2, 11, idMask & 0x7FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extended-address filter: writes into the datalink.uiFilterID3 / uiFilterMask3 bytes.
|
||||||
|
// uiFilterMask3 = flt[12..13] = wire[37..38]
|
||||||
|
// uiFilterID3 = flt[14..15] = wire[39..40]
|
||||||
|
if(extAddr) {
|
||||||
|
const size_t kValueBytes = FltOffset + 14; // uiFilterID3
|
||||||
|
const size_t kMaskBytes = FltOffset + 12; // uiFilterMask3
|
||||||
|
argumentData[kValueBytes + 0] = extAddrByte;
|
||||||
|
argumentData[kMaskBytes + 0] = 0xFF;
|
||||||
|
argumentData[kValueBytes + 1] = 0;
|
||||||
|
argumentData[kMaskBytes + 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t J2534SetupIso15765FlowControlMessage::getIdx(void) const { return read16LE(IdxOffset); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setIdx(uint16_t idx) { write16LE(IdxOffset, idx); }
|
||||||
|
|
||||||
|
uint16_t J2534SetupIso15765FlowControlMessage::getCoreMiniId(void) const { return read16LE(CoreMiniOffset); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setCoreMiniId(uint16_t coreMiniId) { write16LE(CoreMiniOffset, coreMiniId); }
|
||||||
|
|
||||||
|
uint8_t J2534SetupIso15765FlowControlMessage::getPadding(void) const { return argumentData[PaddingOffset]; }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setPadding(uint8_t padding) { argumentData[PaddingOffset] = padding; }
|
||||||
|
|
||||||
|
uint32_t J2534SetupIso15765FlowControlMessage::getId(void) const { return read32LE(IdOffset); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setId(uint32_t id) { write32LE(IdOffset, id); rebuildFilterBytes(); }
|
||||||
|
|
||||||
|
uint32_t J2534SetupIso15765FlowControlMessage::getIdMask(void) const { return read32LE(IdMaskOffset); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setIdMask(uint32_t idMask) { write32LE(IdMaskOffset, idMask); rebuildFilterBytes(); }
|
||||||
|
|
||||||
|
uint32_t J2534SetupIso15765FlowControlMessage::getFcId(void) const { return read32LE(FcIdOffset); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setFcId(uint32_t fcId) { write32LE(FcIdOffset, fcId); }
|
||||||
|
|
||||||
|
uint8_t J2534SetupIso15765FlowControlMessage::getFlowControlExtendedAddress(void) const { return argumentData[FcExtAddrOffset]; }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setFlowControlExtendedAddress(uint8_t addr) { argumentData[FcExtAddrOffset] = addr; }
|
||||||
|
|
||||||
|
uint8_t J2534SetupIso15765FlowControlMessage::getExtendedAddress(void) const { return argumentData[ExtAddrOffset]; }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setExtendedAddress(uint8_t addr) { argumentData[ExtAddrOffset] = addr; rebuildFilterBytes(); }
|
||||||
|
|
||||||
|
uint8_t J2534SetupIso15765FlowControlMessage::getBlockSize(void) const { return argumentData[BlockSizeOffset]; }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setBlockSize(uint8_t blockSize) { argumentData[BlockSizeOffset] = blockSize; }
|
||||||
|
|
||||||
|
uint8_t J2534SetupIso15765FlowControlMessage::getStMin(void) const { return argumentData[StMinOffset]; }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setStMin(uint8_t stMin) { argumentData[StMinOffset] = stMin; }
|
||||||
|
|
||||||
|
uint16_t J2534SetupIso15765FlowControlMessage::getCfTimeout(void) const { return read16LE(CfTimeoutOffset); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setCfTimeout(uint16_t cfTimeout) { write16LE(CfTimeoutOffset, cfTimeout); }
|
||||||
|
|
||||||
|
uint32_t J2534SetupIso15765FlowControlMessage::getFlags(void) const { return read32LE(FlagsOffset); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setFlags(uint32_t flags) { write32LE(FlagsOffset, flags); rebuildFilterBytes(); }
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getEnable(void) const { return getFlagBit(FlagEnable); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setEnable(bool enable) { setFlagBit(FlagEnable, enable); }
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getIs29BitEnabled(void) const { return getFlagBit(FlagId29BitEnable); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setIs29BitEnabled(bool enable) { setFlagBit(FlagId29BitEnable, enable); rebuildFilterBytes(); }
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getIsFc29BitEnabled(void) const { return getFlagBit(FlagFcId29BitEnable); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setIsFc29BitEnabled(bool enable) { setFlagBit(FlagFcId29BitEnable, enable); }
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getExtAddressEnabled(void) const { return getFlagBit(FlagExtAddressEnable); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setExtAddressEnabled(bool enable) { setFlagBit(FlagExtAddressEnable, enable); rebuildFilterBytes(); }
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getFcExtAddressEnabled(void) const { return getFlagBit(FlagFcExtAddressEnable); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setFcExtAddressEnabled(bool enable) { setFlagBit(FlagFcExtAddressEnable, enable); }
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getFlowControlTransmissionEnabled(void) const { return getFlagBit(FlagEnableFlowControlTransmit); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setFlowControlTransmissionEnabled(bool enable) { setFlagBit(FlagEnableFlowControlTransmit, enable); }
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getPaddingEnabled(void) const { return getFlagBit(FlagPaddingEnable); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setPaddingEnabled(bool enable) { setFlagBit(FlagPaddingEnable, enable); }
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getIsCanFd(void) const { return getFlagBit(FlagIsCanFd); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setIsCanFd(bool enable) { setFlagBit(FlagIsCanFd, enable); }
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getIsBrsEnabled(void) const { return getFlagBit(FlagIsBrsEnabled); }
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setIsBrsEnabled(bool enable) { setFlagBit(FlagIsBrsEnabled, enable); }
|
||||||
|
|
||||||
|
void J2534SetupIso15765FlowControlMessage::setFlagBit(uint32_t mask, bool enable) {
|
||||||
|
uint32_t f = read32LE(FlagsOffset);
|
||||||
|
if(enable) f |= mask;
|
||||||
|
else f &= ~mask;
|
||||||
|
write32LE(FlagsOffset, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool J2534SetupIso15765FlowControlMessage::getFlagBit(uint32_t mask) const {
|
||||||
|
return (read32LE(FlagsOffset) & mask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Iso15765TxSetupMessage::getIdx(void) const { return read16LE(SetupIdxOffset); }
|
||||||
|
void Iso15765TxSetupMessage::setIdx(uint16_t idx) { write16LE(SetupIdxOffset, idx); }
|
||||||
|
|
||||||
|
uint16_t Iso15765TxSetupMessage::getCoreMiniId(void) const { return read16LE(SetupCoreMiniOffset); }
|
||||||
|
void Iso15765TxSetupMessage::setCoreMiniId(uint16_t coreMiniId) { write16LE(SetupCoreMiniOffset, coreMiniId); }
|
||||||
|
|
||||||
|
uint32_t Iso15765TxSetupMessage::getMessageLength(void) const { return read32LE(SetupMsgLenOffset); }
|
||||||
|
void Iso15765TxSetupMessage::setMessageLength(uint32_t messageLength) { write32LE(SetupMsgLenOffset, messageLength); }
|
||||||
|
|
||||||
|
uint8_t Iso15765TxSetupMessage::getPadding(void) const { return argumentData[SetupPaddingOffset]; }
|
||||||
|
void Iso15765TxSetupMessage::setPadding(uint8_t padding) { argumentData[SetupPaddingOffset] = padding; }
|
||||||
|
|
||||||
|
uint8_t Iso15765TxSetupMessage::getTxDl(void) const { return argumentData[SetupTxDlOffset]; }
|
||||||
|
void Iso15765TxSetupMessage::setTxDl(uint8_t txDl) { argumentData[SetupTxDlOffset] = txDl; }
|
||||||
|
|
||||||
|
uint32_t Iso15765TxSetupMessage::getId(void) const { return read32LE(SetupIdOffset); }
|
||||||
|
void Iso15765TxSetupMessage::setId(uint32_t id) { write32LE(SetupIdOffset, id); }
|
||||||
|
|
||||||
|
uint32_t Iso15765TxSetupMessage::getFcId(void) const { return read32LE(SetupFcIdOffset); }
|
||||||
|
void Iso15765TxSetupMessage::setFcId(uint32_t fcId) { write32LE(SetupFcIdOffset, fcId); }
|
||||||
|
|
||||||
|
uint32_t Iso15765TxSetupMessage::getFcIdMask(void) const { return read32LE(SetupFcIdMaskOffset); }
|
||||||
|
void Iso15765TxSetupMessage::setFcIdMask(uint32_t fcIdMask) { write32LE(SetupFcIdMaskOffset, fcIdMask); }
|
||||||
|
|
||||||
|
uint8_t Iso15765TxSetupMessage::getFlowControlExtendedAddress(void) const { return argumentData[SetupFcExtAddrOffset]; }
|
||||||
|
void Iso15765TxSetupMessage::setFlowControlExtendedAddress(uint8_t addr) { argumentData[SetupFcExtAddrOffset] = addr; }
|
||||||
|
|
||||||
|
uint8_t Iso15765TxSetupMessage::getExtendedAddress(void) const { return argumentData[SetupExtAddrOffset]; }
|
||||||
|
void Iso15765TxSetupMessage::setExtendedAddress(uint8_t addr) { argumentData[SetupExtAddrOffset] = addr; }
|
||||||
|
|
||||||
|
uint16_t Iso15765TxSetupMessage::getFsTimeout(void) const { return read16LE(SetupFsTimeoutOffset); }
|
||||||
|
void Iso15765TxSetupMessage::setFsTimeout(uint16_t timeout) { write16LE(SetupFsTimeoutOffset, timeout); }
|
||||||
|
|
||||||
|
uint16_t Iso15765TxSetupMessage::getFsWait(void) const { return read16LE(SetupFsWaitOffset); }
|
||||||
|
void Iso15765TxSetupMessage::setFsWait(uint16_t wait) { write16LE(SetupFsWaitOffset, wait); }
|
||||||
|
|
||||||
|
uint32_t Iso15765TxSetupMessage::getFlags(void) const { return read32LE(SetupFlagsOffset); }
|
||||||
|
void Iso15765TxSetupMessage::setFlags(uint32_t flags) { write32LE(SetupFlagsOffset, flags); }
|
||||||
|
|
||||||
|
uint8_t Iso15765TxSetupMessage::getStMin(void) const { return argumentData[SetupStMinOffset]; }
|
||||||
|
void Iso15765TxSetupMessage::setStMin(uint8_t stMin) { argumentData[SetupStMinOffset] = stMin; }
|
||||||
|
|
||||||
|
uint8_t Iso15765TxSetupMessage::getBlockSize(void) const { return argumentData[SetupBlockSizeOffset]; }
|
||||||
|
void Iso15765TxSetupMessage::setBlockSize(uint8_t blockSize) { argumentData[SetupBlockSizeOffset] = blockSize; }
|
||||||
|
|
||||||
|
bool Iso15765TxSetupMessage::getIs29BitEnabled(void) const { return getFlagBit(FlagId29BitEnable); }
|
||||||
|
void Iso15765TxSetupMessage::setIs29BitEnabled(bool enable) { setFlagBit(FlagId29BitEnable, enable); }
|
||||||
|
bool Iso15765TxSetupMessage::getIsFc29BitEnabled(void) const { return getFlagBit(FlagFcId29BitEnable); }
|
||||||
|
void Iso15765TxSetupMessage::setIsFc29BitEnabled(bool enable) { setFlagBit(FlagFcId29BitEnable, enable); }
|
||||||
|
bool Iso15765TxSetupMessage::getExtAddressEnabled(void) const { return getFlagBit(FlagExtAddressEnable); }
|
||||||
|
void Iso15765TxSetupMessage::setExtAddressEnabled(bool enable) { setFlagBit(FlagExtAddressEnable, enable); }
|
||||||
|
bool Iso15765TxSetupMessage::getFcExtAddressEnabled(void) const { return getFlagBit(FlagFcExtAddressEnable); }
|
||||||
|
void Iso15765TxSetupMessage::setFcExtAddressEnabled(bool enable) { setFlagBit(FlagFcExtAddressEnable, enable); }
|
||||||
|
bool Iso15765TxSetupMessage::getOverrideStMin(void) const { return getFlagBit(FlagOverrideStMin); }
|
||||||
|
void Iso15765TxSetupMessage::setOverrideStMin(bool enable) { setFlagBit(FlagOverrideStMin, enable); }
|
||||||
|
bool Iso15765TxSetupMessage::getOverrideBlockSize(void) const { return getFlagBit(FlagOverrideBlockSize); }
|
||||||
|
void Iso15765TxSetupMessage::setOverrideBlockSize(bool enable) { setFlagBit(FlagOverrideBlockSize, enable); }
|
||||||
|
bool Iso15765TxSetupMessage::getPaddingEnabled(void) const { return getFlagBit(FlagPaddingEnable); }
|
||||||
|
void Iso15765TxSetupMessage::setPaddingEnabled(bool enable) { setFlagBit(FlagPaddingEnable, enable); }
|
||||||
|
bool Iso15765TxSetupMessage::getIsCanFd(void) const { return getFlagBit(FlagIsCanFd); }
|
||||||
|
void Iso15765TxSetupMessage::setIsCanFd(bool enable) { setFlagBit(FlagIsCanFd, enable); }
|
||||||
|
bool Iso15765TxSetupMessage::getIsBrsEnabled(void) const { return getFlagBit(FlagIsBrsEnabled); }
|
||||||
|
void Iso15765TxSetupMessage::setIsBrsEnabled(bool enable) { setFlagBit(FlagIsBrsEnabled, enable); }
|
||||||
|
|
||||||
|
bool Iso15765TxSetupMessage::getFlagBit(uint32_t mask) const {
|
||||||
|
return (getFlags() & mask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Iso15765TxSetupMessage::setFlagBit(uint32_t mask, bool enable) {
|
||||||
|
uint32_t f = getFlags();
|
||||||
|
if(enable) f |= mask;
|
||||||
|
else f &= ~mask;
|
||||||
|
setFlags(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Iso15765TxDataMessage::getIdx(void) const { return read16LE(DataIdxOffset); }
|
||||||
|
void Iso15765TxDataMessage::setIdx(uint16_t idx) { write16LE(DataIdxOffset, idx); }
|
||||||
|
|
||||||
|
uint32_t Iso15765TxDataMessage::getOffset(void) const { return read32LE(DataOffsetOffset); }
|
||||||
|
void Iso15765TxDataMessage::setOffset(uint32_t offset) { write32LE(DataOffsetOffset, offset); }
|
||||||
|
|
||||||
|
uint16_t Iso15765TxDataMessage::getLen(void) const { return read16LE(DataLenOffset); }
|
||||||
|
|
||||||
|
const uint8_t* Iso15765TxDataMessage::getData(void) const { return argumentData.data() + DataPayloadOffset; }
|
||||||
|
|
||||||
|
void Iso15765TxDataMessage::setData(const uint8_t* sourceData, uint16_t len) {
|
||||||
|
len = std::min(len, (uint16_t)MaxDataLength);
|
||||||
|
argumentData.resize(DataPayloadOffset + len);
|
||||||
|
write16LE(DataLenOffset, len);
|
||||||
|
if(len > 0 && sourceData != nullptr)
|
||||||
|
std::copy(sourceData, sourceData + len, argumentData.begin() + DataPayloadOffset);
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#include "icsneo/communication/message/mfgconfigmessage.h"
|
||||||
|
#include "icsneo/communication/icspb.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
using namespace icsneo;
|
||||||
|
|
||||||
|
static MfgConfigMessage::VersionNumber versionFromProto(const settings::common::v1::VersionNumber& version) {
|
||||||
|
MfgConfigMessage::VersionNumber decoded;
|
||||||
|
decoded.major = version.major();
|
||||||
|
decoded.minor = version.minor();
|
||||||
|
if(version.has_release())
|
||||||
|
decoded.release = version.release();
|
||||||
|
if(version.has_build())
|
||||||
|
decoded.build = version.build();
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MfgConfigMessage> MfgConfigMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||||
|
MfgConfigMessage decoded;
|
||||||
|
settings::manufacturing::v1::MfgConfig msg;
|
||||||
|
|
||||||
|
if(!protoapi::processResponse(bytestream.data(), bytestream.size(), msg)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg.has_serial_number()) {
|
||||||
|
decoded.serialNumber = msg.serial_number();
|
||||||
|
}
|
||||||
|
if(msg.has_manufacture_date()) {
|
||||||
|
const auto& date = msg.manufacture_date();
|
||||||
|
decoded.manufactureDate = MfgDate{date.manufacture_day(), date.manufacture_month(), date.manufacture_year()};
|
||||||
|
}
|
||||||
|
if(msg.has_hardware_rev()) {
|
||||||
|
decoded.hardwareRev = versionFromProto(msg.hardware_rev());
|
||||||
|
}
|
||||||
|
if(msg.has_product_id()) {
|
||||||
|
decoded.productId = static_cast<uint8_t>(msg.product_id());
|
||||||
|
}
|
||||||
|
if(msg.has_bootloader_rev()) {
|
||||||
|
decoded.bootloaderRev = versionFromProto(msg.bootloader_rev());
|
||||||
|
}
|
||||||
|
if(msg.has_usb_descriptor()) {
|
||||||
|
decoded.usbDescriptor = msg.usb_descriptor();
|
||||||
|
}
|
||||||
|
for(const auto& mac : msg.mac_addresses()) {
|
||||||
|
const auto& bytes = mac.mac_addr();
|
||||||
|
if(bytes.size() < MACAddressLength)
|
||||||
|
continue;
|
||||||
|
MACAddress address{};
|
||||||
|
std::copy_n(bytes.begin(), MACAddressLength, address.begin());
|
||||||
|
decoded.macAddresses.push_back(address);
|
||||||
|
}
|
||||||
|
if(msg.has_pcb_serial()) {
|
||||||
|
decoded.pcbSerial = msg.pcb_serial().pcb_serial();
|
||||||
|
}
|
||||||
|
if(msg.has_chip_id()) {
|
||||||
|
decoded.chipId = static_cast<ChipID>(msg.chip_id());
|
||||||
|
}
|
||||||
|
if(msg.has_imei()) {
|
||||||
|
decoded.imei = msg.imei();
|
||||||
|
}
|
||||||
|
if(msg.has_parent_product_id()) {
|
||||||
|
decoded.parentProductId = static_cast<uint8_t>(msg.parent_product_id());
|
||||||
|
}
|
||||||
|
if(msg.has_software_version_lock()) {
|
||||||
|
decoded.softwareVersionLock = versionFromProto(msg.software_version_lock());
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_shared<MfgConfigMessage>(decoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> MfgConfigMessage::EncodeArgumentsForGet() {
|
||||||
|
settings::manufacturing::v1::MfgConfig msg;
|
||||||
|
msg.Clear();
|
||||||
|
return protoapi::getPayload(protoapi::Command::GET, msg);
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "icsneo/disk/fat.h"
|
#include "icsneo/disk/fat.h"
|
||||||
#include "icsneo/communication/message/filter/extendedresponsefilter.h"
|
#include "icsneo/communication/message/filter/extendedresponsefilter.h"
|
||||||
#include "icsneo/communication/message/networkmutexmessage.h"
|
#include "icsneo/communication/message/networkmutexmessage.h"
|
||||||
|
#include "icsneo/communication/message/mfgconfigmessage.h"
|
||||||
#include "icsneo/communication/message/transmitmessage.h"
|
#include "icsneo/communication/message/transmitmessage.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -923,6 +924,36 @@ std::shared_ptr<HardwareInfo> Device::getHardwareInfo(std::chrono::milliseconds
|
|||||||
return hardwareInfo;
|
return hardwareInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MfgConfigMessage> Device::getMfgConfig() {
|
||||||
|
if(!isOpen()) {
|
||||||
|
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> payload = MfgConfigMessage::EncodeArgumentsForGet();
|
||||||
|
|
||||||
|
auto response = com->waitForMessageSync(
|
||||||
|
[this, payload]() {
|
||||||
|
return com->sendCommand(ExtendedCommand::ProtobufAPI, payload);
|
||||||
|
},
|
||||||
|
std::make_shared<MessageFilter>(Message::Type::MfgConfig),
|
||||||
|
std::chrono::milliseconds(250)
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!response) {
|
||||||
|
report(APIEvent::Type::Timeout, APIEvent::Severity::Error);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mfgConfig = std::dynamic_pointer_cast<MfgConfigMessage>(response);
|
||||||
|
if(!mfgConfig) {
|
||||||
|
report(APIEvent::Type::UnexpectedResponse, APIEvent::Severity::Error);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mfgConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::optional<uint64_t> Device::readLogicalDisk(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, Disk::MemoryType memType) {
|
std::optional<uint64_t> Device::readLogicalDisk(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, Disk::MemoryType memType) {
|
||||||
if(!into || timeout <= std::chrono::milliseconds(0)) {
|
if(!into || timeout <= std::chrono::milliseconds(0)) {
|
||||||
@@ -4096,3 +4127,256 @@ void Device::restartHeartbeat() {
|
|||||||
stopHeartbeat();
|
stopHeartbeat();
|
||||||
startHeartbeat();
|
startHeartbeat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Device::iso15765Enable(const Network& network) {
|
||||||
|
return J2534_EnableIso15765(network, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::iso15765DisableAll(void) {
|
||||||
|
bool ok = true;
|
||||||
|
for(const auto& slot : iso15765FirmwareEnabled)
|
||||||
|
{
|
||||||
|
if (slot.second)
|
||||||
|
{
|
||||||
|
if (!J2534_EnableIso15765(slot.first, false))
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::iso15765TransmitMessage(const Network& network, const Iso15765MessageArgs& msg, const std::chrono::milliseconds& timeout) {
|
||||||
|
if (!isOnline())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(iso15765FirmwareEnabled.find(network) == iso15765FirmwareEnabled.end() || !iso15765FirmwareEnabled[network])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool result;
|
||||||
|
Iso15765TxSetupMessage setupMsg;
|
||||||
|
|
||||||
|
//Set the network ID to use
|
||||||
|
if(const auto& coreMiniId = network.getCoreMini())
|
||||||
|
setupMsg.setCoreMiniId((uint16_t)*coreMiniId);
|
||||||
|
|
||||||
|
const uint8_t txIndex = msg.getTxIndex();
|
||||||
|
setupMsg.setIdx(txIndex);
|
||||||
|
|
||||||
|
setupMsg.setId(msg.getArbId().Id);
|
||||||
|
setupMsg.setFcId(msg.getFlowControlArbId().Id);
|
||||||
|
setupMsg.setFcIdMask(msg.getFlowControlArbIdMask());
|
||||||
|
|
||||||
|
setupMsg.setFsTimeout(msg.getFsTimeout());
|
||||||
|
setupMsg.setFsWait(msg.getFsWaitTimeout());
|
||||||
|
|
||||||
|
const uint32_t messageLength = (uint32_t)msg.getData().size();
|
||||||
|
setupMsg.setMessageLength(messageLength);
|
||||||
|
setupMsg.setIs29BitEnabled(msg.getArbId().Is29Bit);
|
||||||
|
setupMsg.setIsFc29BitEnabled(msg.getFlowControlArbId().Is29Bit);
|
||||||
|
if(const auto& extAddress = msg.getExtendedAddress())
|
||||||
|
{
|
||||||
|
setupMsg.setExtAddressEnabled(true);
|
||||||
|
setupMsg.setExtendedAddress(*extAddress);
|
||||||
|
}
|
||||||
|
if(const auto& extFcAddress = msg.getFlowControlExtendedAddress())
|
||||||
|
{
|
||||||
|
setupMsg.setFcExtAddressEnabled(true);
|
||||||
|
setupMsg.setFlowControlExtendedAddress(*extFcAddress);
|
||||||
|
}
|
||||||
|
if(const auto& stMin = msg.getStMin())
|
||||||
|
{
|
||||||
|
setupMsg.setOverrideStMin(true);
|
||||||
|
setupMsg.setStMin(*stMin);
|
||||||
|
}
|
||||||
|
if(const auto& blockSize = msg.getBlockSize())
|
||||||
|
{
|
||||||
|
setupMsg.setOverrideBlockSize(true);
|
||||||
|
setupMsg.setBlockSize(*blockSize);
|
||||||
|
}
|
||||||
|
if(const auto& padding = msg.getPaddingValue())
|
||||||
|
{
|
||||||
|
setupMsg.setPaddingEnabled(true);
|
||||||
|
setupMsg.setPadding(*padding);
|
||||||
|
}
|
||||||
|
setupMsg.setIsBrsEnabled(msg.getIsBrsEnabled());
|
||||||
|
setupMsg.setIsCanFd(msg.getIsCanFd());
|
||||||
|
setupMsg.setTxDl(msg.getTxDl());
|
||||||
|
|
||||||
|
{
|
||||||
|
uint32_t octetsToSend = messageLength;
|
||||||
|
const uint8_t* payload = msg.getData().data();
|
||||||
|
uint32_t offset = 0;
|
||||||
|
|
||||||
|
result = J2534_Transaction(network, std::move(setupMsg), timeout);
|
||||||
|
while(result && octetsToSend)
|
||||||
|
{
|
||||||
|
const uint16_t chunkSize = (uint16_t)std::min((uint32_t)Iso15765TxDataMessage::MaxDataLength, octetsToSend);
|
||||||
|
|
||||||
|
Iso15765TxDataMessage dataMsg;
|
||||||
|
dataMsg.setIdx(txIndex);
|
||||||
|
dataMsg.setOffset(offset);
|
||||||
|
dataMsg.setData(&payload[offset], chunkSize);
|
||||||
|
|
||||||
|
result = J2534_Transaction(network, std::move(dataMsg), timeout);
|
||||||
|
|
||||||
|
offset += chunkSize;
|
||||||
|
octetsToSend -= chunkSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::iso15765SetupRxFlowControl(const Network& network, const Iso15765MessageArgs& msg) {
|
||||||
|
if (!isOnline())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(iso15765FirmwareEnabled.find(network) == iso15765FirmwareEnabled.end() || !iso15765FirmwareEnabled[network])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
J2534SetupIso15765FlowControlMessage rxFlowControl;
|
||||||
|
|
||||||
|
rxFlowControl.setIsBrsEnabled(msg.getIsBrsEnabled());
|
||||||
|
rxFlowControl.setIsCanFd(msg.getIsCanFd());
|
||||||
|
rxFlowControl.setIdx(msg.getTxIndex());
|
||||||
|
if(const auto& coreMiniId = network.getCoreMini())
|
||||||
|
rxFlowControl.setCoreMiniId((uint16_t)*coreMiniId);
|
||||||
|
rxFlowControl.setEnable(true);
|
||||||
|
if(const auto& blockSize = msg.getBlockSize())
|
||||||
|
{
|
||||||
|
rxFlowControl.setBlockSize(*blockSize);
|
||||||
|
}
|
||||||
|
rxFlowControl.setCfTimeout(msg.getCfTimeout());
|
||||||
|
rxFlowControl.setFlowControlTransmissionEnabled(msg.getIsFlowControlEnabled());
|
||||||
|
if(const auto& extAddress = msg.getExtendedAddress())
|
||||||
|
{
|
||||||
|
rxFlowControl.setExtendedAddress(*extAddress);
|
||||||
|
rxFlowControl.setExtAddressEnabled(true);
|
||||||
|
}
|
||||||
|
if(const auto& fcExtAddress = msg.getFlowControlExtendedAddress())
|
||||||
|
{
|
||||||
|
rxFlowControl.setFlowControlExtendedAddress(*fcExtAddress);
|
||||||
|
rxFlowControl.setFcExtAddressEnabled(true);
|
||||||
|
}
|
||||||
|
rxFlowControl.setFcId(msg.getFlowControlArbId().Id);
|
||||||
|
rxFlowControl.setIsFc29BitEnabled(msg.getFlowControlArbId().Is29Bit);
|
||||||
|
rxFlowControl.setIs29BitEnabled(msg.getArbId().Is29Bit);
|
||||||
|
rxFlowControl.setId(msg.getArbId().Id);
|
||||||
|
rxFlowControl.setIdMask(msg.getFlowControlArbIdMask());
|
||||||
|
if(const auto& padding = msg.getPaddingValue())
|
||||||
|
{
|
||||||
|
rxFlowControl.setPadding(*padding);
|
||||||
|
rxFlowControl.setPaddingEnabled(true);
|
||||||
|
}
|
||||||
|
if(const auto& stMin = msg.getStMin())
|
||||||
|
{
|
||||||
|
rxFlowControl.setStMin(*stMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return J2534_Transaction(network, std::move(rxFlowControl), std::chrono::milliseconds(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::J2534_Transaction(const Network& network, J2534CommandMessage&& msg, const std::chrono::milliseconds& timeout) {
|
||||||
|
msg.network = network;
|
||||||
|
if (timeout.count())
|
||||||
|
{
|
||||||
|
static std::shared_ptr<MessageFilter> filter = std::make_shared<Main51MessageFilter>(Command::J2534Command);
|
||||||
|
const auto& response = com->waitForMessageSync([&](void)
|
||||||
|
{
|
||||||
|
return com->sendCommand(msg.command, msg.getArgumentData());
|
||||||
|
}, filter, timeout);
|
||||||
|
|
||||||
|
if (!response)
|
||||||
|
{
|
||||||
|
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto responseMsg = std::dynamic_pointer_cast<Main51Message>(response);
|
||||||
|
if (!responseMsg || responseMsg->command != Command::J2534Command)
|
||||||
|
{
|
||||||
|
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return com->sendCommand(msg.command, msg.getArgumentData());
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: responseMsg->data.front()
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Device::J2534_ClearRxFilters(const Network& network)
|
||||||
|
{
|
||||||
|
return J2534_Transaction(network, J2534CommandMessage(J2534CommandMessage::J2534Command::SetupClearCanRxFilters, { (uint8_t)0 /* is this necessary? */}), std::chrono::milliseconds(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::J2534_SetupCanRxFilter(const Network& network, const J2534_RxCanFilter& rxCanFilter)
|
||||||
|
{
|
||||||
|
return J2534_Transaction(network, J2534SetupCanRxFilteringMessage(rxCanFilter), std::chrono::milliseconds(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::J2534_EnableFiltering(const Network& network, const bool enable)
|
||||||
|
{
|
||||||
|
return J2534_Transaction(network, J2534EnableFilteringMessage(enable), std::chrono::milliseconds(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool Device::J2534_EnableIso15765(const Network& network, const bool enable)
|
||||||
|
{
|
||||||
|
if (iso15765FirmwareEnabled[network] == enable)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!J2534_Transaction(network, J2534EnableMessage(enable), std::chrono::milliseconds(0)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
iso15765FirmwareEnabled[network] = enable;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
// Turn OFF filtering of CAN messages in the firmware
|
||||||
|
return J2534_EnableFirmwareUsbPassFilters(network, false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::J2534_ClearRxFilter(const Network& network, unsigned int iIndex)
|
||||||
|
{
|
||||||
|
if (const auto& slot = iso15765FirmwareEnabled.find(network); slot != iso15765FirmwareEnabled.end() && slot->second)
|
||||||
|
{
|
||||||
|
J2534_RxCanFilter rxFilter;
|
||||||
|
memset(&rxFilter, 0, sizeof(rxFilter));
|
||||||
|
rxFilter.idx = (uint16_t)iIndex;
|
||||||
|
return J2534_SetupCanRxFilter(network, rxFilter);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::J2534_EnableFirmwareUsbPassFilters(const Network& network, const bool enable)
|
||||||
|
{
|
||||||
|
const auto& slot = iso15765FirmwareEnabled.find(network);
|
||||||
|
if (slot == iso15765FirmwareEnabled.end())
|
||||||
|
return false;
|
||||||
|
//check for disconnect here!
|
||||||
|
if (!slot->second)
|
||||||
|
{
|
||||||
|
// Tried to shut-off Rx table message filtering but FW ISO15765 was not enabled
|
||||||
|
return true; //just ignore it, no filtering can occur anyway
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable) //turning ON filtering in the Firmware based on the rx table
|
||||||
|
{
|
||||||
|
//Rx table message filtering is on by default in the firmware when m_bISO15765_FW_Enabled is true
|
||||||
|
//need to check here to see if we set index 0 to a PASS all filter (i.e. turned off USB filtering)
|
||||||
|
if (!J2534_ClearRxFilters(network))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New "filtering enable" mechanism - old firmware ignores this frame
|
||||||
|
return J2534_EnableFiltering(network, enable);
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ option(LIBICSNEO_BUILD_CPP_ANALOG_OUT_EXAMPLE "Build the analog output example."
|
|||||||
option(LIBICSNEO_BUILD_CPP_DISKFORMAT_EXAMPLE "Build the disk format example." ON)
|
option(LIBICSNEO_BUILD_CPP_DISKFORMAT_EXAMPLE "Build the disk format example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE "Build the T1S example." ON)
|
option(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE "Build the T1S example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE "Build the C++ gPTP settings example." ON)
|
option(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE "Build the C++ gPTP settings example." ON)
|
||||||
|
option(LIBICSNEO_BUILD_CPP_ISO15765_LOOPBACK_EXAMPLE "Build the C++ ISO15765 two-device CAN1 loopback example." ON)
|
||||||
|
|
||||||
add_compile_options(${LIBICSNEO_COMPILER_WARNINGS})
|
add_compile_options(${LIBICSNEO_COMPILER_WARNINGS})
|
||||||
|
|
||||||
@@ -190,3 +191,7 @@ endif()
|
|||||||
if(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE)
|
if(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE)
|
||||||
add_subdirectory(cpp/gptp)
|
add_subdirectory(cpp/gptp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(LIBICSNEO_BUILD_CPP_ISO15765_LOOPBACK_EXAMPLE)
|
||||||
|
add_subdirectory(cpp/iso15765_loopback)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
add_executable(libicsneocpp-iso15765-loopback src/ISO15765Loopback.cpp)
|
||||||
|
target_link_libraries(libicsneocpp-iso15765-loopback icsneocpp)
|
||||||
@@ -0,0 +1,450 @@
|
|||||||
|
#include <cctype>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "icsneo/icsneocpp.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
None,
|
||||||
|
Raw,
|
||||||
|
SingleFrame,
|
||||||
|
Both,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Options {
|
||||||
|
Mode mode = Mode::None;
|
||||||
|
std::string testerSerial;
|
||||||
|
std::string ecuSerial;
|
||||||
|
int64_t baud = 500000;
|
||||||
|
bool keepBaud = false;
|
||||||
|
uint32_t txId = 0x7E0;
|
||||||
|
uint32_t fcId = 0x7E8;
|
||||||
|
std::optional<size_t> payloadBytes;
|
||||||
|
int listenMs = 2000;
|
||||||
|
uint8_t padding = 0x00;
|
||||||
|
uint16_t fsTimeoutMs = 75;
|
||||||
|
uint16_t fsWaitMs = 150;
|
||||||
|
uint16_t cfTimeoutMs = 150;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::mutex gLogMutex;
|
||||||
|
|
||||||
|
void logLine(const std::string& line) {
|
||||||
|
std::lock_guard<std::mutex> lk(gLogMutex);
|
||||||
|
std::cout << line << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool iequals(const std::string& a, const std::string& b) {
|
||||||
|
if(a.size() != b.size())
|
||||||
|
return false;
|
||||||
|
for(size_t i = 0; i < a.size(); i++) {
|
||||||
|
if(std::tolower(static_cast<unsigned char>(a[i])) != std::tolower(static_cast<unsigned char>(b[i])))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string hexBytes(const std::vector<uint8_t>& data) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::hex << std::setfill('0');
|
||||||
|
for(size_t i = 0; i < data.size(); i++) {
|
||||||
|
if(i)
|
||||||
|
oss << ' ';
|
||||||
|
oss << std::setw(2) << static_cast<unsigned>(data[i]);
|
||||||
|
}
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string pciDescribe(const std::vector<uint8_t>& data) {
|
||||||
|
if(data.empty())
|
||||||
|
return {};
|
||||||
|
const uint8_t pciType = static_cast<uint8_t>(data[0] >> 4);
|
||||||
|
const uint8_t pciLow = static_cast<uint8_t>(data[0] & 0x0F);
|
||||||
|
std::ostringstream oss;
|
||||||
|
switch(pciType) {
|
||||||
|
case 0x0:
|
||||||
|
if(pciLow > 7 || data.size() < static_cast<size_t>(1 + pciLow))
|
||||||
|
return {};
|
||||||
|
oss << "SF len=" << static_cast<unsigned>(pciLow);
|
||||||
|
break;
|
||||||
|
case 0x1: {
|
||||||
|
if(data.size() < 8)
|
||||||
|
return {};
|
||||||
|
const uint16_t len = static_cast<uint16_t>((pciLow << 8) | data[1]);
|
||||||
|
if(len < 8)
|
||||||
|
return {};
|
||||||
|
oss << "FF len=" << len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x2:
|
||||||
|
if(data.size() < 2)
|
||||||
|
return {};
|
||||||
|
oss << "CF SN=" << static_cast<unsigned>(pciLow);
|
||||||
|
break;
|
||||||
|
case 0x3: {
|
||||||
|
if(data.size() < 3 || pciLow > 2)
|
||||||
|
return {};
|
||||||
|
static const char* fsName[] = { "CTS", "WAIT", "OVFLW" };
|
||||||
|
oss << "FC FS=" << fsName[pciLow];
|
||||||
|
oss << " BS=" << static_cast<unsigned>(data[1]);
|
||||||
|
oss << " STmin=0x" << std::hex << std::setw(2) << std::setfill('0')
|
||||||
|
<< static_cast<unsigned>(data[2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printUsage(const char* argv0) {
|
||||||
|
std::cerr
|
||||||
|
<< "Usage: " << argv0 << " --raw|--sf|--both [options]\n\n"
|
||||||
|
<< "Two Intrepid devices with CAN1 wired together (CANH/CANL, terminated).\n"
|
||||||
|
<< "Prints CAN1 frames with ISO-TP PCI decode (SF/FF/CF/FC).\n\n"
|
||||||
|
<< "Modes:\n"
|
||||||
|
<< " --raw Raw CAN ping-pong (cable check)\n"
|
||||||
|
<< " --sf Firmware ISO-TP single-frame TX from tester\n"
|
||||||
|
<< " --both Firmware ISO-TP TX on tester, firmware flow-control on ECU\n\n"
|
||||||
|
<< "Devices:\n"
|
||||||
|
<< " --tester SERIAL Tester (sender) serial\n"
|
||||||
|
<< " --ecu SERIAL ECU / peer serial\n"
|
||||||
|
<< " Optional if exactly two devices are found.\n\n"
|
||||||
|
<< "Optional:\n"
|
||||||
|
<< " --baud N CAN1 baud (default 500000, applied temporarily)\n"
|
||||||
|
<< " --keep-baud Do not change device baud\n"
|
||||||
|
<< " --tx-id HEX Tester ISO-TP CAN ID (default 0x7E0)\n"
|
||||||
|
<< " --fc-id HEX Flow-control CAN ID (default 0x7E8)\n"
|
||||||
|
<< " --bytes N ISO-TP payload size (sf default 5, both default 20)\n"
|
||||||
|
<< " --listen-ms N Time to listen after the action (default 2000)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t parseU32(const std::string& s) {
|
||||||
|
return static_cast<uint32_t>(std::stoul(s, nullptr, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseArgs(int argc, char** argv, Options& opt) {
|
||||||
|
for(int i = 1; i < argc; i++) {
|
||||||
|
const std::string a = argv[i];
|
||||||
|
auto need = [&](const char* name) -> std::string {
|
||||||
|
if(i + 1 >= argc)
|
||||||
|
throw std::runtime_error(std::string("missing value for ") + name);
|
||||||
|
return argv[++i];
|
||||||
|
};
|
||||||
|
if(a == "--raw")
|
||||||
|
opt.mode = Mode::Raw;
|
||||||
|
else if(a == "--sf")
|
||||||
|
opt.mode = Mode::SingleFrame;
|
||||||
|
else if(a == "--both")
|
||||||
|
opt.mode = Mode::Both;
|
||||||
|
else if(a == "--tester")
|
||||||
|
opt.testerSerial = need("--tester");
|
||||||
|
else if(a == "--ecu")
|
||||||
|
opt.ecuSerial = need("--ecu");
|
||||||
|
else if(a == "--baud")
|
||||||
|
opt.baud = static_cast<int64_t>(std::stoll(need("--baud")));
|
||||||
|
else if(a == "--keep-baud")
|
||||||
|
opt.keepBaud = true;
|
||||||
|
else if(a == "--tx-id")
|
||||||
|
opt.txId = parseU32(need("--tx-id"));
|
||||||
|
else if(a == "--fc-id")
|
||||||
|
opt.fcId = parseU32(need("--fc-id"));
|
||||||
|
else if(a == "--bytes")
|
||||||
|
opt.payloadBytes = static_cast<size_t>(std::stoul(need("--bytes")));
|
||||||
|
else if(a == "--listen-ms")
|
||||||
|
opt.listenMs = std::stoi(need("--listen-ms"));
|
||||||
|
else if(a == "-h" || a == "--help") {
|
||||||
|
printUsage(argv[0]);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Unknown argument: " << a << "\n";
|
||||||
|
printUsage(argv[0]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(opt.mode == Mode::None) {
|
||||||
|
printUsage(argv[0]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t defaultPayloadSize(Mode mode) {
|
||||||
|
return mode == Mode::SingleFrame ? 5 : 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> makePayload(size_t n) {
|
||||||
|
std::vector<uint8_t> data(n);
|
||||||
|
for(size_t i = 0; i < n; i++)
|
||||||
|
data[i] = static_cast<uint8_t>(i & 0xFF);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isExtended(uint32_t id) {
|
||||||
|
return id > 0x7FFu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printApiResult(const char* what, bool ok) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << " " << what << ": " << (ok ? "OK" : "FAIL");
|
||||||
|
if(!ok) {
|
||||||
|
const auto err = icsneo::GetLastError();
|
||||||
|
if(err.getType() != icsneo::APIEvent::Type::NoErrorFound)
|
||||||
|
oss << " [" << err << "]";
|
||||||
|
}
|
||||||
|
logLine(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool transmitCan(icsneo::Device& device, uint32_t arbId, std::vector<uint8_t> data) {
|
||||||
|
auto frame = std::make_shared<icsneo::CANMessage>();
|
||||||
|
frame->network = icsneo::Network::NetID::DWCAN_01;
|
||||||
|
frame->arbid = arbId;
|
||||||
|
frame->data = std::move(data);
|
||||||
|
frame->isExtended = isExtended(arbId);
|
||||||
|
frame->isCANFD = false;
|
||||||
|
const bool ok = device.transmit(frame);
|
||||||
|
if(!ok)
|
||||||
|
printApiResult("transmit CAN", ok);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillIso15765(icsneo::Iso15765MessageArgs& msg, const Options& opt, const std::vector<uint8_t>& payload, bool rx) {
|
||||||
|
msg.setTxIndex(0);
|
||||||
|
msg.setArbId(icsneo::Iso15765MessageArgs::ArbId(opt.txId, isExtended(opt.txId)));
|
||||||
|
msg.setFlowControlArbId(icsneo::Iso15765MessageArgs::ArbId(opt.fcId, isExtended(opt.fcId)));
|
||||||
|
msg.setFlowControlArbIdMask(isExtended(opt.txId) ? 0x1FFFFFFFu : 0x7FFu);
|
||||||
|
msg.setIsCanFd(false);
|
||||||
|
msg.setIsBrsEnabled(false);
|
||||||
|
msg.setTxDl(8);
|
||||||
|
msg.setPaddingValue(opt.padding);
|
||||||
|
msg.setFsTimeout(opt.fsTimeoutMs);
|
||||||
|
msg.setFsWaitTimeout(opt.fsWaitMs);
|
||||||
|
msg.setCfTimeout(opt.cfTimeoutMs);
|
||||||
|
msg.setIsFlowControlEnabled(rx);
|
||||||
|
if(!payload.empty()) {
|
||||||
|
auto copy = payload;
|
||||||
|
msg.setData(std::move(copy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Sniffer {
|
||||||
|
const char* tag = "";
|
||||||
|
std::optional<uint64_t> t0;
|
||||||
|
std::mutex t0Mutex;
|
||||||
|
|
||||||
|
void onCan(const std::shared_ptr<icsneo::CANMessage>& can) {
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(t0Mutex);
|
||||||
|
if(!t0)
|
||||||
|
t0 = can->timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
double relMs = 0.0;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(t0Mutex);
|
||||||
|
if(t0 && can->timestamp >= *t0)
|
||||||
|
relMs = static_cast<double>(can->timestamp - *t0) / 1e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << " [" << tag << (can->transmitted ? " TX" : " RX") << "] "
|
||||||
|
<< std::fixed << std::setprecision(3) << relMs << " ms "
|
||||||
|
<< can->network << " 0x" << std::hex << std::uppercase
|
||||||
|
<< std::setw(isExtended(can->arbid) ? 8 : 3) << std::setfill('0') << can->arbid
|
||||||
|
<< std::dec << " [" << can->data.size() << "] " << hexBytes(can->data);
|
||||||
|
const auto pci = pciDescribe(can->data);
|
||||||
|
if(!pci.empty())
|
||||||
|
oss << " " << pci;
|
||||||
|
logLine(oss.str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void addCanSniffer(icsneo::Device& device, Sniffer& sniffer) {
|
||||||
|
auto filter = std::make_shared<icsneo::MessageFilter>(icsneo::Network::NetID::DWCAN_01);
|
||||||
|
device.addMessageCallback(std::make_shared<icsneo::MessageCallback>(filter, [&sniffer](std::shared_ptr<icsneo::Message> message) {
|
||||||
|
if(message->type != icsneo::Message::Type::Frame)
|
||||||
|
return;
|
||||||
|
auto frame = std::static_pointer_cast<icsneo::Frame>(message);
|
||||||
|
if(frame->network.getType() != icsneo::Network::Type::CAN)
|
||||||
|
return;
|
||||||
|
sniffer.onCan(std::static_pointer_cast<icsneo::CANMessage>(message));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool openAndOnline(std::shared_ptr<icsneo::Device>& device, const Options& opt) {
|
||||||
|
logLine(std::string("Opening ") + device->describe() + " ...");
|
||||||
|
if(!device->open()) {
|
||||||
|
printApiResult("open", false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!opt.keepBaud && device->settings) {
|
||||||
|
if(!device->settings->setBaudrateFor(icsneo::Network::NetID::DWCAN_01, opt.baud))
|
||||||
|
printApiResult("setBaudrateFor", false);
|
||||||
|
else if(!device->settings->apply(true))
|
||||||
|
printApiResult("settings->apply(temporary)", false);
|
||||||
|
}
|
||||||
|
if(!device->goOnline()) {
|
||||||
|
printApiResult("goOnline", false);
|
||||||
|
device->close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void closeDevice(const std::shared_ptr<icsneo::Device>& device) {
|
||||||
|
if(!device)
|
||||||
|
return;
|
||||||
|
device->iso15765DisableAll();
|
||||||
|
if(device->isOnline())
|
||||||
|
device->goOffline();
|
||||||
|
if(device->isOpen())
|
||||||
|
device->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enableIso(icsneo::Device& device, const char* who) {
|
||||||
|
const bool ok = device.iso15765Enable(icsneo::Network(icsneo::Network::NetID::DWCAN_01));
|
||||||
|
printApiResult((std::string(who) + " ISO15765_Enable").c_str(), ok);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool receiveIso(icsneo::Device& device, const Options& opt) {
|
||||||
|
icsneo::Iso15765MessageArgs msg;
|
||||||
|
fillIso15765(msg, opt, {}, true);
|
||||||
|
const bool ok = device.iso15765SetupRxFlowControl(icsneo::Network(icsneo::Network::NetID::DWCAN_01), msg);
|
||||||
|
printApiResult("ECU ISO15765_ReceiveMessage", ok);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool transmitIso(icsneo::Device& device, const Options& opt, const std::vector<uint8_t>& payload) {
|
||||||
|
icsneo::Iso15765MessageArgs msg;
|
||||||
|
fillIso15765(msg, opt, payload, false);
|
||||||
|
const bool ok = device.iso15765TransmitMessage(
|
||||||
|
icsneo::Network(icsneo::Network::NetID::DWCAN_01), msg, std::chrono::milliseconds(0));
|
||||||
|
printApiResult("tester ISO15765_TransmitMessage", ok);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<icsneo::Device> findBySerial(const std::vector<std::shared_ptr<icsneo::Device>>& devices, const std::string& serial) {
|
||||||
|
for(const auto& d : devices) {
|
||||||
|
if(iequals(d->getSerial(), serial))
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
Options opt;
|
||||||
|
try {
|
||||||
|
if(!parseArgs(argc, argv, opt))
|
||||||
|
return 1;
|
||||||
|
} catch(const std::exception& ex) {
|
||||||
|
std::cerr << ex.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "libicsneo " << icsneo::GetVersion() << std::endl;
|
||||||
|
|
||||||
|
auto devices = icsneo::FindAllDevices();
|
||||||
|
std::cout << "Found " << devices.size() << " device(s)\n";
|
||||||
|
for(const auto& d : devices)
|
||||||
|
std::cout << " " << d->describe() << " serial=" << d->getSerial() << "\n";
|
||||||
|
|
||||||
|
if(devices.size() < 2) {
|
||||||
|
std::cerr << "Need two devices connected.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<icsneo::Device> tester;
|
||||||
|
std::shared_ptr<icsneo::Device> ecu;
|
||||||
|
if(opt.testerSerial.empty() && opt.ecuSerial.empty()) {
|
||||||
|
if(devices.size() != 2) {
|
||||||
|
std::cerr << "More than two devices found; pass --tester and --ecu serials.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
tester = devices[0];
|
||||||
|
ecu = devices[1];
|
||||||
|
std::cout << "No serials given; using first as tester, second as ECU.\n";
|
||||||
|
} else {
|
||||||
|
if(opt.testerSerial.empty() || opt.ecuSerial.empty()) {
|
||||||
|
std::cerr << "Pass both --tester and --ecu, or neither.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
tester = findBySerial(devices, opt.testerSerial);
|
||||||
|
ecu = findBySerial(devices, opt.ecuSerial);
|
||||||
|
if(!tester || !ecu) {
|
||||||
|
std::cerr << "Could not match tester/ECU serials.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t payloadSize = opt.payloadBytes.value_or(defaultPayloadSize(opt.mode));
|
||||||
|
const auto payload = makePayload(payloadSize);
|
||||||
|
|
||||||
|
std::cout << "Tester: " << tester->describe() << "\n"
|
||||||
|
<< "ECU: " << ecu->describe() << "\n";
|
||||||
|
if(opt.mode != Mode::Raw) {
|
||||||
|
std::ostringstream hdr;
|
||||||
|
hdr << "CAN1 TX 0x" << std::hex << std::uppercase << opt.txId
|
||||||
|
<< " FC 0x" << opt.fcId << std::dec
|
||||||
|
<< " payload " << payloadSize << " bytes";
|
||||||
|
std::cout << hdr.str() << "\n";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
if(!openAndOnline(tester, opt) || !openAndOnline(ecu, opt))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
Sniffer testerSniff;
|
||||||
|
testerSniff.tag = "TESTER";
|
||||||
|
Sniffer ecuSniff;
|
||||||
|
ecuSniff.tag = "ECU ";
|
||||||
|
addCanSniffer(*tester, testerSniff);
|
||||||
|
addCanSniffer(*ecu, ecuSniff);
|
||||||
|
|
||||||
|
switch(opt.mode) {
|
||||||
|
case Mode::Raw:
|
||||||
|
logLine("Mode --raw: tester 0x123, then ECU 0x456");
|
||||||
|
transmitCan(*tester, 0x123, { 0x11, 0x22, 0x33, 0x44 });
|
||||||
|
std::this_thread::sleep_for(200ms);
|
||||||
|
transmitCan(*ecu, 0x456, { 0x55, 0x66, 0x77, 0x88 });
|
||||||
|
break;
|
||||||
|
case Mode::SingleFrame:
|
||||||
|
logLine("Mode --sf: firmware ISO-TP single frame from tester");
|
||||||
|
if(payload.size() > 7)
|
||||||
|
logLine(" warning: payload > 7 bytes will be a First Frame (no flow control in this mode)");
|
||||||
|
enableIso(*tester, "tester");
|
||||||
|
transmitIso(*tester, opt, payload);
|
||||||
|
break;
|
||||||
|
case Mode::Both:
|
||||||
|
logLine("Mode --both: firmware TX on tester, firmware flow-control on ECU");
|
||||||
|
enableIso(*tester, "tester");
|
||||||
|
enableIso(*ecu, "ECU");
|
||||||
|
receiveIso(*ecu, opt);
|
||||||
|
std::this_thread::sleep_for(100ms);
|
||||||
|
transmitIso(*tester, opt, payload);
|
||||||
|
break;
|
||||||
|
case Mode::None:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(opt.listenMs));
|
||||||
|
|
||||||
|
closeDevice(tester);
|
||||||
|
closeDevice(ecu);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+125
-25
@@ -1,33 +1,133 @@
|
|||||||
#ifndef _J2534_H
|
#ifndef _J2534_H
|
||||||
#define _J2534_H
|
#define _J2534_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
//J2534 Commands
|
//J2534 Commands
|
||||||
#define J1534_NUM_PERIOD_TX_MSGS 128
|
#define J1534_NUM_PERIOD_TX_MSGS 128
|
||||||
#define J1534_NUM_PERIOD_RX_MSGS 128
|
#define J1534_NUM_PERIOD_RX_MSGS 128
|
||||||
#define J2534NVCMD_SetISJ2534 0
|
|
||||||
#define J2534NVCMD_SetISO5Baud 1
|
enum class J2534Command : uint8_t {
|
||||||
#define J2534NVCMD_SetISOFastInit 2
|
SetISJ2534 = 0,
|
||||||
#define J2534NVCMD_SetISOCheckSum 3
|
SetISO5Baud = 1,
|
||||||
#define J2534NVCMD_SetISO9141Parms 4
|
SetISOFastInit = 2,
|
||||||
#define J2534NVCMD_GetISO9141Parms 5
|
SetISOCheckSum = 3,
|
||||||
#define J2534NVCMD_ISO9141APIChkSum 6
|
SetISO9141Parms = 4,
|
||||||
#define J2534NVCMD_SetNetworkBaudRate 7
|
GetISO9141Parms = 5,
|
||||||
#define J2534NVCMD_GetNetworkBaudRate 8
|
ISO9141APIChkSum = 6,
|
||||||
#define J2534NVCMD_EnableTransmitEvent 9
|
SetNetworkBaudRate = 7,
|
||||||
#define J2534NVCMD_SetTransmitEvent 10
|
GetNetworkBaudRate = 8,
|
||||||
#define J2534NVCMD_BlueEnableStopFilters 11
|
EnableTransmitEvent = 9,
|
||||||
#define J2534NVCMD_Blue15765HWSupport 12
|
SetTransmitEvent = 10,
|
||||||
#define J2534NVCMD_GetTXBufferInfo 13
|
BlueEnableStopFilters = 11,
|
||||||
#define J2534NVCMD_GetEncryptionKey 14
|
Blue15765HWSupport = 12,
|
||||||
#define J2534NVCMD_SetMiscIOForVBATT 15
|
GetTXBufferInfo = 13,
|
||||||
#define J2534NVCMD_EnableISO_KW_Network 16
|
GetEncryptionKey = 14,
|
||||||
#define J2534NVCMD_SetJ1708CheckSum 17
|
SetMiscIOForVBATT = 15,
|
||||||
#define J2534NVCMD_GetTimestamp 18
|
EnableISO_KW_Network = 16,
|
||||||
#define J2534NVCMD_GetCANFDRate 19
|
SetJ1708CheckSum = 17,
|
||||||
#define J2534NVCMD_SetCANFDRate 20
|
GetTimestamp = 18,
|
||||||
#define J2534NVCMD_GetCANFDTermination 21
|
GetCANFDRate = 19,
|
||||||
#define J2534NVCMD_SetCANFDTermination 22
|
SetCANFDRate = 20,
|
||||||
#define J2534NVCMD_GetCANFDFormat 23
|
GetCANFDTermination = 21,
|
||||||
#define J2534NVCMD_SetCANFDFormat 24
|
SetCANFDTermination = 22,
|
||||||
|
GetCANFDFormat = 23,
|
||||||
|
SetCANFDFormat = 24
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(push)
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SubFrame Commands
|
||||||
|
*/
|
||||||
|
enum class J2534SubCommand : uint8_t {
|
||||||
|
Enable = 0,
|
||||||
|
SetupIso15765RxFilter = 1,
|
||||||
|
SetupIso15765TxMessageProperties = 2,
|
||||||
|
SetupIso15765TxMessageDataBytes = 3,
|
||||||
|
SetupCanRxFilter = 4,
|
||||||
|
SetupClearCanRxFilters = 5,
|
||||||
|
EnableFiltering = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t uiFilterMask0;
|
||||||
|
uint16_t uiFilterID0;
|
||||||
|
uint16_t uiFilterMask1;
|
||||||
|
uint16_t uiFilterID1;
|
||||||
|
uint16_t uiFilterMask2;
|
||||||
|
uint16_t uiFilterID2;
|
||||||
|
union {
|
||||||
|
/** Mask and value words if rx filter is datalink filter*/
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t uiFilterMask3;
|
||||||
|
uint16_t uiFilterID3;
|
||||||
|
uint16_t uiFilterMask4;
|
||||||
|
uint16_t uiFilterID4;
|
||||||
|
uint16_t uiFilterMask5;
|
||||||
|
uint16_t uiFilterID5;
|
||||||
|
uint16_t uiFilterMask6;
|
||||||
|
uint16_t uiFilterID6;
|
||||||
|
} datalink;
|
||||||
|
/** Mask and value bytes if rx filter is datalink filter*/
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t uiFilterMask_DB0;
|
||||||
|
uint8_t uiFilterMask_DB1;
|
||||||
|
uint8_t uiFilterID_DB0;
|
||||||
|
uint8_t uiFilterID_DB1;
|
||||||
|
uint8_t uiFilterMask_DB2;
|
||||||
|
uint8_t uiFilterMask_DB3;
|
||||||
|
uint8_t uiFilterID_DB2;
|
||||||
|
uint8_t uiFilterID_DB3;
|
||||||
|
uint8_t uiFilterMask_DB4;
|
||||||
|
uint8_t uiFilterMask_DB5;
|
||||||
|
uint8_t uiFilterID_DB4;
|
||||||
|
uint8_t uiFilterID_DB5;
|
||||||
|
uint8_t uiFilterMask_DB6;
|
||||||
|
uint8_t uiFilterMask_DB7;
|
||||||
|
uint8_t uiFilterID_DB6;
|
||||||
|
uint8_t uiFilterID_DB7;
|
||||||
|
} datalinkBytes;
|
||||||
|
/** Mask and value bytes if rx filter is Iso15765-2*/
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t uiFilterMask_DB0;
|
||||||
|
uint8_t uiFilterID_DB0;
|
||||||
|
uint8_t uiFilterMask_DB1;
|
||||||
|
uint8_t uiFilterID_DB1;
|
||||||
|
uint8_t uiFilterMask_DB2;
|
||||||
|
uint8_t uiFilterID_DB2;
|
||||||
|
uint8_t uiFilterMask_DB3;
|
||||||
|
uint8_t uiFilterID_DB3;
|
||||||
|
uint8_t uiFilterMask_DB4;
|
||||||
|
uint8_t uiFilterID_DB4;
|
||||||
|
uint8_t uiFilterMask_DB5;
|
||||||
|
uint8_t uiFilterID_DB5;
|
||||||
|
uint8_t uiFilterMask_DB6;
|
||||||
|
uint8_t uiFilterID_DB6;
|
||||||
|
uint8_t uiFilterMask_DB7;
|
||||||
|
uint8_t uiFilterID_DB7;
|
||||||
|
} iso15Bytes;
|
||||||
|
} args;
|
||||||
|
} MessageFilterBytes;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t idx;
|
||||||
|
uint16_t enabled;
|
||||||
|
uint16_t filterCount;
|
||||||
|
MessageFilterBytes fb;
|
||||||
|
uint16_t networkId;
|
||||||
|
} J2534_RxCanFilter;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ enum class Command : uint8_t {
|
|||||||
GetLogicalDiskInfo = 0xBB, // Previously known as RED_CMD_GET_SDCARD_INFO
|
GetLogicalDiskInfo = 0xBB, // Previously known as RED_CMD_GET_SDCARD_INFO
|
||||||
RequestStatusUpdate = 0xBC,
|
RequestStatusUpdate = 0xBC,
|
||||||
ReadSettings = 0xC7, // Previously known as 3G_READ_SETTINGS_EX
|
ReadSettings = 0xC7, // Previously known as 3G_READ_SETTINGS_EX
|
||||||
|
J2534Command = 0xD7, // Previously known as RED_CMD_J2534_EXTENSION
|
||||||
SetVBattMonitor = 0xDB, // Previously known as RED_CMD_CM_VBATT_MONITOR
|
SetVBattMonitor = 0xDB, // Previously known as RED_CMD_CM_VBATT_MONITOR
|
||||||
RequestBitSmash = 0xDC, // Previously known as RED_CMD_CM_BITSMASH
|
RequestBitSmash = 0xDC, // Previously known as RED_CMD_CM_BITSMASH
|
||||||
WiVICommand = 0xDD, // Previously known as RED_CMD_WIVI_COMM
|
WiVICommand = 0xDD, // Previously known as RED_CMD_WIVI_COMM
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <common/v1/proto_header.pb.h>
|
#include <common/v1/proto_header.pb.h>
|
||||||
#include <commands/generic/v1/client_id.pb.h>
|
#include <commands/generic/v1/client_id.pb.h>
|
||||||
#include <commands/network/v1/mutex.pb.h>
|
#include <commands/network/v1/mutex.pb.h>
|
||||||
|
#include <settings/manufacturing/v1/mfg_config.pb.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
@@ -36,6 +37,11 @@ struct IDLookup {
|
|||||||
constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_UNSPECIFIED;
|
constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_UNSPECIFIED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IDLookup<settings::manufacturing::v1::MfgConfig> {
|
||||||
|
constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_MFG_CONFIG;
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct IDLookup<commands::network::v1::NetworkMutex> {
|
struct IDLookup<commands::network::v1::NetworkMutex> {
|
||||||
constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_NETWORK_MUTEX;
|
constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_NETWORK_MUTEX;
|
||||||
|
|||||||
@@ -0,0 +1,443 @@
|
|||||||
|
#ifndef __ISO_15765MESSAGE_H_
|
||||||
|
#define __ISO_15765MESSAGE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/main51message.h"
|
||||||
|
#include "icsneo/communication/command.h"
|
||||||
|
#include "icsneo/J2534.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
class J2534CommandMessage : public Main51Message
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class J2534Command : uint8_t
|
||||||
|
{
|
||||||
|
Enable = 0, //RED_CMD_J2534_EXTENSION_ENABLE,
|
||||||
|
SetupIso15765RxFilter = 1, //RED_CMD_J2534_EXTENSION_SETUP_ISO15_RX_FILTER,
|
||||||
|
SetupIso15765TxMessageProperties = 2, //RED_CMD_J2534_EXTENSION_SETUP_ISO15_TX_MESSAGE_PROPERTIES,
|
||||||
|
SetupIso15765TxMessageDataBytes = 3, //RED_CMD_J2534_EXTENSION_SETUP_ISO15_TX_MESSAGE_DATABYTES,
|
||||||
|
SetupCanRxFilter = 4, //RED_CMD_J2534_EXTENSION_SETUP_CAN_RX_FILTER,
|
||||||
|
SetupClearCanRxFilters = 5, //RED_CMD_J2534_EXTENSION_SETUP_CLEAR_CAN_RX_FILTERS,
|
||||||
|
EnableFiltering = 6, //RED_CMD_J2534_EXTENSION_ENABLE_FILTERING,
|
||||||
|
};
|
||||||
|
|
||||||
|
J2534CommandMessage(const J2534Command j2534Command, const std::vector<uint8_t>& arguments = {})
|
||||||
|
: Main51Message() {
|
||||||
|
command = Command::J2534Command;
|
||||||
|
argumentData.push_back((uint8_t)j2534Command);
|
||||||
|
argumentData.push_back(0);
|
||||||
|
setArgumentData(arguments);
|
||||||
|
}
|
||||||
|
virtual ~J2534CommandMessage(void) = default;
|
||||||
|
|
||||||
|
J2534Command getJ2534Command(void) const { return (J2534Command)argumentData[0]; }
|
||||||
|
void setJ2534Command(const J2534Command& j2534Command) { argumentData[0] = (uint8_t)j2534Command; }
|
||||||
|
|
||||||
|
const std::vector<uint8_t>& getArgumentData(void) const { return argumentData; }
|
||||||
|
void setArgumentData(const std::vector<uint8_t>& arguments) { argumentData.insert(argumentData.end(), arguments.begin(), arguments.end()); }
|
||||||
|
|
||||||
|
static std::shared_ptr<J2534CommandMessage> decodeToMessage(const std::vector<uint8_t>& data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<uint8_t> argumentData;
|
||||||
|
|
||||||
|
uint16_t read16LE(size_t o) const;
|
||||||
|
void write16LE(size_t o, uint16_t v);
|
||||||
|
uint16_t read16BE(size_t o) const;
|
||||||
|
void write16BE(size_t o, uint16_t v);
|
||||||
|
void writeBits16LE(size_t o, unsigned bitPos, unsigned bitCount, uint32_t value);
|
||||||
|
uint32_t read32LE(size_t o) const;
|
||||||
|
void write32LE(size_t o, uint32_t v);
|
||||||
|
uint32_t read32BE(size_t o) const;
|
||||||
|
void write32BE(size_t o, uint32_t v);
|
||||||
|
};
|
||||||
|
|
||||||
|
class J2534EnableMessage : public J2534CommandMessage {
|
||||||
|
public:
|
||||||
|
J2534EnableMessage(const bool enable)
|
||||||
|
: J2534CommandMessage(J2534Command::Enable, { (uint8_t)enable }) {
|
||||||
|
}
|
||||||
|
bool getEnable(void) const { return (bool)argumentData[2]; }
|
||||||
|
void setEnable(bool enable) { argumentData[2] = (uint8_t)enable; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class J2534EnableFilteringMessage : public J2534CommandMessage {
|
||||||
|
public:
|
||||||
|
J2534EnableFilteringMessage(const bool enable)
|
||||||
|
: J2534CommandMessage(J2534Command::EnableFiltering, { (uint8_t)enable }) {
|
||||||
|
}
|
||||||
|
bool getEnable(void) const { return (bool)argumentData[2]; }
|
||||||
|
void setEnable(bool enable) { argumentData[2] = (uint8_t)enable; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class J2534SetupCanRxFilteringMessage : public J2534CommandMessage {
|
||||||
|
public:
|
||||||
|
J2534SetupCanRxFilteringMessage(const J2534_RxCanFilter& filter)
|
||||||
|
: J2534CommandMessage(J2534Command::SetupCanRxFilter) {
|
||||||
|
setRxCanFilter(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
J2534_RxCanFilter getRxCanFilter(void) const;
|
||||||
|
|
||||||
|
void setRxCanFilter(const J2534_RxCanFilter& filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
class J2534SetupIso15765FlowControlMessage : public J2534CommandMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
J2534SetupIso15765FlowControlMessage();
|
||||||
|
|
||||||
|
uint16_t getIdx(void) const;
|
||||||
|
void setIdx(uint16_t idx);
|
||||||
|
uint16_t getCoreMiniId(void) const;
|
||||||
|
void setCoreMiniId(uint16_t coreMiniId);
|
||||||
|
uint8_t getPadding(void) const;
|
||||||
|
void setPadding(uint8_t padding);
|
||||||
|
uint32_t getId(void) const;
|
||||||
|
void setId(uint32_t id);
|
||||||
|
uint32_t getIdMask(void) const;
|
||||||
|
void setIdMask(uint32_t idMask);
|
||||||
|
uint32_t getFcId(void) const;
|
||||||
|
void setFcId(uint32_t fcId);
|
||||||
|
uint8_t getFlowControlExtendedAddress(void) const;
|
||||||
|
void setFlowControlExtendedAddress(uint8_t addr);
|
||||||
|
uint8_t getExtendedAddress(void) const;
|
||||||
|
void setExtendedAddress(uint8_t addr);
|
||||||
|
uint8_t getBlockSize(void) const;
|
||||||
|
void setBlockSize(uint8_t blockSize);
|
||||||
|
uint8_t getStMin(void) const;
|
||||||
|
void setStMin(uint8_t stMin);
|
||||||
|
uint16_t getCfTimeout(void) const;
|
||||||
|
void setCfTimeout(uint16_t cfTimeout);
|
||||||
|
uint32_t getFlags(void) const;
|
||||||
|
void setFlags(uint32_t flags);
|
||||||
|
|
||||||
|
bool getEnable(void) const;
|
||||||
|
void setEnable(bool enable);
|
||||||
|
bool getIs29BitEnabled(void) const;
|
||||||
|
void setIs29BitEnabled(bool enable);
|
||||||
|
bool getIsFc29BitEnabled(void) const;
|
||||||
|
void setIsFc29BitEnabled(bool enable);
|
||||||
|
bool getExtAddressEnabled(void) const;
|
||||||
|
void setExtAddressEnabled(bool enable);
|
||||||
|
bool getFcExtAddressEnabled(void) const;
|
||||||
|
void setFcExtAddressEnabled(bool enable);
|
||||||
|
bool getFlowControlTransmissionEnabled(void) const;
|
||||||
|
void setFlowControlTransmissionEnabled(bool enable);
|
||||||
|
bool getPaddingEnabled(void) const;
|
||||||
|
void setPaddingEnabled(bool enable);
|
||||||
|
bool getIsCanFd(void) const;
|
||||||
|
void setIsCanFd(bool enable);
|
||||||
|
bool getIsBrsEnabled(void) const;
|
||||||
|
void setIsBrsEnabled(bool enable);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The legacy wire format was the raw memory of the (now-removed) J2534_RxFlowControlRequest
|
||||||
|
// struct copied into mArgumentData starting at offset 1 (overwriting the header pad byte).
|
||||||
|
// The struct was compiled with `#pragma pack(2)` on MSVC little-endian. All multi-byte
|
||||||
|
// scalars are therefore stored little-endian; the "flt" region reproduces the exact
|
||||||
|
// byte pattern produced by the old MessageBitsCAN bitfield writes.
|
||||||
|
//
|
||||||
|
// Byte layout (mArgumentData indices):
|
||||||
|
// [0] J2534 command header byte (set by base class)
|
||||||
|
// [1] padding
|
||||||
|
// [2..3] idx (u16 LE)
|
||||||
|
// [4..5] iCoreMiniID (u16 LE)
|
||||||
|
// [6] padding (u8)
|
||||||
|
// [7] structure pad byte (unused)
|
||||||
|
// [8..11] id (u32 LE)
|
||||||
|
// [12..15] id_mask (u32 LE)
|
||||||
|
// [16..19] fc_id (u32 LE)
|
||||||
|
// [20] flowControlExtendedAddress (u8)
|
||||||
|
// [21] extendedAddress (u8)
|
||||||
|
// [22] blockSize (u8)
|
||||||
|
// [23] stMin (u8)
|
||||||
|
// [24..25] cf_timeout (u16 LE)
|
||||||
|
// [26..53] MessageFilterBytes flt (28 bytes) -- see RebuildFilterBytes for details
|
||||||
|
// [54..57] flags (u32 LE) -- see kFcFlag* below
|
||||||
|
//
|
||||||
|
// Total wire size: 58 bytes.
|
||||||
|
static const size_t MessageSize = 58;
|
||||||
|
static const size_t IdxOffset = 2;
|
||||||
|
static const size_t CoreMiniOffset = 4;
|
||||||
|
static const size_t PaddingOffset = 6;
|
||||||
|
static const size_t IdOffset = 8;
|
||||||
|
static const size_t IdMaskOffset = 12;
|
||||||
|
static const size_t FcIdOffset = 16;
|
||||||
|
static const size_t FcExtAddrOffset = 20;
|
||||||
|
static const size_t ExtAddrOffset = 21;
|
||||||
|
static const size_t BlockSizeOffset = 22;
|
||||||
|
static const size_t StMinOffset = 23;
|
||||||
|
static const size_t CfTimeoutOffset = 24;
|
||||||
|
static const size_t FltOffset = 26; // 28 bytes
|
||||||
|
static const size_t FltSize = 28;
|
||||||
|
static const size_t FlagsOffset = 54;
|
||||||
|
|
||||||
|
// Bit positions inside the u32 LE flags word (matches the legacy bitfield layout).
|
||||||
|
static const uint32_t FlagEnable = 1u << 0;
|
||||||
|
static const uint32_t FlagId29BitEnable = 1u << 1;
|
||||||
|
static const uint32_t FlagFcId29BitEnable = 1u << 2;
|
||||||
|
static const uint32_t FlagExtAddressEnable = 1u << 3;
|
||||||
|
static const uint32_t FlagFcExtAddressEnable = 1u << 4;
|
||||||
|
static const uint32_t FlagEnableFlowControlTransmit = 1u << 5;
|
||||||
|
static const uint32_t FlagPaddingEnable = 1u << 6;
|
||||||
|
static const uint32_t FlagIsCanFd = 1u << 7;
|
||||||
|
static const uint32_t FlagIsBrsEnabled = 1u << 8;
|
||||||
|
|
||||||
|
// Rebuilds the filter bytes region of mArgumentData based on the current id / id_mask /
|
||||||
|
// id_29_bit_enable / ext_address_enable / extendedAddress state. Preserves the legacy
|
||||||
|
// (pre-existing) wire format bit-for-bit.
|
||||||
|
void rebuildFilterBytes(void);
|
||||||
|
|
||||||
|
void setFlagBit(uint32_t mask, bool enable);
|
||||||
|
|
||||||
|
bool getFlagBit(uint32_t mask) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Iso15765TxSetupMessage : public J2534CommandMessage {
|
||||||
|
public:
|
||||||
|
Iso15765TxSetupMessage()
|
||||||
|
: J2534CommandMessage(J2534Command::SetupIso15765TxMessageProperties) {
|
||||||
|
argumentData.resize(36);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getIdx(void) const;
|
||||||
|
void setIdx(uint16_t idx);
|
||||||
|
uint16_t getCoreMiniId(void) const;
|
||||||
|
void setCoreMiniId(uint16_t coreMiniId);
|
||||||
|
uint32_t getMessageLength(void) const;
|
||||||
|
void setMessageLength(uint32_t messageLength);
|
||||||
|
uint8_t getPadding(void) const;
|
||||||
|
void setPadding(uint8_t padding);
|
||||||
|
uint8_t getTxDl(void) const;
|
||||||
|
void setTxDl(uint8_t txDl);
|
||||||
|
uint32_t getId(void) const;
|
||||||
|
void setId(uint32_t id);
|
||||||
|
uint32_t getFcId(void) const;
|
||||||
|
void setFcId(uint32_t fcId);
|
||||||
|
uint32_t getFcIdMask(void) const;
|
||||||
|
void setFcIdMask(uint32_t fcIdMask);
|
||||||
|
uint8_t getFlowControlExtendedAddress(void) const;
|
||||||
|
void setFlowControlExtendedAddress(uint8_t addr);
|
||||||
|
uint8_t getExtendedAddress(void) const;
|
||||||
|
void setExtendedAddress(uint8_t addr);
|
||||||
|
uint16_t getFsTimeout(void) const;
|
||||||
|
void setFsTimeout(uint16_t timeout);
|
||||||
|
uint16_t getFsWait(void) const;
|
||||||
|
void setFsWait(uint16_t wait);
|
||||||
|
uint32_t getFlags(void) const;
|
||||||
|
void setFlags(uint32_t flags);
|
||||||
|
uint8_t getStMin(void) const;
|
||||||
|
void setStMin(uint8_t stMin);
|
||||||
|
uint8_t getBlockSize(void) const;
|
||||||
|
void setBlockSize(uint8_t blockSize);
|
||||||
|
|
||||||
|
bool getIs29BitEnabled(void) const;
|
||||||
|
void setIs29BitEnabled(bool enable);
|
||||||
|
bool getIsFc29BitEnabled(void) const;
|
||||||
|
void setIsFc29BitEnabled(bool enable);
|
||||||
|
bool getExtAddressEnabled(void) const;
|
||||||
|
void setExtAddressEnabled(bool enable);
|
||||||
|
bool getFcExtAddressEnabled(void) const;
|
||||||
|
void setFcExtAddressEnabled(bool enable);
|
||||||
|
bool getOverrideStMin(void) const;
|
||||||
|
void setOverrideStMin(bool enable);
|
||||||
|
bool getOverrideBlockSize(void) const;
|
||||||
|
void setOverrideBlockSize(bool enable);
|
||||||
|
bool getPaddingEnabled(void) const;
|
||||||
|
void setPaddingEnabled(bool enable);
|
||||||
|
bool getIsCanFd(void) const;
|
||||||
|
void setIsCanFd(bool enable);
|
||||||
|
bool getIsBrsEnabled(void) const;
|
||||||
|
void setIsBrsEnabled(bool enable);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Matches J2534_Iso15TxRequest (#pragma pack(2), little-endian) copied after the
|
||||||
|
// 2-byte J2534 command header, as sent by vspy3 J2534_Transaction.
|
||||||
|
// [0..1] J2534 command header (managed by base class)
|
||||||
|
// [2..3] idx (u16 LE)
|
||||||
|
// [4..5] iCoreMiniID (u16 LE)
|
||||||
|
// [6..9] messageLength (u32 LE)
|
||||||
|
// [10] padding
|
||||||
|
// [11] tx_dl
|
||||||
|
// [12..15] id (u32 LE)
|
||||||
|
// [16..19] fc_id (u32 LE)
|
||||||
|
// [20..23] fc_id_mask (u32 LE)
|
||||||
|
// [24] flowControlExtendedAddress
|
||||||
|
// [25] extendedAddress
|
||||||
|
// [26..27] fs_timeout (u16 LE)
|
||||||
|
// [28..29] fs_wait (u16 LE)
|
||||||
|
// [30..33] flags (u32 LE)
|
||||||
|
// [34] stMin
|
||||||
|
// [35] blockSize
|
||||||
|
|
||||||
|
static const size_t SetupIdxOffset = 2;
|
||||||
|
static const size_t SetupCoreMiniOffset = 4;
|
||||||
|
static const size_t SetupMsgLenOffset = 6;
|
||||||
|
static const size_t SetupPaddingOffset = 10;
|
||||||
|
static const size_t SetupTxDlOffset = 11;
|
||||||
|
static const size_t SetupIdOffset = 12;
|
||||||
|
static const size_t SetupFcIdOffset = 16;
|
||||||
|
static const size_t SetupFcIdMaskOffset = 20;
|
||||||
|
static const size_t SetupFcExtAddrOffset = 24;
|
||||||
|
static const size_t SetupExtAddrOffset = 25;
|
||||||
|
static const size_t SetupFsTimeoutOffset = 26;
|
||||||
|
static const size_t SetupFsWaitOffset = 28;
|
||||||
|
static const size_t SetupFlagsOffset = 30;
|
||||||
|
static const size_t SetupStMinOffset = 34;
|
||||||
|
static const size_t SetupBlockSizeOffset = 35;
|
||||||
|
|
||||||
|
// Flag bit positions within the 32-bit flags word.
|
||||||
|
static const uint32_t FlagId29BitEnable = 1u << 0;
|
||||||
|
static const uint32_t FlagFcId29BitEnable = 1u << 1;
|
||||||
|
static const uint32_t FlagExtAddressEnable = 1u << 2;
|
||||||
|
static const uint32_t FlagFcExtAddressEnable = 1u << 3;
|
||||||
|
static const uint32_t FlagOverrideStMin = 1u << 4;
|
||||||
|
static const uint32_t FlagOverrideBlockSize = 1u << 5;
|
||||||
|
static const uint32_t FlagPaddingEnable = 1u << 6;
|
||||||
|
static const uint32_t FlagIsCanFd = 1u << 7;
|
||||||
|
static const uint32_t FlagIsBrsEnabled = 1u << 8;
|
||||||
|
|
||||||
|
bool getFlagBit(uint32_t mask) const;
|
||||||
|
void setFlagBit(uint32_t mask, bool enable);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Iso15765TxDataMessage : public J2534CommandMessage {
|
||||||
|
public:
|
||||||
|
static constexpr uint16_t MaxDataLength = 500;
|
||||||
|
|
||||||
|
Iso15765TxDataMessage()
|
||||||
|
: J2534CommandMessage(J2534Command::SetupIso15765TxMessageDataBytes) {
|
||||||
|
argumentData.resize(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getIdx(void) const;
|
||||||
|
void setIdx(uint16_t idx);
|
||||||
|
uint32_t getOffset(void) const;
|
||||||
|
void setOffset(uint32_t offset);
|
||||||
|
uint16_t getLen(void) const;
|
||||||
|
const uint8_t* getData(void) const;
|
||||||
|
void setData(const uint8_t* sourceData, uint16_t len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Matches J2534_Iso15TxDataRequest (#pragma pack(2), little-endian) after the
|
||||||
|
// 2-byte J2534 command header.
|
||||||
|
// [0..1] J2534 command header (managed by base class)
|
||||||
|
// [2..3] idx (u16 LE)
|
||||||
|
// [4..7] offset (u32 LE)
|
||||||
|
// [8..9] len (u16 LE)
|
||||||
|
// [10..] data
|
||||||
|
static const size_t DataIdxOffset = 2;
|
||||||
|
static const size_t DataOffsetOffset = 4;
|
||||||
|
static const size_t DataLenOffset = 8;
|
||||||
|
static const size_t DataPayloadOffset = 10;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Iso15765MessageArgs {
|
||||||
|
public:
|
||||||
|
struct ArbId {
|
||||||
|
bool Is29Bit;
|
||||||
|
uint32_t Id;
|
||||||
|
|
||||||
|
ArbId(uint32_t id = 0, bool is29Bit = false)
|
||||||
|
: Is29Bit(is29Bit)
|
||||||
|
, Id(id) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Iso15765MessageArgs(void)
|
||||||
|
: networkId(0)
|
||||||
|
, txIndex(0)
|
||||||
|
, arbId({ false, 0 })
|
||||||
|
, flowControlArbId({ false, 0 })
|
||||||
|
, flowControlArbIdMask(0)
|
||||||
|
, isCanFd(false)
|
||||||
|
, isBrsEnabled(false)
|
||||||
|
, tx_DL(8)
|
||||||
|
, fs_Timeout(0)
|
||||||
|
, fs_WaitTimeout(0)
|
||||||
|
, cf_Timeout(0)
|
||||||
|
, isFlowControlEnabled(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getNetworkId(void) const { return networkId; }
|
||||||
|
void setNetworkId(uint16_t netId) { networkId = netId; }
|
||||||
|
uint8_t getTxIndex(void) const { return txIndex; }
|
||||||
|
void setTxIndex(uint8_t idx) { txIndex = idx; }
|
||||||
|
|
||||||
|
const ArbId& getArbId(void) const { return arbId; }
|
||||||
|
void setArbId(const ArbId& id) { arbId = id; }
|
||||||
|
const ArbId& getFlowControlArbId(void) const { return flowControlArbId; }
|
||||||
|
void setFlowControlArbId(const ArbId& id) { flowControlArbId = id; }
|
||||||
|
uint32_t getFlowControlArbIdMask(void) const { return flowControlArbIdMask; }
|
||||||
|
void setFlowControlArbIdMask(uint32_t mask) { flowControlArbIdMask = mask; }
|
||||||
|
bool getIsCanFd(void) const { return isCanFd; }
|
||||||
|
void setIsCanFd(bool value) { isCanFd = value; }
|
||||||
|
bool getIsBrsEnabled(void) const { return isBrsEnabled; }
|
||||||
|
void setIsBrsEnabled(bool value) { isBrsEnabled = value; }
|
||||||
|
|
||||||
|
uint8_t getTxDl(void) const { return tx_DL; }
|
||||||
|
void setTxDl(uint8_t txDl) { tx_DL = txDl; }
|
||||||
|
std::optional<uint8_t> getStMin(void) const { return stMin; }
|
||||||
|
void setStMin(std::optional<uint8_t> v) { stMin = v; }
|
||||||
|
std::optional<uint8_t> getBlockSize(void) const { return blockSize; }
|
||||||
|
void setBlockSize(std::optional<uint8_t> b) { blockSize = b; }
|
||||||
|
std::optional<uint8_t> getFlowControlExtendedAddress(void) const { return flowControlExtendedAddress; }
|
||||||
|
void setFlowControlExtendedAddress(std::optional<uint8_t> fcExtAddr) { flowControlExtendedAddress = fcExtAddr; }
|
||||||
|
std::optional<uint8_t> getExtendedAddress(void) const { return extendedAddress; }
|
||||||
|
void setExtendedAddress(std::optional<uint8_t> extAddr) { extendedAddress = extAddr; }
|
||||||
|
std::optional<uint8_t> getPaddingValue(void) const { return paddingValue; }
|
||||||
|
void setPaddingValue(std::optional<uint8_t> v) { paddingValue = v; }
|
||||||
|
|
||||||
|
uint16_t getFsTimeout(void) const { return fs_Timeout; }
|
||||||
|
void setFsTimeout(uint16_t timeout) { fs_Timeout = timeout; }
|
||||||
|
uint16_t getFsWaitTimeout(void) const { return fs_WaitTimeout; }
|
||||||
|
void setFsWaitTimeout(uint16_t timeout) { fs_WaitTimeout = timeout; }
|
||||||
|
uint16_t getCfTimeout(void) const { return cf_Timeout; }
|
||||||
|
void setCfTimeout(uint16_t timeout) { cf_Timeout = timeout; }
|
||||||
|
|
||||||
|
const std::vector<uint8_t>& getData(void) const { return data; }
|
||||||
|
void setData(std::vector<uint8_t>&& d) { data = std::move(d); }
|
||||||
|
|
||||||
|
bool getIsFlowControlEnabled(void) const { return isFlowControlEnabled; }
|
||||||
|
void setIsFlowControlEnabled(bool enabled) { isFlowControlEnabled = enabled; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
uint16_t networkId; // The netid of the message (determines which network to transmit on)
|
||||||
|
uint8_t txIndex; // identifier for this transmit message
|
||||||
|
|
||||||
|
ArbId arbId; // arbId of transmitted frames (CAN id to transmit to)
|
||||||
|
ArbId flowControlArbId; // flow control arb id filter value (response id from receiver)
|
||||||
|
uint32_t flowControlArbIdMask; // The flow control arb id filter mask (response id from receiver)
|
||||||
|
bool isCanFd;
|
||||||
|
bool isBrsEnabled;
|
||||||
|
|
||||||
|
uint8_t tx_DL; // Maximum CAN(FD) protocol length for transmitted frames (Valid values are 8, 12, 16, 20, 24, 32, 48, 64)
|
||||||
|
std::optional<uint8_t> stMin; // Overrides the stMin that the receiver reports (Set to J2534's STMIN_TX if <= 0xFF)
|
||||||
|
std::optional<uint8_t> blockSize; // Overrides the block size that the receiver reports (Set to J2534's BS_TX if <= 0xFF)
|
||||||
|
std::optional<uint8_t> flowControlExtendedAddress; // Expected Extended Address byte of response from receiver
|
||||||
|
std::optional<uint8_t> extendedAddress; // Extended Address byte of transmitter
|
||||||
|
std::optional<uint8_t> paddingValue; // The padding byte to use to fill the unused portion of transmitted CAN frames (single frame, first frame, consecutive frame)
|
||||||
|
|
||||||
|
uint16_t fs_Timeout; // max timeout (ms) for waiting on flow control response (Set this to N_BS_MAX's value if J2534)
|
||||||
|
uint16_t fs_WaitTimeout; // max timeout (ms) for waiting on flow control response after receiving flow control with flow status set to WAIT (Set this to N_BS_MAX's value if J2534)
|
||||||
|
uint16_t cf_Timeout; // max timeout (ms) for waiting on consecutive frame (Set this to N_CR_MAX's value in J2534)
|
||||||
|
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
|
bool isFlowControlEnabled; // Enables Flow Control frame transmission (Rx message; from neoVI to ECU)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -51,6 +51,7 @@ public:
|
|||||||
SPIPortKeyOperation = 0x8019,
|
SPIPortKeyOperation = 0x8019,
|
||||||
GenericAPIData = 0x8020,
|
GenericAPIData = 0x8020,
|
||||||
GenericAPIStatus = 0x8021,
|
GenericAPIStatus = 0x8021,
|
||||||
|
MfgConfig = 0x8022,
|
||||||
};
|
};
|
||||||
|
|
||||||
Message(Type t) : type(t) {}
|
Message(Type t) : type(t) {}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#ifndef __MFGCONFIGMESSAGE_H_
|
||||||
|
#define __MFGCONFIGMESSAGE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/message.h"
|
||||||
|
#include "icsneo/communication/message/allmacaddressesmessage.h"
|
||||||
|
#include "icsneo/device/chipid.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
class MfgConfigMessage : public Message {
|
||||||
|
public:
|
||||||
|
struct MfgDate {
|
||||||
|
uint32_t day = 0;
|
||||||
|
uint32_t month = 0;
|
||||||
|
uint32_t year = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VersionNumber {
|
||||||
|
uint32_t major = 0;
|
||||||
|
uint32_t minor = 0;
|
||||||
|
std::optional<uint32_t> release;
|
||||||
|
std::optional<uint32_t> build;
|
||||||
|
};
|
||||||
|
|
||||||
|
MfgConfigMessage() : Message(Message::Type::MfgConfig) {}
|
||||||
|
|
||||||
|
static std::shared_ptr<MfgConfigMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||||
|
static std::vector<uint8_t> EncodeArgumentsForGet();
|
||||||
|
|
||||||
|
std::optional<uint64_t> serialNumber;
|
||||||
|
std::optional<MfgDate> manufactureDate;
|
||||||
|
std::optional<VersionNumber> hardwareRev;
|
||||||
|
std::optional<uint8_t> productId;
|
||||||
|
std::optional<VersionNumber> bootloaderRev;
|
||||||
|
std::optional<std::string> usbDescriptor;
|
||||||
|
std::vector<MACAddress> macAddresses;
|
||||||
|
std::optional<std::string> pcbSerial;
|
||||||
|
std::optional<ChipID> chipId;
|
||||||
|
std::optional<uint64_t> imei;
|
||||||
|
std::optional<uint8_t> parentProductId;
|
||||||
|
std::optional<VersionNumber> softwareVersionLock;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // __MFGCONFIGMESSAGE_H_
|
||||||
@@ -63,6 +63,9 @@
|
|||||||
#include "icsneo/communication/message/gptpstatusmessage.h"
|
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||||
#include "icsneo/communication/message/networkmutexmessage.h"
|
#include "icsneo/communication/message/networkmutexmessage.h"
|
||||||
#include "icsneo/communication/message/allmacaddressesmessage.h"
|
#include "icsneo/communication/message/allmacaddressesmessage.h"
|
||||||
|
#include "icsneo/communication/message/mfgconfigmessage.h"
|
||||||
|
#include "icsneo/communication/message/iso15765message.h"
|
||||||
|
#include "icsneo/J2534.h"
|
||||||
|
|
||||||
#define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \
|
#define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \
|
||||||
static constexpr DeviceType::Enum DEVICE_TYPE = type; \
|
static constexpr DeviceType::Enum DEVICE_TYPE = type; \
|
||||||
@@ -345,6 +348,7 @@ public:
|
|||||||
virtual Network getNetworkByNumber(Network::Type, size_t) const;
|
virtual Network getNetworkByNumber(Network::Type, size_t) const;
|
||||||
|
|
||||||
std::shared_ptr<HardwareInfo> getHardwareInfo(std::chrono::milliseconds timeout = std::chrono::milliseconds(100));
|
std::shared_ptr<HardwareInfo> getHardwareInfo(std::chrono::milliseconds timeout = std::chrono::milliseconds(100));
|
||||||
|
std::shared_ptr<MfgConfigMessage> getMfgConfig();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -907,6 +911,11 @@ public:
|
|||||||
void stopHeartbeat();
|
void stopHeartbeat();
|
||||||
void restartHeartbeat();
|
void restartHeartbeat();
|
||||||
|
|
||||||
|
bool iso15765Enable(const Network& network);
|
||||||
|
bool iso15765DisableAll(void);
|
||||||
|
bool iso15765TransmitMessage(const Network& network, const Iso15765MessageArgs& msg, const std::chrono::milliseconds& timeout);
|
||||||
|
bool iso15765SetupRxFlowControl(const Network& network, const Iso15765MessageArgs& msg);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool online = false;
|
bool online = false;
|
||||||
int messagePollingCallbackID = 0;
|
int messagePollingCallbackID = 0;
|
||||||
@@ -1175,6 +1184,23 @@ private:
|
|||||||
|
|
||||||
bool enableNetworkCommunication(bool enable, uint32_t timeout = 0);
|
bool enableNetworkCommunication(bool enable, uint32_t timeout = 0);
|
||||||
|
|
||||||
|
bool J2534_Transaction(const Network& network, J2534CommandMessage&& msg, const std::chrono::milliseconds& timeout);
|
||||||
|
bool J2534_ClearRxFilters(const Network& network);
|
||||||
|
bool J2534_SetupCanRxFilter(const Network& network, const J2534_RxCanFilter& rxCanFilter);
|
||||||
|
bool J2534_EnableFiltering(const Network& network, const bool enable);
|
||||||
|
|
||||||
|
bool J2534_EnableIso15765(const Network& network, const bool enable);
|
||||||
|
bool J2534_ClearRxFilter(const Network& network, unsigned int iIndex);
|
||||||
|
bool J2534_EnableFirmwareUsbPassFilters(const Network& network, const bool enable);
|
||||||
|
|
||||||
|
struct NetworkHash {
|
||||||
|
size_t operator()(const Network& x) const {
|
||||||
|
return (size_t)x.getNetID();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::unordered_map<Network, bool, NetworkHash> iso15765FirmwareEnabled;
|
||||||
|
|
||||||
|
|
||||||
// Keeponline (keepalive for online)
|
// Keeponline (keepalive for online)
|
||||||
std::unique_ptr<Periodic> keeponline;
|
std::unique_ptr<Periodic> keeponline;
|
||||||
std::unique_ptr<Heartbeat> heartbeat;
|
std::unique_ptr<Heartbeat> heartbeat;
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ protected:
|
|||||||
|
|
||||||
Network::NetID::LIN_01,
|
Network::NetID::LIN_01,
|
||||||
|
|
||||||
|
Network::NetID::FLEXRAY_01,
|
||||||
Network::NetID::FLEXRAY_01A,
|
Network::NetID::FLEXRAY_01A,
|
||||||
Network::NetID::FLEXRAY_01B,
|
Network::NetID::FLEXRAY_01B,
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ void CDCACM::Find(std::vector<FoundDevice>& found) {
|
|||||||
if(ref == nullptr)
|
if(ref == nullptr)
|
||||||
return;
|
return;
|
||||||
io_iterator_t matchingServices = 0;
|
io_iterator_t matchingServices = 0;
|
||||||
kern_return_t kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, ref, &matchingServices);
|
kern_return_t kernResult = IOServiceGetMatchingServices(kIOMainPortDefault, ref, &matchingServices);
|
||||||
if(KERN_SUCCESS != kernResult || matchingServices == 0)
|
if(KERN_SUCCESS != kernResult || matchingServices == 0)
|
||||||
return;
|
return;
|
||||||
IOReleaser matchingServicesReleaser(matchingServices);
|
IOReleaser matchingServicesReleaser(matchingServices);
|
||||||
|
|||||||
Reference in New Issue
Block a user