mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-09-20 07:58:39 +02:00
Compare commits
16
Commits
7a5c8c2879
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb892bfd9b | ||
|
|
8801e949da | ||
|
|
d95a17b360 | ||
|
|
3a6501d116 | ||
|
|
34875129ee | ||
|
|
236c6ad089 | ||
|
|
cf58f819cb | ||
|
|
07e4eca14a | ||
|
|
936566170f | ||
|
|
3aaacb6cc8 | ||
|
|
1dda9f5412 | ||
|
|
78c2e3ff89 | ||
|
|
afedd4bb1f | ||
|
|
9b01e488da | ||
|
|
77a886bbe0 | ||
|
|
aff547b738 |
+5
-24
@@ -1,3 +1,6 @@
|
||||
default:
|
||||
interruptible: true
|
||||
|
||||
variables:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
LIBICSNEO_ICSPB_REPO: https://gitlab-ci-token:${CI_JOB_TOKEN}@${LIBICSNEO_ICSPB_GIT}
|
||||
@@ -35,30 +38,6 @@ 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
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -359,6 +338,7 @@ build python/windows:
|
||||
|
||||
deploy python/pypi:
|
||||
stage: deploy
|
||||
interruptible: false
|
||||
variables:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: $PYPI_TOKEN
|
||||
@@ -383,6 +363,7 @@ deploy python/pypi:
|
||||
|
||||
push github:
|
||||
stage: deploy
|
||||
interruptible: false
|
||||
tags:
|
||||
- linux-build
|
||||
image: alpine:latest
|
||||
|
||||
+9
-1
@@ -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-switch -Wno-unknown-pragmas)
|
||||
set(LIBICSNEO_COMPILER_WARNINGS -Wall -Wno-unknown-pragmas)
|
||||
endif()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
@@ -234,7 +234,14 @@ 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
|
||||
@@ -345,6 +352,7 @@ 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}
|
||||
)
|
||||
|
||||
+20
-11
@@ -5,6 +5,7 @@
|
||||
#include "icsneo/device/devicefinder.h"
|
||||
#include "icsneo/icsneocpp.h"
|
||||
#include "icsneo/communication/io.h"
|
||||
#include "icsneo/communication/network.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -465,11 +466,13 @@ icsneoc2_error_t icsneoc2_device_pcb_serial_get(const icsneoc2_device_t* device,
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
const auto& data = *pcbSerial;
|
||||
if(value) {
|
||||
size_t copyLen = std::min(*value_length, data.size());
|
||||
std::copy(data.begin(), data.begin() + copyLen, value);
|
||||
if(!value) {
|
||||
*value_length = data.size();
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
*value_length = data.size();
|
||||
size_t copyLen = std::min(*value_length, data.size());
|
||||
std::copy(data.begin(), data.begin() + copyLen, value);
|
||||
*value_length = copyLen;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
@@ -503,26 +506,32 @@ 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;
|
||||
}
|
||||
*network_id = static_cast<_icsneoc2_netid_t>(mac_address->network_id);
|
||||
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);
|
||||
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 || !value_length) {
|
||||
if(!mac_address || !value_length) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
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);
|
||||
if(!value) {
|
||||
*value_length = static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN);
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
*value_length = static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN);
|
||||
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;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
|
||||
@@ -471,6 +471,7 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -462,6 +462,8 @@ const char* APIEvent::DescriptionForType(Type type) {
|
||||
return TOO_MANY_EVENTS;
|
||||
case Type::Unknown:
|
||||
return UNKNOWN;
|
||||
case Type::Any:
|
||||
break;
|
||||
}
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -545,15 +545,13 @@ int LegacyDLLExport icsneoGetTimeStampForMsg(void* hObject, icsSpyMessage* pMsg,
|
||||
void LegacyDLLExport icsneoGetISO15765Status(void* hObject, int lNetwork, int lClearTxStatus, int lClearRxStatus,
|
||||
int* lTxStatus, int* lRxStatus)
|
||||
{
|
||||
// TODO Implement
|
||||
return;
|
||||
// Not supported
|
||||
}
|
||||
|
||||
void LegacyDLLExport icsneoSetISO15765RxParameters(void* hObject, int lNetwork, int lEnable, spyFilterLong* pFF_CFMsgFilter,
|
||||
icsSpyMessage* pTxMsg, int lCFTimeOutMs, int lFlowCBlockSize, int lUsesExtendedAddressing, int lUseHardwareIfPresent)
|
||||
{
|
||||
// TODO Implement
|
||||
return;
|
||||
// Not supported
|
||||
}
|
||||
|
||||
int LegacyDLLExport icsneoGetRTC(void* hObject, icsSpyTime* time)
|
||||
@@ -835,26 +833,25 @@ int LegacyDLLExport icsneoGetErrorInfo(int lErrorNumber, char* szErrorDescriptio
|
||||
//ISO15765-2 Functions
|
||||
int LegacyDLLExport icsneoISO15765_EnableNetworks(void* hObject, unsigned long ulNetworks)
|
||||
{
|
||||
// TODO Implement
|
||||
// Not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
int LegacyDLLExport icsneoISO15765_DisableNetworks(void* hObject)
|
||||
{
|
||||
// TODO Implement
|
||||
// Not supported
|
||||
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)
|
||||
{
|
||||
// TODO Implement
|
||||
// Not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
int LegacyDLLExport icsneoISO15765_ReceiveMessage(void* hObject, int ulNetworkID, stCM_ISO157652_RxMessage* pMsg)
|
||||
{
|
||||
// TODO Implement
|
||||
// Not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1285,10 +1282,11 @@ 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 (*CmdBuf)
|
||||
switch (cmd)
|
||||
{
|
||||
case J2534NVCMD_SetNetworkBaudRate:
|
||||
case icsneo::J2534Command::SetNetworkBaudRate:
|
||||
|
||||
pTmp = (uint64_t *)&CmdBuf[1];
|
||||
NetworkID = (uint16_t)*pTmp;
|
||||
@@ -1298,7 +1296,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
||||
iRetVal = 0;
|
||||
break;
|
||||
|
||||
case J2534NVCMD_GetNetworkBaudRate:
|
||||
case icsneo::J2534Command::GetNetworkBaudRate:
|
||||
{
|
||||
pTmp = (uint64_t *)&CmdBuf[1];
|
||||
NetworkID = (uint16_t)*pTmp;
|
||||
@@ -1311,7 +1309,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
||||
*pTmp = static_cast<uint64_t>(ret);
|
||||
break;
|
||||
}
|
||||
case J2534NVCMD_SetCANFDRate:
|
||||
case icsneo::J2534Command::SetCANFDRate:
|
||||
|
||||
pTmp = (uint64_t *)&CmdBuf[1];
|
||||
NetworkID = (uint16_t)*pTmp;
|
||||
@@ -1322,7 +1320,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
||||
iRetVal = 0;
|
||||
break;
|
||||
|
||||
case J2534NVCMD_GetCANFDRate:
|
||||
case icsneo::J2534Command::GetCANFDRate:
|
||||
|
||||
pTmp = (uint64_t *)&CmdBuf[1];
|
||||
NetworkID = (uint16_t)*pTmp;
|
||||
@@ -1332,7 +1330,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
||||
*pTmp = icsneo_getFDBaudrate(device, NetworkID);
|
||||
break;
|
||||
|
||||
case J2534NVCMD_GetCANFDTermination:
|
||||
case icsneo::J2534Command::GetCANFDTermination:
|
||||
|
||||
pTmp = (uint64_t *)&CmdBuf[1];
|
||||
NetworkID = (uint16_t)*pTmp;
|
||||
@@ -1368,7 +1366,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
|
||||
}
|
||||
break;
|
||||
|
||||
case J2534NVCMD_SetCANFDTermination:
|
||||
case icsneo::J2534Command::SetCANFDTermination:
|
||||
|
||||
pTmp = (uint64_t *)&CmdBuf[1];
|
||||
NetworkID = (uint16_t)*pTmp;
|
||||
@@ -1422,11 +1420,9 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,14 @@ install(TARGETS icsneopy LIBRARY DESTINATION icsneopy)
|
||||
|
||||
find_program(STUBGEN_EXE stubgen)
|
||||
if(STUBGEN_EXE)
|
||||
add_custom_command(TARGET icsneopy POST_BUILD COMMAND stubgen -v -p icsneopy -o .)
|
||||
# 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
|
||||
)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/icsneopy.pyi py.typed DESTINATION icsneopy)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ 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("BreakOnly", &LINStatusFlags::BreakOnly)
|
||||
.def_readwrite("WakeupRequest", &LINStatusFlags::WakeupRequest);
|
||||
|
||||
pybind11::classh<LINMessage, Frame> linMessage(m, "LINMessage");
|
||||
|
||||
@@ -39,7 +40,8 @@ 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_ERROR", LINMessage::Type::LIN_ERROR)
|
||||
.value("LIN_WAKEUP_REQUEST", LINMessage::Type::LIN_WAKEUP_REQUEST);
|
||||
|
||||
linMessage
|
||||
.def(pybind11::init<>())
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
#!/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
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
mkdir build >nul 2>&1
|
||||
|
||||
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_UNIT_TESTS=ON ^
|
||||
-DLIBICSNEO_ENABLE_TCP=ON || exit /b 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 --build build || exit /b 1
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#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"
|
||||
@@ -40,6 +44,7 @@
|
||||
#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"
|
||||
@@ -341,6 +346,15 @@ 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;
|
||||
@@ -359,6 +373,9 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
);
|
||||
protoapi::Id protoId = protoapi::getProtoId(responseBody.data(), responseBody.size());
|
||||
switch(protoId) {
|
||||
case protoapi::Id::MfgConfig:
|
||||
result = MfgConfigMessage::DecodeToMessage(responseBody);
|
||||
return true;
|
||||
case protoapi::Id::NetworkMutex:
|
||||
result = NetworkMutexMessage::DecodeToMessage(responseBody);
|
||||
return true;
|
||||
@@ -463,6 +480,14 @@ 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]);
|
||||
@@ -563,6 +588,9 @@ 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
|
||||
|
||||
@@ -234,7 +234,9 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
||||
result = packetizer.packetWrap(result, false);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed Message
|
||||
}
|
||||
|
||||
// Early returns may mean we don't reach this far, check the type you're concerned with
|
||||
|
||||
@@ -163,6 +163,8 @@ void A2BMessage::setChannelSample(Direction dir, uint8_t channel, size_t frame,
|
||||
case PCMType::L24:
|
||||
sampleToSet = sampleToSet << 8;
|
||||
break;
|
||||
case PCMType::L32:
|
||||
break;
|
||||
}
|
||||
|
||||
if(channelSize16) {
|
||||
|
||||
@@ -35,7 +35,7 @@ bool EthPhyMessage::appendPhyMessage(bool writeEnable, bool clause45, uint8_t ph
|
||||
|
||||
bool EthPhyMessage::appendPhyMessage(std::shared_ptr<PhyMessage> message)
|
||||
{
|
||||
if(message != nullptr)
|
||||
if(message)
|
||||
{
|
||||
messages.push_back(message);
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
#include "icsneo/communication/message/iso15765message.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<J2534CommandMessage> J2534CommandMessage::decodeToMessage(const std::vector<uint8_t>& data) {
|
||||
if(data.size() < 2)
|
||||
return nullptr;
|
||||
|
||||
auto msg = std::make_shared<J2534CommandMessage>((J2534Command)data[1]);
|
||||
if(data.size() > 2)
|
||||
msg->setArgumentData(std::vector<uint8_t>(data.begin() + 2, data.end()));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
uint16_t J2534CommandMessage::read16LE(size_t o) const {
|
||||
return (uint16_t)((uint16_t)argumentData[o] | ((uint16_t)argumentData[o + 1] << 8));
|
||||
}
|
||||
|
||||
void J2534CommandMessage::write16LE(size_t o, uint16_t v) {
|
||||
argumentData[o] = (uint8_t)(v & 0xFF);
|
||||
argumentData[o + 1] = (uint8_t)((v >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
uint16_t J2534CommandMessage::read16BE(size_t o) const {
|
||||
return (uint16_t)(((uint16_t)argumentData[o] << 8) | argumentData[o + 1]);
|
||||
}
|
||||
|
||||
void J2534CommandMessage::write16BE(size_t o, uint16_t v) {
|
||||
argumentData[o] = (uint8_t)((v >> 8) & 0xFF);
|
||||
argumentData[o + 1] = (uint8_t)(v & 0xFF);
|
||||
}
|
||||
|
||||
void J2534CommandMessage::writeBits16LE(size_t o, unsigned bitPos, unsigned bitCount, uint32_t value) {
|
||||
const uint16_t mask = (uint16_t)(((1u << bitCount) - 1u) << bitPos);
|
||||
uint16_t word = read16LE(o);
|
||||
word = (uint16_t)((word & ~mask) | (((value << bitPos) & mask)));
|
||||
write16LE(o, word);
|
||||
}
|
||||
|
||||
uint32_t J2534CommandMessage::read32LE(size_t o) const {
|
||||
return (uint32_t)argumentData[o]
|
||||
| ((uint32_t)argumentData[o + 1] << 8)
|
||||
| ((uint32_t)argumentData[o + 2] << 16)
|
||||
| ((uint32_t)argumentData[o + 3] << 24);
|
||||
}
|
||||
|
||||
void J2534CommandMessage::write32LE(size_t o, uint32_t v) {
|
||||
argumentData[o] = (uint8_t)(v & 0xFF);
|
||||
argumentData[o + 1] = (uint8_t)((v >> 8) & 0xFF);
|
||||
argumentData[o + 2] = (uint8_t)((v >> 16) & 0xFF);
|
||||
argumentData[o + 3] = (uint8_t)((v >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
uint32_t J2534CommandMessage::read32BE(size_t o) const {
|
||||
return ((uint32_t)argumentData[o] << 24) | ((uint32_t)argumentData[o + 1] << 16)
|
||||
| ((uint32_t)argumentData[o + 2] << 8) | (uint32_t)argumentData[o + 3];
|
||||
}
|
||||
|
||||
void J2534CommandMessage::write32BE(size_t o, uint32_t v) {
|
||||
argumentData[o] = (uint8_t)((v >> 24) & 0xFF);
|
||||
argumentData[o + 1] = (uint8_t)((v >> 16) & 0xFF);
|
||||
argumentData[o + 2] = (uint8_t)((v >> 8) & 0xFF);
|
||||
argumentData[o + 3] = (uint8_t)(v & 0xFF);
|
||||
}
|
||||
|
||||
J2534_RxCanFilter J2534SetupCanRxFilteringMessage::getRxCanFilter() const {
|
||||
constexpr size_t filterSize = sizeof(J2534_RxCanFilter::fb);
|
||||
J2534_RxCanFilter filter = {};
|
||||
if(argumentData.size() >= (10 + filterSize))
|
||||
{
|
||||
filter.idx = (argumentData[2] << 8) | argumentData[3];
|
||||
filter.enabled = (argumentData[4] << 8) | argumentData[5];
|
||||
filter.filterCount = (argumentData[6] << 8) | argumentData[7];
|
||||
filter.fb = *((MessageFilterBytes*)(argumentData.data() + 8));
|
||||
filter.networkId = (argumentData[8 + filterSize] << 8) | argumentData[9 + filterSize];
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
void J2534SetupCanRxFilteringMessage::setRxCanFilter(const J2534_RxCanFilter& filter) {
|
||||
argumentData.resize(10 + sizeof(filter.fb));
|
||||
argumentData[2] = (filter.idx >> 8) & 0xFF;
|
||||
argumentData[3] = filter.idx & 0xFF;
|
||||
argumentData[4] = (filter.enabled >> 8) & 0xFF;
|
||||
argumentData[5] = filter.enabled & 0xFF;
|
||||
argumentData[6] = (filter.filterCount >> 8) & 0xFF;
|
||||
argumentData[7] = filter.filterCount & 0xFF;
|
||||
*((MessageFilterBytes*)(argumentData.data() + 8)) = filter.fb;
|
||||
argumentData[8 + sizeof(filter.fb)] = (filter.networkId >> 8) & 0xFF;
|
||||
argumentData[9 + sizeof(filter.fb)] = filter.networkId & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
J2534SetupIso15765FlowControlMessage::J2534SetupIso15765FlowControlMessage()
|
||||
: J2534CommandMessage(J2534Command::SetupIso15765RxFilter) {
|
||||
argumentData.resize(MessageSize);
|
||||
// Bytes [0..1] were populated by the base constructor. Everything else starts at zero
|
||||
// (matches the previous behavior which zeroed the flt region and left the rest of the
|
||||
// caller-supplied struct as-is; typical callers value-initialized their struct too).
|
||||
for(size_t i = 2; i < MessageSize; ++i)
|
||||
argumentData[i] = 0;
|
||||
}
|
||||
|
||||
void J2534SetupIso15765FlowControlMessage::rebuildFilterBytes(void) {
|
||||
// Zero the 28-byte flt region.
|
||||
for(size_t i = 0; i < FltSize; ++i)
|
||||
argumentData[FltOffset + i] = 0;
|
||||
|
||||
const uint32_t id = read32LE(IdOffset);
|
||||
const uint32_t idMask = read32LE(IdMaskOffset);
|
||||
const bool is29Bit = getFlagBit(FlagId29BitEnable);
|
||||
const bool extAddr = getFlagBit(FlagExtAddressEnable);
|
||||
const uint8_t extAddrByte = argumentData[ExtAddrOffset];
|
||||
|
||||
// CoreMiniMessageFilterBytes has an interleaved layout:
|
||||
// uiFilterMask0 at flt+0, uiFilterID0 at flt+2
|
||||
// uiFilterMask1 at flt+4, uiFilterID1 at flt+6
|
||||
// uiFilterMask2 at flt+8, uiFilterID2 at flt+10
|
||||
// datalink.uiFilterMask3 at flt+12, datalink.uiFilterID3 at flt+14
|
||||
//
|
||||
// CoreMiniMsgBitsCAN bit layout within each 16-bit unit:
|
||||
// unit0: IDE(bit0), SRR(bit1), SID(bits2-12), NETWORKINDEX(bits13-15)
|
||||
// unit1: EID(bits0-11), TXMSG(bit12), ...
|
||||
// unit2: DLC(bits0-3), ..., RTR(bit9), EID2(bits10-15)
|
||||
const size_t MaskUnit0 = FltOffset + 0;
|
||||
const size_t MaskUnit1 = FltOffset + 4;
|
||||
const size_t MaskUnit2 = FltOffset + 8;
|
||||
const size_t ValueUnit0 = FltOffset + 2;
|
||||
const size_t ValueUnit1 = FltOffset + 6;
|
||||
const size_t ValueUnit2 = FltOffset + 10;
|
||||
|
||||
// filter arbid: pMask->IDE = 1
|
||||
writeBits16LE(MaskUnit0, /*bit*/0, /*width*/1, 1);
|
||||
|
||||
if(is29Bit) {
|
||||
// pValue->IDE = 1; pValue->SID = (id >> 18) & 0x7FF
|
||||
writeBits16LE(ValueUnit0, 0, 1, 1);
|
||||
writeBits16LE(ValueUnit0, 2, 11, (id >> 18) & 0x7FF);
|
||||
// pValue->EID = (id >> 6) & 0xFFF
|
||||
writeBits16LE(ValueUnit1, 0, 12, (id >> 6) & 0xFFF);
|
||||
// pValue->EID2 = id & 0x3F
|
||||
writeBits16LE(ValueUnit2, 10, 6, id & 0x3F);
|
||||
// pMask->SID = (id_mask >> 18) & 0x7FF
|
||||
writeBits16LE(MaskUnit0, 2, 11, (idMask >> 18) & 0x7FF);
|
||||
// pMask->EID = (id_mask >> 6) & 0xFFF (overlaps pValue->{IDE,SID} storage)
|
||||
writeBits16LE(MaskUnit1, 0, 12, (idMask >> 6) & 0xFFF);
|
||||
// pMask->EID2 = id_mask & 0x3F (overlaps pValue->EID storage)
|
||||
writeBits16LE(MaskUnit2, 10, 6, idMask & 0x3F);
|
||||
} else {
|
||||
// pValue->IDE = 0 (already zero); pValue->SID = id
|
||||
writeBits16LE(ValueUnit0, 2, 11, id & 0x7FF);
|
||||
// pMask->SID = id_mask
|
||||
writeBits16LE(MaskUnit0, 2, 11, idMask & 0x7FF);
|
||||
}
|
||||
|
||||
// Extended-address filter: writes into the datalink.uiFilterID3 / uiFilterMask3 bytes.
|
||||
// uiFilterMask3 = flt[12..13] = wire[37..38]
|
||||
// uiFilterID3 = flt[14..15] = wire[39..40]
|
||||
if(extAddr) {
|
||||
const size_t kValueBytes = FltOffset + 14; // uiFilterID3
|
||||
const size_t kMaskBytes = FltOffset + 12; // uiFilterMask3
|
||||
argumentData[kValueBytes + 0] = extAddrByte;
|
||||
argumentData[kMaskBytes + 0] = 0xFF;
|
||||
argumentData[kValueBytes + 1] = 0;
|
||||
argumentData[kMaskBytes + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t J2534SetupIso15765FlowControlMessage::getIdx(void) const { return read16LE(IdxOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIdx(uint16_t idx) { write16LE(IdxOffset, idx); }
|
||||
|
||||
uint16_t J2534SetupIso15765FlowControlMessage::getCoreMiniId(void) const { return read16LE(CoreMiniOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setCoreMiniId(uint16_t coreMiniId) { write16LE(CoreMiniOffset, coreMiniId); }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getPadding(void) const { return argumentData[PaddingOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setPadding(uint8_t padding) { argumentData[PaddingOffset] = padding; }
|
||||
|
||||
uint32_t J2534SetupIso15765FlowControlMessage::getId(void) const { return read32LE(IdOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setId(uint32_t id) { write32LE(IdOffset, id); rebuildFilterBytes(); }
|
||||
|
||||
uint32_t J2534SetupIso15765FlowControlMessage::getIdMask(void) const { return read32LE(IdMaskOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIdMask(uint32_t idMask) { write32LE(IdMaskOffset, idMask); rebuildFilterBytes(); }
|
||||
|
||||
uint32_t J2534SetupIso15765FlowControlMessage::getFcId(void) const { return read32LE(FcIdOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setFcId(uint32_t fcId) { write32LE(FcIdOffset, fcId); }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getFlowControlExtendedAddress(void) const { return argumentData[FcExtAddrOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setFlowControlExtendedAddress(uint8_t addr) { argumentData[FcExtAddrOffset] = addr; }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getExtendedAddress(void) const { return argumentData[ExtAddrOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setExtendedAddress(uint8_t addr) { argumentData[ExtAddrOffset] = addr; rebuildFilterBytes(); }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getBlockSize(void) const { return argumentData[BlockSizeOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setBlockSize(uint8_t blockSize) { argumentData[BlockSizeOffset] = blockSize; }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getStMin(void) const { return argumentData[StMinOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setStMin(uint8_t stMin) { argumentData[StMinOffset] = stMin; }
|
||||
|
||||
uint16_t J2534SetupIso15765FlowControlMessage::getCfTimeout(void) const { return read16LE(CfTimeoutOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setCfTimeout(uint16_t cfTimeout) { write16LE(CfTimeoutOffset, cfTimeout); }
|
||||
|
||||
uint32_t J2534SetupIso15765FlowControlMessage::getFlags(void) const { return read32LE(FlagsOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setFlags(uint32_t flags) { write32LE(FlagsOffset, flags); rebuildFilterBytes(); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getEnable(void) const { return getFlagBit(FlagEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setEnable(bool enable) { setFlagBit(FlagEnable, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getIs29BitEnabled(void) const { return getFlagBit(FlagId29BitEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIs29BitEnabled(bool enable) { setFlagBit(FlagId29BitEnable, enable); rebuildFilterBytes(); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getIsFc29BitEnabled(void) const { return getFlagBit(FlagFcId29BitEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIsFc29BitEnabled(bool enable) { setFlagBit(FlagFcId29BitEnable, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getExtAddressEnabled(void) const { return getFlagBit(FlagExtAddressEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setExtAddressEnabled(bool enable) { setFlagBit(FlagExtAddressEnable, enable); rebuildFilterBytes(); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getFcExtAddressEnabled(void) const { return getFlagBit(FlagFcExtAddressEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setFcExtAddressEnabled(bool enable) { setFlagBit(FlagFcExtAddressEnable, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getFlowControlTransmissionEnabled(void) const { return getFlagBit(FlagEnableFlowControlTransmit); }
|
||||
void J2534SetupIso15765FlowControlMessage::setFlowControlTransmissionEnabled(bool enable) { setFlagBit(FlagEnableFlowControlTransmit, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getPaddingEnabled(void) const { return getFlagBit(FlagPaddingEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setPaddingEnabled(bool enable) { setFlagBit(FlagPaddingEnable, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getIsCanFd(void) const { return getFlagBit(FlagIsCanFd); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIsCanFd(bool enable) { setFlagBit(FlagIsCanFd, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getIsBrsEnabled(void) const { return getFlagBit(FlagIsBrsEnabled); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIsBrsEnabled(bool enable) { setFlagBit(FlagIsBrsEnabled, enable); }
|
||||
|
||||
void J2534SetupIso15765FlowControlMessage::setFlagBit(uint32_t mask, bool enable) {
|
||||
uint32_t f = read32LE(FlagsOffset);
|
||||
if(enable) f |= mask;
|
||||
else f &= ~mask;
|
||||
write32LE(FlagsOffset, f);
|
||||
}
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getFlagBit(uint32_t mask) const {
|
||||
return (read32LE(FlagsOffset) & mask) != 0;
|
||||
}
|
||||
|
||||
uint16_t Iso15765TxSetupMessage::getIdx(void) const { return read16LE(SetupIdxOffset); }
|
||||
void Iso15765TxSetupMessage::setIdx(uint16_t idx) { write16LE(SetupIdxOffset, idx); }
|
||||
|
||||
uint16_t Iso15765TxSetupMessage::getCoreMiniId(void) const { return read16LE(SetupCoreMiniOffset); }
|
||||
void Iso15765TxSetupMessage::setCoreMiniId(uint16_t coreMiniId) { write16LE(SetupCoreMiniOffset, coreMiniId); }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getMessageLength(void) const { return read32LE(SetupMsgLenOffset); }
|
||||
void Iso15765TxSetupMessage::setMessageLength(uint32_t messageLength) { write32LE(SetupMsgLenOffset, messageLength); }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getPadding(void) const { return argumentData[SetupPaddingOffset]; }
|
||||
void Iso15765TxSetupMessage::setPadding(uint8_t padding) { argumentData[SetupPaddingOffset] = padding; }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getTxDl(void) const { return argumentData[SetupTxDlOffset]; }
|
||||
void Iso15765TxSetupMessage::setTxDl(uint8_t txDl) { argumentData[SetupTxDlOffset] = txDl; }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getId(void) const { return read32LE(SetupIdOffset); }
|
||||
void Iso15765TxSetupMessage::setId(uint32_t id) { write32LE(SetupIdOffset, id); }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getFcId(void) const { return read32LE(SetupFcIdOffset); }
|
||||
void Iso15765TxSetupMessage::setFcId(uint32_t fcId) { write32LE(SetupFcIdOffset, fcId); }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getFcIdMask(void) const { return read32LE(SetupFcIdMaskOffset); }
|
||||
void Iso15765TxSetupMessage::setFcIdMask(uint32_t fcIdMask) { write32LE(SetupFcIdMaskOffset, fcIdMask); }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getFlowControlExtendedAddress(void) const { return argumentData[SetupFcExtAddrOffset]; }
|
||||
void Iso15765TxSetupMessage::setFlowControlExtendedAddress(uint8_t addr) { argumentData[SetupFcExtAddrOffset] = addr; }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getExtendedAddress(void) const { return argumentData[SetupExtAddrOffset]; }
|
||||
void Iso15765TxSetupMessage::setExtendedAddress(uint8_t addr) { argumentData[SetupExtAddrOffset] = addr; }
|
||||
|
||||
uint16_t Iso15765TxSetupMessage::getFsTimeout(void) const { return read16LE(SetupFsTimeoutOffset); }
|
||||
void Iso15765TxSetupMessage::setFsTimeout(uint16_t timeout) { write16LE(SetupFsTimeoutOffset, timeout); }
|
||||
|
||||
uint16_t Iso15765TxSetupMessage::getFsWait(void) const { return read16LE(SetupFsWaitOffset); }
|
||||
void Iso15765TxSetupMessage::setFsWait(uint16_t wait) { write16LE(SetupFsWaitOffset, wait); }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getFlags(void) const { return read32LE(SetupFlagsOffset); }
|
||||
void Iso15765TxSetupMessage::setFlags(uint32_t flags) { write32LE(SetupFlagsOffset, flags); }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getStMin(void) const { return argumentData[SetupStMinOffset]; }
|
||||
void Iso15765TxSetupMessage::setStMin(uint8_t stMin) { argumentData[SetupStMinOffset] = stMin; }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getBlockSize(void) const { return argumentData[SetupBlockSizeOffset]; }
|
||||
void Iso15765TxSetupMessage::setBlockSize(uint8_t blockSize) { argumentData[SetupBlockSizeOffset] = blockSize; }
|
||||
|
||||
bool Iso15765TxSetupMessage::getIs29BitEnabled(void) const { return getFlagBit(FlagId29BitEnable); }
|
||||
void Iso15765TxSetupMessage::setIs29BitEnabled(bool enable) { setFlagBit(FlagId29BitEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getIsFc29BitEnabled(void) const { return getFlagBit(FlagFcId29BitEnable); }
|
||||
void Iso15765TxSetupMessage::setIsFc29BitEnabled(bool enable) { setFlagBit(FlagFcId29BitEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getExtAddressEnabled(void) const { return getFlagBit(FlagExtAddressEnable); }
|
||||
void Iso15765TxSetupMessage::setExtAddressEnabled(bool enable) { setFlagBit(FlagExtAddressEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getFcExtAddressEnabled(void) const { return getFlagBit(FlagFcExtAddressEnable); }
|
||||
void Iso15765TxSetupMessage::setFcExtAddressEnabled(bool enable) { setFlagBit(FlagFcExtAddressEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getOverrideStMin(void) const { return getFlagBit(FlagOverrideStMin); }
|
||||
void Iso15765TxSetupMessage::setOverrideStMin(bool enable) { setFlagBit(FlagOverrideStMin, enable); }
|
||||
bool Iso15765TxSetupMessage::getOverrideBlockSize(void) const { return getFlagBit(FlagOverrideBlockSize); }
|
||||
void Iso15765TxSetupMessage::setOverrideBlockSize(bool enable) { setFlagBit(FlagOverrideBlockSize, enable); }
|
||||
bool Iso15765TxSetupMessage::getPaddingEnabled(void) const { return getFlagBit(FlagPaddingEnable); }
|
||||
void Iso15765TxSetupMessage::setPaddingEnabled(bool enable) { setFlagBit(FlagPaddingEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getIsCanFd(void) const { return getFlagBit(FlagIsCanFd); }
|
||||
void Iso15765TxSetupMessage::setIsCanFd(bool enable) { setFlagBit(FlagIsCanFd, enable); }
|
||||
bool Iso15765TxSetupMessage::getIsBrsEnabled(void) const { return getFlagBit(FlagIsBrsEnabled); }
|
||||
void Iso15765TxSetupMessage::setIsBrsEnabled(bool enable) { setFlagBit(FlagIsBrsEnabled, enable); }
|
||||
|
||||
bool Iso15765TxSetupMessage::getFlagBit(uint32_t mask) const {
|
||||
return (getFlags() & mask) != 0;
|
||||
}
|
||||
|
||||
void Iso15765TxSetupMessage::setFlagBit(uint32_t mask, bool enable) {
|
||||
uint32_t f = getFlags();
|
||||
if(enable) f |= mask;
|
||||
else f &= ~mask;
|
||||
setFlags(f);
|
||||
}
|
||||
|
||||
uint16_t Iso15765TxDataMessage::getIdx(void) const { return read16LE(DataIdxOffset); }
|
||||
void Iso15765TxDataMessage::setIdx(uint16_t idx) { write16LE(DataIdxOffset, idx); }
|
||||
|
||||
uint32_t Iso15765TxDataMessage::getOffset(void) const { return read32LE(DataOffsetOffset); }
|
||||
void Iso15765TxDataMessage::setOffset(uint32_t offset) { write32LE(DataOffsetOffset, offset); }
|
||||
|
||||
uint16_t Iso15765TxDataMessage::getLen(void) const { return read16LE(DataLenOffset); }
|
||||
|
||||
const uint8_t* Iso15765TxDataMessage::getData(void) const { return argumentData.data() + DataPayloadOffset; }
|
||||
|
||||
void Iso15765TxDataMessage::setData(const uint8_t* sourceData, uint16_t len) {
|
||||
len = std::min(len, (uint16_t)MaxDataLength);
|
||||
argumentData.resize(DataPayloadOffset + len);
|
||||
write16LE(DataLenOffset, len);
|
||||
if(len > 0 && sourceData != nullptr)
|
||||
std::copy(sourceData, sourceData + len, argumentData.begin() + DataPayloadOffset);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "icsneo/communication/message/mfgconfigmessage.h"
|
||||
#include "icsneo/communication/icspb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
static MfgConfigMessage::VersionNumber versionFromProto(const settings::common::v1::VersionNumber& version) {
|
||||
MfgConfigMessage::VersionNumber decoded;
|
||||
decoded.major = version.major();
|
||||
decoded.minor = version.minor();
|
||||
if(version.has_release())
|
||||
decoded.release = version.release();
|
||||
if(version.has_build())
|
||||
decoded.build = version.build();
|
||||
return decoded;
|
||||
}
|
||||
|
||||
std::shared_ptr<MfgConfigMessage> MfgConfigMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
MfgConfigMessage decoded;
|
||||
settings::manufacturing::v1::MfgConfig msg;
|
||||
|
||||
if(!protoapi::processResponse(bytestream.data(), bytestream.size(), msg)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(msg.has_serial_number()) {
|
||||
decoded.serialNumber = msg.serial_number();
|
||||
}
|
||||
if(msg.has_manufacture_date()) {
|
||||
const auto& date = msg.manufacture_date();
|
||||
decoded.manufactureDate = MfgDate{date.manufacture_day(), date.manufacture_month(), date.manufacture_year()};
|
||||
}
|
||||
if(msg.has_hardware_rev()) {
|
||||
decoded.hardwareRev = versionFromProto(msg.hardware_rev());
|
||||
}
|
||||
if(msg.has_product_id()) {
|
||||
decoded.productId = static_cast<uint8_t>(msg.product_id());
|
||||
}
|
||||
if(msg.has_bootloader_rev()) {
|
||||
decoded.bootloaderRev = versionFromProto(msg.bootloader_rev());
|
||||
}
|
||||
if(msg.has_usb_descriptor()) {
|
||||
decoded.usbDescriptor = msg.usb_descriptor();
|
||||
}
|
||||
for(const auto& mac : msg.mac_addresses()) {
|
||||
const auto& bytes = mac.mac_addr();
|
||||
if(bytes.size() < MACAddressLength)
|
||||
continue;
|
||||
MACAddress address{};
|
||||
std::copy_n(bytes.begin(), MACAddressLength, address.begin());
|
||||
decoded.macAddresses.push_back(address);
|
||||
}
|
||||
if(msg.has_pcb_serial()) {
|
||||
decoded.pcbSerial = msg.pcb_serial().pcb_serial();
|
||||
}
|
||||
if(msg.has_chip_id()) {
|
||||
decoded.chipId = static_cast<ChipID>(msg.chip_id());
|
||||
}
|
||||
if(msg.has_imei()) {
|
||||
decoded.imei = msg.imei();
|
||||
}
|
||||
if(msg.has_parent_product_id()) {
|
||||
decoded.parentProductId = static_cast<uint8_t>(msg.parent_product_id());
|
||||
}
|
||||
if(msg.has_software_version_lock()) {
|
||||
decoded.softwareVersionLock = versionFromProto(msg.software_version_lock());
|
||||
}
|
||||
|
||||
return std::make_shared<MfgConfigMessage>(decoded);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> MfgConfigMessage::EncodeArgumentsForGet() {
|
||||
settings::manufacturing::v1::MfgConfig msg;
|
||||
msg.Clear();
|
||||
return protoapi::getPayload(protoapi::Command::GET, msg);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#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,6 +137,7 @@ 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,6 +142,8 @@ void MultiChannelCommunication::hidReadTask() {
|
||||
dispatchMessage(msg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(currentQueue == nullptr) {
|
||||
|
||||
@@ -72,18 +72,30 @@ 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.BreakOnly),
|
||||
static_cast<bool>(packet->CoreMiniBitsLIN.WakeupRequest)
|
||||
};
|
||||
if(msg->statusFlags.TxCommander || msg->statusFlags.TxResponder)
|
||||
// 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)
|
||||
msg->linMsgType = LINMessage::Type::LIN_COMMANDER_MSG;
|
||||
else if(msg->statusFlags.BreakOnly)
|
||||
msg->linMsgType = LINMessage::Type::LIN_BREAK_ONLY;
|
||||
if( msg->errFlags.ErrRxBreakOnly || msg->errFlags.ErrRxBreakSyncOnly ||
|
||||
if( !wakeupPulse &&
|
||||
(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;
|
||||
@@ -103,7 +115,7 @@ bool HardwareLINPacket::EncodeFromMessage(LINMessage& message, std::vector<uint8
|
||||
}
|
||||
case LINMessage::Type::LIN_BREAK_ONLY:
|
||||
{
|
||||
size |= 0x20u;
|
||||
size |= 0x80u | 0x20u;
|
||||
break;
|
||||
}
|
||||
case LINMessage::Type::NOT_SET:
|
||||
|
||||
+348
-124
@@ -8,6 +8,7 @@
|
||||
#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
|
||||
@@ -92,10 +93,6 @@ Device::~Device() {
|
||||
disableMessagePolling();
|
||||
if(isOpen())
|
||||
close();
|
||||
if(heartbeatThread.joinable()) {
|
||||
stopHeartbeatThread = true;
|
||||
heartbeatThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Device::getTimestampResolution() const {
|
||||
@@ -242,12 +239,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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,12 +264,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;
|
||||
@@ -288,6 +285,8 @@ 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
|
||||
@@ -334,79 +333,6 @@ 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();
|
||||
|
||||
@@ -503,7 +429,7 @@ bool Device::close() {
|
||||
return false;
|
||||
}
|
||||
|
||||
stopHeartbeatThread = true;
|
||||
stopHeartbeat();
|
||||
|
||||
if (isMessagePollingEnabled()) {
|
||||
disableMessagePolling();
|
||||
@@ -534,31 +460,15 @@ bool Device::goOnline() {
|
||||
if(!enableNetworkCommunication(true, onlineTimeoutMs))
|
||||
return false;
|
||||
|
||||
auto startTime = std::chrono::system_clock::now();
|
||||
|
||||
ledState = LEDState::Online;
|
||||
|
||||
updateLEDState();
|
||||
|
||||
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;
|
||||
}
|
||||
// (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));
|
||||
|
||||
if(supportsNetworkMutex) {
|
||||
assignedClientId = com->getClientIDSync();
|
||||
@@ -575,41 +485,46 @@ 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;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// (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));
|
||||
|
||||
online = true;
|
||||
|
||||
// restart the heartbeat in online mode
|
||||
restartHeartbeat();
|
||||
|
||||
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOnline(); return true; });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -625,8 +540,6 @@ bool Device::goOffline() {
|
||||
|
||||
updateLEDState();
|
||||
|
||||
online = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1011,6 +924,36 @@ 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)) {
|
||||
@@ -1988,11 +1931,9 @@ void Device::stopScriptStatusThreadIfNecessary(std::unique_lock<std::mutex> lk)
|
||||
}
|
||||
|
||||
Lifetime Device::suppressDisconnects() {
|
||||
std::lock_guard<std::mutex> lk(heartbeatMutex);
|
||||
heartbeatSuppressedByUser++;
|
||||
stopHeartbeat();
|
||||
return Lifetime([this] {
|
||||
std::lock_guard<std::mutex> lk2(heartbeatMutex);
|
||||
heartbeatSuppressedByUser--;
|
||||
startHeartbeat();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2128,6 +2069,18 @@ 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())
|
||||
@@ -3297,11 +3250,12 @@ 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;
|
||||
@@ -3316,6 +3270,9 @@ 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
|
||||
@@ -4156,3 +4113,270 @@ 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);
|
||||
}
|
||||
|
||||
+24
-17
@@ -1,9 +1,16 @@
|
||||
#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();
|
||||
@@ -166,7 +173,7 @@ bool IDeviceSettings::refresh() {
|
||||
}
|
||||
|
||||
std::vector<uint8_t> rxSettings;
|
||||
bool ret = com->getSettingsSync(rxSettings);
|
||||
bool ret = device->com->getSettingsSync(rxSettings);
|
||||
if(!ret) {
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
@@ -231,10 +238,10 @@ bool IDeviceSettings::apply(bool temporary) {
|
||||
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
|
||||
|
||||
// Pause I/O with the device while the settings are applied
|
||||
applyingSettings = true;
|
||||
device->stopHeartbeat();
|
||||
|
||||
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
|
||||
return com->sendCommand(Command::SetSettings, bytestream);
|
||||
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() {
|
||||
return device->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
|
||||
@@ -259,8 +266,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>(com->waitForMessageSync([this, &bytestream]() {
|
||||
return com->sendCommand(Command::SetSettings, bytestream);
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() {
|
||||
return device->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
|
||||
@@ -272,12 +279,12 @@ bool IDeviceSettings::apply(bool temporary) {
|
||||
}
|
||||
|
||||
if(!temporary) {
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
|
||||
return com->sendCommand(Command::SaveSettings);
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() {
|
||||
return device->com->sendCommand(Command::SaveSettings);
|
||||
}, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000)));
|
||||
}
|
||||
|
||||
applyingSettings = false;
|
||||
device->startHeartbeat();
|
||||
|
||||
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
|
||||
|
||||
@@ -299,10 +306,10 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
||||
return false;
|
||||
}
|
||||
|
||||
applyingSettings = true;
|
||||
device->stopHeartbeat();
|
||||
|
||||
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
|
||||
return com->sendCommand(Command::SetDefaultSettings);
|
||||
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() {
|
||||
return device->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
|
||||
@@ -336,8 +343,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>(com->waitForMessageSync([this, &bytestream]() {
|
||||
return com->sendCommand(Command::SetSettings, bytestream);
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() {
|
||||
return device->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
|
||||
@@ -349,12 +356,12 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
||||
}
|
||||
|
||||
if(!temporary) {
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
|
||||
return com->sendCommand(Command::SaveSettings);
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() {
|
||||
return device->com->sendCommand(Command::SaveSettings);
|
||||
}, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000)));
|
||||
}
|
||||
|
||||
applyingSettings = false;
|
||||
device->startHeartbeat();
|
||||
|
||||
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ option(LIBICSNEO_BUILD_CPP_ANALOG_OUT_EXAMPLE "Build the analog output example."
|
||||
option(LIBICSNEO_BUILD_CPP_DISKFORMAT_EXAMPLE "Build the disk format example." ON)
|
||||
option(LIBICSNEO_BUILD_CPP_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})
|
||||
|
||||
@@ -190,3 +191,7 @@ 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()
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
add_executable(libicsneocpp-iso15765-loopback src/ISO15765Loopback.cpp)
|
||||
target_link_libraries(libicsneocpp-iso15765-loopback icsneocpp)
|
||||
@@ -0,0 +1,450 @@
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "icsneo/icsneocpp.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
enum class Mode {
|
||||
None,
|
||||
Raw,
|
||||
SingleFrame,
|
||||
Both,
|
||||
};
|
||||
|
||||
struct Options {
|
||||
Mode mode = Mode::None;
|
||||
std::string testerSerial;
|
||||
std::string ecuSerial;
|
||||
int64_t baud = 500000;
|
||||
bool keepBaud = false;
|
||||
uint32_t txId = 0x7E0;
|
||||
uint32_t fcId = 0x7E8;
|
||||
std::optional<size_t> payloadBytes;
|
||||
int listenMs = 2000;
|
||||
uint8_t padding = 0x00;
|
||||
uint16_t fsTimeoutMs = 75;
|
||||
uint16_t fsWaitMs = 150;
|
||||
uint16_t cfTimeoutMs = 150;
|
||||
};
|
||||
|
||||
std::mutex gLogMutex;
|
||||
|
||||
void logLine(const std::string& line) {
|
||||
std::lock_guard<std::mutex> lk(gLogMutex);
|
||||
std::cout << line << std::endl;
|
||||
}
|
||||
|
||||
bool iequals(const std::string& a, const std::string& b) {
|
||||
if(a.size() != b.size())
|
||||
return false;
|
||||
for(size_t i = 0; i < a.size(); i++) {
|
||||
if(std::tolower(static_cast<unsigned char>(a[i])) != std::tolower(static_cast<unsigned char>(b[i])))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string hexBytes(const std::vector<uint8_t>& data) {
|
||||
std::ostringstream oss;
|
||||
oss << std::hex << std::setfill('0');
|
||||
for(size_t i = 0; i < data.size(); i++) {
|
||||
if(i)
|
||||
oss << ' ';
|
||||
oss << std::setw(2) << static_cast<unsigned>(data[i]);
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string pciDescribe(const std::vector<uint8_t>& data) {
|
||||
if(data.empty())
|
||||
return {};
|
||||
const uint8_t pciType = static_cast<uint8_t>(data[0] >> 4);
|
||||
const uint8_t pciLow = static_cast<uint8_t>(data[0] & 0x0F);
|
||||
std::ostringstream oss;
|
||||
switch(pciType) {
|
||||
case 0x0:
|
||||
if(pciLow > 7 || data.size() < static_cast<size_t>(1 + pciLow))
|
||||
return {};
|
||||
oss << "SF len=" << static_cast<unsigned>(pciLow);
|
||||
break;
|
||||
case 0x1: {
|
||||
if(data.size() < 8)
|
||||
return {};
|
||||
const uint16_t len = static_cast<uint16_t>((pciLow << 8) | data[1]);
|
||||
if(len < 8)
|
||||
return {};
|
||||
oss << "FF len=" << len;
|
||||
break;
|
||||
}
|
||||
case 0x2:
|
||||
if(data.size() < 2)
|
||||
return {};
|
||||
oss << "CF SN=" << static_cast<unsigned>(pciLow);
|
||||
break;
|
||||
case 0x3: {
|
||||
if(data.size() < 3 || pciLow > 2)
|
||||
return {};
|
||||
static const char* fsName[] = { "CTS", "WAIT", "OVFLW" };
|
||||
oss << "FC FS=" << fsName[pciLow];
|
||||
oss << " BS=" << static_cast<unsigned>(data[1]);
|
||||
oss << " STmin=0x" << std::hex << std::setw(2) << std::setfill('0')
|
||||
<< static_cast<unsigned>(data[2]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void printUsage(const char* argv0) {
|
||||
std::cerr
|
||||
<< "Usage: " << argv0 << " --raw|--sf|--both [options]\n\n"
|
||||
<< "Two Intrepid devices with CAN1 wired together (CANH/CANL, terminated).\n"
|
||||
<< "Prints CAN1 frames with ISO-TP PCI decode (SF/FF/CF/FC).\n\n"
|
||||
<< "Modes:\n"
|
||||
<< " --raw Raw CAN ping-pong (cable check)\n"
|
||||
<< " --sf Firmware ISO-TP single-frame TX from tester\n"
|
||||
<< " --both Firmware ISO-TP TX on tester, firmware flow-control on ECU\n\n"
|
||||
<< "Devices:\n"
|
||||
<< " --tester SERIAL Tester (sender) serial\n"
|
||||
<< " --ecu SERIAL ECU / peer serial\n"
|
||||
<< " Optional if exactly two devices are found.\n\n"
|
||||
<< "Optional:\n"
|
||||
<< " --baud N CAN1 baud (default 500000, applied temporarily)\n"
|
||||
<< " --keep-baud Do not change device baud\n"
|
||||
<< " --tx-id HEX Tester ISO-TP CAN ID (default 0x7E0)\n"
|
||||
<< " --fc-id HEX Flow-control CAN ID (default 0x7E8)\n"
|
||||
<< " --bytes N ISO-TP payload size (sf default 5, both default 20)\n"
|
||||
<< " --listen-ms N Time to listen after the action (default 2000)\n";
|
||||
}
|
||||
|
||||
uint32_t parseU32(const std::string& s) {
|
||||
return static_cast<uint32_t>(std::stoul(s, nullptr, 0));
|
||||
}
|
||||
|
||||
bool parseArgs(int argc, char** argv, Options& opt) {
|
||||
for(int i = 1; i < argc; i++) {
|
||||
const std::string a = argv[i];
|
||||
auto need = [&](const char* name) -> std::string {
|
||||
if(i + 1 >= argc)
|
||||
throw std::runtime_error(std::string("missing value for ") + name);
|
||||
return argv[++i];
|
||||
};
|
||||
if(a == "--raw")
|
||||
opt.mode = Mode::Raw;
|
||||
else if(a == "--sf")
|
||||
opt.mode = Mode::SingleFrame;
|
||||
else if(a == "--both")
|
||||
opt.mode = Mode::Both;
|
||||
else if(a == "--tester")
|
||||
opt.testerSerial = need("--tester");
|
||||
else if(a == "--ecu")
|
||||
opt.ecuSerial = need("--ecu");
|
||||
else if(a == "--baud")
|
||||
opt.baud = static_cast<int64_t>(std::stoll(need("--baud")));
|
||||
else if(a == "--keep-baud")
|
||||
opt.keepBaud = true;
|
||||
else if(a == "--tx-id")
|
||||
opt.txId = parseU32(need("--tx-id"));
|
||||
else if(a == "--fc-id")
|
||||
opt.fcId = parseU32(need("--fc-id"));
|
||||
else if(a == "--bytes")
|
||||
opt.payloadBytes = static_cast<size_t>(std::stoul(need("--bytes")));
|
||||
else if(a == "--listen-ms")
|
||||
opt.listenMs = std::stoi(need("--listen-ms"));
|
||||
else if(a == "-h" || a == "--help") {
|
||||
printUsage(argv[0]);
|
||||
return false;
|
||||
} else {
|
||||
std::cerr << "Unknown argument: " << a << "\n";
|
||||
printUsage(argv[0]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(opt.mode == Mode::None) {
|
||||
printUsage(argv[0]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t defaultPayloadSize(Mode mode) {
|
||||
return mode == Mode::SingleFrame ? 5 : 20;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> makePayload(size_t n) {
|
||||
std::vector<uint8_t> data(n);
|
||||
for(size_t i = 0; i < n; i++)
|
||||
data[i] = static_cast<uint8_t>(i & 0xFF);
|
||||
return data;
|
||||
}
|
||||
|
||||
bool isExtended(uint32_t id) {
|
||||
return id > 0x7FFu;
|
||||
}
|
||||
|
||||
void printApiResult(const char* what, bool ok) {
|
||||
std::ostringstream oss;
|
||||
oss << " " << what << ": " << (ok ? "OK" : "FAIL");
|
||||
if(!ok) {
|
||||
const auto err = icsneo::GetLastError();
|
||||
if(err.getType() != icsneo::APIEvent::Type::NoErrorFound)
|
||||
oss << " [" << err << "]";
|
||||
}
|
||||
logLine(oss.str());
|
||||
}
|
||||
|
||||
bool transmitCan(icsneo::Device& device, uint32_t arbId, std::vector<uint8_t> data) {
|
||||
auto frame = std::make_shared<icsneo::CANMessage>();
|
||||
frame->network = icsneo::Network::NetID::DWCAN_01;
|
||||
frame->arbid = arbId;
|
||||
frame->data = std::move(data);
|
||||
frame->isExtended = isExtended(arbId);
|
||||
frame->isCANFD = false;
|
||||
const bool ok = device.transmit(frame);
|
||||
if(!ok)
|
||||
printApiResult("transmit CAN", ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void fillIso15765(icsneo::Iso15765MessageArgs& msg, const Options& opt, const std::vector<uint8_t>& payload, bool rx) {
|
||||
msg.setTxIndex(0);
|
||||
msg.setArbId(icsneo::Iso15765MessageArgs::ArbId(opt.txId, isExtended(opt.txId)));
|
||||
msg.setFlowControlArbId(icsneo::Iso15765MessageArgs::ArbId(opt.fcId, isExtended(opt.fcId)));
|
||||
msg.setFlowControlArbIdMask(isExtended(opt.txId) ? 0x1FFFFFFFu : 0x7FFu);
|
||||
msg.setIsCanFd(false);
|
||||
msg.setIsBrsEnabled(false);
|
||||
msg.setTxDl(8);
|
||||
msg.setPaddingValue(opt.padding);
|
||||
msg.setFsTimeout(opt.fsTimeoutMs);
|
||||
msg.setFsWaitTimeout(opt.fsWaitMs);
|
||||
msg.setCfTimeout(opt.cfTimeoutMs);
|
||||
msg.setIsFlowControlEnabled(rx);
|
||||
if(!payload.empty()) {
|
||||
auto copy = payload;
|
||||
msg.setData(std::move(copy));
|
||||
}
|
||||
}
|
||||
|
||||
struct Sniffer {
|
||||
const char* tag = "";
|
||||
std::optional<uint64_t> t0;
|
||||
std::mutex t0Mutex;
|
||||
|
||||
void onCan(const std::shared_ptr<icsneo::CANMessage>& can) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(t0Mutex);
|
||||
if(!t0)
|
||||
t0 = can->timestamp;
|
||||
}
|
||||
|
||||
double relMs = 0.0;
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(t0Mutex);
|
||||
if(t0 && can->timestamp >= *t0)
|
||||
relMs = static_cast<double>(can->timestamp - *t0) / 1e6;
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << " [" << tag << (can->transmitted ? " TX" : " RX") << "] "
|
||||
<< std::fixed << std::setprecision(3) << relMs << " ms "
|
||||
<< can->network << " 0x" << std::hex << std::uppercase
|
||||
<< std::setw(isExtended(can->arbid) ? 8 : 3) << std::setfill('0') << can->arbid
|
||||
<< std::dec << " [" << can->data.size() << "] " << hexBytes(can->data);
|
||||
const auto pci = pciDescribe(can->data);
|
||||
if(!pci.empty())
|
||||
oss << " " << pci;
|
||||
logLine(oss.str());
|
||||
}
|
||||
};
|
||||
|
||||
void addCanSniffer(icsneo::Device& device, Sniffer& sniffer) {
|
||||
auto filter = std::make_shared<icsneo::MessageFilter>(icsneo::Network::NetID::DWCAN_01);
|
||||
device.addMessageCallback(std::make_shared<icsneo::MessageCallback>(filter, [&sniffer](std::shared_ptr<icsneo::Message> message) {
|
||||
if(message->type != icsneo::Message::Type::Frame)
|
||||
return;
|
||||
auto frame = std::static_pointer_cast<icsneo::Frame>(message);
|
||||
if(frame->network.getType() != icsneo::Network::Type::CAN)
|
||||
return;
|
||||
sniffer.onCan(std::static_pointer_cast<icsneo::CANMessage>(message));
|
||||
}));
|
||||
}
|
||||
|
||||
bool openAndOnline(std::shared_ptr<icsneo::Device>& device, const Options& opt) {
|
||||
logLine(std::string("Opening ") + device->describe() + " ...");
|
||||
if(!device->open()) {
|
||||
printApiResult("open", false);
|
||||
return false;
|
||||
}
|
||||
if(!opt.keepBaud && device->settings) {
|
||||
if(!device->settings->setBaudrateFor(icsneo::Network::NetID::DWCAN_01, opt.baud))
|
||||
printApiResult("setBaudrateFor", false);
|
||||
else if(!device->settings->apply(true))
|
||||
printApiResult("settings->apply(temporary)", false);
|
||||
}
|
||||
if(!device->goOnline()) {
|
||||
printApiResult("goOnline", false);
|
||||
device->close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void closeDevice(const std::shared_ptr<icsneo::Device>& device) {
|
||||
if(!device)
|
||||
return;
|
||||
device->iso15765DisableAll();
|
||||
if(device->isOnline())
|
||||
device->goOffline();
|
||||
if(device->isOpen())
|
||||
device->close();
|
||||
}
|
||||
|
||||
bool enableIso(icsneo::Device& device, const char* who) {
|
||||
const bool ok = device.iso15765Enable(icsneo::Network(icsneo::Network::NetID::DWCAN_01));
|
||||
printApiResult((std::string(who) + " ISO15765_Enable").c_str(), ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool receiveIso(icsneo::Device& device, const Options& opt) {
|
||||
icsneo::Iso15765MessageArgs msg;
|
||||
fillIso15765(msg, opt, {}, true);
|
||||
const bool ok = device.iso15765SetupRxFlowControl(icsneo::Network(icsneo::Network::NetID::DWCAN_01), msg);
|
||||
printApiResult("ECU ISO15765_ReceiveMessage", ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool transmitIso(icsneo::Device& device, const Options& opt, const std::vector<uint8_t>& payload) {
|
||||
icsneo::Iso15765MessageArgs msg;
|
||||
fillIso15765(msg, opt, payload, false);
|
||||
const bool ok = device.iso15765TransmitMessage(
|
||||
icsneo::Network(icsneo::Network::NetID::DWCAN_01), msg, std::chrono::milliseconds(0));
|
||||
printApiResult("tester ISO15765_TransmitMessage", ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
std::shared_ptr<icsneo::Device> findBySerial(const std::vector<std::shared_ptr<icsneo::Device>>& devices, const std::string& serial) {
|
||||
for(const auto& d : devices) {
|
||||
if(iequals(d->getSerial(), serial))
|
||||
return d;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Options opt;
|
||||
try {
|
||||
if(!parseArgs(argc, argv, opt))
|
||||
return 1;
|
||||
} catch(const std::exception& ex) {
|
||||
std::cerr << ex.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "libicsneo " << icsneo::GetVersion() << std::endl;
|
||||
|
||||
auto devices = icsneo::FindAllDevices();
|
||||
std::cout << "Found " << devices.size() << " device(s)\n";
|
||||
for(const auto& d : devices)
|
||||
std::cout << " " << d->describe() << " serial=" << d->getSerial() << "\n";
|
||||
|
||||
if(devices.size() < 2) {
|
||||
std::cerr << "Need two devices connected.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::shared_ptr<icsneo::Device> tester;
|
||||
std::shared_ptr<icsneo::Device> ecu;
|
||||
if(opt.testerSerial.empty() && opt.ecuSerial.empty()) {
|
||||
if(devices.size() != 2) {
|
||||
std::cerr << "More than two devices found; pass --tester and --ecu serials.\n";
|
||||
return 1;
|
||||
}
|
||||
tester = devices[0];
|
||||
ecu = devices[1];
|
||||
std::cout << "No serials given; using first as tester, second as ECU.\n";
|
||||
} else {
|
||||
if(opt.testerSerial.empty() || opt.ecuSerial.empty()) {
|
||||
std::cerr << "Pass both --tester and --ecu, or neither.\n";
|
||||
return 1;
|
||||
}
|
||||
tester = findBySerial(devices, opt.testerSerial);
|
||||
ecu = findBySerial(devices, opt.ecuSerial);
|
||||
if(!tester || !ecu) {
|
||||
std::cerr << "Could not match tester/ECU serials.\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t payloadSize = opt.payloadBytes.value_or(defaultPayloadSize(opt.mode));
|
||||
const auto payload = makePayload(payloadSize);
|
||||
|
||||
std::cout << "Tester: " << tester->describe() << "\n"
|
||||
<< "ECU: " << ecu->describe() << "\n";
|
||||
if(opt.mode != Mode::Raw) {
|
||||
std::ostringstream hdr;
|
||||
hdr << "CAN1 TX 0x" << std::hex << std::uppercase << opt.txId
|
||||
<< " FC 0x" << opt.fcId << std::dec
|
||||
<< " payload " << payloadSize << " bytes";
|
||||
std::cout << hdr.str() << "\n";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
if(!openAndOnline(tester, opt) || !openAndOnline(ecu, opt))
|
||||
return 1;
|
||||
|
||||
Sniffer testerSniff;
|
||||
testerSniff.tag = "TESTER";
|
||||
Sniffer ecuSniff;
|
||||
ecuSniff.tag = "ECU ";
|
||||
addCanSniffer(*tester, testerSniff);
|
||||
addCanSniffer(*ecu, ecuSniff);
|
||||
|
||||
switch(opt.mode) {
|
||||
case Mode::Raw:
|
||||
logLine("Mode --raw: tester 0x123, then ECU 0x456");
|
||||
transmitCan(*tester, 0x123, { 0x11, 0x22, 0x33, 0x44 });
|
||||
std::this_thread::sleep_for(200ms);
|
||||
transmitCan(*ecu, 0x456, { 0x55, 0x66, 0x77, 0x88 });
|
||||
break;
|
||||
case Mode::SingleFrame:
|
||||
logLine("Mode --sf: firmware ISO-TP single frame from tester");
|
||||
if(payload.size() > 7)
|
||||
logLine(" warning: payload > 7 bytes will be a First Frame (no flow control in this mode)");
|
||||
enableIso(*tester, "tester");
|
||||
transmitIso(*tester, opt, payload);
|
||||
break;
|
||||
case Mode::Both:
|
||||
logLine("Mode --both: firmware TX on tester, firmware flow-control on ECU");
|
||||
enableIso(*tester, "tester");
|
||||
enableIso(*ecu, "ECU");
|
||||
receiveIso(*ecu, opt);
|
||||
std::this_thread::sleep_for(100ms);
|
||||
transmitIso(*tester, opt, payload);
|
||||
break;
|
||||
case Mode::None:
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(opt.listenMs));
|
||||
|
||||
closeDevice(tester);
|
||||
closeDevice(ecu);
|
||||
return 0;
|
||||
}
|
||||
+125
-25
@@ -1,33 +1,133 @@
|
||||
#ifndef _J2534_H
|
||||
#define _J2534_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
//J2534 Commands
|
||||
#define J1534_NUM_PERIOD_TX_MSGS 128
|
||||
#define J1534_NUM_PERIOD_RX_MSGS 128
|
||||
#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
|
||||
|
||||
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
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#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__
|
||||
@@ -43,6 +43,7 @@ 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
|
||||
@@ -73,10 +74,14 @@ 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,6 +14,7 @@
|
||||
#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"
|
||||
|
||||
@@ -31,6 +31,7 @@ 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);
|
||||
@@ -62,7 +63,6 @@ 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; }
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#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
|
||||
@@ -36,6 +37,11 @@ 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,7 +6,6 @@
|
||||
#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>
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#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_
|
||||
@@ -0,0 +1,40 @@
|
||||
#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_
|
||||
@@ -0,0 +1,443 @@
|
||||
#ifndef __ISO_15765MESSAGE_H_
|
||||
#define __ISO_15765MESSAGE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/communication/message/main51message.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/J2534.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class J2534CommandMessage : public Main51Message
|
||||
{
|
||||
public:
|
||||
enum class J2534Command : uint8_t
|
||||
{
|
||||
Enable = 0, //RED_CMD_J2534_EXTENSION_ENABLE,
|
||||
SetupIso15765RxFilter = 1, //RED_CMD_J2534_EXTENSION_SETUP_ISO15_RX_FILTER,
|
||||
SetupIso15765TxMessageProperties = 2, //RED_CMD_J2534_EXTENSION_SETUP_ISO15_TX_MESSAGE_PROPERTIES,
|
||||
SetupIso15765TxMessageDataBytes = 3, //RED_CMD_J2534_EXTENSION_SETUP_ISO15_TX_MESSAGE_DATABYTES,
|
||||
SetupCanRxFilter = 4, //RED_CMD_J2534_EXTENSION_SETUP_CAN_RX_FILTER,
|
||||
SetupClearCanRxFilters = 5, //RED_CMD_J2534_EXTENSION_SETUP_CLEAR_CAN_RX_FILTERS,
|
||||
EnableFiltering = 6, //RED_CMD_J2534_EXTENSION_ENABLE_FILTERING,
|
||||
};
|
||||
|
||||
J2534CommandMessage(const J2534Command j2534Command, const std::vector<uint8_t>& arguments = {})
|
||||
: Main51Message() {
|
||||
command = Command::J2534Command;
|
||||
argumentData.push_back((uint8_t)j2534Command);
|
||||
argumentData.push_back(0);
|
||||
setArgumentData(arguments);
|
||||
}
|
||||
virtual ~J2534CommandMessage(void) = default;
|
||||
|
||||
J2534Command getJ2534Command(void) const { return (J2534Command)argumentData[0]; }
|
||||
void setJ2534Command(const J2534Command& j2534Command) { argumentData[0] = (uint8_t)j2534Command; }
|
||||
|
||||
const std::vector<uint8_t>& getArgumentData(void) const { return argumentData; }
|
||||
void setArgumentData(const std::vector<uint8_t>& arguments) { argumentData.insert(argumentData.end(), arguments.begin(), arguments.end()); }
|
||||
|
||||
static std::shared_ptr<J2534CommandMessage> decodeToMessage(const std::vector<uint8_t>& data);
|
||||
|
||||
protected:
|
||||
std::vector<uint8_t> argumentData;
|
||||
|
||||
uint16_t read16LE(size_t o) const;
|
||||
void write16LE(size_t o, uint16_t v);
|
||||
uint16_t read16BE(size_t o) const;
|
||||
void write16BE(size_t o, uint16_t v);
|
||||
void writeBits16LE(size_t o, unsigned bitPos, unsigned bitCount, uint32_t value);
|
||||
uint32_t read32LE(size_t o) const;
|
||||
void write32LE(size_t o, uint32_t v);
|
||||
uint32_t read32BE(size_t o) const;
|
||||
void write32BE(size_t o, uint32_t v);
|
||||
};
|
||||
|
||||
class J2534EnableMessage : public J2534CommandMessage {
|
||||
public:
|
||||
J2534EnableMessage(const bool enable)
|
||||
: J2534CommandMessage(J2534Command::Enable, { (uint8_t)enable }) {
|
||||
}
|
||||
bool getEnable(void) const { return (bool)argumentData[2]; }
|
||||
void setEnable(bool enable) { argumentData[2] = (uint8_t)enable; }
|
||||
};
|
||||
|
||||
class J2534EnableFilteringMessage : public J2534CommandMessage {
|
||||
public:
|
||||
J2534EnableFilteringMessage(const bool enable)
|
||||
: J2534CommandMessage(J2534Command::EnableFiltering, { (uint8_t)enable }) {
|
||||
}
|
||||
bool getEnable(void) const { return (bool)argumentData[2]; }
|
||||
void setEnable(bool enable) { argumentData[2] = (uint8_t)enable; }
|
||||
};
|
||||
|
||||
class J2534SetupCanRxFilteringMessage : public J2534CommandMessage {
|
||||
public:
|
||||
J2534SetupCanRxFilteringMessage(const J2534_RxCanFilter& filter)
|
||||
: J2534CommandMessage(J2534Command::SetupCanRxFilter) {
|
||||
setRxCanFilter(filter);
|
||||
}
|
||||
|
||||
J2534_RxCanFilter getRxCanFilter(void) const;
|
||||
|
||||
void setRxCanFilter(const J2534_RxCanFilter& filter);
|
||||
};
|
||||
|
||||
class J2534SetupIso15765FlowControlMessage : public J2534CommandMessage
|
||||
{
|
||||
public:
|
||||
J2534SetupIso15765FlowControlMessage();
|
||||
|
||||
uint16_t getIdx(void) const;
|
||||
void setIdx(uint16_t idx);
|
||||
uint16_t getCoreMiniId(void) const;
|
||||
void setCoreMiniId(uint16_t coreMiniId);
|
||||
uint8_t getPadding(void) const;
|
||||
void setPadding(uint8_t padding);
|
||||
uint32_t getId(void) const;
|
||||
void setId(uint32_t id);
|
||||
uint32_t getIdMask(void) const;
|
||||
void setIdMask(uint32_t idMask);
|
||||
uint32_t getFcId(void) const;
|
||||
void setFcId(uint32_t fcId);
|
||||
uint8_t getFlowControlExtendedAddress(void) const;
|
||||
void setFlowControlExtendedAddress(uint8_t addr);
|
||||
uint8_t getExtendedAddress(void) const;
|
||||
void setExtendedAddress(uint8_t addr);
|
||||
uint8_t getBlockSize(void) const;
|
||||
void setBlockSize(uint8_t blockSize);
|
||||
uint8_t getStMin(void) const;
|
||||
void setStMin(uint8_t stMin);
|
||||
uint16_t getCfTimeout(void) const;
|
||||
void setCfTimeout(uint16_t cfTimeout);
|
||||
uint32_t getFlags(void) const;
|
||||
void setFlags(uint32_t flags);
|
||||
|
||||
bool getEnable(void) const;
|
||||
void setEnable(bool enable);
|
||||
bool getIs29BitEnabled(void) const;
|
||||
void setIs29BitEnabled(bool enable);
|
||||
bool getIsFc29BitEnabled(void) const;
|
||||
void setIsFc29BitEnabled(bool enable);
|
||||
bool getExtAddressEnabled(void) const;
|
||||
void setExtAddressEnabled(bool enable);
|
||||
bool getFcExtAddressEnabled(void) const;
|
||||
void setFcExtAddressEnabled(bool enable);
|
||||
bool getFlowControlTransmissionEnabled(void) const;
|
||||
void setFlowControlTransmissionEnabled(bool enable);
|
||||
bool getPaddingEnabled(void) const;
|
||||
void setPaddingEnabled(bool enable);
|
||||
bool getIsCanFd(void) const;
|
||||
void setIsCanFd(bool enable);
|
||||
bool getIsBrsEnabled(void) const;
|
||||
void setIsBrsEnabled(bool enable);
|
||||
|
||||
private:
|
||||
// The legacy wire format was the raw memory of the (now-removed) J2534_RxFlowControlRequest
|
||||
// struct copied into mArgumentData starting at offset 1 (overwriting the header pad byte).
|
||||
// The struct was compiled with `#pragma pack(2)` on MSVC little-endian. All multi-byte
|
||||
// scalars are therefore stored little-endian; the "flt" region reproduces the exact
|
||||
// byte pattern produced by the old MessageBitsCAN bitfield writes.
|
||||
//
|
||||
// Byte layout (mArgumentData indices):
|
||||
// [0] J2534 command header byte (set by base class)
|
||||
// [1] padding
|
||||
// [2..3] idx (u16 LE)
|
||||
// [4..5] iCoreMiniID (u16 LE)
|
||||
// [6] padding (u8)
|
||||
// [7] structure pad byte (unused)
|
||||
// [8..11] id (u32 LE)
|
||||
// [12..15] id_mask (u32 LE)
|
||||
// [16..19] fc_id (u32 LE)
|
||||
// [20] flowControlExtendedAddress (u8)
|
||||
// [21] extendedAddress (u8)
|
||||
// [22] blockSize (u8)
|
||||
// [23] stMin (u8)
|
||||
// [24..25] cf_timeout (u16 LE)
|
||||
// [26..53] MessageFilterBytes flt (28 bytes) -- see RebuildFilterBytes for details
|
||||
// [54..57] flags (u32 LE) -- see kFcFlag* below
|
||||
//
|
||||
// Total wire size: 58 bytes.
|
||||
static const size_t MessageSize = 58;
|
||||
static const size_t IdxOffset = 2;
|
||||
static const size_t CoreMiniOffset = 4;
|
||||
static const size_t PaddingOffset = 6;
|
||||
static const size_t IdOffset = 8;
|
||||
static const size_t IdMaskOffset = 12;
|
||||
static const size_t FcIdOffset = 16;
|
||||
static const size_t FcExtAddrOffset = 20;
|
||||
static const size_t ExtAddrOffset = 21;
|
||||
static const size_t BlockSizeOffset = 22;
|
||||
static const size_t StMinOffset = 23;
|
||||
static const size_t CfTimeoutOffset = 24;
|
||||
static const size_t FltOffset = 26; // 28 bytes
|
||||
static const size_t FltSize = 28;
|
||||
static const size_t FlagsOffset = 54;
|
||||
|
||||
// Bit positions inside the u32 LE flags word (matches the legacy bitfield layout).
|
||||
static const uint32_t FlagEnable = 1u << 0;
|
||||
static const uint32_t FlagId29BitEnable = 1u << 1;
|
||||
static const uint32_t FlagFcId29BitEnable = 1u << 2;
|
||||
static const uint32_t FlagExtAddressEnable = 1u << 3;
|
||||
static const uint32_t FlagFcExtAddressEnable = 1u << 4;
|
||||
static const uint32_t FlagEnableFlowControlTransmit = 1u << 5;
|
||||
static const uint32_t FlagPaddingEnable = 1u << 6;
|
||||
static const uint32_t FlagIsCanFd = 1u << 7;
|
||||
static const uint32_t FlagIsBrsEnabled = 1u << 8;
|
||||
|
||||
// Rebuilds the filter bytes region of mArgumentData based on the current id / id_mask /
|
||||
// id_29_bit_enable / ext_address_enable / extendedAddress state. Preserves the legacy
|
||||
// (pre-existing) wire format bit-for-bit.
|
||||
void rebuildFilterBytes(void);
|
||||
|
||||
void setFlagBit(uint32_t mask, bool enable);
|
||||
|
||||
bool getFlagBit(uint32_t mask) const;
|
||||
};
|
||||
|
||||
class Iso15765TxSetupMessage : public J2534CommandMessage {
|
||||
public:
|
||||
Iso15765TxSetupMessage()
|
||||
: J2534CommandMessage(J2534Command::SetupIso15765TxMessageProperties) {
|
||||
argumentData.resize(36);
|
||||
}
|
||||
|
||||
uint16_t getIdx(void) const;
|
||||
void setIdx(uint16_t idx);
|
||||
uint16_t getCoreMiniId(void) const;
|
||||
void setCoreMiniId(uint16_t coreMiniId);
|
||||
uint32_t getMessageLength(void) const;
|
||||
void setMessageLength(uint32_t messageLength);
|
||||
uint8_t getPadding(void) const;
|
||||
void setPadding(uint8_t padding);
|
||||
uint8_t getTxDl(void) const;
|
||||
void setTxDl(uint8_t txDl);
|
||||
uint32_t getId(void) const;
|
||||
void setId(uint32_t id);
|
||||
uint32_t getFcId(void) const;
|
||||
void setFcId(uint32_t fcId);
|
||||
uint32_t getFcIdMask(void) const;
|
||||
void setFcIdMask(uint32_t fcIdMask);
|
||||
uint8_t getFlowControlExtendedAddress(void) const;
|
||||
void setFlowControlExtendedAddress(uint8_t addr);
|
||||
uint8_t getExtendedAddress(void) const;
|
||||
void setExtendedAddress(uint8_t addr);
|
||||
uint16_t getFsTimeout(void) const;
|
||||
void setFsTimeout(uint16_t timeout);
|
||||
uint16_t getFsWait(void) const;
|
||||
void setFsWait(uint16_t wait);
|
||||
uint32_t getFlags(void) const;
|
||||
void setFlags(uint32_t flags);
|
||||
uint8_t getStMin(void) const;
|
||||
void setStMin(uint8_t stMin);
|
||||
uint8_t getBlockSize(void) const;
|
||||
void setBlockSize(uint8_t blockSize);
|
||||
|
||||
bool getIs29BitEnabled(void) const;
|
||||
void setIs29BitEnabled(bool enable);
|
||||
bool getIsFc29BitEnabled(void) const;
|
||||
void setIsFc29BitEnabled(bool enable);
|
||||
bool getExtAddressEnabled(void) const;
|
||||
void setExtAddressEnabled(bool enable);
|
||||
bool getFcExtAddressEnabled(void) const;
|
||||
void setFcExtAddressEnabled(bool enable);
|
||||
bool getOverrideStMin(void) const;
|
||||
void setOverrideStMin(bool enable);
|
||||
bool getOverrideBlockSize(void) const;
|
||||
void setOverrideBlockSize(bool enable);
|
||||
bool getPaddingEnabled(void) const;
|
||||
void setPaddingEnabled(bool enable);
|
||||
bool getIsCanFd(void) const;
|
||||
void setIsCanFd(bool enable);
|
||||
bool getIsBrsEnabled(void) const;
|
||||
void setIsBrsEnabled(bool enable);
|
||||
|
||||
private:
|
||||
// Matches J2534_Iso15TxRequest (#pragma pack(2), little-endian) copied after the
|
||||
// 2-byte J2534 command header, as sent by vspy3 J2534_Transaction.
|
||||
// [0..1] J2534 command header (managed by base class)
|
||||
// [2..3] idx (u16 LE)
|
||||
// [4..5] iCoreMiniID (u16 LE)
|
||||
// [6..9] messageLength (u32 LE)
|
||||
// [10] padding
|
||||
// [11] tx_dl
|
||||
// [12..15] id (u32 LE)
|
||||
// [16..19] fc_id (u32 LE)
|
||||
// [20..23] fc_id_mask (u32 LE)
|
||||
// [24] flowControlExtendedAddress
|
||||
// [25] extendedAddress
|
||||
// [26..27] fs_timeout (u16 LE)
|
||||
// [28..29] fs_wait (u16 LE)
|
||||
// [30..33] flags (u32 LE)
|
||||
// [34] stMin
|
||||
// [35] blockSize
|
||||
|
||||
static const size_t SetupIdxOffset = 2;
|
||||
static const size_t SetupCoreMiniOffset = 4;
|
||||
static const size_t SetupMsgLenOffset = 6;
|
||||
static const size_t SetupPaddingOffset = 10;
|
||||
static const size_t SetupTxDlOffset = 11;
|
||||
static const size_t SetupIdOffset = 12;
|
||||
static const size_t SetupFcIdOffset = 16;
|
||||
static const size_t SetupFcIdMaskOffset = 20;
|
||||
static const size_t SetupFcExtAddrOffset = 24;
|
||||
static const size_t SetupExtAddrOffset = 25;
|
||||
static const size_t SetupFsTimeoutOffset = 26;
|
||||
static const size_t SetupFsWaitOffset = 28;
|
||||
static const size_t SetupFlagsOffset = 30;
|
||||
static const size_t SetupStMinOffset = 34;
|
||||
static const size_t SetupBlockSizeOffset = 35;
|
||||
|
||||
// Flag bit positions within the 32-bit flags word.
|
||||
static const uint32_t FlagId29BitEnable = 1u << 0;
|
||||
static const uint32_t FlagFcId29BitEnable = 1u << 1;
|
||||
static const uint32_t FlagExtAddressEnable = 1u << 2;
|
||||
static const uint32_t FlagFcExtAddressEnable = 1u << 3;
|
||||
static const uint32_t FlagOverrideStMin = 1u << 4;
|
||||
static const uint32_t FlagOverrideBlockSize = 1u << 5;
|
||||
static const uint32_t FlagPaddingEnable = 1u << 6;
|
||||
static const uint32_t FlagIsCanFd = 1u << 7;
|
||||
static const uint32_t FlagIsBrsEnabled = 1u << 8;
|
||||
|
||||
bool getFlagBit(uint32_t mask) const;
|
||||
void setFlagBit(uint32_t mask, bool enable);
|
||||
};
|
||||
|
||||
class Iso15765TxDataMessage : public J2534CommandMessage {
|
||||
public:
|
||||
static constexpr uint16_t MaxDataLength = 500;
|
||||
|
||||
Iso15765TxDataMessage()
|
||||
: J2534CommandMessage(J2534Command::SetupIso15765TxMessageDataBytes) {
|
||||
argumentData.resize(10);
|
||||
}
|
||||
|
||||
uint16_t getIdx(void) const;
|
||||
void setIdx(uint16_t idx);
|
||||
uint32_t getOffset(void) const;
|
||||
void setOffset(uint32_t offset);
|
||||
uint16_t getLen(void) const;
|
||||
const uint8_t* getData(void) const;
|
||||
void setData(const uint8_t* sourceData, uint16_t len);
|
||||
|
||||
private:
|
||||
// Matches J2534_Iso15TxDataRequest (#pragma pack(2), little-endian) after the
|
||||
// 2-byte J2534 command header.
|
||||
// [0..1] J2534 command header (managed by base class)
|
||||
// [2..3] idx (u16 LE)
|
||||
// [4..7] offset (u32 LE)
|
||||
// [8..9] len (u16 LE)
|
||||
// [10..] data
|
||||
static const size_t DataIdxOffset = 2;
|
||||
static const size_t DataOffsetOffset = 4;
|
||||
static const size_t DataLenOffset = 8;
|
||||
static const size_t DataPayloadOffset = 10;
|
||||
};
|
||||
|
||||
class Iso15765MessageArgs {
|
||||
public:
|
||||
struct ArbId {
|
||||
bool Is29Bit;
|
||||
uint32_t Id;
|
||||
|
||||
ArbId(uint32_t id = 0, bool is29Bit = false)
|
||||
: Is29Bit(is29Bit)
|
||||
, Id(id) {
|
||||
}
|
||||
};
|
||||
|
||||
Iso15765MessageArgs(void)
|
||||
: networkId(0)
|
||||
, txIndex(0)
|
||||
, arbId({ false, 0 })
|
||||
, flowControlArbId({ false, 0 })
|
||||
, flowControlArbIdMask(0)
|
||||
, isCanFd(false)
|
||||
, isBrsEnabled(false)
|
||||
, tx_DL(8)
|
||||
, fs_Timeout(0)
|
||||
, fs_WaitTimeout(0)
|
||||
, cf_Timeout(0)
|
||||
, isFlowControlEnabled(false) {
|
||||
}
|
||||
|
||||
uint16_t getNetworkId(void) const { return networkId; }
|
||||
void setNetworkId(uint16_t netId) { networkId = netId; }
|
||||
uint8_t getTxIndex(void) const { return txIndex; }
|
||||
void setTxIndex(uint8_t idx) { txIndex = idx; }
|
||||
|
||||
const ArbId& getArbId(void) const { return arbId; }
|
||||
void setArbId(const ArbId& id) { arbId = id; }
|
||||
const ArbId& getFlowControlArbId(void) const { return flowControlArbId; }
|
||||
void setFlowControlArbId(const ArbId& id) { flowControlArbId = id; }
|
||||
uint32_t getFlowControlArbIdMask(void) const { return flowControlArbIdMask; }
|
||||
void setFlowControlArbIdMask(uint32_t mask) { flowControlArbIdMask = mask; }
|
||||
bool getIsCanFd(void) const { return isCanFd; }
|
||||
void setIsCanFd(bool value) { isCanFd = value; }
|
||||
bool getIsBrsEnabled(void) const { return isBrsEnabled; }
|
||||
void setIsBrsEnabled(bool value) { isBrsEnabled = value; }
|
||||
|
||||
uint8_t getTxDl(void) const { return tx_DL; }
|
||||
void setTxDl(uint8_t txDl) { tx_DL = txDl; }
|
||||
std::optional<uint8_t> getStMin(void) const { return stMin; }
|
||||
void setStMin(std::optional<uint8_t> v) { stMin = v; }
|
||||
std::optional<uint8_t> getBlockSize(void) const { return blockSize; }
|
||||
void setBlockSize(std::optional<uint8_t> b) { blockSize = b; }
|
||||
std::optional<uint8_t> getFlowControlExtendedAddress(void) const { return flowControlExtendedAddress; }
|
||||
void setFlowControlExtendedAddress(std::optional<uint8_t> fcExtAddr) { flowControlExtendedAddress = fcExtAddr; }
|
||||
std::optional<uint8_t> getExtendedAddress(void) const { return extendedAddress; }
|
||||
void setExtendedAddress(std::optional<uint8_t> extAddr) { extendedAddress = extAddr; }
|
||||
std::optional<uint8_t> getPaddingValue(void) const { return paddingValue; }
|
||||
void setPaddingValue(std::optional<uint8_t> v) { paddingValue = v; }
|
||||
|
||||
uint16_t getFsTimeout(void) const { return fs_Timeout; }
|
||||
void setFsTimeout(uint16_t timeout) { fs_Timeout = timeout; }
|
||||
uint16_t getFsWaitTimeout(void) const { return fs_WaitTimeout; }
|
||||
void setFsWaitTimeout(uint16_t timeout) { fs_WaitTimeout = timeout; }
|
||||
uint16_t getCfTimeout(void) const { return cf_Timeout; }
|
||||
void setCfTimeout(uint16_t timeout) { cf_Timeout = timeout; }
|
||||
|
||||
const std::vector<uint8_t>& getData(void) const { return data; }
|
||||
void setData(std::vector<uint8_t>&& d) { data = std::move(d); }
|
||||
|
||||
bool getIsFlowControlEnabled(void) const { return isFlowControlEnabled; }
|
||||
void setIsFlowControlEnabled(bool enabled) { isFlowControlEnabled = enabled; }
|
||||
|
||||
protected:
|
||||
|
||||
uint16_t networkId; // The netid of the message (determines which network to transmit on)
|
||||
uint8_t txIndex; // identifier for this transmit message
|
||||
|
||||
ArbId arbId; // arbId of transmitted frames (CAN id to transmit to)
|
||||
ArbId flowControlArbId; // flow control arb id filter value (response id from receiver)
|
||||
uint32_t flowControlArbIdMask; // The flow control arb id filter mask (response id from receiver)
|
||||
bool isCanFd;
|
||||
bool isBrsEnabled;
|
||||
|
||||
uint8_t tx_DL; // Maximum CAN(FD) protocol length for transmitted frames (Valid values are 8, 12, 16, 20, 24, 32, 48, 64)
|
||||
std::optional<uint8_t> stMin; // Overrides the stMin that the receiver reports (Set to J2534's STMIN_TX if <= 0xFF)
|
||||
std::optional<uint8_t> blockSize; // Overrides the block size that the receiver reports (Set to J2534's BS_TX if <= 0xFF)
|
||||
std::optional<uint8_t> flowControlExtendedAddress; // Expected Extended Address byte of response from receiver
|
||||
std::optional<uint8_t> extendedAddress; // Extended Address byte of transmitter
|
||||
std::optional<uint8_t> paddingValue; // The padding byte to use to fill the unused portion of transmitted CAN frames (single frame, first frame, consecutive frame)
|
||||
|
||||
uint16_t fs_Timeout; // max timeout (ms) for waiting on flow control response (Set this to N_BS_MAX's value if J2534)
|
||||
uint16_t fs_WaitTimeout; // max timeout (ms) for waiting on flow control response after receiving flow control with flow status set to WAIT (Set this to N_BS_MAX's value if J2534)
|
||||
uint16_t cf_Timeout; // max timeout (ms) for waiting on consecutive frame (Set this to N_CR_MAX's value in J2534)
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
|
||||
bool isFlowControlEnabled; // Enables Flow Control frame transmission (Rx message; from neoVI to ECU)
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
@@ -34,6 +34,7 @@ struct LINStatusFlags {
|
||||
bool HasUpdatedResponderOnce = false;
|
||||
bool BusRecovered = false;
|
||||
bool BreakOnly = false;
|
||||
bool WakeupRequest = false;
|
||||
};
|
||||
|
||||
class LINMessage : public Frame {
|
||||
@@ -45,7 +46,8 @@ 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_ERROR = icsneoc2_lin_msg_type_error,
|
||||
LIN_WAKEUP_REQUEST = icsneoc2_lin_msg_type_wakeup_request
|
||||
};
|
||||
|
||||
static void calcChecksum(LINMessage& message);
|
||||
|
||||
@@ -48,6 +48,10 @@ public:
|
||||
NetworkMutex = 0x8016,
|
||||
ClientId = 0x8017,
|
||||
AllMACAddresses = 0x8018,
|
||||
SPIPortKeyOperation = 0x8019,
|
||||
GenericAPIData = 0x8020,
|
||||
GenericAPIStatus = 0x8021,
|
||||
MfgConfig = 0x8022,
|
||||
};
|
||||
|
||||
Message(Type t) : type(t) {}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef __MFGCONFIGMESSAGE_H_
|
||||
#define __MFGCONFIGMESSAGE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/communication/message/message.h"
|
||||
#include "icsneo/communication/message/allmacaddressesmessage.h"
|
||||
#include "icsneo/device/chipid.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class MfgConfigMessage : public Message {
|
||||
public:
|
||||
struct MfgDate {
|
||||
uint32_t day = 0;
|
||||
uint32_t month = 0;
|
||||
uint32_t year = 0;
|
||||
};
|
||||
|
||||
struct VersionNumber {
|
||||
uint32_t major = 0;
|
||||
uint32_t minor = 0;
|
||||
std::optional<uint32_t> release;
|
||||
std::optional<uint32_t> build;
|
||||
};
|
||||
|
||||
MfgConfigMessage() : Message(Message::Type::MfgConfig) {}
|
||||
|
||||
static std::shared_ptr<MfgConfigMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||
static std::vector<uint8_t> EncodeArgumentsForGet();
|
||||
|
||||
std::optional<uint64_t> serialNumber;
|
||||
std::optional<MfgDate> manufactureDate;
|
||||
std::optional<VersionNumber> hardwareRev;
|
||||
std::optional<uint8_t> productId;
|
||||
std::optional<VersionNumber> bootloaderRev;
|
||||
std::optional<std::string> usbDescriptor;
|
||||
std::vector<MACAddress> macAddresses;
|
||||
std::optional<std::string> pcbSerial;
|
||||
std::optional<ChipID> chipId;
|
||||
std::optional<uint64_t> imei;
|
||||
std::optional<uint8_t> parentProductId;
|
||||
std::optional<VersionNumber> softwareVersionLock;
|
||||
};
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __MFGCONFIGMESSAGE_H_
|
||||
@@ -0,0 +1,43 @@
|
||||
#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,7 +47,8 @@ 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 : 2;
|
||||
uint16_t WakeupRequest : 1; //!< LIN wakeup pulse.
|
||||
uint16_t : 1;
|
||||
} CoreMiniBitsLIN;
|
||||
|
||||
uint8_t data[8];
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
#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"
|
||||
@@ -60,6 +63,9 @@
|
||||
#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; \
|
||||
@@ -342,6 +348,7 @@ 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();
|
||||
|
||||
|
||||
/**
|
||||
@@ -727,6 +734,8 @@ 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
|
||||
*
|
||||
@@ -740,6 +749,7 @@ 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;
|
||||
|
||||
@@ -897,11 +907,19 @@ 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;
|
||||
@@ -934,7 +952,7 @@ protected:
|
||||
std::move(decoder)
|
||||
);
|
||||
setupCommunication(*com);
|
||||
settings = makeSettings<Settings>(com);
|
||||
settings = makeSettings<Settings>(this);
|
||||
setupSettings(*settings);
|
||||
diskReadDriver = std::unique_ptr<DiskRead>(new DiskRead());
|
||||
diskWriteDriver = std::unique_ptr<DiskWrite>(new DiskWrite());
|
||||
@@ -970,8 +988,8 @@ protected:
|
||||
}
|
||||
|
||||
template<typename Settings>
|
||||
std::shared_ptr<IDeviceSettings> makeSettings(std::shared_ptr<Communication> comm) {
|
||||
return std::make_shared<Settings>(comm);
|
||||
std::shared_ptr<IDeviceSettings> makeSettings(Device* device) {
|
||||
return std::make_shared<Settings>(device);
|
||||
}
|
||||
virtual void setupSettings(IDeviceSettings&) {}
|
||||
|
||||
@@ -1036,10 +1054,6 @@ 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();
|
||||
@@ -1050,10 +1064,6 @@ 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
|
||||
@@ -1174,8 +1184,26 @@ 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;
|
||||
|
||||
@@ -811,13 +811,17 @@ typedef struct
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "icsneo/communication/communication.h"
|
||||
#include "icsneo/communication/network.h"
|
||||
#include "icsneo/api/event.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <optional>
|
||||
#include <iostream>
|
||||
#include <atomic>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class Device;
|
||||
|
||||
enum class MiscIOAnalogVoltage : uint8_t
|
||||
{
|
||||
V0 = icsneoc2_misc_io_analog_voltage_v0,
|
||||
@@ -845,7 +849,7 @@ public:
|
||||
static int64_t GetBaudrateValueForEnum(CANBaudrate enumValue);
|
||||
static bool ValidateLINBaudrate(int64_t baudrate);
|
||||
|
||||
IDeviceSettings(std::shared_ptr<Communication> com, size_t size) : com(com), report(com->report), structSize(size) {}
|
||||
IDeviceSettings(Device* device, size_t size);
|
||||
virtual ~IDeviceSettings() {}
|
||||
bool ok() const { return !disabled && settingsLoaded; }
|
||||
|
||||
@@ -1392,10 +1396,8 @@ public:
|
||||
bool disabled = false;
|
||||
|
||||
bool readonly = false;
|
||||
|
||||
std::atomic<bool> applyingSettings{false};
|
||||
protected:
|
||||
std::shared_ptr<Communication> com;
|
||||
Device* device;
|
||||
device_eventhandler_t report;
|
||||
size_t structSize;
|
||||
|
||||
@@ -1407,8 +1409,7 @@ 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, std::shared_ptr<Communication> com)
|
||||
: disabled(true), readonly(true), report(com->report), structSize(0) { (void)createInoperableSettings; }
|
||||
IDeviceSettings(warn_t createInoperableSettings, Device* device);
|
||||
|
||||
// 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
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace icsneo {
|
||||
class NullSettings : public IDeviceSettings {
|
||||
public:
|
||||
// Calls the protected base constructor with "createInoperableSettings"
|
||||
NullSettings(std::shared_ptr<Communication> com) : IDeviceSettings(nullptr, com) {}
|
||||
NullSettings(Device* device) : IDeviceSettings(nullptr, device) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ static_assert(sizeof(etherbadge_settings_t) == 316, "EtherBadge settings size mi
|
||||
|
||||
class EtherBADGESettings : public IDeviceSettings {
|
||||
public:
|
||||
EtherBADGESettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(etherbadge_settings_t)) {}
|
||||
EtherBADGESettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neoviconnect_settings_t)) {}
|
||||
NeoVIConnectSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire_settings_t)) {}
|
||||
NeoVIFIRESettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire2_settings_t)) {}
|
||||
NeoVIFIRE2Settings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3_settings_t)) {}
|
||||
NeoVIFIRE3Settings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3flexray_settings_t)) {}
|
||||
NeoVIFIRE3FlexRaySettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3t1slin_settings_t)) {}
|
||||
NeoVIFIRE3T1SLINSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovired2_settings_t)) {}
|
||||
NeoVIRED2Settings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(rada2b_settings_t)) {}
|
||||
RADA2BSettings(Device* device) : IDeviceSettings(device, 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 device) const {
|
||||
TDMMode getTDMMode(RADA2BDevice a2bDevice) const {
|
||||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
return static_cast<TDMMode>(deviceSettings.tdmMode);
|
||||
}
|
||||
|
||||
uint8_t getNumChannels(RADA2BDevice device) const {
|
||||
return tdmModeToChannelNum(getTDMMode(device));
|
||||
uint8_t getNumChannels(RADA2BDevice a2bDevice) const {
|
||||
return tdmModeToChannelNum(getTDMMode(a2bDevice));
|
||||
}
|
||||
|
||||
ChannelSize getChannelSize(RADA2BDevice device) const {
|
||||
ChannelSize getChannelSize(RADA2BDevice a2bDevice) const {
|
||||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
return static_cast<ChannelSize>(deviceSettings.flags & a2bSettingsFlag16bit);
|
||||
}
|
||||
|
||||
uint8_t getChannelOffset(RADA2BDevice device, A2BMessage::Direction dir) const {
|
||||
uint8_t getChannelOffset(RADA2BDevice a2bDevice, A2BMessage::Direction dir) const {
|
||||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == 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 device) const {
|
||||
NodeType getNodeType(RADA2BDevice a2bDevice) const {
|
||||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
return static_cast<NodeType>(deviceSettings.nodeType);
|
||||
}
|
||||
|
||||
void setNodeType(RADA2BDevice device, NodeType newType) {
|
||||
void setNodeType(RADA2BDevice a2bDevice, NodeType newType) {
|
||||
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
deviceSettings.nodeType = static_cast<uint8_t>(newType);
|
||||
}
|
||||
|
||||
void setTDMMode(RADA2BDevice device, TDMMode newMode) {
|
||||
void setTDMMode(RADA2BDevice a2bDevice, TDMMode newMode) {
|
||||
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
deviceSettings.tdmMode = static_cast<uint8_t>(newMode);
|
||||
}
|
||||
|
||||
void setChannelOffset(RADA2BDevice device, A2BMessage::Direction dir, uint8_t newOffset) {
|
||||
void setChannelOffset(RADA2BDevice a2bDevice, A2BMessage::Direction dir, uint8_t newOffset) {
|
||||
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
if(dir == A2BMessage::Direction::Upstream) {
|
||||
deviceSettings.upstreamChannelOffset = newOffset;
|
||||
@@ -203,9 +203,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void setChannelSize(RADA2BDevice device, ChannelSize newChannelSize) {
|
||||
void setChannelSize(RADA2BDevice a2bDevice, ChannelSize newChannelSize) {
|
||||
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet2_settings_t)) {}
|
||||
RADComet2Settings(Device* device) : IDeviceSettings(device, sizeof(radcomet2_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radcomet2_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
@@ -118,6 +118,18 @@ 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet3_settings_t)) {}
|
||||
RADComet3Settings(Device* device) : IDeviceSettings(device, sizeof(radcomet3_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radcomet3_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
@@ -115,6 +115,18 @@ 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radepsilon_settings_t)) {}
|
||||
RADEpsilonSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgalaxy_settings_t)) {}
|
||||
RADGalaxySettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgalaxy2_settings_t)) {}
|
||||
RADGalaxy2Settings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgemini_settings_t)) {}
|
||||
RADGeminiSettings(Device* device) : IDeviceSettings(device, sizeof(radgemini_settings_t)) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgigastar_settings_t)) {}
|
||||
RADGigastarSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgigastar2_settings_t)) {}
|
||||
RADGigastar2Settings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radjupiter_settings_t)) {}
|
||||
RADJupiterSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmars_settings_t)) {}
|
||||
RADMarsSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon2_settings_t)) {}
|
||||
RADMoon2Settings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon3_settings_t)) {}
|
||||
RADMoon3Settings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoonduo_settings_t)) {}
|
||||
RADMoonDuoSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoont1s_settings_t)) {}
|
||||
RADMoonT1SSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radpluto_settings_t)) {
|
||||
RADPlutoSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radstar2_settings_t)) {
|
||||
RADStar2Settings(Device* device) : IDeviceSettings(device, sizeof(radstar2_settings_t)) {
|
||||
}
|
||||
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
|
||||
@@ -38,7 +38,7 @@ typedef struct {
|
||||
|
||||
class RADSupermoonSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADSupermoonSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radsupermoon_settings_t)) {}
|
||||
RADSupermoonSettings(Device* device) : IDeviceSettings(device, sizeof(radsupermoon_settings_t)) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/device/devicetype.h"
|
||||
#include "icsneo/device/tree/radwbms/radwbmssettings.h"
|
||||
#include "icsneo/disk/neomemorydiskdriver.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
@@ -126,6 +127,8 @@ public:
|
||||
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 = {};
|
||||
|
||||
@@ -70,7 +70,7 @@ static_assert(sizeof(radwbms_settings_t) == 156, "RAD-wBMS settings size mismatc
|
||||
|
||||
class RADwBMSSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADwBMSSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radwbms_settings_t)) {}
|
||||
RADwBMSSettings(Device* device) : IDeviceSettings(device, sizeof(radwbms_settings_t)) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ static_assert(sizeof(valuecan3_settings_t) == 40, "ValueCAN3 settings size misma
|
||||
|
||||
class ValueCAN3Settings : public IDeviceSettings {
|
||||
public:
|
||||
ValueCAN3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan3_settings_t)) {}
|
||||
ValueCAN3Settings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_1_2_settings_t)) {}
|
||||
ValueCAN4_1_2Settings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
|
||||
ValueCAN4_1Settings(Device* device) : ValueCAN4_1_2Settings(device) {}
|
||||
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(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
|
||||
ValueCAN4_2ELSettings(Device* device) : ValueCAN4_4_2ELSettings(device) {}
|
||||
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(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
|
||||
ValueCAN4_2Settings(Device* device) : ValueCAN4_1_2Settings(device) {}
|
||||
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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_4_2el_settings_t)) {}
|
||||
ValueCAN4_4_2ELSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
|
||||
ValueCAN4_4Settings(Device* device) : ValueCAN4_4_2ELSettings(device) {}
|
||||
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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_industrial_settings_t)) {}
|
||||
ValueCAN4IndustrialSettings(Device* device) : IDeviceSettings(device, 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(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(vividcan_settings_t)) {}
|
||||
VividCANSettings(Device* device) : IDeviceSettings(device, sizeof(vividcan_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<vividcan_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -44,7 +44,10 @@ typedef unsigned __int64 uint64_t;
|
||||
#include "cicsSpyStatusBits.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4200)
|
||||
#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
|
||||
#endif
|
||||
|
||||
// MSVC++ 10.0 _MSC_VER == 1600 64-bit version doesn't allow multi-line #if directives...
|
||||
@@ -5440,4 +5443,8 @@ 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 */
|
||||
|
||||
@@ -372,10 +372,11 @@ 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.
|
||||
|
||||
@@ -381,6 +381,7 @@ 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;
|
||||
@@ -409,6 +410,7 @@ 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;
|
||||
|
||||
|
||||
@@ -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(kIOMasterPortDefault, ref, &matchingServices);
|
||||
kern_return_t kernResult = IOServiceGetMatchingServices(kIOMainPortDefault, ref, &matchingServices);
|
||||
if(KERN_SUCCESS != kernResult || matchingServices == 0)
|
||||
return;
|
||||
IOReleaser matchingServicesReleaser(matchingServices);
|
||||
|
||||
+5
-1
@@ -243,6 +243,7 @@ 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;
|
||||
@@ -260,11 +261,14 @@ void Servd::read() {
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
pushRx(buf.data(), bufSize);
|
||||
if(!pushRx(buf.data(), bufSize)) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Servd::write() {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
WriteOperation writeOp;
|
||||
while(!isDisconnected() && !isClosing()) {
|
||||
if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100))) {
|
||||
|
||||
@@ -127,6 +127,28 @@ 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;
|
||||
@@ -1840,6 +1862,7 @@ 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));
|
||||
}
|
||||
|
||||
@@ -1853,6 +1876,7 @@ 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)
|
||||
@@ -1879,6 +1903,7 @@ 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)
|
||||
@@ -2131,3 +2156,28 @@ 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));
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
#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;
|
||||
|
||||
@@ -55,6 +57,16 @@ 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,
|
||||
@@ -139,6 +151,29 @@ 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));
|
||||
@@ -193,3 +228,45 @@ TEST_F(LINEncoderDecoderTest, PacketDecoderTest) {
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user