2 Commits
Author SHA1 Message Date
Gowtham NanjukuttyandGitHub f95d65817e Merge 0c9f1c5f3e into 0dd8dbfb64 2026-07-13 13:36:44 +00:00
Gowtham Nanjukutty (XC-CP/ECC2.3) 0c9f1c5f3e darwin: fix CDCACM device detection on macOS 12+
On macOS 12 and later, Apple replaced IOUSBDevice with IOUSBHostDevice
in the USB host stack. When walking the IORegistry parent chain to find
the USB device providing a serial port, the existing code only checked
IOObjectConformsTo(parent, kIOUSBDeviceClassName). On macOS 12+, this
check fails because the USB device node conforms to IOUSBHostDevice
instead.

Fix by also checking IOObjectConformsTo(parent, "IOUSBHostDevice"),
so CDCACM device discovery works on both old and new macOS.

Verified on macOS 26 (Tahoe, arm64) with a ValueCAN 4-2 (V2D805).
2026-05-22 09:12:58 -04:00
100 changed files with 323 additions and 2935 deletions
+24 -5
View File
@@ -1,6 +1,3 @@
default:
interruptible: true
variables:
DEBIAN_FRONTEND: noninteractive
LIBICSNEO_ICSPB_REPO: https://gitlab-ci-token:${CI_JOB_TOKEN}@${LIBICSNEO_ICSPB_GIT}
@@ -38,6 +35,30 @@ unit_test windows/x64:
- libicsneo-win-x64
timeout: 5m
build windows/x86:
stage: build
script:
- cmd /C ci\build-windows32.bat
artifacts:
when: always
paths:
- build
expire_in: 3 days
tags:
- libicsneo-win-x64
unit_test windows/x86:
stage: unit_test
script:
- build\libicsneo-unit-tests.exe
dependencies:
- build windows/x86
needs:
- build windows/x86
tags:
- libicsneo-win-x64
timeout: 5m
#-------------------------------------------------------------------------------
# Ubuntu
#-------------------------------------------------------------------------------
@@ -338,7 +359,6 @@ build python/windows:
deploy python/pypi:
stage: deploy
interruptible: false
variables:
TWINE_USERNAME: __token__
TWINE_PASSWORD: $PYPI_TOKEN
@@ -363,7 +383,6 @@ deploy python/pypi:
push github:
stage: deploy
interruptible: false
tags:
- linux-build
image: alpine:latest
+1 -9
View File
@@ -82,7 +82,7 @@ if(MSVC)
add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
add_definitions(-D_ITERATOR_DEBUG_LEVEL=0)
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(LIBICSNEO_COMPILER_WARNINGS -Wall -Wno-unknown-pragmas)
set(LIBICSNEO_COMPILER_WARNINGS -Wall -Wno-switch -Wno-unknown-pragmas)
endif()
find_package(Threads REQUIRED)
@@ -234,14 +234,7 @@ set(SRC_FILES
communication/message/ethernetstatusmessage.cpp
communication/message/networkmutexmessage.cpp
communication/message/clientidmessage.cpp
communication/message/mfgconfigmessage.cpp
communication/message/transmitmessage.cpp
communication/message/spiportkeymessage.cpp
communication/message/genericapidatamessage.cpp
communication/message/genericapistatusmessage.cpp
communication/message/iso15765message.cpp
communication/packet/flexraypacket.cpp
communication/packet/canpacket.cpp
communication/packet/a2bpacket.cpp
@@ -352,7 +345,6 @@ add_library(icsneocpp
api/icsneocpp/icsneocpp.cpp
api/icsneocpp/event.cpp
api/icsneocpp/eventmanager.cpp
api/icsneocpp/heartbeat.cpp
api/icsneocpp/version.cpp
${SRC_FILES}
)
-1
View File
@@ -45,7 +45,6 @@ Instructions for installing each API can be found in its respective documentatio
- RAD-Pluto
- RAD-Star 2
- RAD-SuperMoon
- RAD-wBMS
- ValueCAN 3
- ValueCAN 4
+11 -20
View File
@@ -5,7 +5,6 @@
#include "icsneo/device/devicefinder.h"
#include "icsneo/icsneocpp.h"
#include "icsneo/communication/io.h"
#include "icsneo/communication/network.h"
#include <string>
#include <vector>
@@ -466,13 +465,11 @@ icsneoc2_error_t icsneoc2_device_pcb_serial_get(const icsneoc2_device_t* device,
return icsneoc2_error_invalid_type;
}
const auto& data = *pcbSerial;
if(!value) {
*value_length = data.size();
return icsneoc2_error_success;
if(value) {
size_t copyLen = std::min(*value_length, data.size());
std::copy(data.begin(), data.begin() + copyLen, value);
}
size_t copyLen = std::min(*value_length, data.size());
std::copy(data.begin(), data.begin() + copyLen, value);
*value_length = copyLen;
*value_length = data.size();
return icsneoc2_error_success;
}
@@ -506,32 +503,26 @@ icsneoc2_error_t icsneoc2_device_mac_addresses_enumerate(const icsneoc2_device_t
}
tail = node;
}
*mac_entries = head;
return icsneoc2_error_success;
}
icsneoc2_error_t icsneoc2_mac_network_id_get(const icsneoc2_mac_addr_entry_t* mac_address, icsneoc2_netid_t* network_id) {
icsneoc2_error_t icsneoc2_mac_network_id_get(const icsneoc2_mac_addr_entry_t* mac_address, _icsneoc2_netid_t* network_id) {
if(!mac_address || !network_id) {
return icsneoc2_error_invalid_parameters;
}
const auto netid = static_cast<Network::NetID>(mac_address->network_id);
*network_id = Network::GetCoreMiniNetworkFromNetID(netid).has_value()
? mac_address->network_id
: static_cast<icsneoc2_netid_t>(icsneoc2_netid_invalid);
*network_id = static_cast<_icsneoc2_netid_t>(mac_address->network_id);
return icsneoc2_error_success;
}
icsneoc2_error_t icsneoc2_mac_address_get(const icsneoc2_mac_addr_entry_t* mac_address, uint8_t* value, size_t* value_length) {
if(!mac_address || !value_length) {
if(!mac_address || !value || !value_length) {
return icsneoc2_error_invalid_parameters;
}
if(!value) {
*value_length = static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN);
return icsneoc2_error_success;
if(value) {
size_t copyLen = std::min(*value_length, static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN));
std::copy(mac_address->address, mac_address->address + copyLen, value);
}
size_t copyLen = std::min(*value_length, static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN));
std::copy(mac_address->address, mac_address->address + copyLen, value);
*value_length = copyLen;
*value_length = static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN);
return icsneoc2_error_success;
}
-1
View File
@@ -471,7 +471,6 @@ icsneoc2_error_t icsneoc2_message_lin_status_flags_get(const icsneoc2_message_t*
if(lin_msg->statusFlags.HasUpdatedResponderOnce) *status_flags |= ICSNEOC2_LIN_STATUS_HAS_UPDATED_RESPONDER_ONCE;
if(lin_msg->statusFlags.BusRecovered) *status_flags |= ICSNEOC2_LIN_STATUS_BUS_RECOVERED;
if(lin_msg->statusFlags.BreakOnly) *status_flags |= ICSNEOC2_LIN_STATUS_BREAK_ONLY;
if(lin_msg->statusFlags.WakeupRequest) *status_flags |= ICSNEOC2_LIN_STATUS_WAKEUP_REQUEST;
return icsneoc2_error_success;
}
-2
View File
@@ -462,8 +462,6 @@ const char* APIEvent::DescriptionForType(Type type) {
return TOO_MANY_EVENTS;
case Type::Unknown:
return UNKNOWN;
case Type::Any:
break;
}
return INVALID;
}
-60
View File
@@ -1,60 +0,0 @@
#include "icsneo/api/heartbeat.h"
#include "icsneo/api/lifetime.h"
#include "icsneo/device/device.h"
using namespace icsneo;
Heartbeat::Heartbeat(Device& device) :
device(device), mode(device.isOnline() ? Mode::Passive : Mode::Active), thread(&Heartbeat::run, this) {
}
Heartbeat::~Heartbeat() {
{
std::lock_guard lk(mutex);
stop = true;
}
cv.notify_one();
thread.join();
}
void Heartbeat::run() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
auto filter = std::make_shared<MessageFilter>();
filter->includeInternalInAny = true;
bool status = false;
auto cbHandle = device.com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&](std::shared_ptr<Message> msg) {
// TODO: remove DeviceStatus after 2027-08-17, as ResetStatus should be widely supported
const bool isHeartbeat =
(msg->type == Message::Type::ResetStatus) ||
(msg->type == Message::Type::RawMessage && std::static_pointer_cast<RawMessage>(msg)->network == Network::NetID::DeviceStatus);
if(!isHeartbeat)
return;
{
std::lock_guard lk(mutex);
status = true;
}
cv.notify_one();
}));
Lifetime cbLifetime([&] {
device.com->removeMessageCallback(cbHandle);
});
while(true) {
std::unique_lock lk(mutex);
if(mode == Mode::Active) {
if(cv.wait_for(lk, std::chrono::milliseconds(100), [&] { return stop; })) {
break;
}
device.com->sendCommand(Command::RequestStatusUpdate);
}
if(!cv.wait_for(lk, std::chrono::seconds(2), [&] { return status || stop; })) {
// we disconnect instead of close because it indicates to the user that a cleanup is still required (our thread join)
device.report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
device.com->driver->setIsDisconnected(true);
break;
}
if(stop)
break;
status = false;
}
}
+21 -19
View File
@@ -545,13 +545,15 @@ int LegacyDLLExport icsneoGetTimeStampForMsg(void* hObject, icsSpyMessage* pMsg,
void LegacyDLLExport icsneoGetISO15765Status(void* hObject, int lNetwork, int lClearTxStatus, int lClearRxStatus,
int* lTxStatus, int* lRxStatus)
{
// Not supported
// TODO Implement
return;
}
void LegacyDLLExport icsneoSetISO15765RxParameters(void* hObject, int lNetwork, int lEnable, spyFilterLong* pFF_CFMsgFilter,
icsSpyMessage* pTxMsg, int lCFTimeOutMs, int lFlowCBlockSize, int lUsesExtendedAddressing, int lUseHardwareIfPresent)
{
// Not supported
// TODO Implement
return;
}
int LegacyDLLExport icsneoGetRTC(void* hObject, icsSpyTime* time)
@@ -833,25 +835,26 @@ int LegacyDLLExport icsneoGetErrorInfo(int lErrorNumber, char* szErrorDescriptio
//ISO15765-2 Functions
int LegacyDLLExport icsneoISO15765_EnableNetworks(void* hObject, unsigned long ulNetworks)
{
// Not supported
// TODO Implement
return false;
}
int LegacyDLLExport icsneoISO15765_DisableNetworks(void* hObject)
{
// Not supported
// TODO Implement
return false;
}
int LegacyDLLExport icsneoISO15765_TransmitMessage(void* hObject, unsigned long ulNetworkID, stCM_ISO157652_TxMessage* pMsg, unsigned long ulBlockingTimeout)
int LegacyDLLExport icsneoISO15765_TransmitMessage(void* hObject, unsigned long ulNetworkID, stCM_ISO157652_TxMessage* pMsg,
unsigned long ulBlockingTimeout)
{
// Not supported
// TODO Implement
return false;
}
int LegacyDLLExport icsneoISO15765_ReceiveMessage(void* hObject, int ulNetworkID, stCM_ISO157652_RxMessage* pMsg)
{
// Not supported
// TODO Implement
return false;
}
@@ -1085,8 +1088,6 @@ int LegacyDLLExport icsneoGetDeviceSettingsType(void* hObject, EPlasmaIonVnetCha
case NEODEVICE_FIRE3_FLEXRAY:
*pDeviceSettingsType = DeviceFire3FlexraySettingsType;
break;
case NEODEVICE_RAD_BMS:
*pDeviceSettingsType = DeviceRADBMSSettingsType;
default:
return 0;
}
@@ -1282,11 +1283,10 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
return false;
neodevice_t* device = reinterpret_cast<neodevice_t*>(hObject);
const auto& cmd = static_cast<icsneo::J2534Command>(*CmdBuf);
switch (cmd)
switch (*CmdBuf)
{
case icsneo::J2534Command::SetNetworkBaudRate:
case J2534NVCMD_SetNetworkBaudRate:
pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp;
@@ -1296,7 +1296,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
iRetVal = 0;
break;
case icsneo::J2534Command::GetNetworkBaudRate:
case J2534NVCMD_GetNetworkBaudRate:
{
pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp;
@@ -1309,7 +1309,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
*pTmp = static_cast<uint64_t>(ret);
break;
}
case icsneo::J2534Command::SetCANFDRate:
case J2534NVCMD_SetCANFDRate:
pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp;
@@ -1320,7 +1320,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
iRetVal = 0;
break;
case icsneo::J2534Command::GetCANFDRate:
case J2534NVCMD_GetCANFDRate:
pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp;
@@ -1330,7 +1330,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
*pTmp = icsneo_getFDBaudrate(device, NetworkID);
break;
case icsneo::J2534Command::GetCANFDTermination:
case J2534NVCMD_GetCANFDTermination:
pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp;
@@ -1366,7 +1366,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
}
break;
case icsneo::J2534Command::SetCANFDTermination:
case J2534NVCMD_SetCANFDTermination:
pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp;
@@ -1420,9 +1420,11 @@ int LegacyDLLExport icsneoEnableBusVoltageMonitor(void* hObject, unsigned int en
return false;
}
int LegacyDLLExport icsneoISO15765_TransmitMessageEx(void* hObject, unsigned long ulNetworkID, ISO15765_2015_TxMessage* pMsg, unsigned long ulBlockingTimeout)
int LegacyDLLExport icsneoISO15765_TransmitMessageEx(void* hObject,
unsigned long ulNetworkID,
ISO15765_2015_TxMessage* pMsg,
unsigned long ulBlockingTimeout)
{
// Not supported
return false;
}
+1 -8
View File
@@ -57,14 +57,7 @@ install(TARGETS icsneopy LIBRARY DESTINATION icsneopy)
find_program(STUBGEN_EXE stubgen)
if(STUBGEN_EXE)
# Multi-config generators put the extension in Release/ or Debug/. Import
# that freshly built module, not a globally installed older icsneopy.
add_custom_command(TARGET icsneopy POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E rm -f "${CMAKE_CURRENT_BINARY_DIR}/icsneopy.pyi"
COMMAND "${STUBGEN_EXE}" -v -p icsneopy -o "${CMAKE_CURRENT_BINARY_DIR}"
WORKING_DIRECTORY "$<TARGET_FILE_DIR:icsneopy>"
VERBATIM
)
add_custom_command(TARGET icsneopy POST_BUILD COMMAND stubgen -v -p icsneopy -o .)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/icsneopy.pyi py.typed DESTINATION icsneopy)
endif()
@@ -28,8 +28,7 @@ void init_linmessage(pybind11::module_& m) {
.def_readwrite("UpdateResponderOnce", &LINStatusFlags::UpdateResponderOnce)
.def_readwrite("HasUpdatedResponderOnce", &LINStatusFlags::HasUpdatedResponderOnce)
.def_readwrite("BusRecovered", &LINStatusFlags::BusRecovered)
.def_readwrite("BreakOnly", &LINStatusFlags::BreakOnly)
.def_readwrite("WakeupRequest", &LINStatusFlags::WakeupRequest);
.def_readwrite("BreakOnly", &LINStatusFlags::BreakOnly);
pybind11::classh<LINMessage, Frame> linMessage(m, "LINMessage");
@@ -40,8 +39,7 @@ void init_linmessage(pybind11::module_& m) {
.value("LIN_BREAK_ONLY", LINMessage::Type::LIN_BREAK_ONLY)
.value("LIN_SYNC_ONLY", LINMessage::Type::LIN_SYNC_ONLY)
.value("LIN_UPDATE_RESPONDER", LINMessage::Type::LIN_UPDATE_RESPONDER)
.value("LIN_ERROR", LINMessage::Type::LIN_ERROR)
.value("LIN_WAKEUP_REQUEST", LINMessage::Type::LIN_WAKEUP_REQUEST);
.value("LIN_ERROR", LINMessage::Type::LIN_ERROR);
linMessage
.def(pybind11::init<>())
@@ -36,7 +36,6 @@ void init_devicetype(pybind11::module_& m) {
.value("RADEpsilon", DeviceType::Enum::RADEpsilon)
.value("RADEpsilonXL", DeviceType::Enum::RADEpsilonXL)
.value("RADGalaxy2", DeviceType::Enum::RADGalaxy2)
.value("RADwBMS", DeviceType::Enum::RADwBMS)
.value("RADMoon3", DeviceType::Enum::RADMoon3)
.value("RADGemini", DeviceType::Enum::RADGemini)
.value("RADComet2", DeviceType::Enum::RADComet2)
+2 -1
View File
@@ -1,6 +1,7 @@
#!/bin/sh
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_EXAMPLES=ON -DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_EXAMPLES=ON \
-DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1
cmake --build build || exit 1
+2 -1
View File
@@ -3,6 +3,7 @@
mkdir build >nul 2>&1
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DLIBICSNEO_BUILD_UNIT_TESTS=ON-DLIBICSNEO_ENABLE_TCP=ON || exit /b 1
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_UNIT_TESTS=ON ^
-DLIBICSNEO_ENABLE_TCP=ON || exit /b 1
cmake --build build || exit /b 1
-28
View File
@@ -26,10 +26,6 @@
#include "icsneo/communication/message/ethernetstatusmessage.h"
#include "icsneo/communication/message/networkmutexmessage.h"
#include "icsneo/communication/message/clientidmessage.h"
#include "icsneo/communication/message/mfgconfigmessage.h"
#include "icsneo/communication/message/spiportkeymessage.h"
#include "icsneo/communication/message/genericapidatamessage.h"
#include "icsneo/communication/message/genericapistatusmessage.h"
#include "icsneo/communication/command.h"
#include "icsneo/device/device.h"
#include "icsneo/communication/packet/canpacket.h"
@@ -44,7 +40,6 @@
#include "icsneo/communication/packet/i2cpacket.h"
#include "icsneo/communication/packet/scriptstatuspacket.h"
#include "icsneo/communication/packet/linpacket.h"
#include "icsneo/communication/message/iso15765message.h"
#include "icsneo/communication/packet/componentversionpacket.h"
#include "icsneo/communication/packet/supportedfeaturespacket.h"
#include "icsneo/communication/packet/mdiopacket.h"
@@ -346,15 +341,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
case ExtendedCommand::LiveData:
result = HardwareLiveDataPacket::DecodeToMessage(packet->data, report);
return true;
case ExtendedCommand::ExecuteSPIPortKeyOperation:
result = SPIPortKeyMessage::DecodeToMessage(packet->data);
return true;
case ExtendedCommand::ReadGenericAPIData:
result = GenericAPIDataMessage::DecodeToMessage(packet->data);
return true;
case ExtendedCommand::ReadGenericAPIStatus:
result = GenericAPIStatusMessage::DecodeToMessage(packet->data);
return true;
case ExtendedCommand::GetTC10Status:
result = TC10StatusMessage::DecodeToMessage(packet->data);
return true;
@@ -373,9 +359,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
);
protoapi::Id protoId = protoapi::getProtoId(responseBody.data(), responseBody.size());
switch(protoId) {
case protoapi::Id::MfgConfig:
result = MfgConfigMessage::DecodeToMessage(responseBody);
return true;
case protoapi::Id::NetworkMutex:
result = NetworkMutexMessage::DecodeToMessage(responseBody);
return true;
@@ -480,14 +463,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
return true;
}
case Command::J2534Command: {
result = J2534CommandMessage::decodeToMessage(packet->data);
if(!result) {
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
return false;
}
return true;
}
default:
auto msg = std::make_shared<Main51Message>();
msg->command = Command(packet->data[0]);
@@ -588,9 +563,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
}
break;
}
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return false;
}
// For the moment other types of messages will automatically be decoded as raw messages
+1 -3
View File
@@ -234,9 +234,7 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
result = packetizer.packetWrap(result, false);
return true;
}
default:
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
return false; // The message was not a properly formed Message
break;
}
// Early returns may mean we don't reach this far, check the type you're concerned with
-2
View File
@@ -163,8 +163,6 @@ void A2BMessage::setChannelSample(Direction dir, uint8_t channel, size_t frame,
case PCMType::L24:
sampleToSet = sampleToSet << 8;
break;
case PCMType::L32:
break;
}
if(channelSize16) {
+1 -1
View File
@@ -35,7 +35,7 @@ bool EthPhyMessage::appendPhyMessage(bool writeEnable, bool clause45, uint8_t ph
bool EthPhyMessage::appendPhyMessage(std::shared_ptr<PhyMessage> message)
{
if(message)
if(message != nullptr)
{
messages.push_back(message);
return true;
@@ -1,28 +0,0 @@
#include "icsneo/communication/message/genericapidatamessage.h"
#include "icsneo/communication/message/extendedresponsemessage.h"
#include "icsneo/communication/command.h"
using namespace icsneo;
std::shared_ptr<GenericAPIDataMessage> GenericAPIDataMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
return nullptr;
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
if(hdr->command != ExtendedCommand::ReadGenericAPIData)
return nullptr;
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(GenericAPIDataHeader);
if(bytestream.size() < required)
return nullptr;
auto msg = std::make_shared<GenericAPIDataMessage>();
const auto* packet = reinterpret_cast<const GenericAPIDataPacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
msg->functionId = packet->header.functionId;
msg->buffer.resize(packet->header.bufferLength);
std::copy(packet->buffer, packet->buffer + packet->header.bufferLength, msg->buffer.data());
return msg;
}
@@ -1,29 +0,0 @@
#include "icsneo/communication/message/genericapistatusmessage.h"
#include "icsneo/communication/message/extendedresponsemessage.h"
#include "icsneo/communication/command.h"
using namespace icsneo;
std::shared_ptr<GenericAPIStatusMessage> GenericAPIStatusMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
return nullptr;
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
if(hdr->command != ExtendedCommand::ReadGenericAPIStatus)
return nullptr;
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(GenericAPIStatusResponsePacket);
if(bytestream.size() < required)
return nullptr;
auto msg = std::make_shared<GenericAPIStatusMessage>();
const auto* packet = reinterpret_cast<const GenericAPIStatusResponsePacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
msg->functionId = packet->functionId;
msg->finishedProcessing = static_cast<bool>(packet->finishedProcessing);
msg->functionError = packet->functionError;
msg->callbackError = packet->callbackError;
return msg;
}
-337
View File
@@ -1,337 +0,0 @@
#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);
}
@@ -1,77 +0,0 @@
#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);
}
@@ -1,27 +0,0 @@
#include "icsneo/communication/message/spiportkeymessage.h"
#include "icsneo/communication/message/extendedresponsemessage.h"
#include "icsneo/communication/command.h"
#include "icsneo/communication/network.h"
using namespace icsneo;
std::shared_ptr<SPIPortKeyMessage> SPIPortKeyMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
return nullptr;
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
if(hdr->command != ExtendedCommand::ExecuteSPIPortKeyOperation)
return nullptr;
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(SPIPortKeyPacket);
if(bytestream.size() < required)
return nullptr;
auto msg = std::make_shared<SPIPortKeyMessage>();
const auto* packet = reinterpret_cast<const SPIPortKeyPacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
msg->isKeyLoaded = packet->isKeyLoaded;
return msg;
}
@@ -137,7 +137,6 @@ static std::vector<uint8_t> EncodeFromMessageLIN(std::shared_ptr<Frame> frame, c
linpacket->CoreMiniBitsLIN.TXResponder = 1;
break;
case LINMessage::Type::LIN_BREAK_ONLY:
linpacket->CoreMiniBitsLIN.TXCommander = 1;
linpacket->CoreMiniBitsLIN.BreakOnly = 1;
break;
default:
@@ -142,8 +142,6 @@ void MultiChannelCommunication::hidReadTask() {
dispatchMessage(msg);
break;
}
default:
break;
}
if(currentQueue == nullptr) {
+5 -17
View File
@@ -72,30 +72,18 @@ std::shared_ptr<Message> HardwareLINPacket::DecodeToMessage(const std::vector<ui
static_cast<bool>(packet->CoreMiniBitsLIN.UpdateResponderOnce),
static_cast<bool>(packet->CoreMiniBitsLIN.HasUpdatedResponderOnce),
static_cast<bool>(packet->CoreMiniBitsLIN.BusRecovered),
static_cast<bool>(packet->CoreMiniBitsLIN.BreakOnly),
static_cast<bool>(packet->CoreMiniBitsLIN.WakeupRequest)
static_cast<bool>(packet->CoreMiniBitsLIN.BreakOnly)
};
// Wake type only for a wake-only pulse. A UART/LIN break or a complete
// frame may also carry WakeupRequest; those keep their existing type.
const bool wakeupPulse = msg->statusFlags.WakeupRequest &&
packet->CoreMiniBitsLIN.len == 0 &&
packet->CoreMiniBitsLIN.ID == 0 &&
!msg->statusFlags.BreakOnly &&
!msg->errFlags.ErrRxBreakOnly &&
!msg->errFlags.ErrRxBreakSyncOnly;
if(wakeupPulse)
msg->linMsgType = LINMessage::Type::LIN_WAKEUP_REQUEST;
else if(msg->statusFlags.TxCommander || msg->statusFlags.TxResponder)
if(msg->statusFlags.TxCommander || msg->statusFlags.TxResponder)
msg->linMsgType = LINMessage::Type::LIN_COMMANDER_MSG;
else if(msg->statusFlags.BreakOnly)
msg->linMsgType = LINMessage::Type::LIN_BREAK_ONLY;
if( !wakeupPulse &&
(msg->errFlags.ErrRxBreakOnly || msg->errFlags.ErrRxBreakSyncOnly ||
if( msg->errFlags.ErrRxBreakOnly || msg->errFlags.ErrRxBreakSyncOnly ||
msg->errFlags.ErrTxRxMismatch || msg->errFlags.ErrRxBreakNotZero ||
msg->errFlags.ErrRxBreakTooShort || msg->errFlags.ErrRxSyncNot55 ||
msg->errFlags.ErrRxDataLenOver8 || msg->errFlags.ErrFrameSync ||
msg->errFlags.ErrFrameMessageID || msg->errFlags.ErrChecksumMatch ||
msg->errFlags.ErrFrameResponderData) )
msg->errFlags.ErrFrameResponderData )
{ msg->linMsgType = LINMessage::Type::LIN_ERROR; }
msg->timestamp = packet->timestamp;
@@ -115,7 +103,7 @@ bool HardwareLINPacket::EncodeFromMessage(LINMessage& message, std::vector<uint8
}
case LINMessage::Type::LIN_BREAK_ONLY:
{
size |= 0x80u | 0x20u;
size |= 0x20u;
break;
}
case LINMessage::Type::NOT_SET:
+124 -348
View File
@@ -8,7 +8,6 @@
#include "icsneo/disk/fat.h"
#include "icsneo/communication/message/filter/extendedresponsefilter.h"
#include "icsneo/communication/message/networkmutexmessage.h"
#include "icsneo/communication/message/mfgconfigmessage.h"
#include "icsneo/communication/message/transmitmessage.h"
#ifdef _MSC_VER
@@ -93,6 +92,10 @@ Device::~Device() {
disableMessagePolling();
if(isOpen())
close();
if(heartbeatThread.joinable()) {
stopHeartbeatThread = true;
heartbeatThread.join();
}
}
uint16_t Device::getTimestampResolution() const {
@@ -239,12 +242,12 @@ std::vector<VersionReport> Device::getChipVersions(bool refreshComponents) {
auto& version = chipVersions.back();
auto disectedVersion = disectVersion(component.dotVersion);
version.id = chipInfo.id;
version.name = chipInfo.name;
version.major = disectedVersion[0];
version.minor = disectedVersion[1];
version.id = chipInfo.id;
version.name = chipInfo.name;
version.major = disectedVersion[0];
version.minor = disectedVersion[1];
version.maintenance = disectedVersion[2];
version.build = disectedVersion[3];
version.build = disectedVersion[3];
}
}
}
@@ -264,12 +267,12 @@ std::vector<VersionReport> Device::getChipVersions(bool refreshComponents) {
chipVersions.emplace_back();
auto& version = chipVersions.back();
version.id = chipInfo.id;
version.name = chipInfo.name;
version.major = appVer->major;
version.minor = appVer->minor;
version.id = chipInfo.id;
version.name = chipInfo.name;
version.major = appVer->major;
version.minor = appVer->minor;
version.maintenance = 0;
version.build = 0;
version.build = 0;
}
}
return chipVersions;
@@ -285,8 +288,6 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
return false;
}
startHeartbeat();
APIEvent::Type attemptErr = attemptToBeginCommunication();
if(attemptErr != APIEvent::Type::NoErrorFound) {
// We could not communicate with the device, let's see if an extension can
@@ -333,6 +334,79 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
EventManager::GetInstance().cancelErrorDowngradingOnCurrentThread();
}
MessageFilter filter;
filter.includeInternalInAny = true;
internalHandlerCallbackID = com->addMessageCallback(std::make_shared<MessageCallback>(filter, [this](std::shared_ptr<Message> message) {
handleInternalMessage(message);
}));
// Clear the previous heartbeat thread, in case open() was called on this instance more than once
if(heartbeatThread.joinable())
heartbeatThread.join();
stopHeartbeatThread = false;
heartbeatThread = std::thread([this]() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
MessageFilter filter;
filter.includeInternalInAny = true;
std::condition_variable heartbeatCV;
std::mutex receivedMessageMutex;
bool receivedMessage = false;
auto messageReceivedCallbackID = com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&](std::shared_ptr<Message>) {
{
std::scoped_lock<std::mutex> lk(receivedMessageMutex);
receivedMessage = true;
}
heartbeatCV.notify_all();
}));
// Give the device time to get situated
auto i = 150;
while(!stopHeartbeatThread && i != 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
i--;
}
while(!stopHeartbeatThread) {
std::unique_lock<std::mutex> recvLk(receivedMessageMutex);
// Wait for 110ms for a possible heartbeat
if(heartbeatCV.wait_for(recvLk, std::chrono::milliseconds(110), [&]() { return receivedMessage; })) {
receivedMessage = false;
} else if(!stopHeartbeatThread) { // Add this condition here in case the thread was stopped while waiting for the last message
// Some communication, such as the bootloader and extractor interfaces, must
// redirect the input stream from the device as it will no longer be in the
// packet format we expect here. As a result, status updates will not reach
// us here and suppressDisconnects() must be used. We don't want to request
// a status and then redirect the stream, as we'll then be polluting an
// otherwise quiet stream. This lock makes sure suppressDisconnects() will
// block until we've either gotten our status update or disconnected from
// the device.
std::unique_lock<std::mutex> lk(heartbeatMutex);
if(heartbeatSuppressed()) continue;
// No heartbeat received, request a status
com->sendCommand(Command::RequestStatusUpdate);
// Check if we got a message, and if not, if settings are being applied
if(heartbeatCV.wait_for(recvLk, std::chrono::milliseconds(3500), [&](){ return receivedMessage; })) {
receivedMessage = false;
} else {
if(!stopHeartbeatThread) {
close();
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
}
break;
}
}
}
com->removeMessageCallback(messageReceivedCallbackID);
});
if(supportsLiveData())
clearAllLiveData();
@@ -429,7 +503,7 @@ bool Device::close() {
return false;
}
stopHeartbeat();
stopHeartbeatThread = true;
if (isMessagePollingEnabled()) {
disableMessagePolling();
@@ -460,15 +534,31 @@ bool Device::goOnline() {
if(!enableNetworkCommunication(true, onlineTimeoutMs))
return false;
auto startTime = std::chrono::system_clock::now();
ledState = LEDState::Online;
updateLEDState();
// (re)start the keeponline
keeponline = std::make_unique<Periodic>([this] {
static std::vector<uint8_t> timeoutBytes = std::vector<uint8_t>((uint8_t*)&onlineTimeoutMs, (uint8_t*)&onlineTimeoutMs + sizeof(onlineTimeoutMs));
return com->sendCommand(Command::KeepAlive, timeoutBytes);
}, std::chrono::milliseconds(onlineTimeoutMs / 4));
std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Network::NetID::Reset_Status);
filter->includeInternalInAny = true;
// Wait until communication is enabled or 5 seconds, whichever comes first
while((std::chrono::system_clock::now() - startTime) < std::chrono::seconds(5)) {
if(latestResetStatus && latestResetStatus->comEnabled)
break;
bool failOut = false;
com->waitForMessageSync([this, &failOut]() {
if(!com->sendCommand(Command::RequestStatusUpdate)) {
failOut = true;
return false;
}
return true;
}, filter, std::chrono::milliseconds(100));
if(failOut)
return false;
}
if(supportsNetworkMutex) {
assignedClientId = com->getClientIDSync();
@@ -485,26 +575,25 @@ bool Device::goOnline() {
case NetworkMutexEvent::Acquired:
lockedNetworks.emplace(*netMutexMsg->networks.begin());
break;
case NetworkMutexEvent::Expired:
case NetworkMutexEvent::Preempted:
case NetworkMutexEvent::Released: {
auto it = lockedNetworks.find(*netMutexMsg->networks.begin());
if (it != lockedNetworks.end())
lockedNetworks.erase(it);
break;
}
case NetworkMutexEvent::Queued:
break;
}
}
});
}
}
online = true;
// (re)start the keeponline
keeponline = std::make_unique<Periodic>([this] {
static std::vector<uint8_t> timeoutBytes = std::vector<uint8_t>((uint8_t*)&onlineTimeoutMs, (uint8_t*)&onlineTimeoutMs + sizeof(onlineTimeoutMs));
return com->sendCommand(Command::KeepAlive, timeoutBytes);
}, std::chrono::milliseconds(onlineTimeoutMs / 4));
// restart the heartbeat in online mode
restartHeartbeat();
online = true;
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOnline(); return true; });
@@ -512,19 +601,15 @@ bool Device::goOnline() {
}
bool Device::goOffline() {
online = false;
keeponline.reset();
// restart the heartbeat in offline mode
restartHeartbeat();
if(networkMutexCallbackHandle)
removeMessageCallback(*networkMutexCallbackHandle);
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOffline(); return true; });
if(isDisconnected()) {
online = false;
return true;
}
@@ -540,6 +625,8 @@ bool Device::goOffline() {
updateLEDState();
online = false;
return true;
}
@@ -924,36 +1011,6 @@ std::shared_ptr<HardwareInfo> Device::getHardwareInfo(std::chrono::milliseconds
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) {
if(!into || timeout <= std::chrono::milliseconds(0)) {
@@ -1931,9 +1988,11 @@ void Device::stopScriptStatusThreadIfNecessary(std::unique_lock<std::mutex> lk)
}
Lifetime Device::suppressDisconnects() {
stopHeartbeat();
std::lock_guard<std::mutex> lk(heartbeatMutex);
heartbeatSuppressedByUser++;
return Lifetime([this] {
startHeartbeat();
std::lock_guard<std::mutex> lk2(heartbeatMutex);
heartbeatSuppressedByUser--;
});
}
@@ -2069,18 +2128,6 @@ std::optional<EthPhyMessage> Device::sendEthPhyMsg(const EthPhyMessage& message,
return std::make_optional<EthPhyMessage>(*retMsg);
}
bool Device::sendSPIPortKeyOperation(uint8_t portIndex, SPIPortKeyMessage::Operation op, std::array<uint8_t, 16> key) {
std::vector<uint8_t> args(sizeof(SPIPortKeyMessage::SPIPortKeyPacket));
auto& params = *reinterpret_cast<SPIPortKeyMessage::SPIPortKeyPacket*>(args.data());
params.op = op;
params.portIndex = portIndex;
std::copy(key.begin(), key.end(), params.key);
if(!com->sendCommand(ExtendedCommand::ExecuteSPIPortKeyOperation, args)) {
return false;
}
return true;
}
std::optional<bool> Device::SetRootDirectoryEntryFlags(uint8_t mask, uint8_t values, uint32_t collectionEntryByteAddress)
{
if(!supportsWiVI())
@@ -3250,12 +3297,11 @@ bool Device::findVSAOffsetFromTimepoint(ICSClock::time_point point, uint64_t& vs
std::shared_ptr<VSA> midRecord;
auto midRecordStatus = parser.getRecordFromBytes(buffer.data(), Disk::SectorSize, midRecord);
switch(midRecordStatus) {
case VSAParser::RecordParseStatus::NotARecordStart: {
case VSAParser::RecordParseStatus::NotARecordStart:
// This part of the buffer does not contain records
rightIndex = midIndex - 1;
continue;
}
case VSAParser::RecordParseStatus::ConsecutiveExtended: {
case VSAParser::RecordParseStatus::ConsecutiveExtended:
// We dropped in the middle of an extended message record
auto extendedRecord = std::dynamic_pointer_cast<VSAExtendedMessage>(midRecord);
uint64_t pos = readPos;
@@ -3270,9 +3316,6 @@ bool Device::findVSAOffsetFromTimepoint(ICSClock::time_point point, uint64_t& vs
midIndex = (pos - firstOffset) / Disk::SectorSize;
midRecord = extendedRecord;
break;
}
default:
break;
}
if(midIndex <= leftIndex) {
// Extended records cause problems with binary search
@@ -4113,270 +4156,3 @@ bool Device::unlockAllNetworks()
return true;
}
void Device::startHeartbeat() {
if(!heartbeat)
heartbeat = std::make_unique<Heartbeat>(*this);
}
void Device::stopHeartbeat() {
heartbeat.reset();
}
void Device::restartHeartbeat() {
stopHeartbeat();
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);
}
-8
View File
@@ -241,10 +241,6 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
makeIfSerialMatches<RADSupermoon>(dev, newFoundDevices);
#endif
#ifdef __RADWBMS_H_
makeIfSerialMatches<RADwBMS>(dev, newFoundDevices);
#endif
#ifdef __VALUECAN3_H_
makeIfSerialRangeMatches<ValueCAN3>(dev, newFoundDevices);
#endif
@@ -408,10 +404,6 @@ const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
RADSupermoon::DEVICE_TYPE,
#endif
#ifdef __RADWBMS_H_
RADwBMS::DEVICE_TYPE,
#endif
#ifdef __VALUECAN3_H_
ValueCAN3::DEVICE_TYPE,
#endif
+17 -24
View File
@@ -1,16 +1,9 @@
#include "icsneo/device/device.h"
#include "icsneo/device/idevicesettings.h"
#include "icsneo/communication/message/filter/main51messagefilter.h"
#include <cstring>
using namespace icsneo;
IDeviceSettings::IDeviceSettings(Device* device, size_t size)
: device(device), report(device->report), structSize(size) {}
IDeviceSettings::IDeviceSettings(warn_t createInoperableSettings, Device* device)
: disabled(true), readonly(true), report(device->report), structSize(0) { (void)createInoperableSettings; }
std::optional<uint16_t> IDeviceSettings::CalculateGSChecksum(const std::vector<uint8_t>& settings) {
const uint16_t* p = reinterpret_cast<const uint16_t*>(settings.data());
size_t words = settings.size();
@@ -173,7 +166,7 @@ bool IDeviceSettings::refresh() {
}
std::vector<uint8_t> rxSettings;
bool ret = device->com->getSettingsSync(rxSettings);
bool ret = com->getSettingsSync(rxSettings);
if(!ret) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return false;
@@ -238,10 +231,10 @@ bool IDeviceSettings::apply(bool temporary) {
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
// Pause I/O with the device while the settings are applied
device->stopHeartbeat();
applyingSettings = true;
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() {
return device->com->sendCommand(Command::SetSettings, bytestream);
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return com->sendCommand(Command::SetSettings, bytestream);
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000)));
if(!msg || msg->data[0] != 1) { // We did not receive a response
@@ -266,8 +259,8 @@ bool IDeviceSettings::apply(bool temporary) {
bytestream[6] = (uint8_t)(*gsChecksum >> 8);
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() {
return device->com->sendCommand(Command::SetSettings, bytestream);
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return com->sendCommand(Command::SetSettings, bytestream);
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000)));
if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible
@@ -279,12 +272,12 @@ bool IDeviceSettings::apply(bool temporary) {
}
if(!temporary) {
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() {
return device->com->sendCommand(Command::SaveSettings);
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
return com->sendCommand(Command::SaveSettings);
}, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000)));
}
device->startHeartbeat();
applyingSettings = false;
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
@@ -306,10 +299,10 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
return false;
}
device->stopHeartbeat();
applyingSettings = true;
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() {
return device->com->sendCommand(Command::SetDefaultSettings);
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
return com->sendCommand(Command::SetDefaultSettings);
}, std::make_shared<Main51MessageFilter>(Command::SetDefaultSettings), std::chrono::milliseconds(5000)));
if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible
@@ -343,8 +336,8 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
bytestream[6] = (uint8_t)(*gsChecksum >> 8);
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() {
return device->com->sendCommand(Command::SetSettings, bytestream);
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return com->sendCommand(Command::SetSettings, bytestream);
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000)));
if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible
@@ -356,12 +349,12 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
}
if(!temporary) {
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() {
return device->com->sendCommand(Command::SaveSettings);
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
return com->sendCommand(Command::SaveSettings);
}, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000)));
}
device->startHeartbeat();
applyingSettings = false;
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
-5
View File
@@ -36,7 +36,6 @@ 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_T1S_EXAMPLE "Build the T1S 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})
@@ -191,7 +190,3 @@ endif()
if(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE)
add_subdirectory(cpp/gptp)
endif()
if(LIBICSNEO_BUILD_CPP_ISO15765_LOOPBACK_EXAMPLE)
add_subdirectory(cpp/iso15765_loopback)
endif()
+1 -1
View File
@@ -112,7 +112,7 @@ int main() {
}
printf("MACs: %u entr%s\n", mac_count, mac_count == 1 ? "y" : "ies");
for(icsneoc2_mac_addr_entry_t* cur = macs; cur; cur = icsneoc2_mac_addresses_next(cur)) {
icsneoc2_netid_t network_id;
_icsneoc2_netid_t network_id;
icsneoc2_mac_network_id_get(cur, &network_id);
printf(" Network %-5u ", (unsigned)network_id);
uint8_t address[6];
@@ -1,2 +0,0 @@
add_executable(libicsneocpp-iso15765-loopback src/ISO15765Loopback.cpp)
target_link_libraries(libicsneocpp-iso15765-loopback icsneocpp)
@@ -1,450 +0,0 @@
#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;
}
+25 -125
View File
@@ -1,133 +1,33 @@
#ifndef _J2534_H
#define _J2534_H
#include <cstdint>
namespace icsneo {
//J2534 Commands
#define J1534_NUM_PERIOD_TX_MSGS 128
#define J1534_NUM_PERIOD_RX_MSGS 128
enum class J2534Command : uint8_t {
SetISJ2534 = 0,
SetISO5Baud = 1,
SetISOFastInit = 2,
SetISOCheckSum = 3,
SetISO9141Parms = 4,
GetISO9141Parms = 5,
ISO9141APIChkSum = 6,
SetNetworkBaudRate = 7,
GetNetworkBaudRate = 8,
EnableTransmitEvent = 9,
SetTransmitEvent = 10,
BlueEnableStopFilters = 11,
Blue15765HWSupport = 12,
GetTXBufferInfo = 13,
GetEncryptionKey = 14,
SetMiscIOForVBATT = 15,
EnableISO_KW_Network = 16,
SetJ1708CheckSum = 17,
GetTimestamp = 18,
GetCANFDRate = 19,
SetCANFDRate = 20,
GetCANFDTermination = 21,
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
#define J2534NVCMD_SetISJ2534 0
#define J2534NVCMD_SetISO5Baud 1
#define J2534NVCMD_SetISOFastInit 2
#define J2534NVCMD_SetISOCheckSum 3
#define J2534NVCMD_SetISO9141Parms 4
#define J2534NVCMD_GetISO9141Parms 5
#define J2534NVCMD_ISO9141APIChkSum 6
#define J2534NVCMD_SetNetworkBaudRate 7
#define J2534NVCMD_GetNetworkBaudRate 8
#define J2534NVCMD_EnableTransmitEvent 9
#define J2534NVCMD_SetTransmitEvent 10
#define J2534NVCMD_BlueEnableStopFilters 11
#define J2534NVCMD_Blue15765HWSupport 12
#define J2534NVCMD_GetTXBufferInfo 13
#define J2534NVCMD_GetEncryptionKey 14
#define J2534NVCMD_SetMiscIOForVBATT 15
#define J2534NVCMD_EnableISO_KW_Network 16
#define J2534NVCMD_SetJ1708CheckSum 17
#define J2534NVCMD_GetTimestamp 18
#define J2534NVCMD_GetCANFDRate 19
#define J2534NVCMD_SetCANFDRate 20
#define J2534NVCMD_GetCANFDTermination 21
#define J2534NVCMD_SetCANFDTermination 22
#define J2534NVCMD_GetCANFDFormat 23
#define J2534NVCMD_SetCANFDFormat 24
#endif
-38
View File
@@ -1,38 +0,0 @@
#ifndef __HEARTBEAT_H__
#define __HEARTBEAT_H__
#ifdef __cplusplus
#include <thread>
#include <condition_variable>
#include <mutex>
namespace icsneo {
class Device;
class Heartbeat {
public:
Heartbeat(Device& device);
~Heartbeat();
private:
enum class Mode {
Passive, // ResetStatus messages arrive without requesting
Active, // RequestStatusUpdate needs to be sent
};
Device& device;
const Mode mode;
bool stop = false;
std::mutex mutex;
std::condition_variable cv;
std::thread thread;
void run();
};
} // icsneo
#endif // __cplusplus
#endif // __HEARTBEAT_H__
-5
View File
@@ -43,7 +43,6 @@ enum class Command : uint8_t {
GetLogicalDiskInfo = 0xBB, // Previously known as RED_CMD_GET_SDCARD_INFO
RequestStatusUpdate = 0xBC,
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
RequestBitSmash = 0xDC, // Previously known as RED_CMD_CM_BITSMASH
WiVICommand = 0xDD, // Previously known as RED_CMD_WIVI_COMM
@@ -74,14 +73,10 @@ enum class ExtendedCommand : uint16_t {
GetComponentVersions = 0x001A,
SoftwareUpdate = 0x001B,
Reboot = 0x001C,
ReadGenericAPIStatus = 0x001D,
SetRootFSEntryFlags = 0x0027,
TransmitCoreminiMessage = 0x0028,
ReadGenericAPIData = 0x002E,
WriteGenericAPICommand = 0x002F,
GenericBinaryInfo = 0x0030,
LiveData = 0x0035,
ExecuteSPIPortKeyOperation = 0x003C,
RequestTC10Wake = 0x003D,
RequestTC10Sleep = 0x003E,
GetTC10Status = 0x003F,
@@ -14,7 +14,6 @@
#include "icsneo/communication/message/extendedresponsemessage.h"
#include "icsneo/device/deviceversion.h"
#include "icsneo/api/eventmanager.h"
#include "icsneo/api/heartbeat.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/encoder.h"
#include "icsneo/communication/decoder.h"
+1 -1
View File
@@ -31,7 +31,6 @@ public:
virtual driver_finder_t getFinder() = 0;
inline bool isDisconnected() const { return disconnected; };
inline void setIsDisconnected(bool isDisconnected) { disconnected = isDisconnected; }
inline bool isClosing() const { return closing; }
bool waitForRx(size_t limit, std::chrono::milliseconds timeout);
@@ -63,6 +62,7 @@ protected:
};
inline void setIsClosing(bool isClosing) { closing = isClosing; }
inline void setIsDisconnected(bool isDisconnected) { disconnected = isDisconnected; }
// Overridable in case the driver doesn't want to use writeTask and writeQueue
virtual bool writeQueueFull() { return writeQueue.size_approx() > writeQueueSize; }
-6
View File
@@ -9,7 +9,6 @@
#include <common/v1/proto_header.pb.h>
#include <commands/generic/v1/client_id.pb.h>
#include <commands/network/v1/mutex.pb.h>
#include <settings/manufacturing/v1/mfg_config.pb.h>
#ifdef _WIN32
#pragma warning(pop)
#endif
@@ -37,11 +36,6 @@ struct IDLookup {
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 <>
struct IDLookup<commands::network::v1::NetworkMutex> {
constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_NETWORK_MUTEX;
@@ -6,6 +6,7 @@
#include "icsneo/communication/packet/ethphyregpacket.h"
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/packet.h"
#include "icsneo/api/eventmanager.h"
#include <vector>
#include <memory>
@@ -1,44 +0,0 @@
#ifndef __GENERICAPIDATAMESSAGE_H_
#define __GENERICAPIDATAMESSAGE_H_
#ifdef __cplusplus
#include "icsneo/communication/message/message.h"
#include <vector>
#include <memory>
namespace icsneo {
class GenericAPIDataMessage : public Message {
public:
static constexpr size_t GENERIC_API_BUFFER_SIZE = 513;
#pragma pack(push, 1)
struct GenericAPIDataHeader {
uint16_t bufferLength;
uint8_t apiIndex;
uint8_t instance;
uint8_t functionId;
};
struct GenericAPIDataPacket
{
GenericAPIDataHeader header;
uint8_t buffer[GENERIC_API_BUFFER_SIZE];
};
#pragma pack(pop)
static std::shared_ptr<GenericAPIDataMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
GenericAPIDataMessage() : Message(Type::GenericAPIData) {}
uint8_t functionId;
std::vector<uint8_t> buffer;
};
} // namespace icsneo
#endif // __cplusplus
#endif // __GENERICAPIDATAMESSAGE_H_
@@ -1,40 +0,0 @@
#ifndef __GENERICAPISTATUSMESSAGE_H_
#define __GENERICAPISTATUSMESSAGE_H_
#ifdef __cplusplus
#include "icsneo/communication/message/message.h"
#include <memory>
namespace icsneo {
class GenericAPIStatusMessage : public Message {
public:
#pragma pack(push, 2)
struct GenericAPIStatusResponsePacket
{
uint8_t apiIndex;
uint8_t instance;
uint8_t functionId;
uint8_t functionError;
uint8_t callbackError;
uint8_t finishedProcessing;
};
#pragma pack(pop)
static std::shared_ptr<GenericAPIStatusMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
GenericAPIStatusMessage() : Message(Type::GenericAPIStatus) {}
uint8_t functionId;
bool finishedProcessing;
uint8_t functionError;
uint8_t callbackError;
};
} // namespace icsneo
#endif // __cplusplus
#endif // __GENERICAPISTATUSMESSAGE_H_
@@ -1,443 +0,0 @@
#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
@@ -34,7 +34,6 @@ struct LINStatusFlags {
bool HasUpdatedResponderOnce = false;
bool BusRecovered = false;
bool BreakOnly = false;
bool WakeupRequest = false;
};
class LINMessage : public Frame {
@@ -46,8 +45,7 @@ public:
LIN_BREAK_ONLY = icsneoc2_lin_msg_type_break_only,
LIN_SYNC_ONLY = icsneoc2_lin_msg_type_sync_only,
LIN_UPDATE_RESPONDER = icsneoc2_lin_msg_type_update_responder,
LIN_ERROR = icsneoc2_lin_msg_type_error,
LIN_WAKEUP_REQUEST = icsneoc2_lin_msg_type_wakeup_request
LIN_ERROR = icsneoc2_lin_msg_type_error
};
static void calcChecksum(LINMessage& message);
@@ -48,10 +48,6 @@ public:
NetworkMutex = 0x8016,
ClientId = 0x8017,
AllMACAddresses = 0x8018,
SPIPortKeyOperation = 0x8019,
GenericAPIData = 0x8020,
GenericAPIStatus = 0x8021,
MfgConfig = 0x8022,
};
Message(Type t) : type(t) {}
@@ -1,56 +0,0 @@
#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_
@@ -1,43 +0,0 @@
#ifndef __SPIPORTKEYMESSAGE_H_
#define __SPIPORTKEYMESSAGE_H_
#ifdef __cplusplus
#include "icsneo/communication/message/message.h"
#include <array>
#include <memory>
namespace icsneo {
class SPIPortKeyMessage : public Message {
public:
enum class Operation : uint8_t {
WriteKey = 0,
IsKeySet = 1,
ClearKey = 2
};
#pragma pack(push, 2)
struct SPIPortKeyPacket
{
Operation op;
uint8_t portIndex;
bool isKeyLoaded;
uint8_t rsvd;
uint8_t key[16];
};
#pragma pack(pop)
static std::shared_ptr<SPIPortKeyMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
SPIPortKeyMessage() : Message(Type::SPIPortKeyOperation) {}
bool isKeyLoaded;
};
} // namespace icsneo
#endif // __cplusplus
#endif // __SPIPORTKEYMESSAGE_H_
@@ -47,8 +47,7 @@ struct HardwareLINPacket {
uint16_t ResponderByteFerr : 1; //Framing error in one of our responder bytes.
uint16_t TxAborted : 1;//!< This transmit was aborted.
uint16_t BreakOnly : 1;
uint16_t WakeupRequest : 1; //!< LIN wakeup pulse.
uint16_t : 1;
uint16_t : 2;
} CoreMiniBitsLIN;
uint8_t data[8];
-1
View File
@@ -126,7 +126,6 @@ enum class ChipID : icsneoc2_chip_id_t {
RADA2B_REVB_ZCHIP = icsneoc2_chip_id_rada2b_revb_zchip,
RADGigastar_FFG_ZYNQ = icsneoc2_chip_id_radgigastar_ffg_zynq,
VEM_02_FR_FCHIP = icsneoc2_chip_id_vem_02_fr_fchip,
RADBMS_WIL = icsneoc2_chip_id_radbms_wil,
Connect_ZCHIP = icsneoc2_chip_id_connect_zchip,
SFPModule_88q2221_MCHIP = icsneoc2_chip_id_sfpmodule_88q2221_mchip,
RADGALAXY2_SYSMON_CHIP = icsneoc2_chip_id_radgalaxy2_sysmon_chip,
+12 -41
View File
@@ -46,9 +46,6 @@
#include "icsneo/communication/message/extendeddatamessage.h"
#include "icsneo/communication/message/livedatamessage.h"
#include "icsneo/communication/message/tc10statusmessage.h"
#include "icsneo/communication/message/spiportkeymessage.h"
#include "icsneo/communication/message/genericapidatamessage.h"
#include "icsneo/communication/message/genericapistatusmessage.h"
#include "icsneo/core/macseccfg.h"
#include "icsneo/communication/packet/genericbinarystatuspacket.h"
#include "icsneo/communication/packet/livedatapacket.h"
@@ -63,9 +60,6 @@
#include "icsneo/communication/message/gptpstatusmessage.h"
#include "icsneo/communication/message/networkmutexmessage.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) \
static constexpr DeviceType::Enum DEVICE_TYPE = type; \
@@ -139,7 +133,6 @@ public:
RADA2B = 40,
SFPModule_88q2112 = 41,
RADGalaxy2 = 47,
RADwBMS = 48,
RADMoon3 = 49,
RADComet2 = 50,
Connect = 51,
@@ -348,7 +341,6 @@ public:
virtual Network getNetworkByNumber(Network::Type, size_t) const;
std::shared_ptr<HardwareInfo> getHardwareInfo(std::chrono::milliseconds timeout = std::chrono::milliseconds(100));
std::shared_ptr<MfgConfigMessage> getMfgConfig();
/**
@@ -733,8 +725,6 @@ public:
std::optional<EthPhyMessage> sendEthPhyMsg(const EthPhyMessage& message, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
bool sendSPIPortKeyOperation(uint8_t portIndex, SPIPortKeyMessage::Operation op, std::array<uint8_t, 16> key = {});
/**
* Set the flags of the root directory entry specified at given address
@@ -749,7 +739,6 @@ public:
*/
std::optional<bool> SetRootDirectoryEntryFlags(uint8_t mask, uint8_t values, uint32_t collectionEntryByteAddress);
device_eventhandler_t report;
std::shared_ptr<Communication> com;
std::shared_ptr<IDeviceSettings> settings;
@@ -907,19 +896,11 @@ public:
bool unlockAllNetworks();
std::shared_ptr<NetworkMutexMessage> getNetworkMutexStatus(Network::NetID network);
void startHeartbeat();
void stopHeartbeat();
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:
bool online = false;
int messagePollingCallbackID = 0;
int internalHandlerCallbackID = 0;
device_eventhandler_t report;
std::mutex ioMutex;
std::optional<bool> ethActivationStatus;
@@ -952,7 +933,7 @@ protected:
std::move(decoder)
);
setupCommunication(*com);
settings = makeSettings<Settings>(this);
settings = makeSettings<Settings>(com);
setupSettings(*settings);
diskReadDriver = std::unique_ptr<DiskRead>(new DiskRead());
diskWriteDriver = std::unique_ptr<DiskWrite>(new DiskWrite());
@@ -988,8 +969,8 @@ protected:
}
template<typename Settings>
std::shared_ptr<IDeviceSettings> makeSettings(Device* device) {
return std::make_shared<Settings>(device);
std::shared_ptr<IDeviceSettings> makeSettings(std::shared_ptr<Communication> comm) {
return std::make_shared<Settings>(comm);
}
virtual void setupSettings(IDeviceSettings&) {}
@@ -1054,6 +1035,10 @@ private:
APIEvent::Type attemptToBeginCommunication();
// Use heartbeatSuppressed instead when reading
std::atomic<int> heartbeatSuppressedByUser{0};
bool heartbeatSuppressed() const { return heartbeatSuppressedByUser > 0 || (settings && settings->applyingSettings); }
void handleNeoVIMessage(std::shared_ptr<CANMessage> message);
bool firmwareUpdateSupported();
@@ -1064,6 +1049,10 @@ private:
moodycamel::BlockingConcurrentQueue<std::shared_ptr<Message>> pollingContainer;
void enforcePollingMessageLimit();
std::atomic<bool> stopHeartbeatThread{false};
std::mutex heartbeatMutex;
std::thread heartbeatThread;
std::mutex diskMutex;
// Wireless neoVI Stack
@@ -1184,26 +1173,8 @@ private:
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)
std::unique_ptr<Periodic> keeponline;
std::unique_ptr<Heartbeat> heartbeat;
std::optional<uint32_t> assignedClientId;
std::unordered_set<icsneo::Network::NetID> lockedNetworks;
-4
View File
@@ -52,7 +52,6 @@ public:
RADEpsilon = icsneoc2_devicetype_rad_epsilon,
RADEpsilonXL = icsneoc2_devicetype_rad_epsilon_xl,
RADGalaxy2 = icsneoc2_devicetype_rad_galaxy2,
RADwBMS = icsneoc2_devicetype_rad_wbms,
RADMoon3 = icsneoc2_devicetype_rad_moon3,
RADComet2 = icsneoc2_devicetype_rad_comet2,
FIRE3_FlexRay = icsneoc2_devicetype_fire3_flexray,
@@ -217,8 +216,6 @@ public:
return "neoVI Connect";
case RADGigastar2:
return "RAD-Gigastar 2";
case RADwBMS:
return "RAD-wBMS";
case DONT_REUSE0:
case DONT_REUSE1:
case DONT_REUSE2:
@@ -271,7 +268,6 @@ private:
#define ICSNEO_DEVICETYPE_RADEPSILON ((devicetype_t)icsneoc2_devicetype_rad_epsilon)
#define ICSNEO_DEVICETYPE_RADEPSILONXL ((devicetype_t)icsneoc2_devicetype_rad_epsilon_xl)
#define ICSNEO_DEVICETYPE_RADGALAXY2 ((devicetype_t)icsneoc2_devicetype_rad_galaxy2)
#define ICSNEO_DEVICETYPE_RADWBMS ((devicetype_t)icsneoc2_devicetype_rad_wbms)
#define ICSNEO_DEVICETYPE_RADMoon3 ((devicetype_t)icsneoc2_devicetype_rad_moon3)
#define ICSNEO_DEVICETYPE_RADCOMET2 ((devicetype_t)icsneoc2_devicetype_rad_comet2)
#define ICSNEO_DEVICETYPE_FIRE3FLEXRAY ((devicetype_t)icsneoc2_devicetype_fire3_flexray)
+7 -63
View File
@@ -753,75 +753,16 @@ typedef struct
uint16_t cmp_device_id;
} CMP_GLOBAL_DATA;
/* wBMS Structs */
typedef union
{
uint8_t byte;
struct
{
uint8_t onboard_external : 1;
uint8_t type : 1;
uint8_t mode: 3;
uint8_t reserved : 3;
} config;
} sSPI_PORT_SETTING;
typedef struct
{
sSPI_PORT_SETTING port_a; //1
sSPI_PORT_SETTING port_b; //1
} sSPI_PORT_SETTINGS;
#define WBMS_GATEWAY_NETWORK_NONE (0)
#define WBMS_GATEWAY_NETWORK_DWCAN_01 (1)
#define WBMS_GATEWAY_NETWORK_DWCAN_02 (2)
#define WBMS_GATEWAY_NETWORK_UDP_MULTICAST (3)
typedef struct
{
uint8_t wbms1_network;
uint8_t wbms1_canfd_enable;
uint8_t wbms2_network;
uint8_t wbms2_canfd_enable;
uint16_t reserved[6];
} WBMSGatewaySettings;
typedef struct
{
uint8_t wBMSDeviceID;
uint8_t enabled;
} sWIL_FAULT_SERVICING_SETTINGS;
typedef struct
{
uint8_t enabled;
} sWIL_NETWORK_DATA_CAPTURE_SETTINGS;
typedef struct
{
uint8_t using_port_a;
uint8_t using_port_b;
uint8_t attemptConnect;
sWIL_FAULT_SERVICING_SETTINGS fault_servicing_config;
sWIL_NETWORK_DATA_CAPTURE_SETTINGS network_data_capture_config;
uint16_t sensor_buffer_size;
} sWIL_CONNECTION_SETTINGS;
#pragma pack(pop)
#ifdef __cplusplus
#include "icsneo/communication/network.h"
#include "icsneo/api/event.h"
#include "icsneo/api/eventmanager.h"
#include "icsneo/communication/communication.h"
#include <optional>
#include <iostream>
#include <atomic>
namespace icsneo {
class Device;
enum class MiscIOAnalogVoltage : uint8_t
{
V0 = icsneoc2_misc_io_analog_voltage_v0,
@@ -849,7 +790,7 @@ public:
static int64_t GetBaudrateValueForEnum(CANBaudrate enumValue);
static bool ValidateLINBaudrate(int64_t baudrate);
IDeviceSettings(Device* device, size_t size);
IDeviceSettings(std::shared_ptr<Communication> com, size_t size) : com(com), report(com->report), structSize(size) {}
virtual ~IDeviceSettings() {}
bool ok() const { return !disabled && settingsLoaded; }
@@ -1396,8 +1337,10 @@ public:
bool disabled = false;
bool readonly = false;
std::atomic<bool> applyingSettings{false};
protected:
Device* device;
std::shared_ptr<Communication> com;
device_eventhandler_t report;
size_t structSize;
@@ -1409,7 +1352,8 @@ protected:
// Parameter createInoperableSettings exists because it is serving as a warning that you probably don't want to do this
typedef void* warn_t;
IDeviceSettings(warn_t createInoperableSettings, Device* device);
IDeviceSettings(warn_t createInoperableSettings, std::shared_ptr<Communication> com)
: disabled(true), readonly(true), report(com->report), structSize(0) { (void)createInoperableSettings; }
// Devices that embed a Fire3LinuxSettings block in their settings structure override these to
// expose it; all other devices report not-available (nullptr / nullopt) and the Linux accessors
+1 -1
View File
@@ -12,7 +12,7 @@ namespace icsneo {
class NullSettings : public IDeviceSettings {
public:
// Calls the protected base constructor with "createInoperableSettings"
NullSettings(Device* device) : IDeviceSettings(nullptr, device) {}
NullSettings(std::shared_ptr<Communication> com) : IDeviceSettings(nullptr, com) {}
};
}
@@ -69,7 +69,7 @@ static_assert(sizeof(etherbadge_settings_t) == 316, "EtherBadge settings size mi
class EtherBADGESettings : public IDeviceSettings {
public:
EtherBADGESettings(Device* device) : IDeviceSettings(device, sizeof(etherbadge_settings_t)) {}
EtherBADGESettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(etherbadge_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<etherbadge_settings_t>();
if(cfg == nullptr)
@@ -88,7 +88,7 @@ static_assert(sizeof(neoviconnect_settings_t) == 628, "NeoVIConnect settings siz
class NeoVIConnectSettings : public IDeviceSettings {
public:
NeoVIConnectSettings(Device* device) : IDeviceSettings(device, sizeof(neoviconnect_settings_t)) {}
NeoVIConnectSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neoviconnect_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neoviconnect_settings_t>();
return cfg ? &cfg->os_settings : nullptr;
@@ -101,7 +101,7 @@ static_assert(sizeof(neovifire_settings_t) == 744, "NeoVIFire settings size mism
class NeoVIFIRESettings : public IDeviceSettings {
public:
NeoVIFIRESettings(Device* device) : IDeviceSettings(device, sizeof(neovifire_settings_t)) {}
NeoVIFIRESettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovifire_settings_t>();
if(cfg == nullptr)
@@ -125,7 +125,7 @@ static_assert(sizeof(neovifire2_settings_t) == 936, "NeoVIFire2 settings size mi
class NeoVIFIRE2Settings : public IDeviceSettings {
public:
NeoVIFIRE2Settings(Device* device) : IDeviceSettings(device, sizeof(neovifire2_settings_t)) {}
NeoVIFIRE2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire2_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovifire2_settings_t>();
if(cfg == nullptr)
@@ -166,7 +166,7 @@ static_assert(sizeof(neovifire3_settings_t) == 1722, "NeoVIFire3 settings size m
class NeoVIFIRE3Settings : public IDeviceSettings {
public:
NeoVIFIRE3Settings(Device* device) : IDeviceSettings(device, sizeof(neovifire3_settings_t)) {}
NeoVIFIRE3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neovifire3_settings_t>();
return cfg ? &cfg->os_settings : nullptr;
@@ -149,7 +149,7 @@ static_assert(sizeof(neovifire3flexray_settings_t) == 1372, "NeoVIFire3Flexray s
class NeoVIFIRE3FlexRaySettings : public IDeviceSettings {
public:
NeoVIFIRE3FlexRaySettings(Device* device) : IDeviceSettings(device, sizeof(neovifire3flexray_settings_t)) {}
NeoVIFIRE3FlexRaySettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3flexray_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neovifire3flexray_settings_t>();
return cfg ? &cfg->os_settings : nullptr;
@@ -158,7 +158,7 @@ static_assert(sizeof(neovifire3t1slin_settings_t) == 1594, "NeoVIFire3T1SLIN set
class NeoVIFIRE3T1SLINSettings : public IDeviceSettings {
public:
NeoVIFIRE3T1SLINSettings(Device* device) : IDeviceSettings(device, sizeof(neovifire3t1slin_settings_t)) {}
NeoVIFIRE3T1SLINSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3t1slin_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neovifire3t1slin_settings_t>();
return cfg ? &cfg->os_settings : nullptr;
@@ -111,7 +111,7 @@ static_assert(sizeof(neovired2_settings_t) == 918, "NeoVIRED2 settings size mism
class NeoVIRED2Settings : public IDeviceSettings {
public:
NeoVIRED2Settings(Device* device) : IDeviceSettings(device, sizeof(neovired2_settings_t)) {}
NeoVIRED2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovired2_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neovired2_settings_t>();
return cfg ? &cfg->os_settings : nullptr;
@@ -100,7 +100,7 @@ public:
Node
};
RADA2BSettings(Device* device) : IDeviceSettings(device, sizeof(rada2b_settings_t)) {}
RADA2BSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(rada2b_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<rada2b_settings_t>();
if(cfg == nullptr)
@@ -141,27 +141,27 @@ public:
}
}
TDMMode getTDMMode(RADA2BDevice a2bDevice) const {
TDMMode getTDMMode(RADA2BDevice device) const {
auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
return static_cast<TDMMode>(deviceSettings.tdmMode);
}
uint8_t getNumChannels(RADA2BDevice a2bDevice) const {
return tdmModeToChannelNum(getTDMMode(a2bDevice));
uint8_t getNumChannels(RADA2BDevice device) const {
return tdmModeToChannelNum(getTDMMode(device));
}
ChannelSize getChannelSize(RADA2BDevice a2bDevice) const {
ChannelSize getChannelSize(RADA2BDevice device) const {
auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
return static_cast<ChannelSize>(deviceSettings.flags & a2bSettingsFlag16bit);
}
uint8_t getChannelOffset(RADA2BDevice a2bDevice, A2BMessage::Direction dir) const {
uint8_t getChannelOffset(RADA2BDevice device, A2BMessage::Direction dir) const {
auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
if(dir == A2BMessage::Direction::Upstream) {
return deviceSettings.upstreamChannelOffset;
@@ -170,30 +170,30 @@ public:
return deviceSettings.downstreamChannelOffset;
}
NodeType getNodeType(RADA2BDevice a2bDevice) const {
NodeType getNodeType(RADA2BDevice device) const {
auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
return static_cast<NodeType>(deviceSettings.nodeType);
}
void setNodeType(RADA2BDevice a2bDevice, NodeType newType) {
void setNodeType(RADA2BDevice device, NodeType newType) {
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
deviceSettings.nodeType = static_cast<uint8_t>(newType);
}
void setTDMMode(RADA2BDevice a2bDevice, TDMMode newMode) {
void setTDMMode(RADA2BDevice device, TDMMode newMode) {
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
deviceSettings.tdmMode = static_cast<uint8_t>(newMode);
}
void setChannelOffset(RADA2BDevice a2bDevice, A2BMessage::Direction dir, uint8_t newOffset) {
void setChannelOffset(RADA2BDevice device, A2BMessage::Direction dir, uint8_t newOffset) {
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
if(dir == A2BMessage::Direction::Upstream) {
deviceSettings.upstreamChannelOffset = newOffset;
@@ -203,9 +203,9 @@ public:
}
}
void setChannelSize(RADA2BDevice a2bDevice, ChannelSize newChannelSize) {
void setChannelSize(RADA2BDevice device, ChannelSize newChannelSize) {
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
if(newChannelSize == ChannelSize::chSize16) {
deviceSettings.flags |= a2bSettingsFlag16bit;
@@ -89,7 +89,7 @@ static_assert(sizeof(radcomet2_settings_t) == 498, "RADComet2 settings size mism
class RADComet2Settings : public IDeviceSettings {
public:
RADComet2Settings(Device* device) : IDeviceSettings(device, sizeof(radcomet2_settings_t)) {}
RADComet2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet2_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet2_settings_t>();
if(cfg == nullptr)
@@ -118,18 +118,6 @@ public:
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet2_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN_01:
return &(cfg->lin1);
default:
return nullptr;
}
}
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
@@ -86,7 +86,7 @@ static_assert(sizeof(radcomet3_settings_t) == 674, "RADComet3 settings size mism
class RADComet3Settings : public IDeviceSettings {
public:
RADComet3Settings(Device* device) : IDeviceSettings(device, sizeof(radcomet3_settings_t)) {}
RADComet3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet3_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr)
@@ -115,18 +115,6 @@ public:
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN_01:
return &(cfg->lin1);
default:
return nullptr;
}
}
const ETHERNET_SETTINGS2* getEthernetSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr)
@@ -86,7 +86,7 @@ static_assert(sizeof(radepsilon_settings_t) == 400, "RADEpsilon settings size mi
class RADEpsilonSettings : public IDeviceSettings {
public:
RADEpsilonSettings(Device* device) : IDeviceSettings(device, sizeof(radepsilon_settings_t)) {}
RADEpsilonSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radepsilon_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radepsilon_settings_t>();
if(cfg == nullptr)
@@ -109,7 +109,7 @@ static_assert(sizeof(radgalaxy_settings_t) == 776, "RADGalaxy settings size mism
class RADGalaxySettings : public IDeviceSettings {
public:
RADGalaxySettings(Device* device) : IDeviceSettings(device, sizeof(radgalaxy_settings_t)) {}
RADGalaxySettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgalaxy_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radgalaxy_settings_t>();
if(cfg == nullptr)
@@ -125,7 +125,7 @@ static_assert(sizeof(radgalaxy2_settings_t) == 960, "RADGalaxy2 settings size mi
class RADGalaxy2Settings : public IDeviceSettings {
public:
RADGalaxy2Settings(Device* device) : IDeviceSettings(device, sizeof(radgalaxy2_settings_t)) {}
RADGalaxy2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgalaxy2_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radgalaxy2_settings_t>();
if(cfg == nullptr)
@@ -42,7 +42,7 @@ static_assert(sizeof(radgemini_settings_t) == 86, "RADGemini settings size misma
class RADGeminiSettings : public IDeviceSettings {
public:
RADGeminiSettings(Device* device) : IDeviceSettings(device, sizeof(radgemini_settings_t)) {}
RADGeminiSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgemini_settings_t)) {}
};
}
@@ -183,7 +183,6 @@ protected:
Network::NetID::LIN_01,
Network::NetID::FLEXRAY_01,
Network::NetID::FLEXRAY_01A,
Network::NetID::FLEXRAY_01B,
@@ -107,7 +107,7 @@ static_assert(sizeof(radgigastar_settings_t) == 1026, "RADGigastar settings size
class RADGigastarSettings : public IDeviceSettings {
public:
RADGigastarSettings(Device* device) : IDeviceSettings(device, sizeof(radgigastar_settings_t)) {}
RADGigastarSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgigastar_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radgigastar_settings_t>();
if(cfg == nullptr)
@@ -156,7 +156,7 @@ namespace icsneo
class RADGigastar2Settings : public IDeviceSettings
{
public:
RADGigastar2Settings(Device* device) : IDeviceSettings(device, sizeof(radgigastar2_settings_t)) {}
RADGigastar2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgigastar2_settings_t)) {}
const CAN_SETTINGS *getCANSettingsFor(Network net) const override
{
auto cfg = getStructurePointer<radgigastar2_settings_t>();
@@ -90,7 +90,7 @@ static_assert(sizeof(radjupiter_settings_t) == 348, "RAD-Jupiter Settings are no
class RADJupiterSettings : public IDeviceSettings {
public:
RADJupiterSettings(Device* device) : IDeviceSettings(device, sizeof(radjupiter_settings_t)) {}
RADJupiterSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radjupiter_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radjupiter_settings_t>();
@@ -101,7 +101,7 @@ static_assert(sizeof(radmars_settings_t) == 666, "RAD-Mars settings size mismatc
class RADMarsSettings : public IDeviceSettings {
public:
RADMarsSettings(Device* device) : IDeviceSettings(device, sizeof(radmars_settings_t)) {}
RADMarsSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmars_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radmars_settings_t>();
if(cfg == nullptr)
@@ -42,7 +42,7 @@ static_assert(sizeof(radmoon2_settings_t) == 170, "RADMoon2 settings size mismat
class RADMoon2Settings : public IDeviceSettings {
public:
RADMoon2Settings(Device* device) : IDeviceSettings(device, sizeof(radmoon2_settings_t)) {}
RADMoon2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon2_settings_t)) {}
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
auto cfg = getStructurePointer<radmoon2_settings_t>();
@@ -39,7 +39,7 @@ static_assert(sizeof(radmoon3_settings_t) == 68, "RADMoon3 settings size mismatc
class RADMoon3Settings : public IDeviceSettings {
public:
RADMoon3Settings(Device* device) : IDeviceSettings(device, sizeof(radmoon3_settings_t)) {}
RADMoon3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon3_settings_t)) {}
};
}
@@ -55,7 +55,7 @@ static_assert(sizeof(radmoonduo_settings_t) == 38, "RAD-Moon Duo settings size e
class RADMoonDuoSettings : public IDeviceSettings {
public:
RADMoonDuoSettings(Device* device) : IDeviceSettings(device, sizeof(radmoonduo_settings_t)) {}
RADMoonDuoSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoonduo_settings_t)) {}
};
}
@@ -46,7 +46,7 @@ static_assert(sizeof(radmoont1s_settings_t) == 160, "RADMoonT1S settings size mi
class RADMoonT1SSettings : public IDeviceSettings {
public:
RADMoonT1SSettings(Device* device) : IDeviceSettings(device, sizeof(radmoont1s_settings_t)) {}
RADMoonT1SSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoont1s_settings_t)) {}
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
@@ -74,7 +74,7 @@ static_assert(sizeof(radpluto_settings_t) == 322, "RAD-Pluto Settings are not pa
class RADPlutoSettings : public IDeviceSettings {
public:
RADPlutoSettings(Device* device) : IDeviceSettings(device, sizeof(radpluto_settings_t)) {
RADPlutoSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radpluto_settings_t)) {
}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
@@ -75,7 +75,7 @@ static_assert(sizeof(radstar2_settings_t) == 422, "RADStar2 settings size mismat
class RADStar2Settings : public IDeviceSettings {
public:
RADStar2Settings(Device* device) : IDeviceSettings(device, sizeof(radstar2_settings_t)) {
RADStar2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radstar2_settings_t)) {
}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
@@ -38,7 +38,7 @@ typedef struct {
class RADSupermoonSettings : public IDeviceSettings {
public:
RADSupermoonSettings(Device* device) : IDeviceSettings(device, sizeof(radsupermoon_settings_t)) {}
RADSupermoonSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radsupermoon_settings_t)) {}
};
}
@@ -1,182 +0,0 @@
#ifndef __RADWBMS_H_
#define __RADWBMS_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radwbms/radwbmssettings.h"
#include "icsneo/disk/neomemorydiskdriver.h"
namespace icsneo {
class RADwBMS : public Device {
public:
enum class FirmwareVariant {
Invalid = 0,
WIL_1_1 = 0x0101000C,
WIL_2_0 = 0x02000058,
WIL_2_0_9_26 = 0x0200091A,
WIL_2_1 = 0x02010047,
WIL_2_2 = 0x0202000F,
WIL_2_3 = 0x0203020B,
WIL_3_1_0_9 = 0x03010009,
WIL_3_2_0 = 0x03020000,
WIL_3_3_0_27 = 0x0303001B,
};
// Serial numbers start with BS
// USB PID is 0x110B, standard driver is CDACM
// Ethernet MAC allocation is 0x1B, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADwBMS, DeviceType::RADwBMS, "BS");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::DWCAN_01,
Network::NetID::DWCAN_02,
Network::NetID::ETHERNET_01,
};
return supportedNetworks;
}
size_t getEthernetActivationLineCount() const override { return 1; }
bool supportsReboot() const override { return true; }
ProductID getProductID() const override {
return ProductID::RADwBMS;
}
FirmwareVariant variantToFlash = FirmwareVariant::Invalid;
void setVariantToFlash(FirmwareVariant variant) {
variantToFlash = variant;
}
FirmwareVariant getCurrentVariant() {
if(supportsComponentVersions()) {
refreshComponentVersions();
const auto& components = getComponentVersions();
for(const auto& component : components) {
if(!component.valid) {
continue;
}
if(component.identifier == static_cast<uint32_t>(ChipID::RADBMS_WIL)) {
FirmwareVariant res = FirmwareVariant::Invalid;
switch(static_cast<FirmwareVariant>(component.dotVersion)) {
case FirmwareVariant::WIL_1_1:
case FirmwareVariant::WIL_2_0:
case FirmwareVariant::WIL_2_0_9_26:
case FirmwareVariant::WIL_2_1:
case FirmwareVariant::WIL_2_2:
case FirmwareVariant::WIL_2_3:
case FirmwareVariant::WIL_3_1_0_9:
case FirmwareVariant::WIL_3_2_0:
case FirmwareVariant::WIL_3_3_0_27:
res = static_cast<FirmwareVariant>(component.dotVersion);
break;
default:
res = FirmwareVariant::Invalid;
break;
}
if(variantToFlash == FirmwareVariant::Invalid) {
// Set the variantToFlash if it hasn't been set yet, we always flash the same firmware variant as the current if it is unspecified
variantToFlash = res;
}
return res;
}
}
}
return FirmwareVariant::Invalid;
}
const std::vector<ChipInfo>& getChipInfo() const override {
switch (variantToFlash) {
case FirmwareVariant::WIL_1_1: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_1_1_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_0: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_0_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_0_9_26: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_0_9_26_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_1: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_1_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_2: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_2_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_3: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_3_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_3_1_0_9: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_3_1_0_9_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_3_2_0: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_3_2_0_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_3_3_0_27: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_3_3_0_27_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::Invalid:
break; // invalid will be handled below
}
// Return empty chip information if the WIL version is not set
static std::vector<ChipInfo> chips = {};
return chips;
}
BootloaderPipeline getBootloader() override {
return BootloaderPipeline()
.add<EnterBootloaderPhase>()
.add<FlashPhase>(ChipID::RADBMS_MCHIP, BootloaderCommunication::RED)
.add<EnterApplicationPhase>(ChipID::RADBMS_MCHIP)
.add<WaitPhase>(std::chrono::milliseconds(3000))
.add<ReconnectPhase>();
}
std::vector<VersionReport> getChipVersions(bool refreshComponents = true) override {
if(variantToFlash == FirmwareVariant::Invalid) {
getCurrentVariant();
}
return Device::getChipVersions(refreshComponents);
}
protected:
RADwBMS(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADwBMSSettings, Disk::NeoMemoryDiskDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
}
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
std::optional<MemoryAddress> getCoreminiStartAddressFlash() const override {
return 2048 * 512;
}
std::optional<MemoryAddress> getCoreminiStartAddressSD() const override {
return 0;
}
bool supportsEraseMemory() const override {
return true;
}
};
}; // namespace icsneo
#endif // __RADWBMS_H_
@@ -1,80 +0,0 @@
#ifndef __RADWBMSSETTINGS_H_
#define __RADWBMSSETTINGS_H_
#include <stdint.h>
#include "icsneo/device/idevicesettings.h"
#ifdef __cplusplus
namespace icsneo {
#endif // __cplusplus
#pragma pack(push, 2)
typedef struct
{
uint16_t perf_en;
uint64_t termination_enables;
CAN_SETTINGS can1;
CANFD_SETTINGS canfd1;
CAN_SETTINGS can2;
CANFD_SETTINGS canfd2;
uint16_t network_enables;
uint16_t network_enables_2;
uint16_t network_enables_3;
int16_t iso15765_separation_time_offset;
struct
{
uint32_t disableUsbCheckOnBoot : 1;
uint32_t enableLatencyTest : 1;
uint32_t enablePcEthernetComm : 1;
uint32_t reserved : 29;
} flags;
ETHERNET_SETTINGS ethernet;
ETHERNET_SETTINGS2 ethernet2;
uint32_t pwr_man_timeout;
uint16_t pwr_man_enable;
uint16_t network_enabled_on_boot;
uint8_t rsvd[10]; //Was sWILBridgeConfig
sSPI_PORT_SETTINGS spi_config;
sWIL_CONNECTION_SETTINGS wbms_wil_1;
sWIL_CONNECTION_SETTINGS wbms_wil_2;
uint16_t wil1_nwk_metadata_buff_count;
uint16_t wil2_nwk_metadata_buff_count;
WBMSGatewaySettings gateway;
uint16_t network_enables_4;
uint64_t network_enables_5;
} radwbms_settings_t;
#pragma pack(pop)
#ifdef __cplusplus
static_assert(sizeof(radwbms_settings_t) == 156, "RAD-wBMS settings size mismatch");
#include <iostream>
class RADwBMSSettings : public IDeviceSettings {
public:
RADwBMSSettings(Device* device) : IDeviceSettings(device, sizeof(radwbms_settings_t)) {}
};
}
#endif // __cplusplus
#endif // __RADWBMSSETTINGS_H_
@@ -37,7 +37,7 @@ static_assert(sizeof(valuecan3_settings_t) == 40, "ValueCAN3 settings size misma
class ValueCAN3Settings : public IDeviceSettings {
public:
ValueCAN3Settings(Device* device) : IDeviceSettings(device, sizeof(valuecan3_settings_t)) {}
ValueCAN3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan3_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan3_settings_t>();
if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4_1_2Settings : public IDeviceSettings {
public:
ValueCAN4_1_2Settings(Device* device) : IDeviceSettings(device, sizeof(valuecan4_1_2_settings_t)) {}
ValueCAN4_1_2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_1_2_settings_t)) {}
// We do not override getCANSettingsFor or getCANFDSettingsFor here because they will be device specific
};
@@ -9,7 +9,7 @@ namespace icsneo {
class ValueCAN4_1Settings : public ValueCAN4_1_2Settings {
public:
ValueCAN4_1Settings(Device* device) : ValueCAN4_1_2Settings(device) {}
ValueCAN4_1Settings(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_1_2_settings_t>();
if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4_2ELSettings : public ValueCAN4_4_2ELSettings {
public:
ValueCAN4_2ELSettings(Device* device) : ValueCAN4_4_2ELSettings(device) {}
ValueCAN4_2ELSettings(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
if(cfg == nullptr)
@@ -9,7 +9,7 @@ namespace icsneo {
class ValueCAN4_2Settings : public ValueCAN4_1_2Settings {
public:
ValueCAN4_2Settings(Device* device) : ValueCAN4_1_2Settings(device) {}
ValueCAN4_2Settings(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_1_2_settings_t>();
if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4_4_2ELSettings : public IDeviceSettings {
public:
ValueCAN4_4_2ELSettings(Device* device) : IDeviceSettings(device, sizeof(valuecan4_4_2el_settings_t)) {}
ValueCAN4_4_2ELSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_4_2el_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4_4Settings : public ValueCAN4_4_2ELSettings {
public:
ValueCAN4_4Settings(Device* device) : ValueCAN4_4_2ELSettings(device) {}
ValueCAN4_4Settings(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4IndustrialSettings : public IDeviceSettings {
public:
ValueCAN4IndustrialSettings(Device* device) : IDeviceSettings(device, sizeof(valuecan4_industrial_settings_t)) {}
ValueCAN4IndustrialSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_industrial_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_industrial_settings_t>();
if(cfg == nullptr)
@@ -48,7 +48,7 @@ static_assert(sizeof(vividcan_settings_t) == 64, "VividCAN settings size mismatc
class VividCANSettings : public IDeviceSettings {
public:
VividCANSettings(Device* device) : IDeviceSettings(device, sizeof(vividcan_settings_t)) {}
VividCANSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(vividcan_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<vividcan_settings_t>();
if(cfg == nullptr)
+1 -8
View File
@@ -44,10 +44,7 @@ typedef unsigned __int64 uint64_t;
#include "cicsSpyStatusBits.h"
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4200) // zero-sized array in struct/union
#pragma warning(disable : 4201) // nameless struct/union
#pragma warning(disable : 4121) // member alignment sensitive to packing
#pragma warning(disable : 4200)
#endif
// MSVC++ 10.0 _MSC_VER == 1600 64-bit version doesn't allow multi-line #if directives...
@@ -5443,8 +5440,4 @@ CHECK_STRUCT_SIZE(FlashAccessoryFirmwareParams);
#undef CHECK_STRUCT_SIZE
#endif /* INTREPID_NO_CHECK_STRUCT_SIZE */
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif /* _ICSNVC40_H */
+1 -2
View File
@@ -372,11 +372,10 @@ icsneoc2_error_t icsneoc2_device_mac_addresses_enumerate(const icsneoc2_device_t
*
* @param[in] mac_address The MAC address object to get the network ID of.
* @param[out] network_id Pointer to an icsneoc2_netid_t to copy the network ID into.
* Unrecognized values are normalized to icsneoc2_netid_invalid.
*
* @return icsneoc2_error_t icsneoc2_error success if successful, icsneoc2_error_invalid_parameters on failure.
*/
icsneoc2_error_t icsneoc2_mac_network_id_get(const icsneoc2_mac_addr_entry_t* mac_address, icsneoc2_netid_t* network_id);
icsneoc2_error_t icsneoc2_mac_network_id_get(const icsneoc2_mac_addr_entry_t* mac_address, _icsneoc2_netid_t* network_id);
/**
* Get the MAC Address bytes of a MAC address.
-2
View File
@@ -381,7 +381,6 @@ typedef enum _icsneoc2_lin_msg_type_t {
icsneoc2_lin_msg_type_sync_only = 4,
icsneoc2_lin_msg_type_update_responder = 5,
icsneoc2_lin_msg_type_error = 6,
icsneoc2_lin_msg_type_wakeup_request = 7,
} _icsneoc2_lin_msg_type_t;
typedef uint8_t icsneoc2_lin_msg_type_t;
@@ -410,7 +409,6 @@ typedef uint32_t icsneoc2_lin_err_flags_t;
#define ICSNEOC2_LIN_STATUS_HAS_UPDATED_RESPONDER_ONCE 0x20
#define ICSNEOC2_LIN_STATUS_BUS_RECOVERED 0x40
#define ICSNEOC2_LIN_STATUS_BREAK_ONLY 0x80
#define ICSNEOC2_LIN_STATUS_WAKEUP_REQUEST 0x100
typedef uint32_t icsneoc2_lin_status_flags_t;
-2
View File
@@ -42,7 +42,6 @@ typedef enum _icsneoc2_devicetype_t {
icsneoc2_devicetype_rad_epsilon = 0x00000018,
icsneoc2_devicetype_rad_epsilon_xl = 0x0000001e,
icsneoc2_devicetype_rad_galaxy2 = 0x00000021,
icsneoc2_devicetype_rad_wbms = 0x00000022,
icsneoc2_devicetype_rad_moon3 = 0x00000023,
icsneoc2_devicetype_rad_comet2 = 0x00000024,
icsneoc2_devicetype_fire3_flexray = 0x00000025,
@@ -666,7 +665,6 @@ typedef enum _icsneoc2_chip_id_t {
icsneoc2_chip_id_rada2b_revb_zchip = 116,
icsneoc2_chip_id_radgigastar_ffg_zynq = 117,
icsneoc2_chip_id_vem_02_fr_fchip = 118,
icsneoc2_chip_id_radbms_wil = 119,
icsneoc2_chip_id_connect_zchip = 121,
icsneoc2_chip_id_sfpmodule_88q2221_mchip = 122,
icsneoc2_chip_id_radgalaxy2_sysmon_chip = 123,
-1
View File
@@ -33,7 +33,6 @@
#include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2.h"
#include "icsneo/device/tree/radsupermoon/radsupermoon.h"
#include "icsneo/device/tree/radwbms/radwbms.h"
#include "icsneo/device/tree/valuecan3/valuecan3.h"
#include "icsneo/device/tree/valuecan4/valuecan4-1.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2.h"
@@ -33,7 +33,6 @@
#include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2.h"
#include "icsneo/device/tree/radsupermoon/radsupermoon.h"
#include "icsneo/device/tree/radwbms/radwbms.h"
#include "icsneo/device/tree/valuecan3/valuecan3.h"
#include "icsneo/device/tree/valuecan4/valuecan4-1.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2.h"
+4 -3
View File
@@ -86,7 +86,7 @@ void CDCACM::Find(std::vector<FoundDevice>& found) {
if(ref == nullptr)
return;
io_iterator_t matchingServices = 0;
kern_return_t kernResult = IOServiceGetMatchingServices(kIOMainPortDefault, ref, &matchingServices);
kern_return_t kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, ref, &matchingServices);
if(KERN_SUCCESS != kernResult || matchingServices == 0)
return;
IOReleaser matchingServicesReleaser(matchingServices);
@@ -108,8 +108,9 @@ void CDCACM::Find(std::vector<FoundDevice>& found) {
releasers.emplace_back(parent);
current = parent;
// On old macOSes, IOUSBDevice is the type of the class we want
// On newer macOSes, IOUSBDevice may further be subclassed as IOUSBHostDevice
if(IOObjectConformsTo(parent, kIOUSBDeviceClassName)) {
// On macOS 12+, IOUSBHostDevice is the main USB device class (separate hierarchy from IOUSBDevice)
if(IOObjectConformsTo(parent, kIOUSBDeviceClassName) ||
IOObjectConformsTo(parent, "IOUSBHostDevice")) {
usb = parent;
break;
}
+1 -5
View File
@@ -243,7 +243,6 @@ bool Servd::enableCommunication(bool enable, bool& sendMsg) {
}
void Servd::read() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
std::vector<uint8_t> buf(2 * 1024 * 1024);
while(!isDisconnected() && !isClosing()) {
bool hasData;
@@ -261,14 +260,11 @@ void Servd::read() {
setIsDisconnected(true);
return;
}
if(!pushRx(buf.data(), bufSize)) {
EventManager::GetInstance().add(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
}
pushRx(buf.data(), bufSize);
}
}
void Servd::write() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
WriteOperation writeOp;
while(!isDisconnected() && !isClosing()) {
if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100))) {
-50
View File
@@ -127,28 +127,6 @@ TEST(icsneoc2, test_icsneoc2_device_is_valid)
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_is_valid(NULL));
}
TEST(icsneoc2, test_icsneoc2_mac_address_get_query_length)
{
icsneoc2_mac_addr_entry_t mac_address = {};
size_t value_length = 0;
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_address_get(&mac_address, NULL, &value_length));
ASSERT_EQ(ICSNEO_MAC_ADDRESS_LEN, value_length);
}
TEST(icsneoc2, test_icsneoc2_mac_address_get_truncated_length)
{
icsneoc2_mac_addr_entry_t mac_address = {};
const uint8_t expected[ICSNEO_MAC_ADDRESS_LEN] = {0x00, 0xFC, 0x70, 0x1E, 0x18, 0x70};
std::copy(std::begin(expected), std::end(expected), mac_address.address);
uint8_t value[3] = {};
size_t value_length = sizeof(value);
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_address_get(&mac_address, value, &value_length));
ASSERT_EQ(sizeof(value), value_length);
ASSERT_EQ(0, memcmp(expected, value, sizeof(value)));
}
TEST(icsneoc2, test_icsneoc2_error_invalid_parameters_and_invalid_device)
{
bool placeholderBool = false;
@@ -1862,7 +1840,6 @@ TEST(icsneoc2, test_lin_msg_type_enum_values)
ASSERT_EQ(icsneoc2_lin_msg_type_sync_only, 4);
ASSERT_EQ(icsneoc2_lin_msg_type_update_responder, 5);
ASSERT_EQ(icsneoc2_lin_msg_type_error, 6);
ASSERT_EQ(icsneoc2_lin_msg_type_wakeup_request, 7);
ASSERT_EQ(sizeof(icsneoc2_lin_msg_type_t), sizeof(uint8_t));
}
@@ -1876,7 +1853,6 @@ TEST(icsneoc2, test_lin_msg_type_cpp_enum_sync)
ASSERT_EQ(static_cast<uint8_t>(T::LIN_SYNC_ONLY), icsneoc2_lin_msg_type_sync_only);
ASSERT_EQ(static_cast<uint8_t>(T::LIN_UPDATE_RESPONDER), icsneoc2_lin_msg_type_update_responder);
ASSERT_EQ(static_cast<uint8_t>(T::LIN_ERROR), icsneoc2_lin_msg_type_error);
ASSERT_EQ(static_cast<uint8_t>(T::LIN_WAKEUP_REQUEST), icsneoc2_lin_msg_type_wakeup_request);
}
TEST(icsneoc2, test_lin_flag_bitmask_values)
@@ -1903,7 +1879,6 @@ TEST(icsneoc2, test_lin_flag_bitmask_values)
ASSERT_EQ(ICSNEOC2_LIN_STATUS_HAS_UPDATED_RESPONDER_ONCE, 0x20);
ASSERT_EQ(ICSNEOC2_LIN_STATUS_BUS_RECOVERED, 0x40);
ASSERT_EQ(ICSNEOC2_LIN_STATUS_BREAK_ONLY, 0x80);
ASSERT_EQ(ICSNEOC2_LIN_STATUS_WAKEUP_REQUEST, 0x100);
}
TEST(icsneoc2, test_icsneoc2_eth_create)
@@ -2156,28 +2131,3 @@ TEST(icsneoc2, test_gptp_enum_alignment)
ASSERT_EQ(sizeof(RADGPTPRole), sizeof(icsneoc2_gptp_role_t));
}
TEST(icsneoc2, test_mac_network_id_get)
{
icsneoc2_mac_addr_entry_t entry {};
icsneoc2_netid_t network_id = 0;
entry.network_id = icsneoc2_netid_ethernet_01;
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_network_id_get(&entry, &network_id));
ASSERT_EQ(icsneoc2_netid_ethernet_01, network_id);
entry.network_id = 43;
network_id = 0;
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_network_id_get(&entry, &network_id));
ASSERT_EQ(icsneoc2_netid_invalid, network_id);
entry.network_id = icsneoc2_netid_invalid;
network_id = 0;
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_network_id_get(&entry, &network_id));
ASSERT_EQ(icsneoc2_netid_invalid, network_id);
ASSERT_EQ(icsneoc2_error_invalid_parameters,
icsneoc2_mac_network_id_get(nullptr, &network_id));
ASSERT_EQ(icsneoc2_error_invalid_parameters,
icsneoc2_mac_network_id_get(&entry, nullptr));
}
+1 -78
View File
@@ -2,14 +2,12 @@
#include "icsneo/communication/encoder.h"
#include "icsneo/communication/packet/linpacket.h"
#include "icsneo/communication/message/linmessage.h"
#include "icsneo/communication/message/transmitmessage.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/core/ringbuffer.h"
#include "icsneo/api/eventmanager.h"
#include "gtest/gtest.h"
#include <vector>
#include <iostream>
#include <cstring>
using namespace icsneo;
@@ -57,16 +55,6 @@ protected:
0x00, 0x00,
0xE2, 0x41};
// Break-only LIN 1: commander (0x80) | break-only (0x20) | len 3 => 0xa3
// ID 0x00 pID 0x80
std::vector<uint8_t> testControllerBreakOnly =
{0xaa, 0x0c,
0x0d, 0x00,
0x10, 0x00,
0x00, 0xa3,
0x00, 0x00,
0x80, 0x41};
std::vector<uint8_t> recvBytes =
{0xaa, 0x0c, 0x22, 0x00,
0x10, 0x00, 0x88, 0x03,
@@ -151,29 +139,6 @@ TEST_F(LINEncoderDecoderTest, PacketEncoderControllerHeaderTest) {
EXPECT_EQ(bytestream, testControllerHeaderOnly);
}
TEST_F(LINEncoderDecoderTest, PacketEncoderControllerBreakOnlyTest) {
std::vector<uint8_t> bytestream;
auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x00u));
message->network = icsneo::Network::NetID::LIN_01;
message->linMsgType = icsneo::LINMessage::Type::LIN_BREAK_ONLY;
message->isEnhancedChecksum = false;
packetEncoder->encode(*packetizer, bytestream, message);
EXPECT_EQ(bytestream, testControllerBreakOnly);
}
TEST_F(LINEncoderDecoderTest, TransmitMessageBreakOnlySetsCommander) {
auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x00u));
message->network = icsneo::Network::NetID::LIN_01;
message->linMsgType = icsneo::LINMessage::Type::LIN_BREAK_ONLY;
auto bytes = TransmitMessage::EncodeFromMessage(message, 1, report);
ASSERT_FALSE(bytes.empty());
ASSERT_GE(bytes.size(), sizeof(TransmitMessage));
auto* tx = reinterpret_cast<TransmitMessage*>(bytes.data());
auto* lin = reinterpret_cast<HardwareLINPacket*>(tx->commonHeader);
EXPECT_EQ(lin->CoreMiniBitsLIN.TXCommander, 1);
EXPECT_EQ(lin->CoreMiniBitsLIN.BreakOnly, 1);
}
TEST_F(LINEncoderDecoderTest, PacketEncoderControllerWithDataTest) {
std::vector<uint8_t> bytestream;
auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x11u));
@@ -227,46 +192,4 @@ TEST_F(LINEncoderDecoderTest, PacketDecoderTest) {
EXPECT_EQ(msg2->isEnhancedChecksum, testMessage2->isEnhancedChecksum);
EXPECT_EQ(msg2->data, testMessage2->data);
EXPECT_EQ(msg2->checksum, testMessage2->checksum);
}
static std::shared_ptr<LINMessage> decodeLinPacket(const HardwareLINPacket& pkt) {
std::vector<uint8_t> bytes(sizeof(pkt));
std::memcpy(bytes.data(), &pkt, sizeof(pkt));
return std::dynamic_pointer_cast<LINMessage>(HardwareLINPacket::DecodeToMessage(bytes));
}
TEST_F(LINEncoderDecoderTest, WakeupPulseDecodeTest) {
HardwareLINPacket pkt{};
pkt.CoreMiniBitsLIN.WakeupRequest = 1;
auto msg = decodeLinPacket(pkt);
ASSERT_NE(msg, nullptr);
EXPECT_EQ(msg->linMsgType, LINMessage::Type::LIN_WAKEUP_REQUEST);
EXPECT_TRUE(msg->statusFlags.WakeupRequest);
}
TEST_F(LINEncoderDecoderTest, WakeupFlagOnUartBreakStaysError) {
HardwareLINPacket pkt{};
pkt.CoreMiniBitsLIN.WakeupRequest = 1;
pkt.CoreMiniBitsLIN.ErrRxOnlyBreak = 1;
auto msg = decodeLinPacket(pkt);
ASSERT_NE(msg, nullptr);
EXPECT_EQ(msg->linMsgType, LINMessage::Type::LIN_ERROR);
EXPECT_TRUE(msg->statusFlags.WakeupRequest);
EXPECT_TRUE(msg->errFlags.ErrRxBreakOnly);
}
TEST_F(LINEncoderDecoderTest, WakeupFlagOnCompleteFrameKeepsCommander) {
HardwareLINPacket pkt{};
pkt.CoreMiniBitsLIN.WakeupRequest = 1;
pkt.CoreMiniBitsLIN.TXCommander = 1;
pkt.CoreMiniBitsLIN.ID = 0x10;
pkt.CoreMiniBitsLIN.len = 3; // two responder bytes plus the checksum
pkt.data[0] = 0xaa;
pkt.data[1] = 0xbb;
pkt.data[2] = 0x99; // classic checksum, otherwise the frame decodes as LIN_ERROR
auto msg = decodeLinPacket(pkt);
ASSERT_NE(msg, nullptr);
EXPECT_EQ(msg->linMsgType, LINMessage::Type::LIN_COMMANDER_MSG);
EXPECT_TRUE(msg->statusFlags.WakeupRequest);
EXPECT_EQ(msg->ID, 0x10);
}
}